Files
zhuiguang-ai/scripts/_rebuild-avatars.mjs

114 lines
4.3 KiB
JavaScript
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
#!/usr/bin/env node
// scripts/_rebuild-avatars.mjs(临时脚本,_ 前缀不入镜像)
// 从 DrawLogo 的 10 种风格头像中各取前 10 个,重构追光AI 用户头像库
// - 10 风格 × 10 个 = 100 个 SVG → public/avatars/
// - 重写 public/avatars/manifest.json
// - 重写 src/lib/avatar-library.ts(AVATAR_LIBRARY)
// 用法: node scripts/_rebuild-avatars.mjs
import { readFileSync, writeFileSync, copyFileSync, existsSync } from "fs";
import { resolve, dirname } from "path";
import { fileURLToPath } from "url";
const __dirname = dirname(fileURLToPath(import.meta.url));
const ZG_ROOT = resolve(__dirname, "..");
const DRAW_SRC = resolve("D:/SGP_KF/DrawLogo/output/agent-avatars-png/avatars");
const AVATAR_DIR = resolve(ZG_ROOT, "public/avatars");
const MANIFEST_PATH = resolve(AVATAR_DIR, "manifest.json");
const LIB_TS_PATH = resolve(ZG_ROOT, "src/lib/avatar-library.ts");
// 12 种风格(rings/shapes 渲染杂乱已移除,新增 open-peeps/lorelei/big-smile/croodles)
const STYLES = [
{ id: "bottts", name: "科技机器人" },
{ id: "bottts-neutral", name: "极简机器人" },
{ id: "micah", name: "米迦人物" },
{ id: "pixel-art", name: "像素风" },
{ id: "fun-emoji", name: "趣味表情" },
{ id: "avataaars", name: "阿凡达" },
{ id: "notionists", name: "Notion 风" },
{ id: "adventurer", name: "冒险家" },
{ id: "open-peeps", name: "简笔人物" },
{ id: "lorelei", name: "人物插画" },
{ id: "big-smile", name: "笑脸人物" },
{ id: "croodles", name: "涂鸦人物" },
];
const PER_STYLE = 10; // 每种风格 10 个
// 读取 DrawLogo meta.json 获取每种风格渐变颜色
const metaColors = {};
try {
const meta = JSON.parse(readFileSync(resolve(DRAW_SRC, "meta.json"), "utf8"));
for (const s of meta.styles || []) metaColors[s.id] = [s.c1, s.c2];
} catch {
console.log("⚠️ 未读到 meta.json,颜色使用默认值");
}
const avatars = [];
for (const st of STYLES) {
for (let i = 1; i <= PER_STYLE; i++) {
const n = String(i).padStart(3, "0");
const srcFile = resolve(DRAW_SRC, st.id, `${st.id}-${n}.svg`);
if (!existsSync(srcFile)) {
console.log(`❌ 缺少源文件: ${srcFile}`);
process.exit(1);
}
const id = `${st.id}_${n}`;
const destFile = resolve(AVATAR_DIR, `${id}.svg`);
copyFileSync(srcFile, destFile);
// Next.js image-optimizer 按 magic bytes 识别类型,SVG 必须以 <?xml 开头才被识别为有效图片
// (否则 /_next/image 返回 400,页面图片空白)
const raw = readFileSync(destFile, "utf8").replace(/^\uFEFF/, "");
if (!raw.trimStart().startsWith("<?xml")) {
writeFileSync(destFile, `<?xml version="1.0" encoding="UTF-8"?>\n${raw}`);
}
avatars.push({
id,
theme: st.id,
url: `/avatars/${id}.svg`,
colors: metaColors[st.id] || ["#334155", "#64748b"],
shape: "circle",
});
}
}
if (avatars.length !== STYLES.length * PER_STYLE) {
console.log(`❌ 期望 ${STYLES.length * PER_STYLE} 个,实际 ${avatars.length} 个`);
process.exit(1);
}
// —— manifest.json ——
const manifest = {
generatedAt: new Date().toISOString(),
total: avatars.length,
categories: {},
themes: {},
avatars,
};
for (const st of STYLES) {
const count = avatars.filter((a) => a.theme === st.id).length;
manifest.categories[st.id] = count;
manifest.themes[st.id] = count;
}
writeFileSync(MANIFEST_PATH, JSON.stringify(manifest, null, 2), "utf8");
// —— src/lib/avatar-library.ts ——
const idSet = avatars.map((a) => `"${a.id}"`);
const libLines = [
"// 头像库100个头像ID列表",
"// 由 scripts/_rebuild-avatars.mjs 生成(DrawLogo 10 风格 × 10)",
`// 自动生成时间: ${new Date().toISOString().slice(0, 10)}`,
"",
"export const AVATAR_LIBRARY = [",
];
for (const st of STYLES) {
const group = idSet.filter((id) => id.startsWith(`"${st.id}_`));
libLines.push(` // === ${st.name} (${group.length}) ===`);
libLines.push(` ${group.join(",")},`);
}
libLines.push("];");
writeFileSync(LIB_TS_PATH, libLines.join("\n"), "utf8");
console.log(`✅ 完成: ${avatars.length} 个头像 → public/avatars/`);
console.log(` 清单: public/avatars/manifest.json`);
console.log(` 库表: src/lib/avatar-library.ts`);
for (const st of STYLES) console.log(` ${st.id}(${st.name}): ${manifest.categories[st.id]} 个`);