# 管理端主题列表: 卡片新增「创建人姓名」字段 createdByName（企微昵称优先 fallback 用户名）

> **服务**: hl-product-service-v2 (端口 8083)
> **PR**: [#1944](https://git.1814.love:8443/wx/HL/pulls/1944) — 已合并到 main
> **Issue**: [#1943](https://git.1814.love:8443/wx/HL/issues/1943) — 已关闭
> **日期**: 2026-05-11
> **影响范围**: 管理后台「产品管理 → 主题列表」(/product/line) 卡片
> **状态**: ✅ **已上线正式服**（2026-05-11 18:06，release PR [#1945](https://git.1814.love:8443/wx/HL/pulls/1945)，image_tag `9ffad0ee`）

---

## ⚠️ 关键变化（覆盖本日早些时候那条 heads-up）

主题列表卡片每张多一个字段 **`createdByName`**（String，可能为 null）。

**显示规则（后端已实现）**：
- 创建人 admin_user 绑定了企业微信 → 返回**企业微信昵称**
- 未绑企微 → 返回 **admin_user.username**（用户名兜底）
- 极端情况（user-service 降级 / admin 已删）→ 返回 null

前端**无需自己 fallback**，后端已聚合好，直接展示 `createdByName` 即可。

---

## 一、测试服已验证 (硬性凭证)

```
GET https://api.test.1814.love:9443/admin/product/line/list?pageNo=1&pageSize=5
Authorization: Bearer <admin 真 token>

HTTP 200
data.records[*].createdByName 字段存在性: 5/5 条全部都有 ✓
非 null 命中:              5/5 条 (createdBy 有值的全部回填) ✓

实测样本:
  lineId=2053279457388494849 createdBy=2021059720172838914 createdByName='王骁'
  lineId=2053278451187535873 createdBy=2021059720172838914 createdByName='王骁'
  lineId=2053060320829599746 createdBy=1001                createdByName='admin'       (username fallback)
  lineId=2053060194102898690 createdBy=1002                createdByName='test_admin' (username fallback)
  lineId=2049467101390819329 createdBy=2033349910786715649 createdByName='小松'        (企微昵称)
```

---

## 二、背景

超级管理员/运营组长视角下，主题列表卡片看不出谁建的，特别是私人定制类主题（不同销售各自开），需要快速识别 owner。

---

## 三、变更接口清单

| # | 接口 | 方法 | 路径 | 变更类型 | 说明 |
|---|------|------|------|----------|------|
| 1 | 主题列表 | GET | `/admin/product/line/list` | 响应体新增字段 | 每条多 `createdByName` |
| 2 | 主题详情 | GET | `/admin/product/line/{lineId}` | 响应体新增字段 | 多 `createdByName` |

后端 0 个 break、0 个删除、0 个语义变化。仅追加字段。

---

## 四、接口详情

### 1. 主题列表 `GET /admin/product/line/list`

**VO**: `ProductLineRespVO`

#### 出参（仅列出新增/相关字段）

| 字段 | 类型 | 说明 |
|------|------|------|
| `lineId` | Long | 主题 ID（已有） |
| `name` | String | 主题名（已有） |
| `createdBy` | Long | 创建人 admin_id（已有，前端无需用） |
| **`createdByName`** | **String** | **🆕 创建人显示名（企微昵称优先 fallback username，可能 null）** |
| `createTime` | DateTime | 创建时间（已有） |
| ... | ... | 其他字段不变 |

#### 响应示例

```json
{
  "code": 200,
  "message": "成功",
  "success": true,
  "data": {
    "records": [
      {
        "lineId": "2053279457388494849",
        "name": "私人订制",
        "createdBy": "2021059720172838914",
        "createdByName": "王骁",
        "createTime": "2026-05-10 09:02:25",
        "...其他字段": "..."
      }
    ]
  }
}
```

### 2. 主题详情 `GET /admin/product/line/{lineId}`

同样追加 `createdByName` 字段，结构与列表一致。

---

## 五、前端实现要点

### UI 位置（建议）

主题卡片在「创建时间」一行旁边或上面加一行「创建人: xxx」，排版方式由前端拍板。

### Null 处理

- `createdByName === null` → 显示「-」或不显示该行（不要显示「null」字样）
- 不要尝试自己用 createdBy ID 调 user-service 兜底 —— 后端已经处理过，再调也是相同结果

### 主题详情页

如果详情页也想展示创建人，同样读 `createdByName` 字段。

---

## 六、不影响范围

- ✅ MP 端任何接口：0 改动（C 端不需要看创建人）
- ✅ 主题创建/编辑/删除接口：0 改动（写入侧不受影响）
- ✅ 现有筛选条件（关键字/状态/主题类型）：0 改动
- ✅ 历史 27 条主题数据：无需迁移（createdBy 已写入，靠 enrich 实时取，老数据如 createdBy 已删则返 null）

---

## 七、降级/边界

- user-service 降级（Feign 失败）→ 后端 catch 异常，所有 createdByName 返 null，列表照常返回，**不阻断页面**
- batchGetAdminInfo 返空（admin 已删）→ 该条 createdByName = null
- admin_user 未绑企微 → wechatName 为 null，自动 fallback username

---

## 八、相关历史

| PR | Issue | 说明 | 是否仍有效 |
|----|-------|------|------------|
| **#1944** | #1943 | 主题列表/详情新增 createdByName | ✅ **本次**（已合 dev + 测试服已验证） |

参考类似实现：产品列表 `ProductQueryService.enrichCreatedByName():243-267`（已上线很久，前端已使用 `createdByName` 字段）。

---

## 九、相关文档

- 关联 Issue: [wx/HL#1943](https://git.1814.love:8443/wx/HL/issues/1943)
- 关联 PR: [wx/HL#1944](https://git.1814.love:8443/wx/HL/pulls/1944)
- Feign 接口: `hl-common/hl-common-feign/.../UserFeignClient.java:36-37`
- AdminBasicDTO: `hl-common/hl-common-core/.../AdminBasicDTO.java:17,25-26`
- 仿写模板: `hl-product-service-v2/.../ProductQueryService.java:243-267`
