Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01JJ1g8XV1YhhmHRzhwWEW7o
20 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(设计期返回球) |
— | 仅原型,不还原 | 不实现 |
.btn.lg(登录/注册主按钮 h44/pad22/fs14) |
DsButton(large:true) |
全宽居中 | 已有 |
.check / .agree(自绘复选 18px+勾) |
DsCheck(ds_atoms) |
value/onChanged/Widget label/alignTop | 已有 |
.theme-switch(auth 页右上 A/B/C 圆钮) |
ThemePickerPill(onSurface:true)(表单面板右上) |
2026-07-03 用户拍板:不用原型 A/B/C,复用主界面小衣服 pill 浅色变体 | 已有 |
.auth + .brand(两栏卡片+品牌渐变面板) |
AuthPageScaffold/AuthBrandPanel |
栏宽/窄屏折叠 | 已有 |
块 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 |
✅ KPI/徽章/列/副标/toolbar 已还原 | ✅ golden 自比 | ✅ golden 自比 |
| 库存列表(移动) | m-inventory.html |
同上窄屏(卡片流) | ✅ golden 自比 | ✅ golden 自比 | ✅ golden 自比 |
| 往来单位(桌面) | partners.html |
partners_screen.dart |
✅ Phase2 重建:单表+类型 chips/应收应付列(finance summary)/详情抽屉/frow 弹窗;fidelity 2.5–3.5%≤8% | ✅ fidelity | ✅ fidelity |
| 往来单位(移动) | m-partners.html |
同上窄屏(卡片流) | ✅ golden 自比 | ✅ golden 自比 | ✅ golden 自比 |
| 基础数据(桌面) | products.html |
products_screen.dart |
✅ Phase2 重建:.seg 5 tab(档案/介绍/系列/规格/仓库)+三套视图+编辑抽屉复用;fidelity 2.4–3.5%≤8%(已知差异见下) | ✅ fidelity | ✅ fidelity |
| 基础数据(移动) | m-products.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 |
✅ Phase2 重建:时间范围 chips(真实过滤)+KPI 4 卡(stock summary 环比)+收支趋势柱状图(DsBarChart, /finance/trend)+应收应付汇总(/finance/summary)+流水表+往来抽屉+登记收支(补往来单位);fidelity 3.0–4.2%≤8% | ✅ fidelity | ✅ fidelity |
| 设备管理(桌/移) | devices.html |
device_management_screen.dart |
✅ Phase2 重建:会话表(DsTable)+外设卡网格(custom_fields.peripherals 本地存档)+打印模板;fidelity 2.4–3.0%≤8% | ✅ fidelity | ✅ fidelity |
| 系统设置(桌/移) | settings.html |
settings_screen.dart |
✅ Phase2 重建:subnav 5 面板(门店/用户预览/编号规则/授权兑换券/偏好);假「系统参数」已删;fidelity 1.7–2.3%≤8% | ✅ fidelity | ✅ fidelity |
| 用户管理(桌/移) | users.html |
users_screen.dart(/settings/users) |
✅ Phase2 新独立页:KPI 4 卡+搜索/角色筛选+rcard 弹窗,角色四级拉平;fidelity 1.3–2.1%≤8% | ✅ fidelity | ✅ fidelity |
| 关于我们(桌/移) | about.html |
about_screen.dart |
✅ Phase2 重建:Hero/产品信息/授权信息/更新日志 timeline(/public/release 同源);fidelity 2.2–2.7%≤8% | ✅ fidelity | ✅ fidelity |
| 登录 | login.html |
login_screen.dart |
✅ Phase2 重建(2026-07-03):两栏卡片(品牌渐变面板+表单)+右上主题切换器+记住我/忘记密码+lg 主按钮;fidelity 1.4–2.1%≤8%(已知差异见下) | ✅ fidelity | ✅ fidelity |
| 注册新门店 | register.html |
register_screen.dart |
✅ Phase2 重建(2026-07-03):品牌面板三步时间线+grid2 表单+协议勾选;暂不入 fidelity 闸(少 门店编号/兑换券 两字段致结构错位,用户拍板先不加,见下) | ✅ golden ×3 | ✅ golden ×3 |
共享组件杠杆:
StatusBadge(入/出库单据状态)一处升级两屏受益;StatusPill/KpiCard现已被库存/往来/入出库/财务/设备/设置/关于复用——新屏直接套,无需重做徽章/卡片。
全量清扫收尾(其余屏状态)
| 屏 | 状态 |
|---|---|
| 登录/注册 | ✅ Phase2 已照原型重建(login.html/register.html,见上验收表) |
| 盘点 | ✅ 斑马行 token 化(表单屏,0 残留,无 golden:静态态不含明细) |
| 商品列表(基础数据) | ✅ Phase2 已照原型重建(.seg 5 tab,见上验收表);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→设计→实现,不在「既有屏设计语言升级」范围内。
Phase 2 已解决(2026-07-02):
- 往来单位:应收/应付列改由
GET /finance/summary(按 partner 聚合未结清)供给,两 Tab 改回原型的类型 chips 单表;详情抽屉近期单据走finance/records?partner_id=。- 基础数据:tab 集合按用户口径收敛为 5 个 档案/介绍/系列/规格/仓库(商品名称并入档案;产地/保质期/储存/香型撤管理入口,后端字典保留)。
- 商品详情:
getDetail聚合已就绪(3 KPI/仓库分布/流水,见 product_detail golden)。基础数据屏已知差异(数据/模型驱动,fidelity 残差包含它们):
- 档案无「分类」列、无香型筛选 chips(香型弃用);无「状态(在售/停用)」列(products 无 status 字段,用户拍板不加)。
- 档案无「新增商品」按钮(product=序列号铁律:入库每行自动建档)。
- 字典视图无「关联商品」计数列(无后端计数源);seg 第 5 tab 香型→仓库。
- 档案 pager 用带控件分页(真实数据量大);介绍/字典/仓库 pager 仅文案(对齐原型)。
库存屏已知差异(2026-07-02 用户口径调整):
- 搜索合一:原型 名称/拼音(240)+编码(180) 两框 → 一框「商品名 / 拼音 / 编码」(后端 keyword 本就四列 LIKE),回车触发(原型 oninput 即搜)。
- 工具栏「状态」筛选 chip 删除(用户裁定无用);状态列 + 列头漏斗 + KPI 缺货点击筛选保留。
- reload 不再白屏:skipLoadingOnReload + DsLoadingScrim 半透明遮罩(与入库/出库屏一致)。
商品编辑抽屉(2026-07-03 用户增强):
- 「从介绍库选择」由原型 .pe-pick 普通菜单升级为搜索下拉(GridComboCell 表单形态,供应商选择器同款:弹层搜索 + ✓ 选中 + 计数);收起态外观与原型一致。
出入库列表补闸 + 单元格对齐(2026-07-03):
- stock-in/stock-out 此前漏注册 fidelity(偏差长期未被闸住)→ 桌面 golden 改外壳挂载并入册(阈值 9%,实测 3.0–5.2%)。
- 单元格对齐原型:单号 = .pcode(faint+mono,弃蓝色链接样式);金额 = ¥+千分位无小数(td.num mono);审核员空值 = faint「—」。
- 全局 InputDecorationTheme 渗漏修复:内嵌裸 TextField 的组合控件显式屏蔽主题边框(搜索框双层框根因)。旧 DataTableCard 组件已无引用,删除。
登录/注册屏重建(2026-07-03):
- 主题切换(用户拍板):原型右上角 A/B/C 圆钮不用,改放主界面同款小衣服
ThemePickerPill(onSurface:true)于表单面板右上角(宽窄屏都落白底)。- 登录已知差异(功能位保留):门店编号/账号历史下拉(后缀箭头)+ 密码可见切换(后缀眼睛)为原型没有的功能件;密码空值显示 hint(原型演示值 8 dots);服务器错误条/离线条/授权锁定引导卡在按钮上方按需出现。「记住我」= 记录并预填最近登录账号(关闭则不记录),「忘记密码」= toast 提示联系管理员。
- 注册已知差异(用户拍板 2026-07-03:先不加):无「门店编号(留空自动分配)」「授权兑换券」两字段——后端 RegisterInput 暂不支持;门店地址必填(后端 binding:required,原型选填);密码下限 6 位(后端 min=6,原型文案 8 位)。表单因此少两行 → fidelity 暂撤册(screens.mjs 有注释存根),golden ×3 锁回归;后端补 shop_code/voucher 后恢复入闸。
- 校验口径 = 原型:提交时逐项 toast(DsToast),无内联错误文案,38 高盒式字段不抖动。
出入库定价重设计(2026-07-03 用户拍板,plan 批准):
- 出库详情明细:单价/金额 两列 → 成本价/售价/利润 三列(管理员);operator 见 售价/小计。合计区双行:合计金额(总售价)+ 合计利润(管理员)。
- 出库建单:金额列(=售价×数量,qty=1 与售价重复)→ 利润列(实时,负数 danger);商品名称下带编码(字体同系列列);底栏加合计利润;进价/利润列仅管理员。
- 入库建单列头:进价 → 进价(单瓶)、售价 → 参考售价、金额 → 总进价。
- 原型已同步(stock-in.js 双模式 + stock-out-list.html 详情抽屉),与真实页一致。
- 底层字段消歧:unit_price/total_price/total_amount → cost_price/cost_amount/cost_total(入)/sale_amount/sale_total/profit_total(出),见 CLAUDE.md「定价字段口径」。
全局对话框统一(2026-07-03 用户要求遍历):
- 主题层钉真相源:
DialogTheme(surface/r-xl/边框/标题 fs-h2·700)、全局InputDecorationTheme(.input 盒式,禁下划线兜底)、Elevated/FilledButton 主题(.btn.primary 规格)。- 全部 AlertDialog 动作行换
DsButton(取消=ghost / 确认=primary / 删除·拒绝=danger / 通过=success / 撤回·结清=accent,DsBtnVariant扩 success/accent);表单字段改DsField(label 在上)+ 盒式输入(添加设备等)。- 例外保留:
public_product_screen(对外扫码页,自有品牌配色非 ds 体系);表格行内链接式 TextButton(备注/打标签/测试打印)非对话框不在此列。出入库列表 KPI 口径(2026-07-03 用户拍板):
- 原型「本月入库/出库笔数·金额 + 较上月」自然月口径月初必然全 0(7-03 实测 0/¥0/▼100% 观感如坏数据)→ 卡片与头部小字改「近30天」滚动窗(
summary?window=rolling30,对照前一个 30 天);财务屏仍用自然月口径(原型「本月销售/采购额」文案不变),同一接口两种 window。财务屏已知差异(2026-07-02 Phase2 第 9 屏):
- KPI3/4 delta:原型「逾期 ¥9.2万 / 本周到期 ¥4.8万」无到期日数据源 → 改「未结清 N 笔 / 按到期及时结清」。
- KPI 应收/应付值 =
/finance/summary实算求和(原型硬编码 ¥48.6万 与其汇总表行自身不一致)。- 流水类型 chips 原型 3 个扩到 5(含应收/应付),并追加 状态/操作 两列(结清能力不回退);关联单号列显示
单据类型 #id(原型 SK/FK 单号字符串无对应模型)。- 时间范围 chips 真实过滤流水(原型只改文案);趋势柱最高 140px(原型 ~157,标签悬浮方式不同)。
设备/设置/用户/关于 已知差异(2026-07-02 Phase2 第 6-8 屏):
- 设备:外设设备=登记式本地存档(店级
custom_fields.peripherals,无真实连接协议),测试打印/配置/模板预览为占位 toast;打印模板静态两卡。- 设置:子导航比原型多「编号规则」(真实功能保留);门店卡多 Logo 行;授权卡保留降级说明;偏好即时生效无「保存」按钮;原型「系统参数」假设置删除。
- 用户:独立页挂
/settings/users(原型导航同样高亮系统设置);角色四级(后端为准),原型 settings 预览三级口径弃用;授权数据 settings/about 同源 licenseProvider(原型两处数字不一致)。- 关于:旧版 帮助文档/扫码防伪/系统信息 卡删除,构建号并入版本 cell;更新日志走
/public/release(与官网时间线同源),接口不可达回退只显当前版本。
验收法(HTML→Flutter 特例):HTML(Chromium) 与 Flutter 渲染器不同,严格 0.1% pixelmatch 不适用跨渲染器(见 design-distill references/flutter-golden.md)。本项目双闸:
- 保真闸(人工目检):
node tools/ds-compare.mjs --html .superpowers/prototype/screens/<screen>.html --prefix <prefix>→ 截原型基准 + 与 Flutter golden 用 montage 并排 →design/_compare/。 - 回归闸(自动):
test/golden/<screen>_golden_test.dart走pumpGolden/goldenAcrossThemes(test/support/golden_harness.dart)出 A/B/C 三主题 golden,入库随flutter test同渲染器自比,抓串色/漏 token。 - token 残留闸:
grep 0xFF…该屏为 0(颜色全走context.tokens)。
基建就位(本轮):golden 骨架 + 整屏还原闸(库存列表已接)+ ds-compare 目检编排 + design-distill skill 补全(montage/flutter-golden/跨渲染器分流/多主题 codegen)。 后续屏(商品/单据/往来/财务/系统域)逐个追加块 3 规格 + 块 4 行 + 一份
*_golden_test.dart,一屏一闭环,禁积压。