# 【修改接口·管理后台】标签库支持系统/个人作用域分类 (#3940)

> **PR**: #3943 | **服务**: hl-order-service-v3 | **更新时间**: 2026-06-17

## 1. 接口背景

原有标签库属于「个人标签」——仅创建该标签的管理员本人可见。业务方需要一批所有管理员都能使用的「系统标签」（如客户分类、跟进阶段等高净値标签），避免每人各自重建一遍。本次引入「作用域」概念，将标签区分为：

- **SYSTEM（系统标签）**：全员共享，所有登录管理员均可见、可选用，且任何管理员均可增删改排序，无额外权限限制。
- **PERSONAL（个人标签）**：仅创建者本人可见、可维护，其他人无法操作。

## 2. 变更清单

| # | 接口 | 方法 | 路径 | 变更类型 | 说明 |
|---|------|------|------|----------|------|
| 1 | 新增标签库预设 | POST | /v3/admin/tag-library | 修改入参 + 修改出参 | 入参新增 `tagScope` 字段；出参新增 `tagScope` 字段 |
| 2 | 查询标签库列表 | GET | /v3/admin/tag-library | 修改出参 + 返回口径变化 | 出参新增 `tagScope`；返回「全部系统标签 ∪ 当前管理员个人标签」 |
| 3 | 修改标签库预设 | PUT | /v3/admin/tag-library/{id} | 修改出参 | 出参新增 `tagScope` 字段 |

## 3. 接口详情

### 3.1 新增标签库预设

- **使用场景**：管理员在标签库管理页点击「新建标签」时调用，可选择创建个人标签还是系统标签。
- **认证**：需要 JWT（`Authorization: Bearer <token>`），从请求头 `X-Admin-Id` 读取操作人 userId，前端无需在请求体传操作人字段。
- **幂等性**：否（重复调用将重复创建）。
- **限流**：无。

请求体变更：新增 `tagScope` 字段（选填），不传时默认 `PERSONAL`。

### 3.2 查询标签库列表

- **使用场景**：标签库管理页加载时、给订单挂标签弹窗展示可选标签时调用。
- **认证**：需要 JWT，列表仅返回「全部系统标签 ∪ 当前登录管理员的个人标签」，不返回其他管理员的个人标签。
- **幂等性**：是（只读）。
- **限流**：无。

重要行为变更：原来列表仅返回当前管理员自己创建的标签；现在额外包含所有 SYSTEM 作用域的标签，即系统标签所有人共享可见。

排序规则不变：`is_pinned DESC`、`sort_order ASC`、`last_used_at DESC`。

### 3.3 修改标签库预设

- **使用场景**：管理员编辑某条标签（改名/改颜色/置顶排序）时调用。
- **认证**：需要 JWT。权限规则：SYSTEM 标签任何管理员可改；PERSONAL 标签仅创建者本人可改，他人修改返回 581423。
- **幂等性**：是（同参数多次调用结果相同）。
- **限流**：无。

## 4. 接口入参

### 4.1 路径参数 / Query 参数

| 接口 | 字段 | 类型 | 必填 | 说明 |
|------|------|------|------|------|
| PUT /v3/admin/tag-library/{id} | id | Long（String格式） | 是 | 路径参数，标签 ID |

### 4.2 请求体字段（POST /v3/admin/tag-library）

| 字段 | 类型 | 必填 | 说明 | 校验规则 |
|------|------|------|------|----------|
| tagName | String | 是 | 标签名称 | 不能为空，长度 ≤ 50 字符 |
| tagColor | String | 否 | 标签颜色，十六进制格式 | 格式 `#RRGGBB`，如 `#5B8FF9`；不传默认 `#5B8FF9` |
| tagScope | String | 否 | 标签作用域 | 可选値 `SYSTEM` / `PERSONAL`；不传默认 `PERSONAL` |

重名校验规则（新增）：

- SYSTEM 标签：按 `tagName` 全局唯一（所有 SYSTEM 标签不能同名）。
- PERSONAL 标签：按（当前用户 + tagName）唯一（不同人可以有同名个人标签）。

