Files
jiu/docs/plans/2026-07-14-six-frontend-tweaks.md
T
2026-07-14 11:23:26 +08:00

17 KiB
Raw Blame History

六项前端体验优化 实现计划

For agentic workers: REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (- [ ]) syntax for tracking.

Goal: 一次性落地 6 个前端小需求:①库存抽屉加供应商 ②库存桌面列批次号/生产日期换位 ③出入库单详情抽屉加「生产日期+批次号」双行列(两端)④出入库列表状态筛选多选+默认草稿/待审核 ⑤新建单默认填充默认仓库 ⑥财务加往来单位筛选+自定义时间换统一组件。

Architecture: 全部为前端(Flutter client/+ 设计原型(design/prototype/)改动,后端零改动(调研已核实:供应商/批次/生产日期数据链路已通、status 已支持逗号多值、partner_id 过滤已存在、warehouses.is_default 全链路齐备)。按 design-first 铁律:每个任务先改原型、再改真实代码、原型与代码同一提交

Tech Stack: Flutter/Riverpod + 原型 HTML/JStokens/atoms 单源);验收闸 check-ds / check_ds_code / check-l1-sync / fidelity / golden。

Global Constraints

  • design-first 铁律(用户 2026-07-14 重申):涉及页面的改动必须先改 design/prototype/ 原型再开发,原型与代码同一提交;改到的屏必须保持 CONTRACT「同步」态。
  • 颜色/间距一律走 tokencontext.tokens),禁硬编码 hex;新原子先登记原型 index.html
  • 弹窗/抽屉宽度改动属 L1 层(atoms.css),须原型与 Flutter 常量同提交(过 tools/check-l1-sync.mjs)。
  • 多租户/权限口径不变:出库成本/利润仅管理员可见的逻辑不受本次改动影响(新增列均为非成本字段)。
  • DoDflutter analyze --no-fatal-infos --no-fatal-warnings 零 error、flutter test 全绿、node client/tool/check_ds_code.mjsnode tools/check-l1-sync.mjs 过闸、涉及屏 fidelity ≤ 8%不发版、不打 tag、不部署,完成后停在本地提交态等用户验收。
  • 提交规范:每个需求一个提交,feat(client): ...,原型改动包含在同一提交内。

已定决策(评审时可推翻)

  • D1 供应商行两端同显:库存商品抽屉两端共用 product_editor_drawer.dart_infoBody,加一行两端同时生效、成本为零;桌面端抽屉当前也没有供应商(表格有),一并补齐更一致。行位置:紧跟「生产日期」行之后。
  • D2 库存抽屉顺手补「批次号」行(推荐做):与需求③口径一致(出入库抽屉都有生产日期+批次号,库存抽屉只有生产日期不对称);Inventory.batchNo 数据已有,走与供应商相同的入参传递。若你只要最小改动(仅供应商),评审时说一声即去掉。
  • D3 状态筛选「重置」回默认:重置按钮把状态恢复为默认 draft,pending(与进入页面初始态一致),不是回「全部」。
  • D4 退单伪状态与多选互斥ret:partial/ret:full 保持与主状态互斥——选退单态清空状态多选,选任一主状态清退单态(沿用现语义,最小改动)。
  • D5 移动端 KPI 卡片点击 = 覆盖为单值:点「待审核」卡即只看待审核(覆盖当前多选集合),保持现有心智。
  • D6 移动端财务往来单位筛选形态:在时间 chips 行尾追加「往来单位」chip,点开 showMSheet 底部可搜索单选列表(与桌面 ComboSearchField 对应);再点 × 清除。
  • D7 出库抽屉加宽 600→660:出库管理员形态 7→8 列太紧,atoms.css .drawer.wide 600→660px 与 Flutter order_detail_drawer.dart:44 常量同提交;入库 5→6 列余量够,只微调列宽不加宽。

执行分组(多 agent 调度)

波次 任务 关键文件域 并行性
1 A 库存域 Task 1 + Task 2 product_editor_drawer / inventory_list_screen / inventory.html / product-editor.js / m-inventory.html 与 B、D 并行
1 B 出入库抽屉 Task 3 order_detail_drawer / 两 list_screen(传参处)/ atoms.css / stock-*-list.html ×4 与 A、D 并行
1 D 财务域 Task 6 finance_screen / finance_provider / finance.html / m-finance.html 与 A、B 并行
2 C 出入库筛选+表单 Task 4 + Task 5 两 provider / 两 list_screen / 两 form_screen / stock-*-list.html ×4 / stock-in.js 必须等 B 完成(同文件)
3 收尾 Task 7 CONTRACT.md / fidelity / golden / 手册核查 最后

