feat: 协作台账支持归档并精简状态列
This commit is contained in:
+61
-12
@@ -79,7 +79,7 @@ CK 自带完整生命周期(导入 → 验证 → 使用/失效 → 重贴/重
|
||||
| `order_no` | varchar(64) **unique** | 订单编号(Excel B 列),唯一 |
|
||||
| `shop` | varchar(64) index | 店铺(A 列) |
|
||||
| `owner_id` | int FK `users.id` index | 负责人(C 列);**不填默认 = 创建人**(新建时不用选,要转单在列表里改) |
|
||||
| `uid` | varchar(32) **unique, nullable** | 虎牙 uid(从 CK 解析;空 = 还没贴 CK) |
|
||||
| `uid` | varchar(32) **普通索引, nullable** | 虎牙 uid(从 CK 解析;空 = 还没贴 CK)。2026-10-16 起**不再唯一**:同一买家多件常继续用同一份 CK(迁移 0058) |
|
||||
| `yyuid` | varchar(32) | 虎牙 yyuid |
|
||||
| `hy_username` | varchar(128) | CK 里的 `udb_passport`(登录名) |
|
||||
| `nickname` | varchar(128) | 昵称(探针查到后补全) |
|
||||
@@ -102,8 +102,11 @@ CK 自带完整生命周期(导入 → 验证 → 使用/失效 → 重贴/重
|
||||
| `bound_at` | datetime | 绑定完成时间 |
|
||||
| `recharged_at` | datetime | 充值完成时间 |
|
||||
| `scripted_at` | datetime | 上脚本时间 |
|
||||
| `done_at` | datetime | 归档完成时间 |
|
||||
| `done_at` | datetime | 抢购成功时间 |
|
||||
| `void_reason` | varchar(256) | 作废原因(`status=void` 时必填) |
|
||||
| `archived_at` | datetime index | **归档时间**;非空 = 已归档(可见性状态,不是业务状态,§4.4) |
|
||||
| `archived_by` | int FK `users.id` | 归档人 |
|
||||
| `archive_reason` | varchar(256) | 归档备注;取消归档时清空,审计里保留原文 |
|
||||
| `points` | int nullable | 最近一次只读查询的积分快照 |
|
||||
| `elite_opened` | bool nullable | 最近一次只读查询的宝典开通状态 |
|
||||
| `snapshot_at` | datetime | 上面两个快照的查询时间 |
|
||||
@@ -112,7 +115,7 @@ CK 自带完整生命周期(导入 → 验证 → 使用/失效 → 重贴/重
|
||||
| `version` | int | **乐观锁版本号**,每次写入 +1(见 §7.2 为什么不用 `updated_at`) |
|
||||
| `created_at` / `updated_at` | datetime | `updated_at` 只用于显示与排序 |
|
||||
|
||||
索引:`order_no`(unique)、`uid`(**普通索引**,2026-10-16 由 unique 降级,见 §3.2)、`shop`、`owner_id`、`status`、`ck_status`、`updated_at`。
|
||||
索引:`order_no`(unique)、`uid`(**普通索引**,2026-10-16 由 unique 降级,见 §3.2)、`shop`、`owner_id`、`status`、`ck_status`、`archived_at`、`updated_at`。
|
||||
|
||||
### 3.2 两个 key 设计上的选择
|
||||
|
||||
@@ -277,6 +280,27 @@ CK 失效了业务上可能仍然有效。列表上只做**显式提示**(红
|
||||
- 每次状态变化必须同时写 `*_at` 时间戳 + `audit_logs`;
|
||||
- 加一条测试:**任何**状态写入都必须带审计行(漏了就是 bug)。
|
||||
|
||||
### 4.4 归档(可见性,不是第三种状态,2026-10-19)
|
||||
|
||||
抢购成功的单会越积越多,但它们不该一直挤在活跃台账里;「归档」把行从默认视图里
|
||||
**藏起来**,但**不改变业务状态**(`status` 仍是 `done` / 抢购成功),也不删 CK、
|
||||
截图、积分快照或审计记录。
|
||||
|
||||
| 项 | 口径 |
|
||||
| --- | --- |
|
||||
| 可归档 | **只有 `status=done` 的活跃行**;`failed` 不归档(先处理或作废) |
|
||||
| 判定 | `archived_at IS NULL` = 活跃;非空 = 已归档 |
|
||||
| 列表/统计 | `archive_scope=active`(默认)/ `archived` / `all`;默认列表与统计都排除归档行 |
|
||||
| 只读 | 归档行不能改状态、CK、字段、图片、删除,也不能查积分/兑换记录;接口统一 409 `order_archived`,必须先取消归档 |
|
||||
| 备注 | 归档时可写 `archive_reason`(≤256 字);取消归档清空该字段,但审计保留原始备注 |
|
||||
| 批量 | 单行 / 勾选 / 「归档当前筛选结果」三种入口;按筛选归档强制 `active + done`,前端传 `expected_count`,数量变化返回 409 `archive_count_changed`;单次上限 `ARCHIVE_BATCH_MAX=5000` |
|
||||
| 审计 | `huya:collab:archive` / `huya:collab:unarchive`,写单号、状态与备注;归档/取消归档都会 `_touch()` 递增 `version` |
|
||||
| 权限 | 复用 `huya:collab:edit`,不新增权限点 |
|
||||
| 实时 | 归档变化发布 `scope=orders` 的 `order.archive` / `order.unarchive` 失效通知 |
|
||||
|
||||
归档视图仍支持原有筛选与关键词搜索(订单号、店铺、绑定账号、角色、虎牙号、礼包、备注),
|
||||
只是所有写操作隐藏,仅保留「详情」与「取消归档」。
|
||||
|
||||
---
|
||||
|
||||
## 5. CK 的 CRUD 与全生命周期
|
||||
@@ -329,7 +353,8 @@ CK 失效了业务上可能仍然有效。列表上只做**显式提示**(红
|
||||
### 5.4 删除 / 作废
|
||||
|
||||
- `void` 作废:保留行、留 `void_reason`,列表默认过滤掉(可切换显示)。
|
||||
- 物理删除:`huya:collab:manage` 才能做,且要**级联清理图片**(§6.4),并记审计。
|
||||
- **归档**(2026-10-19):只针对抢购成功的活跃行,保留全部数据、默认隐藏、取消归档前只读(§4.4)。
|
||||
- 物理删除:`huya:collab:manage` 才能做,且要**级联清理图片**(§6.4),并记审计;归档行必须先取消归档。
|
||||
|
||||
### 5.5 新建协作单的必填项与礼包(2026-10-16 用户拍板)
|
||||
|
||||
@@ -503,8 +528,8 @@ CK 失效了业务上可能仍然有效。列表上只做**显式提示**(红
|
||||
|
||||
| 方法 | 路径 | 权限 | 说明 |
|
||||
| --- | --- | --- | --- |
|
||||
| GET | `/api/huya/external-orders` | `huya:collab:view` | 列表;筛选 `shop/owner_id/status/ck_status/keyword`,分页,默认排除 `void` |
|
||||
| GET | `/api/huya/external-orders/summary` | `huya:collab:view` | 各状态计数(页头统计条) |
|
||||
| GET | `/api/huya/external-orders` | `huya:collab:view` | 列表;筛选 `shop/owner_id/status/ck_status/keyword/include_void/archive_scope`,分页,默认排除 `void` 与归档行 |
|
||||
| GET | `/api/huya/external-orders/summary` | `huya:collab:view` | 各状态计数(页头统计条),口径跟随 `include_void/archive_scope`;另返回 `archived_total` |
|
||||
| POST | `/api/huya/external-orders` | `huya:collab:edit` | 新建(可带 CK 文本) |
|
||||
| GET | `/api/huya/external-orders/{id}` | `huya:collab:view` | 详情(含图片 key、审计时间线) |
|
||||
| PUT | `/api/huya/external-orders/{id}` | `huya:collab:edit` | 编辑(带 `expected_version`) |
|
||||
@@ -515,6 +540,8 @@ CK 失效了业务上可能仍然有效。列表上只做**显式提示**(红
|
||||
| POST | `/api/huya/external-orders/ck/preview` | `huya:collab:edit` | 粘贴 CK 后的即时预览(探针 + 拉活动礼包,**只读不写库**) |
|
||||
| POST | `/api/huya/external-orders/ck/verify` | `huya:collab:edit` | 批量验证 CK(探针,body `{ids: [...]}`,最多 50 条) |
|
||||
| POST | `/api/huya/external-orders/status/batch` | `huya:collab:edit` | 勾选多行切成同一个状态(逐行 SAVEPOINT 隔离,最多 50 条;§4.1) |
|
||||
| POST | `/api/huya/external-orders/archive` | `huya:collab:edit` | 归档抢购成功订单:`ids` 单条/勾选,或 `archive_filtered=true` + 筛选条件按当前筛选批量;可带 `reason`,`expected_count` 校验数量(§4.4) |
|
||||
| POST | `/api/huya/external-orders/unarchive` | `huya:collab:edit` | 取消归档(`{ids: [...]}`),恢复回活跃台账 |
|
||||
| POST | `/api/huya/external-orders/activity/query` | `huya:collab:edit` | 勾选多行查积分 + 兑换记录(串行带间隔,每行写一条生命周期快照;§5.7) |
|
||||
| POST | `/api/huya/external-orders/{id}/activity/query` | `huya:collab:edit` | 查这一行的积分 + 兑换记录(单行「查询」按钮) |
|
||||
| GET | `/api/huya/external-orders/{id}/metrics` | `huya:collab:view` | 账号全生命周期时间线(每次查询的快照,新→旧;§3.5) |
|
||||
@@ -549,15 +576,16 @@ CK 失效了业务上可能仍然有效。列表上只做**显式提示**(红
|
||||
|
||||
- **内联编辑**:店铺 / 负责人 / 礼包名 / 备注(点开即改,失焦提交,走 §7.2 乐观锁);
|
||||
- **图片列**:缩略图 + 张数,点击开大图(`Image.PreviewGroup`);
|
||||
- **状态**:Tag 展示,行内"下一步"按钮推进(带二次确认);
|
||||
- **状态**:**只展示当前状态 Tag**;行内不再放「→ 下一步」快捷按钮(2026-10-19),推进统一走详情抽屉或批量改状态;
|
||||
- **CK 状态**:Tag + 一键"验证";
|
||||
- **工具栏批量动作**(都要先勾选):批量验证 CK / 批量改状态 / 批量查积分·兑换 / **导出 CK**(勾选几行导几行,写剪贴板;§11.8);
|
||||
- **工具栏批量动作**(都要先勾选):批量验证 CK / 批量改状态 / 批量查积分·兑换 / 批量归档(仅全部选中行都是活跃 `done`)/ **导出 CK**(勾选几行导几行,写剪贴板;§11.8);
|
||||
- **归档入口**(2026-10-19,§4.4):筛选行右侧「查看归档」开关 + 已归档总数角标;活跃视图提供「批量归档」和(状态筛选为 `done` 时)「归档当前筛选结果(N)」;归档视图提供「批量取消归档」,写操作全部隐藏;
|
||||
- **顶部工具区固定两行**(2026-10-16 用户反馈「不要选中后两行」):
|
||||
第一行永远筛选 = 店铺 / 负责人 / 业务状态 / CK 状态 / 关键词(订单号、店铺、绑定账号、角色、虎牙号、礼包、备注)/ 显示已作废;
|
||||
第二行永远动作 = 刷新 + 上面那四个批量动作 + 粘贴导入 / 店铺管理 / 新建。
|
||||
第一行永远筛选 = 店铺 / 负责人 / 业务状态 / CK 状态 / 关键词(订单号、店铺、绑定账号、角色、虎牙号、礼包、备注)/ 显示已作废 / 查看归档;
|
||||
第二行永远动作 = 刷新 + 上面那些批量动作 + 粘贴导入 / 店铺管理 / 新建。
|
||||
**不要**用「筛选 + 动作放在同一个 `wrap` 里靠 `space-between` 排」那种写法 ——
|
||||
不勾选时两组挤成一行、勾选后按钮多了「(N)」就被顶到第二行,列表跟着往下跳;
|
||||
- 页头统计条:`待处理 N / 已确认绑定 N / 已充值·已上脚本 N / 抢购成功 N / 抢购失败 N / 已作废 N`(`done` / `failed` 的展示名 2026-10-16 由「已完成」/「兑换失败」改成「抢购成功」/「抢购失败」,枚举值与库里数据不变)。
|
||||
- 页头统计条:`全部 N / 待补资料 N / 待处理 N / 已确认绑定 N / 已充值 N / 已上脚本 N / 抢购成功 N / 抢购失败 N / CK 失效 N`,右上角是「实时同步」开关(可手动暂停;暂停后不建 WebSocket、不轮询,只能手动刷新);已归档总数显示在筛选行的「查看归档」开关旁(`done` / `failed` 的展示名 2026-10-16 由「已完成」/「兑换失败」改成「抢购成功」/「抢购失败」,枚举值与库里数据不变)。
|
||||
|
||||
> 交互细节(2026-10-16 用户拍板):**店铺是点选按钮组**(列表里点单元格弹出同一组按钮,
|
||||
> 筛选条里也是),不是下拉;**新建时不用选负责人**——默认就是当前登录账号
|
||||
@@ -573,6 +601,9 @@ CK 失效了业务上可能仍然有效。列表上只做**显式提示**(红
|
||||
右侧:字段编辑 + 操作按钮(验证 CK / 重建 CK / 推进状态 / 作废 / 删除);
|
||||
底部:审计时间线(谁在什么时候改了什么)。
|
||||
|
||||
**归档行**(§4.4):标题与描述区显示「已归档」+ 归档时间/归档人/备注;字段编辑、图片编辑、
|
||||
状态推进、CK 操作与积分查询**全部隐藏**,只保留审计时间线与「取消归档」。
|
||||
|
||||
### 9.3 批量导入弹窗
|
||||
|
||||
- 大文本框贴 Excel 区域(TSV,`\t` 分隔,直接 Ctrl+V 即可);
|
||||
@@ -588,7 +619,7 @@ CK 失效了业务上可能仍然有效。列表上只做**显式提示**(红
|
||||
|
||||
| # | 问题 | 决定 |
|
||||
| --- | --- | --- |
|
||||
| 1 | 一行(一单)跟虎牙 CK 的基数关系 | **1 单 = 1 个 CK**(`uid` 在台账内唯一) |
|
||||
| 1 | 一行(一单)跟虎牙 CK 的基数关系 | **1 单 = 1 个 CK**;`uid` 2026-10-16 起**不再唯一**(同一买家多件可复用同一份 CK,迁移 0058) |
|
||||
| 2 | 台账与 `huya_accounts` 的关系 | **完全独立一套表,自己存 CK,不碰现有账号体系** |
|
||||
| 3 | 店铺 / 订单编号来源 | **全部人工录入 + 支持 Excel 粘贴批量导入** |
|
||||
| 4 | 协作范围与权限 | **所有登录用户共享同一张表,都能编辑**(靠审计留痕) |
|
||||
@@ -932,6 +963,24 @@ CK 失效了业务上可能仍然有效。列表上只做**显式提示**(红
|
||||
**没有动的地方**:详情抽屉里编辑既有订单的礼包名仍是"显示这一单自己的值"(本来就该如此);
|
||||
补资料弹窗的初值仍是**这一单自己的礼包**(不是"上次选的"),没有改成空白。
|
||||
|
||||
### 11.11 2026-10-19 第八轮:统计拆分、暂停实时同步、状态列清理与归档
|
||||
|
||||
需求原文:"拆分已充值和已上脚本统计;实时同步放右上角并可手动暂停;状态列只显示当前状态;
|
||||
抢购成功的单太多,需要归档(可备注),归档后默认不显示但能搜索查看,取消归档前只读"。
|
||||
|
||||
| 面 | 落地 |
|
||||
| --- | --- |
|
||||
| 统计条 | 「已充值」「已上脚本」拆成两张卡;右上角新增「实时同步」卡,开关状态存 `localStorage['huya.collab.realtime-paused']`。暂停后**不建 WebSocket、不排轮询、丢弃待刷新**,恢复时立即重拉一次 |
|
||||
| 状态列 | 删除行内「→ 下一步」`Popconfirm`,只保留当前状态 Tag(归档行额外显示「已归档」)。推进仍在详情抽屉与批量改状态里 |
|
||||
| 数据模型 | 迁移 `20261019_0060`:`archived_at` / `archived_by`(FK `users.id`)/ `archive_reason`(varchar 256)+ `archived_at` 索引。`status=done` 保持不变,归档只是可见性(§4.4) |
|
||||
| 后端 | `list_orders` / `summary` 增加 `archive_scope`(`active` 默认 / `archived` / `all`);新增 `POST /external-orders/archive` 与 `/unarchive`;归档行所有写入口(状态、CK、字段、图片、删除、积分查询)统一 409 `order_archived` |
|
||||
| 批量归档 | 单行 / 勾选 / 「归档当前筛选结果」;按筛选强制 `active + done` 并校验 `expected_count`(409 `archive_count_changed`),单次上限 5000;返回逐行 `results`(成功/跳过原因) |
|
||||
| 前端 | 筛选行「查看归档」开关 + 已归档总数;归档弹窗可填 ≤256 字备注;归档视图只读,提供详情与单行/批量「取消归档」;归档行在列表与详情里的内联编辑、图片编辑、状态与 CK 操作全部隐藏 |
|
||||
| 审计 | `huya:collab:archive` / `huya:collab:unarchive`,记录单号、状态与备注;取消归档清空行上的 `archive_reason`,审计保留原文;两个动作都递增 `version` 并清掉实时缓存 |
|
||||
|
||||
**验收口径**:默认列表/统计不含归档行;归档视图能按原有关键词与筛选搜到;归档行改任何东西都提示先取消归档;
|
||||
取消归档后回到原位置(业务状态未变),归档备注仍能在审计时间线里查到。
|
||||
|
||||
---
|
||||
|
||||
## 12. 风险
|
||||
|
||||
Reference in New Issue
Block a user