## 5. 出参（响应）

### 5.1 标签对象 TagLibraryItemVO（新增 tagScope 字段）

以下字段适用于 POST 新增返回、GET 列表内每条元素、PUT 修改返回。

| 字段 | 类型 | 说明 |
|------|------|------|
| id | String | 标签 ID（雪花 ID，String 格式） |
| tagName | String | 标签名称 |
| tagColor | String | 标签颜色，如 `#5B8FF9` |
| tagScope | String | **[新增]** 作用域，値为 `SYSTEM` 或 `PERSONAL` |
| sortOrder | Integer | 排序値，越小越靠前 |
| isPinned | Boolean | 是否置顶 |
| usedCount | Integer | 被挂单次数 |
| lastUsedAt | String | 最近一次挂单时间，ISO-8601 格式，如 `2026-06-17T10:00:00` |

### 5.2 GET /v3/admin/tag-library 列表响应结构

```json
{
  "code": 200,
  "data": [
    {
      "id": "2067178767255560193",
      "tagName": "高净値",
      "tagColor": "#5B8FF9",
      "tagScope": "SYSTEM",
      "sortOrder": 0,
      "isPinned": false,
      "usedCount": 3,
      "lastUsedAt": "2026-06-17T10:00:00"
    },
    {
      "id": "2067178767255560195",
      "tagName": "重点跟进",
      "tagColor": "#5B8FF9",
      "tagScope": "PERSONAL",
      "sortOrder": 0,
      "isPinned": false,
      "usedCount": 1,
      "lastUsedAt": "2026-06-16T09:30:00"
    }
  ],
  "message": "ok",
  "success": true
}
```

## 6. 枚举 / 数据字典

### 6.1 tagScope（标签作用域枚举）

**所属字段**：`tagScope`（入参 + 出参均有）| **类型**：`String` | **入参必填**：否（默认 PERSONAL）

| 値 | 中文 | 说明 |
|----|------|------|
| `SYSTEM` | 系统标签 | 全员可见，任何管理员可增删改排序，按 tagName 全局唯一 |
| `PERSONAL` | 个人标签 | 仅创建者本人可见/可维护，按（创建者 + tagName）唯一 |

## 7. 错误码

| code | 含义 | 触发场景 |
|------|------|----------|
| 581421 | 标签名已存在 | SYSTEM 标签重名（全局唯一），或 PERSONAL 标签与本人已有标签同名 |
| 581423 | 无权操作 | 尝试修改/删除他人的 PERSONAL 标签时 |
| 581424 | 标签不存在 | PUT/DELETE 传了不存在的标签 ID |
| 581428 | 标签作用域非法 | 传入了 `SYSTEM`/`PERSONAL` 之外的 tagScope 値 |
| 401 | 未登录 | 未携带或 token 无效 |

## 8. 示例（3 组：典型 / 边界 / 异常）

### 8.1 典型成功 — 管理员 A 新建系统标签

请求：
```
POST /v3/admin/tag-library
Authorization: Bearer <token>
Content-Type: application/json

{
  "tagName": "高净値",
  "tagScope": "SYSTEM"
}
```

响应：
```json
{
  "code": 200,
  "data": {
    "id": "2067178767255560193",
    "tagName": "高净値",
    "tagColor": "#5B8FF9",
    "tagScope": "SYSTEM",
    "sortOrder": 0,
    "isPinned": false,
    "usedCount": 0,
    "lastUsedAt": null
  },
  "message": "ok",
  "success": true
}
```

### 8.2 边界情况 — 不传 tagScope，默认 PERSONAL

请求：
```
POST /v3/admin/tag-library
Authorization: Bearer <token>
Content-Type: application/json

{
  "tagName": "重点跟进"
}
```

响应（tagScope 自动为 PERSONAL）：
```json
{
  "code": 200,
  "data": {
    "id": "2067178767255560194",
    "tagName": "重点跟进",
    "tagColor": "#5B8FF9",
    "tagScope": "PERSONAL",
    "sortOrder": 0,
    "isPinned": false,
    "usedCount": 0,
    "lastUsedAt": null
  },
  "message": "ok",
  "success": true
}
```