Task 1: 库存商品抽屉加「供应商」行(+D2 批次号行)【两端】

Files:

  • Modify: design/prototype/screens/product-editor.js:60-75infoRows()
  • Modify: design/prototype/screens/m-inventory.html:98(详情 sheet 行序)
  • Modify: client/lib/widgets/product_editor_drawer.dart(入参 + _infoBody 385-471
  • Modify: client/lib/screens/inventory/inventory_list_screen.dart:123_openEditor 传参)

Interfaces:

  • Produces: showProductEditorDrawer(..., String? supplier, String? batchNo) 两个新可空入参;不传即不显示(条件行机制),其它调用方(products_screen.dart 等)零改动。

  • Step 1(原型先行): product-editor.js infoRows() 在「生产日期」行后加「批次号」「供应商」两行(假数据示例 B20260701 / XX贸易);m-inventory.html 详情 sheet 同步行序。本地 5180 预览确认。

  • Step 2(代码): product_editor_drawer.dartshowProductEditorDrawerString? supplier, String? batchNo 入参并透传;_infoBody 在生产日期行后按非空条件渲染「批次号」「供应商」两行(样式照抄现有 info 行)。

  • Step 3(接线): inventory_list_screen.dart _openEditorsupplier: item.supplierName, batchNo: item.batchNo

  • Step 4(验证): cd client && flutter analyze --no-fatal-infos --no-fatal-warnings && flutter test;若库存屏 golden 覆盖抽屉则 regen。

  • Step 5(提交): feat(client): 库存商品抽屉增加供应商与批次号信息行(两端,原型同步)

Task 2: 库存桌面表格「批次号」「生产日期」列换位【仅桌面】

Files:

  • Modify: design/prototype/screens/inventory.html:128COLS 数组对调)
  • Modify: client/lib/screens/inventory/inventory_list_screen.dart:58-73_colDefs 对调)

前提核实(调研已确认):移动端卡片无批次号字段,不涉及;列偏好/排序白名单均按 key 存,换位只动数组顺序不动 key,用户已存配置不受影响。

  • Step 1(原型先行): inventory.html COLS 中 batch 与 prodDate 位置对调,5180 预览确认。
  • Step 2(代码): _colDefs 同步对调两项顺序(连同对应 cell 构建顺序)。
  • Step 3(验证): flutter analyze && flutter test;库存列表 golden 如有列序断言则 regen。
  • Step 4(提交): feat(client): 库存列表批次号与生产日期列位对调(原型同步)

Task 3: 出入库单详情抽屉明细加「生产日期+批次号」双行列【两端】

Files:

  • Modify: design/prototype/screens/stock-in-list.html:311-312(明细 grid + 假数据 lines 补 pdate/batch
  • Modify: design/prototype/screens/stock-out-list.html:306-308GRID 常量 + 假数据)
  • Modify: design/prototype/screens/m-stock-in-list.html:145-149m-stock-out-list.htmlopenOrder lineRows 插入「生产日期/批次号」双行列)
  • Modify: design/prototype/atoms.css:218-220.drawer.wide 600→660D7
  • Modify: client/lib/widgets/order_detail_drawer.dartOrderLine:67-92 加字段;_LinesTable:418-618 加列;_mLineRow:331-367 插双行列;:44 宽度 660
  • Modify: client/lib/screens/stock_in/stock_in_list_screen.dart:988-999client/lib/screens/stock_out/stock_out_list_screen.dart:1064-1080(构造 OrderLine 传两字段)
  • Modify: client/lib/models/stock_in.dart:63-64StockInItem 两字段改 lineOrProduct 兜底,对齐 stock_out 写法)
  • Test: client/test/order_detail_drawer_columns_test.dart(列结构断言同步更新)

