17 KiB
A01 分层 PSD 与正式 PNG 资产实施计划
执行要求: 只允许在当前会话内使用
superpowers:executing-plans逐任务执行。用户明确禁止子代理、worktree、git add、commit、push、reset、checkout和上传,因此本计划不包含这些动作;每个任务以测试输出和用户视觉确认作为检查点。
目标: 使用本机 Adobe Photoshop 2021 建立 A01 真正分层的 PSD,并从同一 PSD 导出可直接投入 uni-app 的干净 PNG 资产与密码/验证码代表图。
架构: a01-psd-manifest.json 是 PSD 图层、坐标、导出尺寸和文件路径的唯一机器可读所有者;PowerShell 负责校验环境并调用 Photoshop COM,ExtendScript 负责建立 PSD、切换状态和导出。ImageGen 只逐项生成缺少的原始美术层,所有候选先进入设计候选目录,经检查和用户确认后才进入 PSD 与正式资产目录。
技术栈: Windows PowerShell、Adobe Photoshop 2021 COM、ExtendScript JSX、PNG/PSD、ImageGen、uni-app 现有 PowerShell 合同测试。
全局约束
- 当前只处理 A01 分层 PSD 和 PNG 资产,不修改
pages/auth/a01-entry.vue,不进行接口对接。 - 不使用 Figma,不把整张效果图作为页面资产,不从扁平图硬裁被遮挡的脏素材。
- PSD 工作画布为
1236 × 2745,对应412 × 915的三倍密度基准。 brand-seal唯一来源为static/assets/foundation/transparent/brand-seal.png。- 宗祠背景不得生成空牌匾、替代牌匾或新 Logo 底座;现有
brand-seal.png直接作为独立图层叠放在宗祠中央。 - 密码锁唯一复用来源为
static/assets/modules/auth/transparent/a01-icon-lock-v1.png。 - 闭眼图标必须保留中心瞳孔;短信验证码图标必须是消息气泡加且仅加三个点。
- 密码和验证码为独立图层组,共用背景、卷轴、品牌和按钮资产。
- 所有生成资产先写入
docs/design/assets/a01-vnext/candidates/,不得覆盖现有候选或正式文件。 - Photoshop 自动化不得保存、关闭或覆盖用户原先打开的文档,只处理脚本自己创建或打开的临时文档。
- 没有 PSD 图层复核、PNG Alpha 检查、412 × 915 代表图和用户确认,不得宣称资产完成。
文件边界
新建:
docs/design/assets/a01-vnext/source/a01-psd-manifest.json:图层、组、位置、状态和导出规格的唯一机器可读所有者。docs/design/assets/a01-vnext/source/A01-layered-source-v1.psd:最终分层源文件。scripts/photoshop/a01-build-layered-psd.jsx:按清单建立 PSD、组和图层。scripts/photoshop/a01-export-layered-assets.jsx:从 PSD 导出 PNG 与四状态代表图。scripts/build-a01-layered-psd.ps1:验证环境和路径后调用构建 JSX。scripts/export-a01-layered-assets.ps1:调用导出 JSX 并校验输出。tests/a01-layered-psd-contract.ps1:审计清单、脚本、PSD 和 PNG 契约。docs/design/assets/a01-vnext/review/:透明检查图、联系表和代表图候选。
仅在资产通过用户确认后修改:
docs/design/A01_启动登录引导_设计记录.mddocs/design/P00_页面结构与资产清单.mddocs/交接记录.md
本计划禁止修改:
pages/auth/a01-entry.vuepages.json- A01 之外的页面、测试和资产
任务 1:建立 PSD 资产契约测试
文件:
- 新建:
tests/a01-layered-psd-contract.ps1 - 读取:
docs/superpowers/specs/2026-07-15-a01-layered-psd-assets-design.md
接口: 缺少文件或契约时抛出明确错误;全部满足时输出 A01-LAYERED-PSD-CONTRACT PASS。
- 步骤 1:编写失败测试
测试至少包含以下可执行断言:
$ErrorActionPreference = 'Stop'
$root = Split-Path -Parent $PSScriptRoot
$requiredFiles = @(
'docs/design/assets/a01-vnext/source/a01-psd-manifest.json',
'scripts/build-a01-layered-psd.ps1',
'scripts/export-a01-layered-assets.ps1',
'scripts/photoshop/a01-build-layered-psd.jsx',
'scripts/photoshop/a01-export-layered-assets.jsx'
)
foreach ($relative in $requiredFiles) {
if (-not (Test-Path -LiteralPath (Join-Path $root $relative))) {
throw "Missing layered PSD contract file: $relative"
}
}
$manifestPath = Join-Path $root $requiredFiles[0]
$manifest = Get-Content -Raw -Encoding UTF8 -LiteralPath $manifestPath | ConvertFrom-Json
if ($manifest.canvas.width -ne 1236 -or $manifest.canvas.height -ne 2745) {
throw 'PSD canvas must be 1236x2745.'
}
foreach ($group in @('00-参考','10-背景','20-卷轴','30-品牌与标题装饰','40-公共控件皮肤','50-密码登录','60-验证码登录','70-内容与标注')) {
if ($manifest.groups.name -notcontains $group) { throw "Missing PSD group: $group" }
}
foreach ($state in @('password-hidden','password-visible','sms-default','sms-countdown')) {
if ($manifest.states.name -notcontains $state) { throw "Missing PSD state: $state" }
}
Write-Output 'A01-LAYERED-PSD-CONTRACT PASS'
- 步骤 2:运行测试并确认按预期失败
powershell.exe -NoProfile -ExecutionPolicy Bypass -File tests/a01-layered-psd-contract.ps1
预期:失败并显示 Missing layered PSD contract file。
- 步骤 3:观察并保留工作区状态
git status --short
预期:只记录输出,不清理、暂存或提交任何文件。
任务 2:建立清单和 Photoshop 自动化空壳
文件:
- 新建:
docs/design/assets/a01-vnext/source/a01-psd-manifest.json - 新建:
scripts/build-a01-layered-psd.ps1 - 新建:
scripts/export-a01-layered-assets.ps1 - 新建:
scripts/photoshop/a01-build-layered-psd.jsx - 新建:
scripts/photoshop/a01-export-layered-assets.jsx - 测试:
tests/a01-layered-psd-contract.ps1
接口:
-
清单提供
canvas、groups、layers、states、exports。 -
build-a01-layered-psd.ps1 -ManifestPath <path> -OutputPath <path>使用Photoshop.Application.150。 -
export-a01-layered-assets.ps1 -ManifestPath <path> -PsdPath <path>使用同一 COM 接口。 -
JSX 从
JIAPU_A01_ROOT、JIAPU_A01_MANIFEST、JIAPU_A01_PSD读取路径,不硬编码用户名。 -
步骤 1:创建最小清单
{
"schemaVersion": 1,
"canvas": { "width": 1236, "height": 2745, "logicalWidth": 412, "logicalHeight": 915, "scale": 3 },
"groups": [
{ "name": "00-参考", "visible": false },
{ "name": "10-背景", "visible": true },
{ "name": "20-卷轴", "visible": true },
{ "name": "30-品牌与标题装饰", "visible": true },
{ "name": "40-公共控件皮肤", "visible": true },
{ "name": "50-密码登录", "visible": true },
{ "name": "60-验证码登录", "visible": false },
{ "name": "70-内容与标注", "visible": true }
],
"layers": [],
"states": [
{ "name": "password-hidden", "show": ["50-密码登录"], "hide": ["60-验证码登录"] },
{ "name": "password-visible", "show": ["50-密码登录"], "hide": ["60-验证码登录"] },
{ "name": "sms-default", "show": ["60-验证码登录"], "hide": ["50-密码登录"] },
{ "name": "sms-countdown", "show": ["60-验证码登录"], "hide": ["50-密码登录"] }
],
"exports": []
}
- 步骤 2:创建 PowerShell COM 包装
核心调用固定为:
$app = New-Object -ComObject 'Photoshop.Application.150'
$env:JIAPU_A01_ROOT = $root
$env:JIAPU_A01_MANIFEST = $resolvedManifest
$env:JIAPU_A01_PSD = $resolvedOutput
$jsx = (Resolve-Path -LiteralPath (Join-Path $root 'scripts/photoshop/a01-build-layered-psd.jsx')).Path
$escaped = $jsx.Replace('\', '\\')
$app.DoJavaScript("$.evalFile(new File('$escaped'));", @(), 1)
调用前验证 Photoshop 正在运行、输入输出位于项目根目录,并拒绝覆盖不符合 A01-layered-source-v*.psd 的文件。
- 步骤 3:创建 JSX 空壳构建器
#target photoshop
app.displayDialogs = DialogModes.NO;
var created = null;
try {
var manifestFile = File($.getenv('JIAPU_A01_MANIFEST'));
var psdFile = File($.getenv('JIAPU_A01_PSD'));
manifestFile.encoding = 'UTF8';
manifestFile.open('r');
var manifest = eval('(' + manifestFile.read() + ')');
manifestFile.close();
created = app.documents.add(manifest.canvas.width, manifest.canvas.height, 72, 'JIAPU_A01_SCRIPT_SOURCE', NewDocumentMode.RGB, DocumentFill.TRANSPARENT);
for (var i = 0; i < manifest.groups.length; i++) {
var group = created.layerSets.add();
group.name = manifest.groups[i].name;
group.visible = manifest.groups[i].visible;
}
var options = new PhotoshopSaveOptions();
options.layers = true;
created.saveAs(psdFile, options, true, Extension.LOWERCASE);
created.close(SaveOptions.DONOTSAVECHANGES);
created = null;
} catch (error) {
if (created) { created.close(SaveOptions.DONOTSAVECHANGES); }
throw error;
}
- 步骤 4:运行契约测试
powershell.exe -NoProfile -ExecutionPolicy Bypass -File tests/a01-layered-psd-contract.ps1
预期:A01-LAYERED-PSD-CONTRACT PASS。
- 步骤 5:运行空壳 PSD 冒烟检查
powershell.exe -NoProfile -ExecutionPolicy Bypass -File scripts/build-a01-layered-psd.ps1
预期:生成 docs/design/assets/a01-vnext/source/A01-layered-source-v1.psd,Photoshop 中包含八个命名组;脚本执行前已打开的用户文档未被保存或关闭。
任务 3:制作三类母图并由 Photoshop 拆出干净图层
文件:
- 新建候选:
docs/design/assets/a01-vnext/candidates/下的版本化 PNG - 修改:
docs/design/assets/a01-vnext/source/a01-psd-manifest.json - 新建检查图:
docs/design/assets/a01-vnext/review/
接口: ImageGen 只生成完整无字卷轴、无字按钮与装饰板、四枚功能图标板三类母图;Photoshop 将母图拆成每个只承载一个清单图层的 PNG。每个 layers 项包含 name、group、source、x、y、width、height、visible、exportName、alpha。
- 步骤 1:制作宗祠背景候选
使用用户已认可的宗祠母图,不再重新生成。保留 ImageGen 原始母图,再由 Photoshop 裁剪为 1236 × 510 候选;现有 brand-seal.png 后续作为独立图层叠放。
验收:中央为 brand-seal 留出干净视觉空间,但建筑本身不出现空牌匾、替代牌匾或新 Logo 底座;四边没有被截断的文字或控件。
- 步骤 2:生成一张完整无字卷轴母图并拆分
一次生成完整无字卷轴母图,使用可清除的纯色背景。Photoshop 从同一母图拆出顶部卷轴、无字宣纸平铺纹理、左边框、右边框和底部卷轴,不从完整登录页面截图裁切。
验收:在纯黑、纯白和项目暖宣纸底色上检查透明边缘;拼接处没有亮线、断纹或重复阴影。
- 步骤 3:生成一张无字按钮与装饰母图并拆分
主按钮先形成无字完整皮肤,再由 Photoshop 分出左端、可横向延展中段和右端;标题云纹、分隔纹样和四角回纹分别独立。
验收:按钮三段重新拼接后与完整皮肤一致;所有纹样不包含文字、Logo 或不可复用背景。
- 步骤 4:生成一张四图标母板并拆分
在同一高分辨率纯色背景母板中生成彼此完全分离的手机、睁眼、保留瞳孔的闭眼、短信气泡三点图标,再由 Photoshop 分别导出;密码锁继续引用 a01-icon-lock-v1.png,Logo 继续引用 brand-seal.png。微信标志不由 ImageGen 重绘,继续使用具有来源记录的项目资产,只重新制作其容器皮肤。
验收:目标显示尺寸下仍清楚;短信气泡只有三个点;闭眼中心瞳孔可见。
- 步骤 5:每类输出一张检查联系表并等待确认
联系表包含原尺寸、白底、黑底和页面底色预览。未收到用户确认前,不把该类候选写入正式导出清单,也不修改 A01 页面。
任务 4:组装真实 PSD
文件:
- 修改:
docs/design/assets/a01-vnext/source/a01-psd-manifest.json - 修改:
scripts/photoshop/a01-build-layered-psd.jsx - 生成:
docs/design/assets/a01-vnext/source/A01-layered-source-v1.psd - 测试:
tests/a01-layered-psd-contract.ps1
接口: JSX 读取 layers,打开 PNG,复制到目标组并设置名称、位置和可见性。目标层名与 exportName 一一对应;每次从清单重建,不在旧 PSD 上堆叠。
- 步骤 1:扩展失败测试
验证每个源文件存在,坐标和尺寸为整数,源路径位于工作区,exportName 唯一,且可导出层属于 10 至 60 的合法组。
- 步骤 2:先运行测试确认不完整清单失败
powershell.exe -NoProfile -ExecutionPolicy Bypass -File tests/a01-layered-psd-contract.ps1
预期:报告第一项缺失或重复的图层契约。
- 步骤 3:实现 PNG 导入与精确定位
JSX 只复制脚本打开的源 PNG 合并像素层,复制后立即关闭源文档且不保存;位置按 x × 3、y × 3 和清单目标尺寸设置,不手工拖动猜测。
- 步骤 4:重建并复核 PSD
powershell.exe -NoProfile -ExecutionPolicy Bypass -File scripts/build-a01-layered-psd.ps1
预期:八个组顺序正确,密码和验证码可单独显示,公共图层只有一份,参考图默认隐藏。
- 步骤 5:确认用户原文档未受影响
检查 Photoshop:脚本运行前用户已打开文档的数量、名称和未保存状态保持不变;脚本临时文档已关闭。
任务 5:从 PSD 导出 PNG 与四状态代表图
文件:
- 修改:
scripts/photoshop/a01-export-layered-assets.jsx - 生成候选:
docs/design/assets/a01-vnext/exports/v1/ - 生成联系表:
docs/design/assets/a01-vnext/review/A01-layered-states-v1-contact-sheet.png - 测试:
tests/a01-layered-psd-contract.ps1
接口: exports 定义来源层、裁切矩形、尺寸、Alpha 和文件名;四状态固定为 password-hidden、password-visible、sms-default、sms-countdown。
- 步骤 1:添加导出失败测试
验证每个 exports.path 存在、PNG 文件头正确、像素尺寸与清单一致;透明资产四角 Alpha 为 0,不透明资产四角 Alpha 为 255。未执行导出时测试必须失败。
- 步骤 2:实现独立图层导出
JSX 打开 PSD 后记录原可见性,只显示目标层或组,按清单矩形复制到新的透明临时文档并保存 PNG;完成后关闭脚本打开的 PSD 副本且不写回可见性变化。
- 步骤 3:实现四状态代表图和联系表
按清单切换密码/验证码组以及眼睛、倒计时等状态专用层,分别导出 412 × 915 预览,再组合为一张两行两列联系表。代表图只进入 review,页面不得引用。
- 步骤 4:运行导出验证
powershell.exe -NoProfile -ExecutionPolicy Bypass -File scripts/export-a01-layered-assets.ps1
powershell.exe -NoProfile -ExecutionPolicy Bypass -File tests/a01-layered-psd-contract.ps1
git diff --check
预期:导出成功,合同输出 A01-LAYERED-PSD-CONTRACT PASS,无新增空白错误。
- 步骤 5:只展示一张联系表并等待用户确认
确认宗祠、卷轴、按钮、图标、密码/验证码状态和公共区域。用户未明确通过前,导出仍是候选,不复制到 static/assets,不修改页面。
任务 6:冻结资产证据并停在页面实施门禁前
文件:
- 修改:
docs/design/A01_启动登录引导_设计记录.md - 修改:
docs/design/P00_页面结构与资产清单.md - 修改:
docs/交接记录.md - 保留:
docs/design/assets/a01-vnext/source/A01-layered-source-v1.psd - 保留:
docs/design/assets/a01-vnext/exports/v1/
接口: A01 设计记录拥有用户视觉决定;P00 拥有正式资产路径、尺寸、Alpha 和引用状态;交接记录只保存真实停点。
- 步骤 1:记录文件证据
Get-FileHash -Algorithm SHA256 docs/design/assets/a01-vnext/source/A01-layered-source-v1.psd
Get-ChildItem docs/design/assets/a01-vnext/exports/v1 -File | Get-FileHash -Algorithm SHA256
把 PSD 和已确认 PNG 的哈希、尺寸、Alpha、用途写入 A01 设计记录和 P00。
- 步骤 2:更新真实状态
只能写“PSD 与 PNG 资产已获用户确认,A01 页面实现尚未开始”或事实对应的更早状态;不得写 A01 已验收、已冻结或页面已完成。
- 步骤 3:运行最终验证
powershell.exe -NoProfile -ExecutionPolicy Bypass -File tests/a01-layered-psd-contract.ps1
powershell.exe -NoProfile -ExecutionPolicy Bypass -File tests/a01-a02-ui-contract.ps1
git diff --check
git status --short
git status --short --ignored
预期:PSD 合同通过;既有 A01/A02 合同保持当前事实,若因页面尚未切换而失败则如实记录、不改页面;所有既有修改和未跟踪文件继续保留。
- 步骤 4:停止
只有用户再次确认进入页面落地,才新建独立的 A01 image-to-code/TDD 实施计划;不得在本计划中顺手修改页面。