// 导出蓝湖可下载资产到设计归档,并生成索引(命名切图 + 图片填充) import { readFileSync, writeFileSync, readdirSync, mkdirSync } from 'node:fs' import { join } from 'node:path' const raw = '.scratch/lanhu-cockpit-asset-replacement/research/raw' const outDir = '.scratch/lanhu-cockpit-asset-replacement/design-archive' mkdirSync(outDir, { recursive: true }) const files = readdirSync(raw).filter((f) => /^desktop-\d+\.json$/.test(f)).sort() const exportLayers = [] const imageFills = [] for (const file of files) { const j = JSON.parse(readFileSync(join(raw, file), 'utf8')) const ab = j.artboard function walk(node, path) { const p = path ? `${path}/${node.name}` : node.name if (node.hasExportImage) { exportLayers.push({ artboard: ab.name, path: p, w: Math.round(node.frame?.width ?? 0), h: Math.round(node.frame?.height ?? 0), type: node.type }) } for (const f of node.style?.fills || []) { const url = f.ddsImage?.imageUrl || f.image?.imageUrl || f.imageUrl if (f.type === 'image' && url) { imageFills.push({ artboard: ab.name, path: p, w: Math.round(node.frame?.width ?? 0), h: Math.round(node.frame?.height ?? 0), url }) } } for (const ch of node.layers || []) walk(ch, p) } for (const l of ab.layers || []) walk(l, '') } // 项目级 assets(PNG/SVG 成对)—— 与 25 个 hasExportImage 图层一一对应 const assetUrls = [] for (const file of files) { const j = JSON.parse(readFileSync(join(raw, file), 'utf8')) for (const u of j.assets || []) assetUrls.push({ artboard: j.artboard.name, url: u }) } const index = { exportLayers, imageFills, assetUrls } writeFileSync(join(raw, 'asset-index.json'), JSON.stringify(index, null, 1)) console.log('export-marked layers:', exportLayers.length) for (const e of exportLayers) console.log(` ${e.artboard} | ${e.path} | ${e.w}x${e.h} | ${e.type}`) console.log('\nimage fills:', imageFills.length, '| unique urls:', new Set(imageFills.map((i) => i.url)).size) for (const i of imageFills) console.log(` ${i.artboard} | ${i.path} | ${i.w}x${i.h}`) console.log('\nasset files:', assetUrls.length, '| unique:', new Set(assetUrls.map((a) => a.url)).size)