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