Interfaces:

  • Produces: OrderLine(..., String? productionDate, String? batchNo);桌面新列单元格样式 = 上行生产日期(fsSm mono+ 下行批次号(fsXs faint mono),复用「商品·编码」列先例。

  • Step 1(原型先行): 四个原型文件明细区插入「生产日期/批次号」双行列(桌面:入库 grid 插 ~72px 列并把 124→110、88→78;出库 GRID 插列且抽屉用 wide 660+ 移动 lineRows 在金额左侧同样插入双行列(上=生产日期 fsSm mono,下=批次号 fsXs faint,与桌面同构;用户 2026-07-14 审阅指定);atoms.css .drawer.wide 600→660。假数据补 pdate/batch。5180 预览两端四屏。

  • Step 2(模型兜底): stock_in.dart StockInItem.fromJson 的 production_date/batch_no 改用 lineOrProduct 兜底(照 stock_out.dart:68-69)。

  • Step 3(抽屉代码): OrderLine 加两字段;_LinesTable 入库 5→6 列 / 出库 7→8 列,新列插在「系列·规格」后,列宽按原型定稿值;_mLineRow 在金额区左侧插入双行列(上=生产日期 fsSm mono,下=批次号 fsXs faint;两值都空则不渲染该列,避免空占位);:44 桌面宽度 min(660, 94%)

  • Step 4(接线): 两个 list_screen 构造 OrderLine 时传 productionDate: it.productionDate, batchNo: it.batchNo(显示截 substring(0,10))。

  • Step 5(测试): 更新 order_detail_drawer_columns_test.dart 列数/列头断言;flutter analyze && flutter test;涉及 goldenstock_{in,out}_list*)若开抽屉则 regen。

  • Step 6L1 闸): node tools/check-l1-sync.mjs 过闸(atoms.css 与 Flutter 常量同源)。

  • Step 7(提交): feat(client): 出入库单详情抽屉明细增加生产日期+批次号列(两端,抽屉加宽 660,原型同步)

Task 4: 出入库列表状态筛选多选 + 默认「草稿+待审核」【两端】

Files:

  • Modify: design/prototype/screens/stock-in-list.html:67stock-out-list.htmlchipStatus 单选→多选,默认态 draft+pending,摘要「值/N 项」,参照 inventory.html:69,138-139 既有多选形态)
  • Modify: design/prototype/screens/m-stock-in-list.html:101-102m-stock-out-list.html(状态 sheet 单选→多选勾选)
  • Modify: client/lib/providers/stock_in_provider.dart:41stock_out_provider.dart:41(默认 _status = 'draft,pending'
  • Modify: client/lib/screens/stock_in/stock_in_list_screen.dart:86-113 归一逻辑重写;:773-790 桌面 chip 改 showDsMultiMenu:678-724 移动 sheet 改多选;:621-630 KPI 点击、_resetFilters
  • Modify: client/lib/screens/stock_out/stock_out_list_screen.dart:100-128 归一、_MenuChip 调用点 ~813、:1973-2020、KPI :548-560/:650-659 同构改法)

Interfaces:

  • Consumes: 后端 status IN (逗号分隔) 已支持(stock_in.go:44-45 / stock_out.go:55-56),零改动。
  • Produces: 屏内状态 = Set<String>,落 provider 时 join(',');空集 = 全部。

关键陷阱(调研确认):两屏 initState 有「归零残留多值」逻辑,会把 'pending,draft' 重置为 ''——必须重写为「按逗号拆分后逐值校验合法性,非法才归默认」,否则默认值刚设就被清掉。

  • Step 1(原型先行): 四个原型文件状态筛选改多选(复用 inventory 屏 chip 摘要形态 / m 端 sheet 勾选形态),默认选中 草稿+待审核。5180 预览。
  • Step 2provider: 两个 provider 默认值改 'draft,pending'
  • Step 3(归一重写): 两屏 initState 残留清洗逻辑改为逐值校验(合法集 = draft/pending/approved/rejected),并兼容退单伪状态互斥(D4)。
  • Step 4(桌面 chip: 单选 PopupMenu → _multiChip + showDsMultiMenu(照 inventory_list_screen.dart:209-246widgets/ds/ds_menu.dart:51),摘要:1 项显示值 / 多项「N 项」/ × 清为默认(D3)。
  • Step 5(移动 sheet + KPI: _openStatusSheet 改多选勾选(确定时应用);KPI 卡点击 = 覆盖单值(D5);_resetFilters 状态回 draft,pendingD3)。
  • Step 6(验证): flutter analyze && flutter test;两屏列表 golden regen(默认筛选态变了,golden 基线会变)。
  • Step 7(提交): feat(client): 出入库列表状态筛选改多选并默认草稿+待审核(两端,原型同步)

Task 5: 新建入库/出库单默认填充默认仓库【两端,同一代码路径】

Files:

  • Modify: design/prototype/screens/stock-in.jsstate.doc.warehouse 新建时默认取默认仓,双模式驱动 in/out 两屏)
  • Modify: client/lib/screens/stock_in/stock_in_form_screen.dart_warehouseId:43,加载仓库后填充)
  • Modify: client/lib/screens/stock_out/stock_out_form_screen.dart:158 同构)

