baseline: Clover 独立仓库首次基线提交

将 Clover 从上层产品包旧仓库中独立出来,建立专属版本控制。
当前状态=纵切片端到端已打通(登录→选品→出文出图→审核→下载包),
M1文案质量去套路化已验收。此提交作为后续按核销清单逐条修复的基线。

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
yangqianqian
2026-06-16 11:30:22 +08:00
commit 6a2632da70
253 changed files with 27467 additions and 0 deletions

View File

@@ -0,0 +1,39 @@
# 核销表 · 第12环 归档
> 90分级验收孙总方法论·硬门禁。已吸收独立交叉验证修正。auto=机器判定human=目视。
## 模块目标
①history 按日期/品类筛选(现平铺) ②approved 下载交付包 zip 结构完整 ③多套打包(1-3套各独立笔记夹) ④客户输入物(产品/标杆)可导出(数据归属红线)。
## Ralph 修改步骤
| # | 改什么 | 落点 |
|---|--------|------|
| S1 | list_tasks 加 date_from/date_to/product_id query paramfromisoformat 转换invalid 返回 40001 | tasks.py:137-149 |
| S2 | _fmt_task 加 product_name(调用方传入)list_tasks 一次性 `Product.id.in_([...])` 建 id→name dict 避免N+1顶部补 `from app.models.product import Product`(当前无此import) | tasks.py:58-64 |
| S3 | history/page.tsx 加 dateFrom/dateTo state + 两个 `<input type=date>`(提 DateRangeFilter 子组件防超100行) | history/page.tsx:28-44 + JSX 50-94 |
| S4 | HistoryTable 表头/行加"产品"列(显 product_name ?? '-') | history/components.tsx:70-127 |
| S5 | TaskListItem 加 `product_name?:string` | dto.tasks.ts:8-16 |
| S6 | ⚠️多套打包:查所有 is_selected=True TextCandidate 按 angle_label 分组每组取第一notes 列表长度=选中套数(改 line 77-85 为 for loop)images_data 循环外查一次,每套传 `list(images_data)` 副本(退化:图共享复制进各套夹) | packaging_task.py:45-47,77-85 |
| S7 | 新建 GET /products/export + /benchmarks/export(format=json/csv)require_write_permissionbenchmarks/export 需 Product JOIN 填 product_name(复用 _fmt_benchmark 不够,只有 product_id) | products.py + benchmarks.py |
| S8 | 配置页产品 tab + 历史归档页各加"导出数据"按钮,通用 ExportButton(url,filename) 调 getBlob 下载 | history/components.tsx 或 config/ExportTab.tsx |
## 验收清单(做完一个勾一个)
- [ ] **A1**auto日期筛选传 date_from/date_to → items 全落区间;传 date_from=2099 → 空数组 total=0。⚠审计补:再验 `date_from=not-a-date` → code=40001(非500)。
- [ ] **A2**autoproduct_id 筛选:传 product_id=1 → 每条 product_id=1 且 product_name 非空。
- [ ] **A3**human前端产品列/history 表头有"产品"列,每行显产品名(非数字),与 GET /products/{id}.name 一致。
- [ ] **A4**human日期控件有开始/结束 date input填后表格刷新XHR URL 含 date_from/date_to结果≤全量。
- [ ] **A5**human下载交付包approved 任务点"下载交付包"≤60s 触发下载 delivery-{id}.zip(>1KB)`unzip -l` 含 note_01/文案.txt/发布清单/合规说明。
- [ ] **A6**autozip 结构完整:`unzip -l` grep 文案.txt/发布清单/合规说明/note_01//.jpg 全非空。⚠️审计补:若 .jpg 空先查 ImageCandidate.url 文件容器内可达(packaging_task.py:64-70 读失败静默跳过)。
- [ ] **A7**auto文案.txt 格式:`unzip -p note_01/文案.txt` 含"【标题】"、不以 `{` 开头(JSON 已解析)。
- [ ] **A8**human+auto多套打包审计改 human(需先 seed 3条 is_selected TextCandidate)→构造后 `unzip -l|grep 'note_0[1-3]/'|wc -l`≥3三套标题互不相同。
- [ ] **A9**auto产品 JSON 导出GET /products/export → 200,application/json,数组,每元素含 id/name/selling_points,且 selling_points 是数组(非JSON字符串)。
- [ ] **A10**auto标杆 CSV 导出GET /benchmarks/export?format=csv → 200,text/csv,首行表头含 product_id/highlights/created_at,行数≥已录标杆数。
- [ ] **A11**auto导出权限审计注——require_write_permission 当前只查 workspace_members 不分角色(workspace_guard.py:65-88);未登录调 → code=40101workspace 成员 → 200。
- [ ] **A12**human不显 token 余额(红线):⚠️审计改 human(curl 拿不到Next.js水合后DOM)——浏览器 Ctrl+F 搜"余额/用量/tokens/balance"无结果。
## 待北哥定义(不阻断代码)
- 多套打包图片套间对应ImageCandidate 无 set_index是否加列关联文案还是退化"图共享复制进每套夹"(本期默认退化)。
- 导出入口位置(产品管理 tab 按钮 / 历史归档页全局)。
- CSV 是否加 UTF-8 BOM(Windows Excel 不乱码)。