Files
jiu/design/CONTRACT.md
wangjia b10b450db0 docs(design): CONTRACT 全量清扫收尾状态(登录/盘点/商品/公开页/Web)
记录:登录+盘点 token 化;商品列表/详情 token 净(富数据待后端);
公开页有意独立设计保持现状;Web 营销站 color.css 已对齐品牌。
应用内注册/购买流归 Phase 6 新建功能,非既有屏重建范围。

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01TSKEiHsvauyxYUW2itzUXX
2026-06-25 14:06:02 +08:00

128 lines
12 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 设计契约 — 岩美酒库 Flutter 还原(Phase 1 起:库存列表)
> design-distill 阶段 1 产物。像素以 `.superpowers/prototype/` 原型为**唯一基准**
> token 走 codegen 单源(已在 P0 落地);还原由截图 diff 验收,不靠目测。
> 本文件是**执行真相源**(与 plan `.md` 同性质,机器/diff 引用),随逐屏推进增补。
## 阶段 0 · 归一化产物(已就位)
| 项 | 位置 | 说明 |
|---|---|---|
| token 单源 | `.superpowers/prototype/tokens.css` | 三主题 `[data-theme=a/b/c]`,已 snapshot 到 `client/lib/core/theme/token_source/tokens.css` |
| token codegen | `client/lib/core/theme/tool/gen_tokens.mjs``app_tokens.g.dart` | 单源生成,**禁手改**`kTokensA/B/C` + `appTokensOf(key)` |
| 实现层 | `themes.dart`buildTheme+ `context_tokens.dart``context.tokens` | AppTokens ThemeExtension 挂三 ThemeData |
| 原型清单 | `.superpowers/prototype/screens/*.html` | 桌面 + `m-*` 移动;viewport 桌面 1280×860 / 移动 390×844 |
| 设计铁律 | `.superpowers/prototype/index.html`atoms 注册)+ `tools/check-ds.mjs` 闸 | 颜色只走 token;组件出自已登记 atoms |
| 验收工具 | `~/.claude/skills/design-distill/tools/{shoot-prototype,diff}.mjs` | prototype shoot 已验证三主题可出图 |
### 主题
- **a 经典蓝**(浅,**diff 基准**) · **b 琥珀**(深) · **c 酒窖**(暖浅)。结构/密度/字阶三套统一,只换颜色。
---
## 块 1 · token 映射表(prototype CSS var → Flutter AppTokens
颜色字段 P0 已 1:1 落地(同名)。下表为 a 主题取值(来源 `tokens.css`b/c 见 `app_tokens.g.dart`):
| 原型 var | a 值 | AppTokens 字段 | 用途 |
|---|---|---|---|
| `--page` | `#E7EBF1` | `page` | 最外层底 |
| `--bg` | `#F5F7FA` | `bg` | 内容区底 |
| `--surface` | `#FFFFFF` | `surface` | 卡片/工具条/表格面 |
| `--border` / `--border-subtle` | `#DCE2EB` / `#ECEFF4` | `border` / `borderSubtle` | 描边 |
| `--text` / `--heading` / `--title` | `#232934` / `#1B2430` / `#1B2430` | `text` / `heading` / `title` | 正文/小标题/大标题 |
| `--muted` / `--faint` | `#6E7888` / `#99A3B3` | `muted` / `faint` | 次要/极弱文字 |
| `--primary` / `--primary-dark` / `--on-primary` | `#2563AC` / `#154072` / `#FFFFFF` | `primary` / `primaryDark` / `onPrimary` | 主操作 |
| `--brand400` / `--brand50` / `--accent` | `#4F86C6` / `#EEF4FB` / `#8B2331` | `brand400` / `brand50` / `accent` | 品牌/强调 |
| `--th-bg` / `--row-hover` / `--shadow` | `#F7F9FC` / `#EEF4FB` | `thBg` / `rowHover` / `shadow` | 表头/悬停/投影 |
| 顶栏 `--top-*` / 侧栏 `--side-*` / 用户菜单 `--menu-user-*` | — | `topBg…/sideBg…/menuUser*` | 外壳 chromeP0 已迁移) |
| 状态徽章 `.badge.b-在售/预警/缺货` | success/warn/danger 系 | `success`+`okSoft` / `warn`+`warnBg` / `danger`+`dangerBg` | 状态色 |
### ⚠️ 缺口(鲁棒还原前需补)
AppTokens 目前**仅颜色**。原型还驱动:
- **字阶** `--fs-display 28 / h1 21 / h2 17 / title 15 / body 13 / sm 12 / xs 11`
- **圆角** `--r-sm 4 / md 6 / lg 10 / xl 14 / pill 999`
- **间距** kpis gap 14、toolbar pad 12/14、head mb 18、searchbox 240/180 等
→ 还原前需把字阶/圆角(必要时间距)补进 token 单源 + codegenP1 第一步,**禁页面里写死 px**)。
---
## 块 2 · 组件清单(原型 atom → Flutter widget
| 原型 atom | Flutter | props / 状态 | 现状 |
|---|---|---|---|
| `.top`(顶栏,品牌+门店+主题+通知+用户) | `shell/app_shell.dart` 顶栏 | active 项、主题选择器、通知红点、用户菜单 | 已有,需对齐新视觉 |
| `.side`(分组导航 单据/经营/系统 + 用户页脚) | `shell/app_shell.dart` 侧栏/Drawer | 分组、active、窄屏 Drawer | 已有,需分组化 |
| `.kpi` / `.kpi.alert.click`(KPI 卡 + 图标 + 同比) | **新** `widgets/kpi_card.dart` | icon/title/value/delta(up/down)/onTap/alert | **缺**,需新建 |
| `.toolbar` + `.searchbox` + `.chip`(筛选条) | `widgets/` 复用 + 列头 chip | 搜索/编码/状态 chip/重置 | 部分有 |
| `.table` + `.fh.filtered`(列头漏斗筛选) | `widgets/data_table_card.dart` + `FilterableColumnHeader` | 列头内嵌筛选、可隐藏列、`thBg` 表头 | 已有 |
| `.badge.b-*`(状态徽章 圆点+色) | `widgets/status_badge.dart` | 在售/预警/缺货 → ok/warn/danger | 已有,校色 |
| `.qty.low`(低库存染色 qty≤10 | data row 单元 | qty≤min_stock 染 danger | 需补 |
| `.pager` + `.pgsize-btn`(分页 + 每页条数) | `widgets/` 分页 | 页码/每页 10/20/50/100 | 需对齐 |
| `.ds-fab`(设计期返回球) | — | 仅原型,不还原 | 不实现 |
---
## 块 3 · 页面像素规格 — 库存列表(`screens/inventory.html`,桌面 1280×860
数值取自原型源码(`inventory.html` 内联 + `atoms.css`/`tokens.css`),非目测。
- **head**`align-items:flex-end; gap:14; margin-bottom:18``h1` `fs-h1(21)/700/title/letter .3px``.sub` `fs-sm(12)/muted``.actions` 右对齐 gap 10`列设置`(ghost) `导出`(ghost) `新增入库`(primary)。
- **kpis**`grid 4×1fr gap:14 margin-bottom:20`。每卡:左 `.ic`(圆角 `r-xl` 色块 info/ok/blue/alert+ `.t`(fs-sm muted) + `.v`(大数值) + `.d`(同比 up=success▲ / down=danger▼)。第 4 卡 `alert.click` → 点击筛状态=缺货;第 1 卡 click → 清筛选。
- **toolbar**`surface` 面、`border` 无下边、上圆角 `r-lg``pad 12/14 gap 10``searchbox` 240(商品名/拼音);`searchbox.code` 180(商品编码);`chip` 状态(`.on` 高亮 + 选中值);右侧 `重置`(ghost sm)。
- **table**`flush-top` 接 toolbar):表头 `thBg`;列见块 4。行 `click` 进商品抽屉;`qty≤10``low`(danger)`生产日期` 等宽 `text``入库时间` 等宽 `muted``status``.badge.b-{在售|预警|缺货}``act` 列 眼睛图标查看。空态 `.empty「没有匹配的商品 · 试试调整筛选或搜索」`
- **pager**`每页 [10▾] 条`10/20/50/100 菜单) + `显示 ab,共 N` + 页码 ` 1 2 … `,当前页 `.cur`
- **移动**`m-inventory.html`390×844):表格 → `MobileListCard` 卡片流(复用 `mobile_list_card.dart`);筛选 pill 换行不横滚(原型已修)。
### 列定义(顺序 = 还原顺序)
`商品`(name+code 两行,fixed) · `规格` · `系列` · `批次号` · `库存`(num,≤10染色) · `成本价`(num) · `单价`(num) · `生产日期`(mono) · `入库时间`(mono,muted) · `供应商` · `状态`(filter) · `操作`(fixed)
> 真实后端字段对齐:name=品牌 / series=型号 / spec=版本 / code=商品编号 / batch_no / production_date;状态派生 qty vs `products.min_stock`(在售 / 预警 / 缺货)。快照列回退 `COALESCE(p.*, 快照)`。
---
## 块 4 · 逐屏验收清单(每屏 × 主题;diff 闸)
| 屏 | 原型 | Flutter | a(基准) | b | c |
|---|---|---|---|---|---|
| 库存列表(桌面) | `inventory.html` | `inventory_list_screen.dart` | ✅ KPI/徽章/列/副标/toolbar 已还原 | ✅ golden 自比 | ✅ golden 自比 |
| 库存列表(移动) | `m-inventory.html` | 同上窄屏(卡片流) | ✅ golden 自比 | ✅ golden 自比 | ✅ golden 自比 |
| 往来单位(桌面) | `partners.html` | `partners_screen.dart` | ✅ 副标/状态徽章/两行名称/响应式 toolbar | ✅ golden 自比 | ✅ golden 自比 |
| 往来单位(移动) | `m-partners.html` | 同上窄屏(卡片流) | ✅ golden 自比 | ✅ golden 自比 | ✅ golden 自比 |
| 入库列表(桌/移) | `stock-in-list.html` | `stock_in_list_screen.dart` | ✅ 副标 + 共享 StatusPill(草稿/待审/已审/已拒) | ✅ golden | ✅ golden |
| 出库列表(桌/移) | `stock-out-list.html` | `stock_out_list_screen.dart` | ✅ 副标 + 共享 StatusPill | ✅ golden | ✅ golden |
| 财务(桌/移) | `finance.html` | `finance_screen.dart` | ✅ KpiCard + 类型/结清 StatusPill + 离线条 token | ✅ golden | ✅ golden |
| 设备管理(桌/移) | `devices.html` | `device_management_screen.dart` | ✅ 在线/离线 StatusPill | ✅ golden | ✅ golden |
| 系统设置·参数 | `settings.html` | `settings_screen.dart` | ✅ 主题选择器三色板 + 角色 StatusPill | ✅ golden | ✅ golden |
| 关于我们(桌/移) | `about.html` | `about_screen.dart` | ✅ 正文已 token 化(golden 锁定) | ✅ golden | ✅ golden |
> **共享组件杠杆**`StatusBadge`(入/出库单据状态)一处升级两屏受益;`StatusPill`/`KpiCard` 现已被库存/往来/入出库/财务/设备/设置/关于复用——新屏直接套,无需重做徽章/卡片。
### 全量清扫收尾(其余屏状态)
| 屏 | 状态 |
|---|---|
| 登录 | ✅ 离线条 token 化 + 整屏 golden ×3 |
| 盘点 | ✅ 斑马行 token 化(表单屏,0 残留,无 golden:静态态不含明细) |
| 商品列表(基础数据) | ✅ 已 token 净(仅 default 金星 FFB300 为有意 accent);原型 商品档案/香型/介绍 富数据重排**待后端** |
| 商品详情 | ✅ 主数据/价格/描述区 token 净;原型 3 KPI/仓库分布/流水 **待后端聚合** |
| 公开商品/门店页 | ✅ **有意独立设计**warm-paper/酒红 bespoke 调色板 `_kPaper/_kBurgundy…`),顾客扫码固定品牌页,不参与 A/B/C 主题——保持现状 |
| Web 营销站 | ✅ **已对齐品牌**`web/assets/color.css``--brand-500:#2563AC` / `--accent` 酒红 / 灰阶 与原型令牌一致,roadmap「Web 镜像品牌」已满足 |
### 仍属「新建功能」(Phase 6,非重建既有屏)
应用内注册 / 购买·套餐·下单(设计+前端壳,**支付不接**)——这是 net-new 功能开发,需各自 spec→设计→实现,不在「既有屏设计语言升级」范围内。
> **重要发现(原型 vs 现有数据)**:原型是「理想态富数据重设计」,多数屏的富数据区**当前后端不供给**,无法一次完整还原:
> - **商品列表**8 tab vs 原型 5 tab;香型字典 / 商品介绍 缺后端 → 暂缓。
> - **商品详情**:原型 3 KPI(库存/货值/出库)+ 仓库分布 + 流水,`getDetail` 仅返回商品主数据 → 需聚合接口,暂缓。
> - **往来单位**:原型 应收/应付 列,Partner 模型无该字段 → 暂缓;类型 chips 暂保留为两 Tab。
>
> 故本阶段策略 = **「设计语言升级」**:把每屏视觉升到新 token/组件系(副标 / StatusPill / KpiCard〔数据够时〕/ 两行名称 / 响应式 toolbar / token 间距)+ 接 golden 闸;富数据区(应收应付 / 富 KPI / 仓库分布 / 流水 / tab 重排)等后端聚合就绪再做二期。库存屏因 KPI 可由已加载数据现算,是少数能一次到位的。
**验收法(HTML→Flutter 特例)**HTML(Chromium) 与 Flutter 渲染器不同,**严格 0.1% pixelmatch 不适用跨渲染器**(见 design-distill `references/flutter-golden.md`)。本项目双闸:
1. **保真闸(人工目检)**`node tools/ds-compare.mjs --html .superpowers/prototype/screens/<screen>.html --prefix <prefix>` → 截原型基准 + 与 Flutter golden 用 montage 并排 → `design/_compare/`
2. **回归闸(自动)**`test/golden/<screen>_golden_test.dart``pumpGolden`/`goldenAcrossThemes``test/support/golden_harness.dart`)出 A/B/C 三主题 golden,入库随 `flutter test` 同渲染器自比,抓串色/漏 token。
3. token 残留闸:`grep 0xFF…` 该屏为 0(颜色全走 `context.tokens`)。
> **基建就位**(本轮):golden 骨架 + 整屏还原闸(库存列表已接)+ ds-compare 目检编排 + design-distill skill 补全(montage/flutter-golden/跨渲染器分流/多主题 codegen)。
> 后续屏(商品/单据/往来/财务/系统域)逐个追加块 3 规格 + 块 4 行 + 一份 `*_golden_test.dart`,一屏一闭环,禁积压。