diff --git a/changelogs-v2/2026-06/17_3940_标签库系统个人作用域分类-修改接口-管理后台.md b/changelogs-v2/2026-06/17_3940_标签库系统个人作用域分类-修改接口-管理后台.md new file mode 100644 index 0000000..d203cc8 --- /dev/null +++ b/changelogs-v2/2026-06/17_3940_标签库系统个人作用域分类-修改接口-管理后台.md @@ -0,0 +1,307 @@ +# 【修改接口·管理后台】标签库支持系统/个人作用域分类 (#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 `),从请求头 `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 +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 +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 +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 +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 diff --git a/changelogs-v2/2026-06/17_3941_订单标签移除type字段及分组-修改接口-管理后台.md b/changelogs-v2/2026-06/17_3941_订单标签移除type字段及分组-修改接口-管理后台.md new file mode 100644 index 0000000..1a238d2 --- /dev/null +++ b/changelogs-v2/2026-06/17_3941_订单标签移除type字段及分组-修改接口-管理后台.md @@ -0,0 +1,261 @@ +# 【修改接口·管理后台】⚠️ 订单标签移除 tagType 字段及系统分组 (#3941) + +> **PR**: #3944 | **服务**: hl-order-service-v3 | **更新时间**: 2026-06-17 + +## 1. 接口背景 + +订单标签 `order_tag` 原有 `tagType` 字段(値:`SYSTEM_LOCKED` / `SYSTEM_LOGIC` / `PERSONAL`),用于区分系统自动打标 vs 手工标签,并基于此限制了部分系统标签不可删改。由于系统自动打标功能不再实施,本次统一移除 `tagType` 字段及相关分组/保护逻辑:全部标签统一为「手工挂、可改可删、不分类型」。 + +## 2. 变更清单 + +| # | 接口 | 方法 | 路径 | 变更类型 | 说明 | +|---|------|------|------|----------|------| +| 1 | 查询订单已挂标签 | GET | /v3/admin/order/{orderId}/tags | 删除入参 + 出参结构重构 | 删 `includeLibrary` 参数;`attached` 从三组对象改为扁平数组;删 `tagType`、`systemLogicCatalog`、`personalLibrary` | +| 2 | 订单详情 tags[] | GET | /v3/admin/order/{orderId} | 删除出参字段 | `tags[]` 元素删除 `type` 字段 | +| 3 | 订单列表 tags[] | GET | /v3/admin/order/list(或分页接口) | 删除出参字段 | `tags[]` 元素删除 `type` 字段 | + +## 3. 接口详情 + +### 3.1 查询订单已挂标签 + +- **使用场景**:订单详情页「标签」Tab 加载时调用,展示已挂标签列表供管理员增删。 +- **认证**:需要 JWT。 +- **幂等性**:是(只读)。 +- **限流**:无。 + +入参变更:删除 query 参数 `includeLibrary`(此参数原已废弃死参,传了也无效,请前端移除对此参数的传递)。 + +出参结构重构(破坏性变更): + +旧结构 `attached` 为分组对象: +```json +{ + "attached": { + "systemLocked": [ { "id": "...", "tagName": "...", "tagType": "SYSTEM_LOCKED", ... } ], + "systemLogic": [ { "id": "...", "tagName": "...", "tagType": "SYSTEM_LOGIC", ... } ], + "personal": [ { "id": "...", "tagName": "...", "tagType": "PERSONAL", ... } ] + }, + "systemLogicCatalog": ["未定日期"], + "personalLibrary": [ ... ] +} +``` + +新结构 `attached` 为扁平数组,无分组、无 tagType: +```json +{ + "attached": [ + { "id": "...", "orderId": "...", "tagName": "...", "tagColor": "...", "creator": "...", "createdAt": "..." } + ] +} +``` + +### 3.2 订单详情 tags[] + +- **使用场景**:GET /v3/admin/order/{orderId} 返回值中的 `tags` 字段。 +- **入参**:无变化。 +- **出参变更**:`tags[]` 元素(`TagVO`)删除 `type` 字段,保留 `name`、`color`、`creator`。 + +### 3.3 订单列表 tags[] + +- **使用场景**:订单列表接口返回中每条订单的 `tags` 字段。 +- **入参**:无变化。 +- **出参变更**:`tags[]` 元素删除 `type` 字段,保留 `name`、`color`、`creator`。 + +## 4. 接口入参 + +### 4.1 路径参数 / Query 参数 + +| 接口 | 字段 | 变更 | 类型 | 说明 | +|------|------|------|------|------| +| GET /v3/admin/order/{orderId}/tags | orderId | 不变 | Long(String格式) | 路径参数,订单 ID | +| GET /v3/admin/order/{orderId}/tags | includeLibrary | **已删除** | Boolean(原) | 原废弃死参,传了无效;请前端移除此参数 | + +### 4.2 请求体字段 + +以上接口均为 GET,无请求体。 + +## 5. 出参(响应) + +### 5.1 GET /v3/admin/order/{orderId}/tags 响应字段 + +| 字段 | 类型 | 变更 | 说明 | +|------|------|------|------| +| attached | Array | **结构重构** | 由分组对象改为扁平数组,元素为 OrderTagVO | +| systemLogicCatalog | Array | **已删除** | 原固定返回 `["未定日期"]`,已移除 | +| personalLibrary | Array | **已删除** | 原标签库备选列表,已移除 | + +OrderTagVO 元素字段: + +| 字段 | 类型 | 变更 | 说明 | +|------|------|------|------| +| id | String | 不变 | 订单标签记录 ID | +| orderId | String | 不变 | 所属订单 ID | +| tagName | String | 不变 | 标签名称 | +| tagColor | String | 不变 | 标签颜色,如 `#5B8FF9` | +| creator | String | 不变 | 创建人 | +| createdAt | String | 不变 | 挂标时间,ISO-8601 格式 | +| tagType | String | **已删除** | 原字段(SYSTEM_LOCKED/SYSTEM_LOGIC/PERSONAL),已移除 | + +### 5.2 订单详情/列表 tags[] 元素字段(TagVO) + +| 字段 | 类型 | 变更 | 说明 | +|------|------|------|------| +| name | String | 不变 | 标签名称 | +| color | String | 不变 | 标签颜色 | +| creator | String | 不变 | 创建人 | +| type | String | **已删除** | 原标签类型字段,已移除 | + +## 6. 枚举 / 数据字典 + +原 `tagType` 枚举(已删除,不再返回): + +| 値 | 含义 | 状态 | +|----|------|------| +| `SYSTEM_LOCKED` | 系统锁定标签(原不可删) | 已删除,不再有此分类 | +| `SYSTEM_LOGIC` | 系统逻辑标签(原不可删) | 已删除,不再有此分类 | +| `PERSONAL` | 手工标签 | 已删除,所有标签统一无类型 | + +## 7. 错误码 + +| code | 含义 | 变更 | +|------|------|------| +| 581412 | SYSTEM_LOCKED 标签不可删除 | **已删除**,不再返回此错误码 | +| 581413 | SYSTEM_LOGIC 标签不可删除 | **已删除**,不再返回此错误码 | +| 581432 | 系统标签不可修改 | **已删除**,不再返回此错误码 | +| 581433 | 无权修改(非创建人) | 保留不变 | + +## 8. 示例(3 组:典型 / 边界 / 异常) + +### 8.1 典型成功 — 查询订单已挂标签(新结构) + +请求: +``` +GET /v3/admin/order/2067178767255560193/tags +Authorization: Bearer +``` + +响应(attached 为扁平数组,无 tagType / systemLogicCatalog / personalLibrary): +```json +{ + "code": 200, + "data": { + "attached": [ + { + "id": "2067178767255560201", + "orderId": "2067178767255560193", + "tagName": "高净値", + "tagColor": "#5B8FF9", + "creator": "张管理", + "createdAt": "2026-06-17T10:00:00" + }, + { + "id": "2067178767255560202", + "orderId": "2067178767255560193", + "tagName": "重点跟进", + "tagColor": "#FF6B6B", + "creator": "李管理", + "createdAt": "2026-06-16T14:30:00" + } + ] + }, + "message": "ok", + "success": true +} +``` + +### 8.2 边界情况 — 订单无标签时返回空数组 + +请求: +``` +GET /v3/admin/order/2067178767255560194/tags +Authorization: Bearer +``` + +响应: +```json +{ + "code": 200, + "data": { + "attached": [] + }, + "message": "ok", + "success": true +} +``` + +### 8.3 订单详情/列表 tags[] 结构参考 + +订单详情/列表接口(GET /v3/admin/order/{orderId} 或列表接口)中 tags 字段示例: +```json +{ + "tags": [ + { + "name": "高净値", + "color": "#5B8FF9", + "creator": "张管理" + } + ] +} +``` + +注意:`type` 字段已删除,不再出现。 + +## 9. 业务边界 + +- 适用:所有订单标签均可删除,无论是什么类型(原 SYSTEM_LOCKED/SYSTEM_LOGIC 保护已解除)。 +- 适用:任何管理员可以删除/修改自己创建的标签(581433 创建者限制仍保留)。 +- 特殊边界:`includeLibrary` 参数即使传了也不报错(后端兼容忽略),但返回结果不含 `personalLibrary` 字段,请前端彻底移除此参数的传递,避免多余请求参数污染 URL。 + +## 10. 修改前后对比 + +### 10.1 字段级对比 + +| 字段 | 改前 | 改后 | +|------|------|------| +| GET .../tags 中 `attached` | 对象 `{ systemLocked: [], systemLogic: [], personal: [] }` | 扁平数组 `[{id, orderId, tagName, tagColor, creator, createdAt}]` | +| GET .../tags 中 `systemLogicCatalog` | `["未定日期"]` | **已删除** | +| GET .../tags 中 `personalLibrary` | 标签库备选列表数组 | **已删除** | +| OrderTagVO 中 `tagType` | `SYSTEM_LOCKED` / `SYSTEM_LOGIC` / `PERSONAL` | **已删除** | +| 订单详情/列表 TagVO 中 `type` | `SYSTEM_LOCKED` / `SYSTEM_LOGIC` / `PERSONAL` | **已删除** | +| 入参 `includeLibrary` | 可传 Boolean(实际已废弃死参) | **已删除** | + +### 10.2 行为级对比 + +| 行为 | 改前 | 改后 | +|------|------|------| +| SYSTEM_LOCKED 标签删除 | 返回 581412 禁止删除 | 可正常删除 | +| SYSTEM_LOGIC 标签删除 | 返回 581413 禁止删除 | 可正常删除 | +| 系统标签修改 | 返回 581432 禁止修改 | 可正常修改 | + +## 11. 影响评估 / 回滚 + +### 11.1 影响评估 + +- **是否破坏向后兼容**:**是(破坏性变更)**。`attached` 结构从对象改为数组,`tagType`/`systemLogicCatalog`/`personalLibrary`/`type` 字段均已删除,前端需同步更新解析逻辑。 +- **前端是否必须同步上线**:**是**。若前端仍按旧结构访问 `attached.systemLocked` / `attached.personal` 等字段,将得到 `undefined`;若仍渲染 `tags[].type`,将得到 `undefined`。 + +### 11.2 回滚方案 + +- **回滚方式**:revert PR #3944 并重新部署 hl-order-service-v3 即可恢复旧字段结构。 + +## 12. 注意事项 + +- 前端 workaround 清理点: + 1. `GET .../tags` 返回解析:将 `attached.systemLocked` / `attached.systemLogic` / `attached.personal` 的三路分支解析改为直接读取 `attached` 数组。 + 2. `systemLogicCatalog` / `personalLibrary` 字段读取逻辑请删除,不再返回。 + 3. 订单详情/列表中 `tags[].type` 字段读取/渲染请删除。 + 4. 调用 `GET .../tags` 时如有传 `includeLibrary` 参数,请移除。 + 5. 原基于 `tagType` 的删除保护逻辑(SYSTEM_LOCKED/SYSTEM_LOGIC 无法删除)已解除,如前端有对应 UI 逻辑(如隐藏删除按钮/报错提示),请检查是否需要调整。 +- 测试服已验证:listTags 扁平结构正常、订单详情 tags 无 type 字段、加标签可删、无 SQL 异常。 + +## 13. 关联 / 联系人 + +### 13.1 链接 + +- **Issue**: [#3941](https://git.1814.love:8443/wx/HL/issues/3941) +- **PR**: [#3944](https://git.1814.love:8443/wx/HL/pulls/3944) +- **Merge commit**: [b6f5ca5de](https://git.1814.love:8443/wx/HL/commit/b6f5ca5de) + +### 13.2 联系人 + +- **后端负责人**: @yaosutu