Files
cmbuyer/docs/tasks/T-202.md

5.0 KiB
Raw Permalink Blame History

id, title, phase, deps, status, created, vikunja_task_id, context_ref, work_branch, needs_device, needs_human_review, write_paths
id title phase deps status created vikunja_task_id context_ref work_branch needs_device needs_human_review write_paths
T-202 手工建单与 DRAFT 基础列表 2
T-201
T-004
T-005
DONE 2026-08-04 27 1c35155 task/t-202-admin-draft false false
docs/tasks/T-202.md
admin/cmd/server/main.go
admin/internal/config/**
admin/internal/server/**
admin/internal/tasks/**
admin/internal/storage/sqlite/**
admin/internal/transport/webui/**
admin/README.md

问题 / 背景

T-201 已提供管理员会话;T-004 已提供 tasks 表。根据 T-010 加速门禁,T-103 尚未完成时只允许实现不启动试选的 DRAFT 手工建单与基础列表。

关联需求与交互

F-001、US-001、IX-002;GET /tasks、GET /tasks/new、POST /tasks;沿用已确认的传统表格与创建弹窗/直达页。

方案

  1. 显式数据库配置并打开已迁移 SQLite;以仓储接口隔离 HTTP 和 SQL,创建事务只写 MANUAL、DRAFT、version=1。
  2. 表单校验任务名称、canonical 拼多多链接、颜色分类、尺码、正整数数量和正十进制总额上限;金额只用字符串并规范为两位小数。链接只接受 HTTPS mobile.yangkeduo.com/goods.html 且 goods_id 为唯一纯数字参数,额外查询参数不进入数据库。
  3. 以服务端生成的 create_key 同时作为任务 ID;重复相同 key 和相同内容返回原结果,不创建第二条,内容不同则冲突。
  4. GET /tasks 默认 created_at DESC 显示 DRAFT 基础表格;创建入口用服务端渲染的 modal 状态,/tasks/new 复用同一表单作为无脚本兜底;失败保留非密码输入并显示字段错误,成功 303 回列表且新任务第一行。
  5. 页面只显示需求字段、采购结果占位、DRAFT 状态与创建时间;不读取或伪造规格面板价格/证据,不提供勾选开始试选、状态推进、详情或设备接口。

验收要点

  • 覆盖创建成功、倒序第一行、严格链接/goods_id、数量、金额、空白/长度、CSRF/未登录、幂等重放与冲突、SQL 错误 fail closed。
  • 弹窗与 /tasks/new 共享校验;错误保留输入并可访问;标题只链接到由 goods_id 重建的 canonical PDD URL并使用安全新标签属性。
  • go test ./...、go test -race ./...、go vet ./...、go build ./...、完整 init.ps1、上下文校验和 diff-check 通过。

执行记录

2026-08-04T08:30:47Z · ila

已完成:DRAFT 手工建单与基础列表;已验证链接、金额、CSRF、幂等、SQLite 并发和 SSR 无障碍,Go 与上下文门禁均通过。

边界

  • 本任务只创建 source=MANUAL、status=DRAFT、version=1 的任务并显示 DRAFT 基础列表;不得 实现勾选、批量开始试选、DRAFT → PENDING 或任何其他状态流转,也不得新增设备领取接口。
  • 不增加或修改数据库 schema,不读写 spec_trials、order_authorizations、order_submissions, 不生成或展示机器实际规格、规格面板单价、截图、证据哈希或 PDD 页面判据。
  • 启动服务必须从显式 CMBUYER_DATABASE_SOURCE 读取 SQLite data source;缺失时明确失败,不提供 隐式内存库或仓库内默认数据库。服务不自动猜迁移目录;README 必须先给出显式迁移命令。
  • 商品链接只接受 https://mobile.yangkeduo.com/goods.html,且必须恰有一个纯数字 goods_id; 拒绝 userinfo、端口、fragment、重复参数、其他 host/scheme/path 和编码绕过。数据库只保存 goods_id, 展示链接由 goods_id 重建 canonical URL;uin 等额外查询参数既不保存也不回显。
  • 标题、颜色分类、尺码必须去除首尾空白后非空并受明确长度上限约束;数量必须是可表示的正整数; 总额上限必须是大于零、最多两位小数的十进制字符串并规范为两位小数。金额校验、保存与展示均不得 使用浮点数或从其他数字推测。
  • create_key 由服务端用 crypto/rand 生成并验证格式,同时作为任务 ID;相同 key 与相同规范化内容 重放只能返回原任务,不得二次 INSERT,相同 key 携带不同内容必须冲突。SQL 必须参数化,创建失败 不得留下半条或未知状态记录。
  • GET /tasks、GET /tasks/new、POST /tasks 都必须复用 T-201 管理会话;POST 必须验证 CSRF。 校验失败保留非敏感输入并逐字段提示,数据库内部错误只给通用响应,不泄露 SQL、路径或凭据。
  • 页面只使用服务端模板转义;标题商品链接在新标签打开时必须带 noopener noreferrer。导入按钮只作 禁用占位;不得加载外部资源或把原型假数据、真机数据、地址、手机号带进生产页面。
  • 不实现或引用试选、数量设置、订单确认、提交围栏、提交订单、付款、免密支付或先用后付能力。