From b89a9d567b36ee56652bc1a8d44fd94792e7e92e Mon Sep 17 00:00:00 2001 From: wangjia <809946525@qq.com> Date: Thu, 25 Jun 2026 11:10:12 +0800 Subject: [PATCH] =?UTF-8?q?build(tools):=20ds-compare.mjs=20=E8=BF=98?= =?UTF-8?q?=E5=8E=9F=E4=BF=9D=E7=9C=9F=E7=9B=AE=E6=A3=80=E7=BC=96=E6=8E=92?= =?UTF-8?q?=20+=20gitignore=20=E5=AF=B9=E6=AF=94=E5=9B=BE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 一键流程:对某屏按 A/B/C 截原型基准 + 与 Flutter golden 用 montage 并排 → design/_compare/_.png 人工目检。封装 design-distill skill 的 shoot-prototype + montage。对比图可重生,已 gitignore。 Co-Authored-By: Claude Opus 4.8 Claude-Session: https://claude.ai/code/session_01TSKEiHsvauyxYUW2itzUXX --- .gitignore | 3 ++ tools/ds-compare.mjs | 70 ++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 73 insertions(+) create mode 100644 tools/ds-compare.mjs diff --git a/.gitignore b/.gitignore index ab6140d..05acde2 100644 --- a/.gitignore +++ b/.gitignore @@ -69,3 +69,6 @@ backend/gencode # brainstorming visual companion .superpowers/ + +# design-distill 保真目检对比图(可重生,见 tools/ds-compare.mjs) +design/_compare/ diff --git a/tools/ds-compare.mjs b/tools/ds-compare.mjs new file mode 100644 index 0000000..1426274 --- /dev/null +++ b/tools/ds-compare.mjs @@ -0,0 +1,70 @@ +#!/usr/bin/env node +/** + * ds-compare.mjs — 还原保真目检编排(原型基准 ↔ Flutter golden 并排) + * + * design-distill 阶段4「保真闸」的项目侧一键流程:对某屏,按 A/B/C 三主题 + * 截原型基准图,再与已生成的 Flutter golden 用 montage 并排,产出对比图供人工目检。 + * 跨渲染器(Chromium↔Skia)不跑严格 pixelmatch;回归靠 Flutter golden 自比(flutter test)。 + * + * 前置:先生成 Flutter golden: + * cd client && flutter test --update-goldens test/golden/_golden_test.dart + * + * 用法(从仓库根运行): + * node tools/ds-compare.mjs --html .superpowers/prototype/screens/inventory.html \ + * --prefix inventory_list [--themes a,b,c] [--width 1280] [--height 860] [--wait-for .app] + * + * 输出:design/_compare/_.png(gitignore,可重生)。 + * 依赖:design-distill skill(shoot-prototype.mjs / montage.mjs),默认 ~/.claude/skills/design-distill,可用 DD_SKILL 覆盖。 + */ +import { parseArgs } from 'node:util'; +import { execFileSync } from 'node:child_process'; +import { mkdirSync, existsSync } from 'node:fs'; +import { homedir } from 'node:os'; +import { join, resolve } from 'node:path'; + +const { values } = parseArgs({ + options: { + html: { type: 'string' }, + prefix: { type: 'string' }, + themes: { type: 'string', default: 'a,b,c' }, + width: { type: 'string', default: '1280' }, + height: { type: 'string', default: '860' }, + 'wait-for': { type: 'string', default: '.app' }, + 'goldens-dir': { type: 'string', default: 'client/test/golden/goldens' }, + help: { type: 'boolean', default: false }, + }, +}); + +if (values.help || !values.html || !values.prefix) { + console.log(`用法: node tools/ds-compare.mjs --html <原型.html> --prefix [--themes a,b,c --width 1280 --height 860 --wait-for .app]`); + process.exit(values.help ? 0 : 1); +} + +const SKILL = process.env.DD_SKILL || join(homedir(), '.claude/skills/design-distill'); +const shoot = join(SKILL, 'tools/shoot-prototype.mjs'); +const montage = join(SKILL, 'tools/montage.mjs'); +for (const t of [shoot, montage]) { + if (!existsSync(t)) { console.error(`[ds-compare] 找不到 skill 工具: ${t}(设 DD_SKILL 覆盖)`); process.exit(2); } +} + +const outDir = 'design/_compare'; +mkdirSync(outDir, { recursive: true }); +const themes = values.themes.split(',').map((s) => s.trim()).filter(Boolean); + +for (const theme of themes) { + const base = join(outDir, `${values.prefix}_proto_${theme}.png`); + const golden = resolve(values['goldens-dir'], `${values.prefix}_${theme}.png`); + const out = join(outDir, `${values.prefix}_${theme}.png`); + + execFileSync('node', [shoot, values.html, base, + '--width', values.width, '--height', values.height, + '--theme', theme, '--lang', 'zh', '--wait-for', values['wait-for']], + { stdio: 'inherit' }); + + if (!existsSync(golden)) { + console.error(`[ds-compare] ⚠ 缺 Flutter golden: ${golden} —— 先跑 flutter test --update-goldens。跳过 ${theme} 的并排。`); + continue; + } + execFileSync('node', [montage, out, base, golden, '--dir', 'v'], { stdio: 'inherit' }); + console.log(`[ds-compare] ✅ ${theme}: ${out}(上=原型 下=Flutter,人工目检)`); +}