Compare commits

..

8 Commits

Author SHA1 Message Date
wangjia b20be72155 docs: 重画系统架构图——单脊柱布局替代五线乌鸦脚,补 Redis 节点
Design Source Checks / design-source (push) Successful in 53s
客户端五端收进分组条(单一竖线入 nginx),标签白底不再压线,
nginx 泳道排满不留空带,MySQL/Redis 并排(jiu_redis 上线后架构图欠账)。

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01JJ1g8XV1YhhmHRzhwWEW7o
2026-07-07 22:27:28 +08:00
wangjia fb8337b156 ci: retrigger checks——pangolin runner 误挂 mac 标签抢跑已摘除
Design Source Checks / design-source (push) Successful in 1m2s
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01JJ1g8XV1YhhmHRzhwWEW7o
2026-07-07 19:12:59 +08:00
wangjia 05203a9b5b refactor: 原型迁移 .superpowers/prototype → design/prototype(与 CONTRACT 同目录)
Design Source Checks / design-source (push) Failing after 14m23s
- git mv 全目录(历史保留);.gitignore 收敛为整个 .superpowers/ 忽略
- 全仓 16 处引用同步(CI checks.yml / l1-sync / screens.mjs / hooks /
  CLAUDE.md / CONTRACT / SSR 模板注释 / docs / web 注释)