### 8.3 业务失败 — 传入非法 tagScope 及跨人权限操作

场景 1：传入非法 tagScope

请求：
```
POST /v3/admin/tag-library
Authorization: Bearer <token>
Content-Type: application/json

{
  "tagName": "测试标签",
  "tagScope": "FOO"
}
```

响应：
```json
{
  "code": 581428,
  "message": "标签作用域非法（仅 SYSTEM/PERSONAL）",
  "success": false
}
```

场景 2：管理员 B 修改管理员 A 的个人标签

请求：
```
PUT /v3/admin/tag-library/2067178767255560194
Authorization: Bearer <B的token>
Content-Type: application/json

{
  "tagName": "重命名"
}
```

响应：
```json
{
  "code": 581423,
  "message": "无权操作该标签",
  "success": false
}
```

## 9. 业务边界

- 适用：任何已登录管理员均可创建 SYSTEM 或 PERSONAL 标签，不需要特殊角色权限。
- 适用：SYSTEM 标签可被任何管理员修改/删除/排序，不限制操作人。
- 不适用：PERSONAL 标签只有创建者本人可修改/删除，他人操作返回 581423。
- 不适用：`tagScope` 传 `SYSTEM`/`PERSONAL` 以外的値，一律返回 581428。
- 特殊边界：GET 列表只返回「全部 SYSTEM 标签 + 当前登录人的 PERSONAL 标签」，当前管理员不会看到其他人的 PERSONAL 标签。

## 10. 修改前后对比

### 10.1 字段级对比

| 字段 | 改前 | 改后 |
|------|------|------|
| tagScope（入参） | 不存在 | 新增选填字段，不传默认 `PERSONAL` |
| tagScope（出参 TagLibraryItemVO） | 不存在 | 新增，値为 `SYSTEM` 或 `PERSONAL` |

### 10.2 行为级对比

| 行为 | 改前 | 改后 |
|------|------|------|
| GET /v3/admin/tag-library 返回口径 | 仅返回当前登录管理员自己创建的标签 | 返回「全部 SYSTEM 标签 ∪ 当前管理员的 PERSONAL 标签」 |
| 重名校验 | 按（创建者 + tagName）唯一 | SYSTEM：tagName 全局唯一；PERSONAL：按（创建者 + tagName）唯一 |
| SYSTEM 标签删改权限 | 无 SYSTEM 标签 | 任何管理员均可操作 |

## 11. 影响评估 / 回滚

### 11.1 影响评估

- **是否破坏向后兼容**：否。入参 tagScope 选填默认 PERSONAL，原有不传的调用行为不变；出参新增字段不影响现有字段。
- **前端是否必须同步上线**：否。新字段选填，前端若暂不接入，所有标签仍以 PERSONAL 逻辑运行，无破坏性。但若要展示系统标签功能，需前端接入 tagScope 字段。

### 11.2 回滚方案

- **回滚方式**：revert PR #3943 并重新部署 hl-order-service-v3 即可。
- **回滚后清理**：回滚后已创建的 SYSTEM 类型标签仍在库中，但列表接口将只返回当前管理员自己的标签，业务上无资损。

## 12. 注意事项

- tagScope 字段已在测试服验评 11 场景全部通过，包括：创建 SYSTEM/PERSONAL、列表混合返回、重名校验分支、跨管理员权限阻断、非法値 581428 等。
- GET 列表返回量可能因新增系统标签而增加，若前端有硬编码长度假设请检查。
- 若前端之前未处理 `tagScope` 字段（JSON 中多余字段），无影响（标准 JSON 忽略多余字段）。

## 13. 关联 / 联系人

### 13.1 链接

- **Issue**: [#3940](https://git.1814.love:8443/wx/HL/issues/3940)
- **PR**: [#3943](https://git.1814.love:8443/wx/HL/pulls/3943)
- **Merge commit**: [f36bbbf13](https://git.1814.love:8443/wx/HL/commit/f36bbbf13)

### 13.2 联系人

- **后端负责人**: @yaosutu
