Files
wangjia 1340b477a7 feat(client): 字体可注入 + 启用 golden 视觉回归闸
- pangolin_theme: PangolinFonts 加 useBundled 开关 + sora/manrope/jetBrainsMono/
  manropeTextTheme 封装(生产走 google_fonts / 测试走 bundled family);
  PangolinText 与 _build 改调封装,移除散落的 GoogleFonts 直接调用
- test/flutter_test_config.dart: 全测试前置,FontLoader 注册 test/fonts 真实
  Sora/Manrope/JetBrainsMono + Lucide 图标字体,置 useBundled=true
- 启用 test/golden(去 @Skip):连接键三态+推荐卡+额度卡×明暗 12 基准图
- tool/visual-diff.md: 标注 golden 严格闸已落地

测试: flutter test 76 通过(原 64+1skip → 76 无 skip), analyze 0 error

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-16 11:36:50 +08:00

2.9 KiB
Raw Permalink Blame History

视觉 diff 工作流(pangolin 客户端 ↔ design/ui_kits 原型)

design-distill skill 的截图 diff 工具,把 Flutter 实现与 design/ui_kits/{desktop,tablet,mobile} React 原型对照。

工具

  • 原型截图:~/.claude/skills/design-distill/tools/shoot-prototype.mjs
  • 像素 diff~/.claude/skills/design-distill/tools/diff.mjs

原型基准(已验证可用)

从项目根运行(脚本自动起临时 http server,让 Babel 原型能 fetch jsx):

SHOOT=~/.claude/skills/design-distill/tools/shoot-prototype.mjs
# desktop 连接页 明/暗(920×600 内容,截外层 sand 画布给点余量)
node $SHOOT design/ui_kits/desktop/index.html shots/desktop_connect_light.png \
  --width 1000 --height 720 --theme light --lang zh --wait-for "#root > *"
node $SHOOT design/ui_kits/desktop/index.html shots/desktop_connect_dark.png \
  --width 1000 --height 720 --theme dark  --lang zh --wait-for "#root > *"

原型是 SPA,默认显示连接页。截其它页需给 shoot-prototype 加 --click <navSelector>(待补)。

diff

node ~/.claude/skills/design-distill/tools/diff.mjs <baseline.png> <impl.png> <diff.png> --threshold 0.05

实现侧截图:两条路径与现状

A. Flutter golden(已启用 CI 严格回归闸)

flutter test --update-goldens test/goldenRepaintBoundary,无 chrome/窗口问题,入 CI。 字体方案(已落地):PangolinFonts.useBundled 开关 + test/flutter_test_config.dartFontLoader 注册 test/fonts/ 真实 Sora/Manrope/JetBrainsMono + Lucide 图标字体,测试态绕过 google_fonts。

  • 改组件视觉后:flutter test test/golden 失败即回归;确认是预期变更则 --update-goldens 重生成基准。
  • 现覆盖:连接键三态 + 推荐卡 + 额度卡 × 明暗(test/golden/components_golden_test.dart)。
  • 注:CJK 文案用 fallbackNoto Sans SC 未打包,体积大),基准自洽不影响回归检测;新增屏/组件按此模式扩展。

B. screencapture 真实 app(已可截,但受限)

真实渲染、字体真实,但:macOS 原生标题栏(红绿灯) vs 原型自绘 chrome 结构不同;窗口精确定位需「辅助功能」权限。 用途:作为人工视觉对照(生成 diff 图定位结构偏差),非严格像素闸。

C. iOS 模拟器(最干净的全屏,未接)

xcrun simctl io booted screenshot 截模拟器无桌面 chrome、字体真实,适合 mobile/tablet。导航多页仍需 integration_test 驱动。

建议

  • 严格回归闸 → 走 A,先做 PangolinText 字体可注入(一次性小重构),启用 golden。
  • 对照设计原型 → 原型基准(本文档)+ A 的 golden 截图,用 diff.mjs 比对。
  • desktop 因 chrome 差异,像素级 100% 对齐不是目标;以布局/间距/颜色结构一致为验收口径。