| 1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465 |
- // 下载可下载资产到 design-archive/,生成带 sha256 的索引
- import { readFileSync, writeFileSync, mkdirSync, createWriteStream } from 'node:fs'
- import { createHash } from 'node:crypto'
- import { join } from 'node:path'
- import { Readable } from 'node:stream'
- import { pipeline } from 'node:stream/promises'
- const raw = '.scratch/lanhu-cockpit-asset-replacement/research/raw'
- const outDir = '.scratch/lanhu-cockpit-asset-replacement/design-archive'
- mkdirSync(outDir, { recursive: true })
- const index = JSON.parse(readFileSync(join(raw, 'asset-index.json'), 'utf8'))
- const slug = (s) => s.replace(/[^\w\u4e00-\u9fa5.-]+/g, '_').slice(0, 40)
- const extOf = (u) => {
- const m = /\.([a-z0-9]+)(\?|$)/i.exec(u)
- return m ? m[1].toLowerCase() : 'bin'
- }
- const tasks = []
- // 1) 图片填充(去重 URL,保留首次出现的来源画板)
- const seen = new Map()
- for (const f of index.imageFills) {
- if (!seen.has(f.url)) seen.set(f.url, f)
- }
- for (const [url, f] of seen) {
- tasks.push({ kind: 'image-fill', artboard: f.artboard, layer: f.path, w: f.w, h: f.h, url })
- }
- // 2) 项目级 assets(无名字,按画板顺序编号)
- const perArtboard = new Map()
- for (const a of index.assetUrls) {
- const n = (perArtboard.get(a.artboard) || 0) + 1
- perArtboard.set(a.artboard, n)
- tasks.push({ kind: 'slice', artboard: a.artboard, layer: `slice-${String(n).padStart(2, '0')}`, w: null, h: null, url: a.url })
- }
- const results = []
- for (const t of tasks) {
- const ext = extOf(t.url)
- const hash8 = (t.url.match(/([0-9a-f]{8})[0-9a-f]*\.[a-z0-9]+$/i) || [, 'unknown'])[1]
- const name = `${slug(t.artboard)}__${t.kind}__${slug(t.layer)}__${hash8}.${ext}`
- const dest = join(outDir, name)
- const res = await fetch(t.url)
- if (!res.ok) {
- results.push({ ...t, local: null, error: `HTTP ${res.status}` })
- continue
- }
- await pipeline(Readable.fromWeb(res.body), createWriteStream(dest))
- const buf = readFileSync(dest)
- results.push({
- kind: t.kind,
- artboard: t.artboard,
- layer: t.layer,
- w: t.w,
- h: t.h,
- url: t.url,
- local: name,
- bytes: buf.length,
- sha256: createHash('sha256').update(buf).digest('hex'),
- })
- }
- writeFileSync(join(outDir, 'index.json'), JSON.stringify({ downloadedAt: new Date().toISOString(), count: results.length, files: results }, null, 1))
- console.log('downloaded:', results.filter((r) => !r.error).length, 'of', tasks.length)
- for (const r of results) console.log(` ${r.error ? 'ERR ' + r.error : r.local} | ${r.kind} | ${r.artboard} | ${r.layer} | ${r.bytes ?? ''}`)
|