# 新增字段:管理员表加「企业微信客服ID」(customerServiceId)

**类型**: 后端新增字段 + 前端管理后台展示/编辑
**关联**: 工单 #1519 / PR #1521 / 用户(wx)需求
**日期**: 2026-04-28
**影响范围**: 管理员管理（admin/user）模块的所有列表、详情、新增、编辑接口

---

## 背景

管理员管理页面要展示并维护每个管理员对应的企业微信「客服系统」客服 ID（open_kfid），用于后续与企业微信客服 API 对接。

**与现有 `enterpriseWechatId` 的区别**：
- `enterpriseWechatId` = 员工的企业微信 userid（已有字段，通过 `/wechat-binding` 专属接口换绑）
- `customerServiceId` = 企业微信「客服系统」里的客服账号 ID（新增字段，open_kfid，无需换绑校验）

---

## 数据库变更

`admin_user` 表新增列：

```sql
ALTER TABLE admin_user ADD COLUMN customer_service_id VARCHAR(64) DEFAULT NULL
  COMMENT '企业微信客服系统客服ID(open_kfid)，可空' AFTER enterprise_wechat_id;
```

- 类型 `VARCHAR(64)`，**可为 NULL**
- 不建索引、不加唯一约束
- 不参与查询过滤

---

## 接口变更（共 4 处，全部位于现有 admin 接口）

### 1. 新增管理员 `POST /admin/user`

请求体 `CreateAdminRequest` 新增字段：

| 字段 | 类型 | 必填 | 长度 | 说明 |
|---|---|---|---|---|
| `customerServiceId` | string | 否 | ≤64 | 企业微信客服系统客服ID(open_kfid) |

请求示例：
```json
{
  "username": "zhangsan",
  "roleIds": [3],
  "customerServiceId": "wkAJ2GCAAA_kfid_001"
}
```

### 2. 更新管理员 `PUT /admin/user/{adminId}`

请求体 `UpdateAdminRequest` 新增字段：

| 字段 | 类型 | 必填 | 长度 | 说明 |
|---|---|---|---|---|
| `customerServiceId` | string | 否 | ≤64 | 企业微信客服系统客服ID。**传 null 保留原值，传空字符串 `""` 清空** |

请求示例：
```json
{
  "roleIds": [3],
  "customerServiceId": "wkNEW_kfid_002"
}
```

> ⚠️ 与 `enterpriseWechatId`（PUT 时被忽略，需走专属换绑接口）不同，`customerServiceId` 在 PUT 接口直接生效，不需要换绑校验。

### 3. 管理员详情 `GET /admin/user/{adminId}`

响应体 `AdminUser` 新增字段：

| 字段 | 类型 | 说明 |
|---|---|---|
| `customerServiceId` | string \| null | 企业微信客服系统客服ID |

### 4. 管理员列表 `GET /admin/user`

响应数组每个元素新增同字段 `customerServiceId`。

---

## 校验规则

- 长度 ≤64 字符
- 超长返回 HTTP 200 + 业务码 400：
  ```json
  {
    "code": 400,
    "message": "customerServiceId: 客服ID长度不能超过64个字符",
    "data": null,
    "success": false
  }
  ```

---

## 前端处理（yst / mmg）

### 必做改动
1. **管理员管理列表页**（截图位置：`管理员管理` 主表格）
   - 加列「客服 ID」（建议放在「企业微信」列右边）
   - 单元格直接展示 `customerServiceId` 字符串，为 null 时显示 `-`

2. **新增成员表单**
   - 加输入框「客服 ID」，placeholder 提示 `wkAJ2GCAA...（企业微信客服系统 open_kfid）`
   - 单行文本，maxlength=64
   - **非必填**

3. **编辑成员表单**（同新增）
   - 字段名 `customerServiceId`
   - 不传 = 保留原值；传空串 `""` = 清空原值

### 兼容性
- **零破坏**：新增字段，未传入时后端落空值，原有调用方完全无影响
- **TypeScript 类型补充**：`AdminUser` 类型加 `customerServiceId?: string | null`

---

## 单元 + E2E 测试覆盖

### 单元测试（4/4 全绿）
- `createAdmin_withCustomerServiceId_persistsField`
- `createAdmin_nullCustomerServiceId_persistsNull`
- `updateAdmin_withCustomerServiceId_overwritesValue`
- `updateAdmin_nullCustomerServiceId_keepsOriginalValue`

### 测试服 E2E（6/6 全过）
- 创建管理员 + customerServiceId → ✅
- GET 详情返回 → ✅
- PUT 更新覆盖 → ✅
- PUT null 保留原值 → ✅
- 列表查询返回 → ✅
- @Size(max=64) 校验 400 → ✅

---

## 不在本次范围
- 不与企业微信客服 API 真正对接（后续工单）
- 字段不参与查询过滤、不分单
- 不建索引、不加唯一约束

---

## 部署状态
- ✅ 测试服 `admin_user` 已 ALTER（生产环境上线时需同步执行 ALTER）
- ✅ 测试服 hl-user-service 已 Deploy Panel 部署
- ✅ 测试服端到端验证通过（经网关 `https://api.test.1814.love:9443`）