Interfaces:

  • Consumes: Warehouse.isDefaultclient/lib/models/warehouse.dart:5,18,已存在);设置页已可指定默认仓。

  • Step 1(原型先行): stock-in.js 新建单时仓库字段预填默认仓(假数据标记一个默认仓)。5180 预览 in/out 两屏。

  • Step 2(代码): 两张表单新建模式(非编辑回填)在仓库列表加载完成后:_warehouseId ??= 列表中 isDefault 的仓 ?? (列表仅 1 个仓时取它 : 保持 null)。编辑模式不受影响(仍从单据回填)。

  • Step 3(验证): flutter analyze && flutter test(两表单已有测试如断言初始空值需同步)。

  • Step 4(提交): feat(client): 新建出入库单默认填充默认仓库(两端,原型同步)

Task 6: 财务加「往来单位」筛选 + 自定义时间换统一组件【两端】

Files:

  • Modify: design/prototype/screens/finance.html:82-86 timerow「自定义」接 datewheel.js openRange(照 stock-in-list.html:228 写法);流水表 toolbar 加往来单位下拉)
  • Modify: design/prototype/screens/m-finance.html(回填真实端已有的时间 chips 行【存量漂移】+ 时间行尾加「往来单位」chip→sheet,D6
  • Modify: client/lib/providers/finance_provider.dart:18-88(加 _partnerId + setPartner(),照 setType 写法约 8 行)
  • Modify: client/lib/screens/finance/finance_screen.dart:89-103 _applyRange 自定义分支 showDateRangePickershowDateRangeDropdown(anchorCtx, initial:)anchor 用「自定义」chip 的 Builder context,照 stock_in _dateMenu:247-270:532-557 _flowTable toolbar 加 ComboSearchField 往来单位(照 stock_out_list_screen.dart:783-797);移动分支时间行尾加往来单位 chip→showMSheet 可搜单选)

Interfaces:

  • Consumes: 后端 /finance/records?partner_id= 已支持(finance.go:34,51-52);finance_repository.listRecords 已有 partnerId 参数(:16,28);数据源 allPartnersProviderpartner_provider.dart:31);showDateRangeDropdownwidgets/wheel_date_picker.dart,组件内部自适应桌面下拉/窄屏 sheet)。

  • Step 1(原型先行): finance.html 自定义时间接 datewheel + toolbar 加往来下拉;m-finance.html 回填时间行 + 往来单位 chip/sheet。5180 预览两端。

  • Step 2provider: FinanceListNotifier_partnerId/setPartner() 并接入 listRecords

  • Step 3(统一时间): _applyRange 自定义分支换 showDateRangeDropdown(一处代码两端生效,删除 showDateRangePicker 引用)。

  • Step 4(桌面往来筛选): _flowTable toolbar 类型 chips 旁加 ComboSearchField(可搜单选,清除回全部)。

  • Step 5(移动往来筛选): 时间 chips 行尾加「往来单位」chip → 底部 sheet 可搜单选(D6)。

  • Step 6(验证): flutter analyze && flutter test;财务屏 golden regentoolbar 变了)。

  • Step 7(提交): feat(client): 财务筛选增加往来单位并统一自定义时间组件(两端,原型同步)

Task 7: 收尾——CONTRACT 台账回填 + fidelity 体检 + 手册核查

Files:

  • Modify: design/CONTRACT.md(块 4:库存 :100-101、出入库列表 :106-107、财务 :108 各行备注回填本次改动,保持「同步」态)

  • Check: web/content/docs.md / docs/manual/user-manual.html(若有「出入库列表默认显示」「财务筛选」相关描述则同步;无则不动)

  • Step 1: 跑受影响屏 fidelitynode tools/fidelity.mjs(库存、入库列表、出库列表、财务,桌面+移动),超 8% 回改对齐。

  • Step 2: CONTRACT.md 对应行回填改动说明与 fidelity 结果。

  • Step 3: 手册核查:默认筛选行为变化(草稿+待审核)如手册有描述则两侧同步(web/content/docs.md + user-manual.html)。

  • Step 4(全量 DoD: flutter analyze && flutter testnode client/tool/check_ds_code.mjsnode tools/check-l1-sync.mjs 全绿。

  • Step 5(提交): docs(design): 六项前端优化 CONTRACT 台账回填与手册同步