- 修 pre-commit 路径正则残留;5180 评审服务已切新路径
- 验证:check-ds 12 道 / l1-sync 6 道 / fidelity 抽查全过

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01JJ1g8XV1YhhmHRzhwWEW7o
2026-07-07 18:47:31 +08:00
wangjia d1b7e8e2e9 refactor(client): 前端体系治理——漏斗退役/老卡片标 legacy/fidelity 收阈/文档口径修正
- DsFilterHeader 删除(筛选已全部上移工具栏 chips,屏内零引用)
- mobile_list_card 标 LEGACY 禁新用(6 屏迁移 MCard 登记 todo #13)
- fidelity 阈值按 2026-07-07 实测收紧:一刀切 8% → 各屏实测最大残差+2pp
  (4%~7%),新阈下 36 屏×主题全过;proto 基准同步重摄(含库存改版)
- CLAUDE.md 修正:表格筛选口径(工具栏 chips+列头仅排序)、响应式导航
  (Drawer 退役→底部 5 tab,修文字滞后)

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01JJ1g8XV1YhhmHRzhwWEW7o
2026-07-07 18:24:48 +08:00
wangjia 21a4a8cab7 ci: 补三道缺口闸——CI 强制 flutter test + SSR 模板 token 同源 + 徽章图标映射同集
- checks.yml 加 flutter test(DoD 写了但此前无闸,golden 回归全靠自觉;
  本地 /release client 门禁同步加了 flutter test,该文件 gitignore 不入库)
- check-l1-sync ⑤:backend 公开页模板内联 token 值须与原型 tokens.css
  对应主题块一致(模板自包含手拷值,此前仅注释约定零校验;已注入漂移自证)
- check-l1-sync ⑥:BADGE_ICON ↔ kStatusIcons 状态词同集(此前两端手工转录)
- 顺修 gen_tokens 旧路径注释(client/lib/core/theme/tool/ → client/tool/)

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01JJ1g8XV1YhhmHRzhwWEW7o
2026-07-07 18:24:34 +08:00
wangjia 8912b8ef7f docs: 前端开发全景文档——设计系统/工具链/各道闸/规则单一入口
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01JJ1g8XV1YhhmHRzhwWEW7o
2026-07-07 17:51:07 +08:00
wangjia 33987faa9b chore(scripts): local_test.sh 过滤锁屏 iPhone 的 xcodebuild 握手噪音
DTDK passcode protected 每 3s 刷屏(构建 generic/platform=iOS 不需真机),
stderr 定向过滤堆栈噪音,真错误仍透传。

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01JJ1g8XV1YhhmHRzhwWEW7o
2026-07-07 17:31:27 +08:00
wangjia 7328d85912 chore: release client-v1.1.7
Design Source Checks / design-source (push) Successful in 18s
Deploy Client / build-client-web (push) Successful in 55s
Deploy Client / build-windows (push) Successful in 2m11s
Deploy Client / build-macos (push) Successful in 2m57s
Deploy Client / build-android (push) Successful in 1m40s
Deploy Client / build-ios (push) Successful in 3m9s
Deploy Client / release-deploy-client (push) Successful in 1m33s
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01JJ1g8XV1YhhmHRzhwWEW7o
2026-07-07 17:11:04 +08:00
118 changed files with 439 additions and 142 deletions
+1 -1
View File
@@ -40,7 +40,7 @@ export PATH="/opt/homebrew/bin:$PATH"
```
- **client**
```bash
cd client && flutter analyze --no-fatal-infos --no-fatal-warnings
cd client && flutter analyze --no-fatal-infos --no-fatal-warnings && flutter test
```
- **site**
```bash
+9 -3
View File
@@ -1,8 +1,9 @@
name: Design Source Checks
# 设计真相源检查(治理规则见 CLAUDE.md「设计真相源分层」):
# PR 与合并 main 时自动跑四道闸,全部纯静态检查node + dart format
# 不跑 golden/fidelity(重型像素闸维持「定期体检」定位,本地手动跑)。
# PR 与合并 main 时自动跑四道静态闸(node + dart format+ flutter test
# (单测 + golden ×3 主题回归自比,2026-07-07 纳入——此前 DoD 写了但无闸)。
# fidelity 重型像素闸维持「定期体检」定位,本地手动跑。
on:
pull_request:
push:
@@ -23,7 +24,7 @@ jobs:
run: sh scripts/ci/provision-mac.sh
- name: 原型设计系统闸(check-ds 12 道)
run: node .superpowers/prototype/tools/check-ds.mjs
run: node design/prototype/tools/check-ds.mjs
- name: L1 真相源同源闸(tokens 快照 / icons / 官网 token 值 / web hex
run: node tools/check-l1-sync.mjs
@@ -37,3 +38,8 @@ jobs:
node tool/gen_tokens.mjs
dart format lib/core/theme/app_tokens.g.dart lib/core/theme/app_dims.g.dart lib/core/theme/app_chrome.g.dart
git diff --exit-code -- lib/core/theme/app_tokens.g.dart lib/core/theme/app_dims.g.dart lib/core/theme/app_chrome.g.dart
- name: Flutter 测试(单测 + golden ×3 主题回归自比)
run: |
cd client
flutter test
+2 -4
View File
@@ -67,10 +67,8 @@ backend/gencode
# iOS 证书私钥(绝不入库)
.ios-certs/
# superpowers 工作目录brainstorm/sdd 是草稿不入库;
# prototype 是设计像素真源 + 设计系统守门闸(check-ds.mjs),入库供 CI 跑。
.superpowers/*
!.superpowers/prototype/
# superpowers 工作目录(草稿不入库)。原型已迁 design/prototype/2026-07-07)。
.superpowers/
# design-distill 保真目检对比图(可重生,见 tools/ds-compare.mjs
design/_compare/
+10
View File
@@ -5,6 +5,16 @@ All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
## [1.1.7] - 2026-07-07
### 新功能
- 库存列表列头排序:点击 库存 / 成本价 / 总价 / 生产日期 / 入库时间 列头
即可全局排序(升序 ↑ / 降序 ↓ / 再点恢复默认)。
### 改进
- 库存筛选全部移到工具栏(与出库管理同一形式):规格 / 系列 / 仓库 / 状态
改为工具栏下拉标签,可单独清除;列头不再放筛选漏斗。
## [1.1.6] - 2026-07-07
### 新功能
+6 -6
View File
@@ -257,7 +257,7 @@ cd client && flutter test
### 设计真相源分层(原型漂移治理,2026-07-04 拍板)
原型(`.superpowers/prototype/`)与真实页面**不追求全量永久同步**,按层分治:
原型(`design/prototype/`)与真实页面**不追求全量永久同步**,按层分治:
- **L1 设计系统层**`tokens.css` / `atoms.css` / `mobile-atoms.css` / `icons.js` + `index.html` 登记):原型是**单一真源**。新增颜色/组件/图标必须**先登记原型再同步**代码与官网(如 `web/_includes/icons.njk`)。闸:pre-commit `check-ds.mjs` 12 道(本地钩子,新机器先跑 `sh scripts/hooks/install.sh`+ 代码侧 `client/tool/check_ds_code.mjs`
- **L2 屏级三态**(台账 = `design/CONTRACT.md` 块 4「真相源」列):
@@ -268,16 +268,16 @@ cd client && flutter test
- **漂移体检**:不逐提交强制同步;大版本/整屏改版前跑 `node tools/fidelity.mjs`,按报告逐屏决定「重新对齐原型」或「降级快照」,结果回填 CONTRACT。
- **CI 闸**`.gitea/workflows/checks.yml`PR + main push 自动跑):① `check-ds.mjs` 原型 12 道;② `tools/check-l1-sync.mjs` L1 同源四道(tokens 快照逐字节 / icons 两端同集同内容 / 官网 token 值对齐原型主题 A / web 硬编码 hex,白名单 #fff#1677ff`ds-allow` 可豁免);③ `client/tool/check_ds_code.mjs` Flutter 颜色单源;④ codegen 新鲜度(regen→`dart format`→与入库产物零 diff)。本地可直接跑同名命令。
### 表格与列头筛选(ds 真相源)
- 列表屏统一 `DsTable``widgets/ds/ds_table.dart`toolbar+表格+pager 连成一卡),列定义 `DsColumn`,可筛选列走其列头漏斗(`filtered` 态高亮),可隐藏列走列设置菜单
- 不要在 toolbar 放独立筛选按钮,筛选入口内嵌列头或工具栏 `DsChip`
### 表格与筛选/排序ds 真相源)
- 列表屏统一 `DsTable``widgets/ds/ds_table.dart`toolbar+表格+pager 连成一卡),列定义 `DsColumn`,可隐藏列走列设置菜单
- **筛选统一放工具栏 `DsChip`**2026-07-07 用户口径,形式参照出库管理:单选/多选 chip + 选中值/N 项摘要 + × 单清);列头**只放排序** `DsSortHeader`(点击循环 无→升→降→无,服务端全局排序)。列头漏斗 `DsFilterHeader` 已退役删除
-`FilterableColumnHeader`/`multi_select_dropdown.dart` 仅存量引用,勿在新屏使用
### 响应式 / 移动端适配
- 断点判定统一用 `context.isMobile``client/lib/core/responsive/responsive.dart`,宽度 < 600 为窄屏/手机),**禁止**在各处散落 `MediaQuery.width < 600` 这类魔法数
- **列表屏**:统一用 `DsTable``widgets/ds/ds_table.dart`,真相源表格:toolbar+列+pager);窄屏卡片流`MobileListCard` / `MobileCardField``widgets/mobile_list_card.dart`)。`DataTableCard` 已删除(2026-07-03),勿再引用
- **列表屏**:统一用 `DsTable``widgets/ds/ds_table.dart`,真相源表格:toolbar+列+pager);窄屏卡片流用 `MCard``widgets/ds/m_card.dart`,镜像原型 mobile-atoms)。旧 `MobileListCard` 为 legacy 仅存量引用(迁移在 todo),`DataTableCard` 已删除(2026-07-03),勿再引用
- **弹窗固定宽度**:一律用 `context.dialogWidth(X)`(≤ 屏宽 92%),**禁止**裸写 `width: <固定值>` 导致窄屏溢出
- **导航**:窄屏(手机)用 Drawer 抽屉(`app_shell.dart`),宽屏保持侧边栏;新增页面无需单独处理,挂在 shell 下即可
- **导航**:窄屏(手机)= 底部 5 tab(库存/入库/出库/财务/我的)+「我的」hub 聚合二级屏(`app_shell.dart` + `m_tab_bar.dart`2026-07-04 起,Drawer 已退役);宽屏保持侧边栏;一切弹层窄屏统一走 `showMSheet` 底部 sheet
- 平台判断仍遵守上面「前端平台判断」规则(`kIsWeb` 先于 `dart:io`
### 权限中间件(已全局挂载)
@@ -6,7 +6,7 @@
<title>{{.PageTitle}}</title>{{.OGTags}}
<style>
/* 设计系统单一真源:变量名与三主题(a 经典蓝浅 / b 琥珀深 / c 酒窖暖浅)色值
逐字取自 .superpowers/prototype/tokens.css。SSR 页自包含无法直接引 tokens.css
逐字取自 design/prototype/tokens.css。SSR 页自包含无法直接引 tokens.css
改配色须先改原型令牌再同步此处。--glow/--seal-bg 为本页派生变量(主色低透明度/表面高透明度)。 */
:root{
--r-md:6px; --r-lg:10px; --r-xl:14px; --r-pill:999px;
@@ -5,7 +5,7 @@
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>{{.PageTitle}}</title>{{.OGTags}}
<style>
/* 设计系统单一真源:变量名与三主题(a/b/c)色值逐字取自 .superpowers/prototype/tokens.css。
/* 设计系统单一真源:变量名与三主题(a/b/c)色值逐字取自 design/prototype/tokens.css。
与商品公开页同族;改配色须先改原型令牌再同步此处。--glow 为本页派生变量(主色低透明度)。 */
:root{
--r-md:6px; --r-lg:10px; --r-xl:14px; --r-pill:999px;
+2 -35
View File
@@ -523,38 +523,5 @@ class DsSortHeader extends StatelessWidget {
}
}
/// 原型 thead th .fh 漏斗列头:label + funnel(12, sw1.6),有筛选值时整体 primary。
/// 点击回调携带列头自身 BuildContext(供 showDsMenu 锚定)
class DsFilterHeader extends StatelessWidget {
final String label;
final bool filtered;
final void Function(BuildContext anchorContext) onOpen;
const DsFilterHeader(
{super.key,
required this.label,
required this.filtered,
required this.onOpen});
@override
Widget build(BuildContext context) {
final t = context.tokens;
final color = filtered ? t.primary : t.muted;
return Builder(
builder: (bctx) => InkWell(
onTap: () => onOpen(bctx),
child: Row(
mainAxisSize: MainAxisSize.min,
children: [
Text(label,
style: TextStyle(
fontSize: AppDims.fsSm,
fontWeight: FontWeight.w600,
color: color)),
const SizedBox(width: 5),
Icon(LucideIcons.funnel, size: 12, color: color),
],
),
),
);
}
}
// DsFilterHeader(列头漏斗筛选)已于 2026-07-07 退役删除:筛选统一上移工具栏
// chips(用户口径,形式参照出库管理),列头仅保留 DsSortHeader 排序
+5
View File
@@ -1,6 +1,11 @@
import 'package:flutter/material.dart';
import '../core/theme/context_tokens.dart';
// ⚠️ LEGACY2026-07-07 标注):本组件为旧移动卡片范式(label:value 竖排字段),
// 新范式 = widgets/ds/m_card.dart 的 MCard(镜像原型 mobile-atoms .m-card
// 图标徽章 + 双栏紧凑)。**新屏禁用本组件,一律用 MCard**;存量 6 屏
// (出入库录单/往来/盘点/基础数据/财务)迁移已登记 todo,迁完删除本文件。
/// 移动端列表卡片的单个字段(label: value)。
class MobileCardField {
final String label;
Binary file not shown.

Before

Width:  |  Height:  |  Size: 393 KiB

After

Width:  |  Height:  |  Size: 394 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 389 KiB

After

Width:  |  Height:  |  Size: 389 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 445 KiB

After

Width:  |  Height:  |  Size: 443 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 434 KiB

After

Width:  |  Height:  |  Size: 438 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 423 KiB

After

Width:  |  Height:  |  Size: 426 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 435 KiB

After

Width:  |  Height:  |  Size: 439 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 383 KiB

After

Width:  |  Height:  |  Size: 384 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 373 KiB

After

Width:  |  Height:  |  Size: 374 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 385 KiB

After

Width:  |  Height:  |  Size: 386 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 277 KiB

After

Width:  |  Height:  |  Size: 276 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 271 KiB

After

Width:  |  Height:  |  Size: 271 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 278 KiB

After

Width:  |  Height:  |  Size: 278 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 438 KiB

After

Width:  |  Height:  |  Size: 438 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 426 KiB

After

Width:  |  Height:  |  Size: 426 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 439 KiB

After

Width:  |  Height:  |  Size: 439 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 383 KiB

After

Width:  |  Height:  |  Size: 388 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 374 KiB

After

Width:  |  Height:  |  Size: 379 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 384 KiB

After

Width:  |  Height:  |  Size: 388 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 362 KiB

After

Width:  |  Height:  |  Size: 362 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 354 KiB

After

Width:  |  Height:  |  Size: 355 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 362 KiB

After

Width:  |  Height:  |  Size: 363 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 193 KiB

After

Width:  |  Height:  |  Size: 193 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 190 KiB

After

Width:  |  Height:  |  Size: 191 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 194 KiB

After

Width:  |  Height:  |  Size: 194 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 402 KiB

After

Width:  |  Height:  |  Size: 405 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 392 KiB

After

Width:  |  Height:  |  Size: 394 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 404 KiB

After

Width:  |  Height:  |  Size: 407 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 400 KiB

After

Width:  |  Height:  |  Size: 402 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 388 KiB

After

Width:  |  Height:  |  Size: 391 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 401 KiB

After

Width:  |  Height:  |  Size: 404 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 216 KiB

After

Width:  |  Height:  |  Size: 216 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 212 KiB

After

Width:  |  Height:  |  Size: 212 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 218 KiB

After

Width:  |  Height:  |  Size: 218 KiB

+4 -4
View File
@@ -11,11 +11,11 @@
| 项 | 位置 | 说明 |
|---|---|---|
| token 单源 | `.superpowers/prototype/tokens.css` | 三主题 `[data-theme=a/b/c]`,已 snapshot 到 `client/lib/core/theme/token_source/tokens.css` |
| token 单源 | `design/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 |
| 原型清单 | `design/prototype/screens/*.html` | 桌面 + `m-*` 移动;viewport 桌面 1280×860 / 移动 390×844 |
| 设计铁律 | `design/prototype/index.html`atoms 注册)+ `tools/check-ds.mjs` 闸 | 颜色只走 token;组件出自已登记 atoms |
| 验收工具 | `~/.claude/skills/design-distill/tools/{shoot-prototype,diff}.mjs` | prototype shoot 已验证三主题可出图 |
### 主题
@@ -206,7 +206,7 @@ AppTokens 目前**仅颜色**。原型还驱动:
> - 关于:旧版 帮助文档/扫码防伪/系统信息 卡删除,构建号并入版本 cell;更新日志走 `/public/release`(与官网时间线同源),接口不可达回退只显当前版本。
**验收法(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/`
1. **保真闸(人工目检)**`node tools/ds-compare.mjs --html design/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`)。

Some files were not shown because too many files have changed in this diff Show More