/** * 🎯 简洁科技感头像 PNG —— 从资源库直接挑 10 个 lucide 线性图标 * 10 个图标:bot / brain-circuit / cpu / sparkles / satellite / radar / * circuit-board / atom / terminal / rocket * 统一深蓝渐变圆底 + 白色线性图标 + 亮蓝细环,Chrome headless 导出 1024×1024 PNG。 * * 用法:node scripts/gen-icon-avatars-png.js */ 'use strict'; const fs = require('fs'); const path = require('path'); const vm = require('vm'); const { execFileSync } = require('child_process'); const ROOT = path.resolve(__dirname, '..'); const OUT_DIR = path.join(ROOT, 'output', 'agent-avatars-png'); const TMP_DIR = path.join(ROOT, 'output', '.tmp-icons'); const CHROME = 'C:\\Program Files\\Google\\Chrome\\Application\\chrome.exe'; // —— 1. 加载资源库 lucide 源 —— global.window = global; const lucideFile = path.join(ROOT, 'js', 'data', 'sources', 'lucide.js'); vm.runInThisContext(fs.readFileSync(lucideFile, 'utf8'), { filename: lucideFile }); const lucideIcons = window['HGB_Source_lucide'].icons; // —— 2. 挑选 10 个科技感图标(按名称匹配,保证存在)—— const PICK = ['bot', 'brain-circuit', 'cpu', 'sparkles', 'satellite', 'radar', 'circuit-board', 'atom', 'terminal', 'rocket']; const picked = PICK.map(name => { const icon = lucideIcons.find(x => x.name === name); if (!icon) { console.error('❌ 资源库未找到 lucide:' + name); process.exit(1); } return { id: icon.id, name, body: icon.svg }; }); const BG_FROM = '#0b1220', BG_TO = '#16294a'; const RING = '#3b82f6'; const S = 24; // lucide 画布 24 const ZOOM = 20; // 放大到 480px function buildHtml(body) { return `
`; } // —— 3. 导出 PNG —— fs.mkdirSync(OUT_DIR, { recursive: true }); fs.mkdirSync(TMP_DIR, { recursive: true }); picked.forEach((p, i) => { const idx = String(i + 1).padStart(2, '0'); const htmlFile = path.join(TMP_DIR, `avatar-${idx}.html`); const pngFile = path.join(OUT_DIR, `agent-${idx}.png`); fs.writeFileSync(htmlFile, buildHtml(p.body), 'utf8'); try { execFileSync(CHROME, [ '--headless=new', '--disable-gpu', '--hide-scrollbars', '--force-device-scale-factor=1', '--default-background-color=00000000', '--window-size=1024,1024', '--virtual-time-budget=1000', `--screenshot=${pngFile}`, 'file:///' + htmlFile.replace(/\\/g, '/') ], { stdio: 'pipe' }); console.log(`✅ agent-${idx}.png ← lucide:${p.name}`); } catch (e) { console.error(`❌ agent-${idx}.png 失败:`, e.message.split('\n')[0]); } }); fs.rmSync(TMP_DIR, { recursive: true, force: true }); console.log('\n🎉 完成 → output/agent-avatars-png/');