Files
jiu/design/CONTRACT.md
T
wangjia b79f11e350 docs(design): 库存列表设计契约 CONTRACT(design-distill 阶段1)
token映射(prototype var→AppTokens,已1:1)/组件清单/库存列表像素规格/
逐屏验收清单(HTML→Flutter 跨渲染器特例:基准并排目检+三主题自比)。
标注缺口:AppTokens 目前仅颜色,字阶/圆角/间距需补进 token 单源。
登记进 docs/index.html。

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01TSKEiHsvauyxYUW2itzUXX
2026-07-01 20:46:51 +08:00

98 lines
7.9 KiB
Markdown
Raw 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` | ☐ 像素 diff ≤阈 | ☐ 结构 | ☐ 结构 |
| 库存列表(移动) | `m-inventory.html` | 同上窄屏 | ☐ | ☐ | ☐ |
**验收法(HTML→Flutter 特例)**HTML(Chromium) 与 Flutter 渲染器不同,**严格 0.1% pixelmatch 不适用跨渲染器**。本项目采用:
1. **原型基准**`shoot-prototype.mjs <screen>.html out.png --width 1280 --height 860 --theme a|b|c`(已验证)。
2. **Flutter 实现图**golden / integration_test 截目标屏 → png。
3. **a 主题**:原型 vs Flutter **并排人工目检** + 关键区域结构 diff(容差放宽);**b/c**Flutter 三主题自比,确认 chrome/表头/徽章随主题换色、无残留硬编码。
4. token 残留闸:`grep 0xFF…` 该屏为 0(颜色全走 `context.tokens`)。
> 后续屏(商品/单据/往来/财务/系统域)逐个追加块 3 规格 + 块 4 行,一屏一闭环,禁积压。