feat: 首次推送到Gitea - 完整项目代码 + 安全加固 + 知识库
This commit is contained in:
@@ -0,0 +1,113 @@
|
||||
#!/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]} 个`);
|
||||
Reference in New Issue
Block a user