114 lines
5.0 KiB
JavaScript
114 lines
5.0 KiB
JavaScript
// 临时脚本:从候选池选 100 个生成「画个标」logo 设计稿 HTML
|
||
const fs = require('fs');
|
||
const path = require('path');
|
||
const ROOT = process.cwd();
|
||
const OUT = '_design-test';
|
||
|
||
const cands = JSON.parse(fs.readFileSync(path.join(OUT, 'candidates2.json'), 'utf8'));
|
||
|
||
// 主题配额(共 100)
|
||
const QUOTA = { design: 25, brand: 20, symbol: 18, tech: 12, commerce: 10, misc: 15 };
|
||
// 源优先级:经典线条在前,大库补充
|
||
const SRC_ORDER = ['feather', 'lucide', 'heroicons', 'iconoir', 'tabler', 'bootstrap', 'remix', 'phosphor', 'fluent', 'fluent-mdl2'];
|
||
|
||
// 按主题分组
|
||
const byTheme = {};
|
||
cands.forEach(c => { (byTheme[c.theme] = byTheme[c.theme] || []).push(c); });
|
||
|
||
// 跨源轮选:每主题按源优先级轮流取,配额内
|
||
const picked = [];
|
||
for (const [theme, n] of Object.entries(QUOTA)) {
|
||
const pool = byTheme[theme] || [];
|
||
// 每源分组
|
||
const perSrc = {};
|
||
pool.forEach(c => { (perSrc[c.source] = perSrc[c.source] || []).push(c); });
|
||
const rounds = Math.ceil(n / SRC_ORDER.length);
|
||
let taken = 0;
|
||
for (let r = 0; r < rounds && taken < n; r++) {
|
||
for (const sid of SRC_ORDER) {
|
||
const arr = perSrc[sid];
|
||
if (arr && arr.length > r) {
|
||
picked.push(arr[r]);
|
||
taken++;
|
||
if (taken >= n) break;
|
||
}
|
||
}
|
||
}
|
||
// 配额未满则从剩余补
|
||
if (taken < n) {
|
||
const rest = pool.filter(c => !picked.includes(c));
|
||
for (const c of rest) { if (taken >= n) break; picked.push(c); taken++; }
|
||
}
|
||
}
|
||
console.log('选中 ' + picked.length + ' 个');
|
||
const srcStat = {};
|
||
picked.forEach(c => { srcStat[c.source] = (srcStat[c.source] || 0) + 1; });
|
||
console.log('来源分布:' + JSON.stringify(srcStat));
|
||
|
||
// 品牌配色(12 组,深底白图标)
|
||
const PALETTES = [
|
||
['#FF5A5F', '#FF2D55'], ['#FF9500', '#E66A00'], ['#FFD60A', '#E6B800'],
|
||
['#34C759', '#1F9D4F'], ['#00C7BE', '#009B94'], ['#0A84FF', '#0055D4'],
|
||
['#5E5CE6', '#3B36C7'], ['#FF375F', '#D40035'], ['#AF52DE', '#8E2BC7'],
|
||
['#30B0C7', '#1B7F94'], ['#8E8E93', '#48484A'], ['#111111', '#000000']
|
||
];
|
||
// 徽章形状轮换:圆 / 圆角方 / 方
|
||
const SHAPES = ['round', 'squircle', 'square'];
|
||
|
||
let cards = '';
|
||
picked.forEach((c, i) => {
|
||
const [c1, c2] = PALETTES[i % PALETTES.length];
|
||
const shape = SHAPES[i % SHAPES.length];
|
||
const grad = `linear-gradient(135deg, ${c1} 0%, ${c2} 100%)`;
|
||
const chip = `background:${c1};`;
|
||
cards += `
|
||
<div class="card" style="--grad:${grad};">
|
||
<div class="badge ${shape}" style="background:var(--grad);">
|
||
<svg viewBox="0 0 24 24" width="56" height="56" fill="none" stroke="#fff" stroke-width="1.6" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg">${c.svg}</svg>
|
||
</div>
|
||
<div class="name">画个标</div>
|
||
<div class="en">DrawLogo</div>
|
||
<div class="meta">
|
||
<span class="tag" style="${chip}">${c.theme}</span>
|
||
<span class="src" title="${c.source}:${c.id}">${c.source}:${c.id}</span>
|
||
</div>
|
||
<div class="lic">${c.license}${c.licenseNote ? ' · ' + c.licenseNote : ''}</div>
|
||
</div>`;
|
||
});
|
||
|
||
const html = `<!DOCTYPE html>
|
||
<html lang="zh">
|
||
<head>
|
||
<meta charset="UTF-8">
|
||
<title>画个标 · 100 个 LOGO 候选设计稿(外部调取测试)</title>
|
||
<style>
|
||
* { box-sizing: border-box; margin: 0; padding: 0; }
|
||
body { font-family: "PingFang SC", "Microsoft YaHei", sans-serif; background: #0e0e12; color: #eee; padding: 32px; }
|
||
h1 { font-size: 22px; margin-bottom: 4px; }
|
||
.sub { color: #888; font-size: 13px; margin-bottom: 24px; }
|
||
.grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(200px, 1fr)); gap: 16px; }
|
||
.card { background: #1a1a22; border: 1px solid #2a2a35; border-radius: 14px; padding: 18px 14px 14px; display: flex; flex-direction: column; align-items: center; text-align: center; }
|
||
.badge { width: 96px; height: 96px; display: flex; align-items: center; justify-content: center; margin-bottom: 12px; }
|
||
.badge.round { border-radius: 50%; }
|
||
.badge.squircle { border-radius: 26px; }
|
||
.badge.square { border-radius: 6px; }
|
||
.badge svg { display: block; }
|
||
.name { font-size: 18px; font-weight: 700; letter-spacing: 2px; }
|
||
.en { font-size: 11px; color: #777; letter-spacing: 3px; margin-top: 2px; }
|
||
.meta { margin-top: 10px; display: flex; align-items: center; gap: 6px; }
|
||
.tag { color: #fff; font-size: 10px; padding: 2px 8px; border-radius: 20px; }
|
||
.src { font-size: 10px; color: #777; }
|
||
.lic { font-size: 10px; color: #555; margin-top: 6px; }
|
||
</style>
|
||
</head>
|
||
<body>
|
||
<h1>画个标 · 100 个 LOGO 候选设计稿</h1>
|
||
<div class="sub">数据来源:画个标共享图标库(manifest/icons.json)· 指令四「跨项目调取」测试 · 每稿含来源与协议标注</div>
|
||
<div class="grid">${cards}</div>
|
||
</body>
|
||
</html>`;
|
||
|
||
fs.writeFileSync(path.join(OUT, '100-logos.html'), html, 'utf8');
|
||
fs.writeFileSync(path.join(OUT, 'picked.json'), JSON.stringify(picked.map(c => ({ theme: c.theme, source: c.source, id: c.id, name: c.name, license: c.license })), null, 1), 'utf8');
|
||
console.log('✅ 生成 ' + OUT + '/100-logos.html(' + picked.length + ' 稿)');
|