b10b450db0
记录:登录+盘点 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
128 lines
12 KiB
Markdown
128 lines
12 KiB
Markdown
# 设计契约 — 岩美酒库 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*` | 外壳 chrome(P0 已迁移) |
|
||
| 状态徽章 `.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 单源 + codegen(P1 第一步,**禁页面里写死 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 菜单) + `显示 a–b,共 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`,一屏一闭环,禁积压。
|