# tag-library: 私人标签库 6 接口真实化完成 + QA 验收通过

> **存放目录**: `changelogs-v2/2026-05/`（v3 二期）
> **服务**: hl-order-service-v3
> **关联**: 19 号已发布骨架版（[`19_2045_tag-library模块私人标签库管理-新增接口-管理后台.md`](./19_2045_tag-library模块私人标签库管理-新增接口-管理后台.md)）
> **真实化 PR**: #2606（DB 业务实现）
> **关联 PR**: #2777（不直接相关，仅同会话）
> **日期**: 2026-05-21
> **影响范围**: 管理后台「我的标签库」管理页 + 创建订单时的标签下拉

---

## ⚠️ 关键变化

**接口契约 0 变化**。19 号骨架版发布时承诺的「契约本次发布后不再变」**已兑现** —— 字段名 / 类型 / 必填 / 路径 / 错误码全部与 19 号一致。

本次变化仅是**实现状态**：

| 项 | 19 号骨架版 | 本次（2026-05-21） |
|---|---|---|
| ServiceImpl | **Mock 硬编码样例** | **真实 DB**（`tag_library` 表） |
| 数据持久化 | ❌ 不落库，每次返样例 | ✅ INSERT / UPDATE / SOFT DELETE 真实生效 |
| 错误码 581421/581423/581424/581425/581427 | 未触发（Mock 永远成功） | **全部按设计触发**（QA 已验证） |
| 多用户隔离 | 未生效（Mock 不区分 userId） | **生效**（user_id 隔离 + 越权拦截） |
| 排序持久化 | 仅返样例数据，不响应排序请求 | **真实持久化**（sort_order 列） |
| 软删后同名复用 | N/A | **支持**（唯一索引 `(user_id, tag_name, deleted_at)`） |

**前端意义**：之前按 19 号骨架对接的代码**无需任何改动**，但**联调时机解锁** —— 现在可以真实创建 / 修改 / 删除 / 排序 / 置顶并看到数据持久化和正确的错误码反馈。

---

## 一、背景

19 号 6 接口骨架版上线时 ServiceImpl 是 Mock 实现，前端可按契约对接但无法真实联调（数据不落库、错误码不触发）。
本次 PR #2606 完成 DB 真实化，今天通过 33 项 QA 用例全量验收。

---

## 二、变更清单

| # | 接口 | 方法 | 路径 | 本次变更 |
|---|------|------|------|----------|
| 1 | 查我的标签库 | GET | `/v3/admin/tag-library` | Mock → 真实 DB 查询，支持 keyword 模糊 / pinnedOnly 过滤 / 后端固定排序 |
| 2 | 新增标签库预设 | POST | `/v3/admin/tag-library` | Mock → 真实 INSERT，sortOrder=MAX+1 / 重名 581421 触发 / 默认色 `#5B8FF9` 生效 |
| 3 | 修改（重命名/换色） | PUT | `/v3/admin/tag-library/{id}` | Mock → 真实 UPDATE，越权 581423 / 改名重名 581421 / 排除自身校验生效 |
| 4 | 删除（软删） | DELETE | `/v3/admin/tag-library/{id}` | Mock → 真实软删（`deleted_at=NOW()`），越权 581424 / 软删后同名可复用 |
| 5 | 批量排序 | PUT | `/v3/admin/tag-library/sort` | Mock → 真实事务包裹 UPDATE，含他人 id 581425 整批回滚 / 重复 id 581427 |
| 6 | 置顶 toggle | PUT | `/v3/admin/tag-library/{id}/pin` | Mock → 真实 UPDATE，越权 581424 |

---

## 三、接口契约

**未变更**，详见 [`19_2045_tag-library模块私人标签库管理-新增接口-管理后台.md`](./19_2045_tag-library模块私人标签库管理-新增接口-管理后台.md)：入参 / 出参 / 枚举 / 字段约束 / 路径全部一致。

---

## 四、错误码契约（全部经 QA 验证）

| Code | 触发场景 | 接口 |
|---|---|---|
| 581421 | 同用户已有同名标签 | POST 新增 / PUT 改名 |
| 581423 | 标签不存在 / 已软删 / 非本人 | PUT 更新 |
| 581424 | 标签不存在 / 已软删 / 非本人 | DELETE 删除 / PUT 置顶 |
| 581425 | 排序 items 含他人 id（**整批回滚，不部分成功**） | PUT 排序 |
| 581427 | 排序 items 含重复 id | PUT 排序 |
| 400 | 参数校验失败（tagName 空 / 超 50 字 / tagColor 格式非法 / pinned 缺失 / items 空数组） | 全部 |
| 401 | 未登录 | 全部 |

---

## 五、QA 验收结果

- **覆盖**：6 接口 × 33 用例（创建 7 / 列表 5 / 更新 7 / 删除 4 / 排序 5 / 置顶 5）
- **通过率**：33 / 33 = **100%**
- **验证维度**：
  - 字段校验（必填 / 长度 ≤50 / `#RRGGBB` 格式）
  - 错误码契约（5 个业务错误码全部按设计触发）
  - 多用户隔离（user_id=9999 脏数据无法被 user_id=1001 修改 / 删除 / 排序 / 置顶）
  - 事务一致性（排序含他人 id 时，本人 id 也未被改）
  - 软删行为（删后立即同名 create 成功）
  - 排序规则（`is_pinned DESC, sort_order ASC, last_used_at DESC`）
  - Long ID 序列化（响应中为字符串，无 JS 精度丢失）

---

## 六、注意事项

1. **前端不需要做任何代码改动**。19 号骨架对接的请求 / 响应解析 / 错误码处理逻辑直接复用。
2. **联调时机**：本次发布后可正式进入真实联调（之前 Mock 期不能验持久化和错误码）。
3. **路径**：`/v3/admin/tag-library` 前缀，**带 `/v3`**，经 Gateway 转发到 hl-order-service-v3。
4. **userId 自动派生**：前端不传操作人，后端从 JWT 注入。

---

## 七、关联

- 骨架版 changelog：`19_2045_tag-library模块私人标签库管理-新增接口-管理后台.md`
- 真实化 PR：https://git.1814.love:8443/wx/HL/pulls/2606
- v5.14 §14 章节规范：详见 SRS v5.14
- 负责人：yst
