extract-assets.mjs 2.2 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546
  1. // 导出蓝湖可下载资产到设计归档,并生成索引(命名切图 + 图片填充)
  2. import { readFileSync, writeFileSync, readdirSync, mkdirSync } from 'node:fs'
  3. import { join } from 'node:path'
  4. const raw = '.scratch/lanhu-cockpit-asset-replacement/research/raw'
  5. const outDir = '.scratch/lanhu-cockpit-asset-replacement/design-archive'
  6. mkdirSync(outDir, { recursive: true })
  7. const files = readdirSync(raw).filter((f) => /^desktop-\d+\.json$/.test(f)).sort()
  8. const exportLayers = []
  9. const imageFills = []
  10. for (const file of files) {
  11. const j = JSON.parse(readFileSync(join(raw, file), 'utf8'))
  12. const ab = j.artboard
  13. function walk(node, path) {
  14. const p = path ? `${path}/${node.name}` : node.name
  15. if (node.hasExportImage) {
  16. exportLayers.push({ artboard: ab.name, path: p, w: Math.round(node.frame?.width ?? 0), h: Math.round(node.frame?.height ?? 0), type: node.type })
  17. }
  18. for (const f of node.style?.fills || []) {
  19. const url = f.ddsImage?.imageUrl || f.image?.imageUrl || f.imageUrl
  20. if (f.type === 'image' && url) {
  21. imageFills.push({ artboard: ab.name, path: p, w: Math.round(node.frame?.width ?? 0), h: Math.round(node.frame?.height ?? 0), url })
  22. }
  23. }
  24. for (const ch of node.layers || []) walk(ch, p)
  25. }
  26. for (const l of ab.layers || []) walk(l, '')
  27. }
  28. // 项目级 assets(PNG/SVG 成对)—— 与 25 个 hasExportImage 图层一一对应
  29. const assetUrls = []
  30. for (const file of files) {
  31. const j = JSON.parse(readFileSync(join(raw, file), 'utf8'))
  32. for (const u of j.assets || []) assetUrls.push({ artboard: j.artboard.name, url: u })
  33. }
  34. const index = { exportLayers, imageFills, assetUrls }
  35. writeFileSync(join(raw, 'asset-index.json'), JSON.stringify(index, null, 1))
  36. console.log('export-marked layers:', exportLayers.length)
  37. for (const e of exportLayers) console.log(` ${e.artboard} | ${e.path} | ${e.w}x${e.h} | ${e.type}`)
  38. console.log('\nimage fills:', imageFills.length, '| unique urls:', new Set(imageFills.map((i) => i.url)).size)
  39. for (const i of imageFills) console.log(` ${i.artboard} | ${i.path} | ${i.w}x${i.h}`)
  40. console.log('\nasset files:', assetUrls.length, '| unique:', new Set(assetUrls.map((a) => a.url)).size)