// generate-team-ppt.js const pptxgenjs = require("C:/nvm4w/nodejs/node_modules/pptxgenjs"); // ── 颜色常量 ────────────────────────────────────────────── const C = { accent: "E20074", accentDk: "BE0060", bg: "F7F7FA", bgCard: "FFFFFF", bgHover: "F0F0F5", border: "E0E0EA", text: "1A1A2E", text2: "4A4A6A", text3: "8888AA", green: "00896A", orange: "CC6200", blue: "2A68C8", purple: "5A46B4", red: "C0392B", darkBg: "1A1A2E", }; // ── 辅助函数 ───────────────────────────────────────────── function makeShadow() { return { type: "outer", color: "000000", opacity: 0.08, blur: 6, offset: 2, angle: 45 }; } function topBar(slide) { slide.addShape("rect", { x: 0, y: 0, w: "100%", h: 0.04, fill: { type: "grad", stops: [{ position: 0, color: C.accent }, { position: 100, color: C.accentDk }] }, line: { color: C.accent, width: 0 }, }); } function sectionLabel(slide, text, x, y) { slide.addText(text, { x, y, w: 9, h: 0.25, fontSize: 9, bold: true, color: C.accent, charSpacing: 3, fontFace: "Calibri", }); } function sectionTitle(slide, text, x, y) { slide.addText(text, { x, y, w: 9, h: 0.5, fontSize: 26, bold: true, color: C.text, fontFace: "Calibri", }); } function sectionSub(slide, text, x, y) { slide.addText(text, { x, y, w: 10, h: 0.3, fontSize: 12, color: C.text3, fontFace: "Calibri", }); } function slideNum(slide, n, total) { slide.addText(`${n} / ${total}`, { x: 12, y: 7.1, w: 1.2, h: 0.25, fontSize: 9, color: C.text3, align: "right", fontFace: "Calibri Light", }); } // ── 初始化 PPT ─────────────────────────────────────────── const prs = new pptxgenjs(); prs.layout = "LAYOUT_WIDE"; prs.defineLayout({ name: "LAYOUT_WIDE", width: 13.33, height: 7.5 }); // ════════════════════════════════════════════════════════ // Slide 1 — 封面 // ════════════════════════════════════════════════════════ { const sl = prs.addSlide(); // 浅色背景 sl.addShape("rect", { x: 0, y: 0, w: "100%", h: "100%", fill: { color: C.bg }, line: { color: C.bg, width: 0 }, }); // 左侧品牌色竖栏 3.2" sl.addShape("rect", { x: 0, y: 0, w: 3.2, h: 7.5, fill: { type: "grad", stops: [{ position: 0, color: "B0005A" }, { position: 100, color: C.accent }] }, line: { color: C.accent, width: 0 }, }); // 左栏:英文副标题 sl.addText("EMS & EHS Compliance\nIntelligence Hub", { x: 0.3, y: 1.8, w: 2.6, h: 0.7, fontSize: 11, italic: true, color: "FFFFFF", fontFace: "Calibri Light", align: "center", }); // 左栏:项目大标题 sl.addText("AI + 合规\n智能中枢", { x: 0.2, y: 2.6, w: 2.8, h: 1.2, fontSize: 24, bold: true, color: "FFFFFF", fontFace: "Calibri", align: "center", }); // 左栏:分隔线 sl.addShape("rect", { x: 0.6, y: 3.9, w: 2.0, h: 0.02, fill: { color: "FFFFFF", transparency: 60 }, line: { color: "FFFFFF", width: 0 }, }); // 左栏:团队 + 日期 sl.addText("T-Systems · AI 合规项目组", { x: 0.2, y: 4.0, w: 2.8, h: 0.28, fontSize: 10, color: "FFFFFF", fontFace: "Calibri Light", align: "center", }); sl.addText("2026 年 05 月", { x: 0.2, y: 4.3, w: 2.8, h: 0.28, fontSize: 10, color: "FFFFFF", fontFace: "Calibri Light", align: "center", }); // 右侧:标签 sl.addText("TEAM PROGRESS REPORT", { x: 3.6, y: 1.2, w: 6, h: 0.25, fontSize: 9, bold: true, color: C.accent, charSpacing: 3, fontFace: "Calibri", }); // 右侧:汇报标题 sl.addText("团队阶段性汇报", { x: 3.6, y: 1.5, w: 9, h: 0.65, fontSize: 34, bold: true, color: C.text, fontFace: "Calibri", }); // 右侧:说明文字 sl.addText("基于 Agent 协同的多模块法规合规智能平台\n多团队协作 · 阶段成果汇报 · 分工与规划", { x: 3.6, y: 2.25, w: 9, h: 0.6, fontSize: 12, color: C.text2, fontFace: "Calibri Light", }); // 右侧:3个数字指标卡 const stats = [ { num: "5", label: "功能模块\n已完成/开发中", color: C.accent }, { num: "17+", label: "REST API 接口\n已设计并文档化", color: C.green }, { num: "6+", label: "法规来源\n接入覆盖", color: C.orange }, ]; stats.forEach((s, i) => { const sx = 3.6 + i * 2.8; sl.addShape("rect", { x: sx, y: 3.1, w: 2.5, h: 1.4, fill: { color: C.bgCard }, line: { color: C.border, width: 0.5 }, shadow: makeShadow(), }); sl.addShape("rect", { x: sx, y: 3.1, w: 2.5, h: 0.05, fill: { color: s.color }, line: { color: s.color, width: 0 }, }); sl.addText(s.num, { x: sx + 0.15, y: 3.2, w: 2.2, h: 0.65, fontSize: 40, bold: true, color: s.color, fontFace: "Calibri", }); sl.addText(s.label, { x: sx + 0.15, y: 3.85, w: 2.2, h: 0.55, fontSize: 10, color: C.text3, fontFace: "Calibri Light", }); }); // 底部机密标注 sl.addText("INTERNAL · CONFIDENTIAL", { x: 3.6, y: 7.1, w: 6, h: 0.25, fontSize: 9, color: C.text3, fontFace: "Calibri", }); } // ════════════════════════════════════════════════════════ // Slide 2 — 项目背景 // ════════════════════════════════════════════════════════ { const sl = prs.addSlide(); sl.addShape("rect", { x: 0, y: 0, w: "100%", h: "100%", fill: { color: C.bg }, line: { color: C.bg, width: 0 }, }); topBar(sl); sectionLabel(sl, "项目背景", 0.5, 0.55); sectionTitle(sl, "为什么要做这个系统?", 0.5, 0.85); sectionSub(sl, "汽车行业合规管理三大核心痛点,传统人工方式已无法满足需求", 0.5, 1.4); slideNum(sl, 2, 10); const painPoints = [ { topColor: ["B0005A", "E20074"], icon: "📋", title: "法规碎片化", body: "GB、MIIT、UN-ECE、IATF 16949、ISO 45001、EUR-Lex 等多源法规并存,更新频繁,人工跟踪极易遗漏,合规窗口期短。", }, { topColor: ["C05000", "FF8800"], icon: "⏱", title: "响应周期长", body: "从法规发布到内部解读、影响评估、整改计划,人工流程往往需要数周,无法满足快速迭代的合规要求。", }, { topColor: ["00A080", "00D4AA"], icon: "💼", title: "人工成本高", body: "合规专家大量时间消耗在文档检索、条款比对、报告撰写等重复性工作上,高价值判断时间被严重压缩。", }, ]; painPoints.forEach((p, i) => { const cx = 0.5 + i * 4.22; sl.addShape("rect", { x: cx, y: 1.9, w: 4.0, h: 4.8, fill: { color: C.bgCard }, line: { color: C.border, width: 0.5 }, shadow: makeShadow(), }); sl.addShape("rect", { x: cx, y: 1.9, w: 4.0, h: 0.07, fill: { type: "grad", stops: [{ position: 0, color: p.topColor[0] }, { position: 100, color: p.topColor[1] }] }, line: { color: p.topColor[0], width: 0 }, }); sl.addText(p.icon, { x: cx + 0.25, y: 2.1, w: 0.7, h: 0.6, fontSize: 28, fontFace: "Segoe UI Emoji", }); sl.addText(p.title, { x: cx + 0.25, y: 2.75, w: 3.5, h: 0.4, fontSize: 16, bold: true, color: C.text, fontFace: "Calibri", }); sl.addText(p.body, { x: cx + 0.25, y: 3.25, w: 3.5, h: 2.8, fontSize: 12, color: C.text2, fontFace: "Calibri Light", paraSpaceAfter: 4, lineSpacingMultiple: 1.4, }); }); } // ════════════════════════════════════════════════════════ // Slide 3 — 本阶段工作总览 // ════════════════════════════════════════════════════════ { const sl = prs.addSlide(); sl.addShape("rect", { x: 0, y: 0, w: "100%", h: "100%", fill: { color: C.bg }, line: { color: C.bg, width: 0 }, }); topBar(sl); sectionLabel(sl, "阶段成果", 0.5, 0.55); sectionTitle(sl, "本阶段工作总览", 0.5, 0.85); sectionSub(sl, "5 个功能模块 · 核心 Agent 问答链路全通 · 角色分工一览", 0.5, 1.4); slideNum(sl, 3, 10); const modules = [ { icon: "📡", num: "01", name: "法规智能感知", desc: "六大法规源事件流,影响分级过滤,SSE 流式 AI 影响解读", status: "⟳ 进行中", statusColor: C.orange, role: "前端工程师 / 后端工程师", }, { icon: "📚", num: "02", name: "文档知识库管理", desc: "PDF/Word 入库,5 步 Pipeline 可视化,双引擎 OCR 解析", status: "⟳ 进行中", statusColor: C.orange, role: "后端工程师 / AI 工程师", }, { icon: "🔍", num: "03", name: "合规分析审查", desc: "逐段风险评分,内嵌 Agent 对话,风险聚合仪表盘", status: "⟳ 进行中", statusColor: C.orange, role: "全栈工程师", }, { icon: "💬", num: "04", name: "法规 Agent 对话", desc: "Milvus 向量检索 + LLM 全链路贯通,多轮追问,来源归因", status: "✓ 核心链路已通", statusColor: C.green, role: "AI 工程师 / 后端工程师", }, { icon: "🖥️", num: "05", name: "系统状态监控", desc: "五项基础设施健康检查,17+ API,系统配置总览", status: "✓ 已完成", statusColor: C.green, role: "后端工程师 / 运维", }, ]; modules.forEach((m, i) => { const ry = 1.85 + i * 1.02; sl.addShape("rect", { x: 0.5, y: ry, w: 12.3, h: 0.9, fill: { color: C.bgCard }, line: { color: C.border, width: 0.5 }, shadow: makeShadow(), }); sl.addText(m.icon, { x: 0.7, y: ry + 0.18, w: 0.55, h: 0.55, fontSize: 20, fontFace: "Segoe UI Emoji", }); sl.addText(m.num, { x: 1.3, y: ry + 0.28, w: 0.4, h: 0.28, fontSize: 8, color: C.text3, fontFace: "Calibri", bold: true, }); sl.addText(m.name, { x: 1.7, y: ry + 0.12, w: 2.8, h: 0.3, fontSize: 13, bold: true, color: C.text, fontFace: "Calibri", }); sl.addText(m.desc, { x: 1.7, y: ry + 0.46, w: 5.8, h: 0.28, fontSize: 10, color: C.text2, fontFace: "Calibri Light", }); sl.addText(m.status, { x: 7.7, y: ry + 0.26, w: 2.2, h: 0.28, fontSize: 9, bold: true, color: m.statusColor, fill: { color: m.statusColor, transparency: 88 }, line: { color: m.statusColor, width: 0.5, transparency: 70 }, align: "center", margin: [2, 6, 2, 6], fontFace: "Calibri", }); sl.addText(m.role, { x: 10.1, y: ry + 0.26, w: 2.5, h: 0.28, fontSize: 9, color: C.text3, fontFace: "Calibri Light", align: "right", }); }); } // ════════════════════════════════════════════════════════ // Slide 4 — 核心功能演示 1/2 // ════════════════════════════════════════════════════════ { const sl = prs.addSlide(); sl.addShape("rect", { x: 0, y: 0, w: "100%", h: "100%", fill: { color: C.bg }, line: { color: C.bg, width: 0 }, }); topBar(sl); sectionLabel(sl, "产品演示", 0.5, 0.55); sectionTitle(sl, "核心功能一览(1/2)", 0.5, 0.85); sectionSub(sl, "前 3 个模块已上线,功能可演示", 0.5, 1.4); slideNum(sl, 4, 10); const features = [ { bg: ["FCE8F3", "FCD5E8"], icon: "📡", name: "法规智能感知", tags: [{ t: "高影响", c: C.accent }, { t: "中影响", c: C.orange }, { t: "低影响", c: C.green }], liveBadge: true, desc: "六大法规源实时事件流,影响等级分级过滤,选中事件触发 SSE 流式 AI 影响分析", }, { bg: ["EEF2FD", "DCE8FB"], icon: "📚", name: "文档知识库管理", tags: [{ t: "LOAD", c: C.blue }, { t: "PARSE", c: C.blue }, { t: "EMBED", c: C.blue }, { t: "STORE", c: C.green }], liveBadge: false, desc: "PDF/Word 上传入库,5 步 Pipeline 可视化进度,双引擎解析,文档列表管理", }, { bg: ["FFF5E8", "FDE8CC"], icon: "🔍", name: "合规分析审查", tags: [{ t: "⚠ 高风险", c: C.red }, { t: "✓ 合规", c: C.green }], liveBadge: false, desc: "上传文件逐段风险评分,内嵌 Agent 对话针对具体条款实时问答,风险聚合仪表盘", }, ]; features.forEach((f, i) => { const cx = 0.5 + i * 4.22; sl.addShape("rect", { x: cx, y: 1.85, w: 4.0, h: 5.0, fill: { color: C.bgCard }, line: { color: C.border, width: 0.5 }, shadow: makeShadow(), }); sl.addShape("rect", { x: cx, y: 1.85, w: 4.0, h: 2.0, fill: { type: "grad", stops: [{ position: 0, color: f.bg[0] }, { position: 100, color: f.bg[1] }] }, line: { color: C.border, width: 0 }, }); sl.addText(f.icon, { x: cx + 1.4, y: 2.0, w: 1.2, h: 0.9, fontSize: 32, align: "center", fontFace: "Segoe UI Emoji", }); let tx = cx + 0.15; f.tags.forEach(tag => { const tw = tag.t.length > 4 ? 0.85 : 0.7; sl.addText(tag.t, { x: tx, y: 3.05, w: tw, h: 0.22, fontSize: 8, bold: true, color: tag.c, fill: { color: tag.c, transparency: 88 }, line: { color: tag.c, width: 0.4, transparency: 70 }, align: "center", margin: [2, 4, 2, 4], fontFace: "Calibri", }); tx += tw + 0.05; }); if (f.liveBadge) { sl.addText("LIVE", { x: cx + 3.15, y: 1.95, w: 0.65, h: 0.22, fontSize: 8, bold: true, color: C.green, fill: { color: C.green, transparency: 88 }, line: { color: C.green, width: 0.4, transparency: 70 }, align: "center", margin: [2, 4, 2, 4], fontFace: "Calibri", }); } sl.addText(f.name, { x: cx + 0.15, y: 3.45, w: 3.7, h: 0.35, fontSize: 13, bold: true, color: C.text, fontFace: "Calibri", }); sl.addText(f.desc, { x: cx + 0.15, y: 3.85, w: 3.7, h: 2.7, fontSize: 11, color: C.text2, fontFace: "Calibri Light", lineSpacingMultiple: 1.4, }); }); } // ════════════════════════════════════════════════════════ // Slide 5 — 核心功能演示 2/2 // ════════════════════════════════════════════════════════ { const sl = prs.addSlide(); sl.addShape("rect", { x: 0, y: 0, w: "100%", h: "100%", fill: { color: C.bg }, line: { color: C.bg, width: 0 }, }); topBar(sl); sectionLabel(sl, "产品演示", 0.5, 0.55); sectionTitle(sl, "核心功能一览(2/2)", 0.5, 0.85); sectionSub(sl, "Agent 对话核心链路真实运行(Milvus + LLM)· 监控模块已完成", 0.5, 1.4); slideNum(sl, 5, 10); // 左宽卡 — Agent 对话 (w=8.3) sl.addShape("rect", { x: 0.5, y: 1.85, w: 8.3, h: 5.0, fill: { color: C.bgCard }, line: { color: C.green, width: 1 }, shadow: makeShadow(), }); sl.addShape("rect", { x: 0.5, y: 1.85, w: 8.3, h: 1.8, fill: { type: "grad", stops: [{ position: 0, color: "E8F5EF" }, { position: 100, color: "D0EDE2" }] }, line: { color: C.border, width: 0 }, }); sl.addText("💬", { x: 0.8, y: 1.95, w: 0.8, h: 0.7, fontSize: 26, fontFace: "Segoe UI Emoji", }); sl.addText('"GB 18384 对我们的 BMS 设计有什么影响?" → Agent 检索 Milvus → 流式回答 + 来源引用', { x: 0.8, y: 2.78, w: 5.7, h: 0.5, fontSize: 10, color: C.green, fill: { color: C.green, transparency: 90 }, line: { color: C.green, width: 0.5, transparency: 70 }, margin: [4, 8, 4, 8], fontFace: "Calibri Light", }); // 右侧组件 badges const agentBadges = ["Milvus 向量库", "MinIO 对象库", "Embedding 引擎", "Reranker", "Sessions 会话"]; agentBadges.forEach((b, i) => { sl.addText(b, { x: 6.55, y: 1.93 + i * 0.3, w: 2.05, h: 0.24, fontSize: 8, color: C.green, fill: { color: C.green, transparency: 90 }, line: { color: C.green, width: 0.4, transparency: 60 }, align: "center", margin: [2, 4, 2, 4], fontFace: "Calibri", }); }); sl.addText("法规 Agent 对话", { x: 0.7, y: 3.82, w: 4.5, h: 0.35, fontSize: 14, bold: true, color: C.text, fontFace: "Calibri", }); sl.addText("● 核心链路已通", { x: 5.0, y: 3.86, w: 2.2, h: 0.28, fontSize: 10, color: C.green, fontFace: "Calibri", }); sl.addText("真实 Milvus 向量检索 + LLM 流式输出全链路贯通\n会话管理、来源归因卡片、多轮追问、法规类型筛选", { x: 0.7, y: 4.25, w: 7.8, h: 0.9, fontSize: 11, color: C.text2, fontFace: "Calibri Light", lineSpacingMultiple: 1.5, }); // 右窄卡 — 系统监控 (w=3.9) sl.addShape("rect", { x: 9.0, y: 1.85, w: 3.9, h: 5.0, fill: { color: C.bgCard }, line: { color: C.border, width: 0.5 }, shadow: makeShadow(), }); sl.addShape("rect", { x: 9.0, y: 1.85, w: 3.9, h: 1.8, fill: { type: "grad", stops: [{ position: 0, color: "F0ECFF" }, { position: 100, color: "E2D8FF" }] }, line: { color: C.border, width: 0 }, }); sl.addText("🖥️", { x: 9.4, y: 2.0, w: 0.7, h: 0.65, fontSize: 24, fontFace: "Segoe UI Emoji", }); const healthBadges = [ { t: "Milvus ✓", c: C.green }, { t: "MinIO ✓", c: C.green }, { t: "LLM ✓", c: C.green }, ]; healthBadges.forEach((b, i) => { sl.addText(b.t, { x: 9.05 + i * 1.25, y: 3.0, w: 1.2, h: 0.22, fontSize: 8, bold: true, color: b.c, fill: { color: b.c, transparency: 88 }, line: { color: b.c, width: 0.4, transparency: 70 }, align: "center", margin: [2, 4, 2, 4], fontFace: "Calibri", }); }); sl.addText("系统状态监控", { x: 9.15, y: 3.82, w: 3.5, h: 0.35, fontSize: 14, bold: true, color: C.text, fontFace: "Calibri", }); sl.addText("✓ 已完成", { x: 9.15, y: 4.25, w: 2, h: 0.25, fontSize: 10, bold: true, color: C.green, fontFace: "Calibri", }); sl.addText("五项基础设施实时健康检查,文档统计,系统配置总览(LLM / Embedding / 解析引擎)", { x: 9.15, y: 4.6, w: 3.6, h: 2.0, fontSize: 11, color: C.text2, fontFace: "Calibri Light", lineSpacingMultiple: 1.4, }); } // ── 保存 ──────────────────────────────────────────────── const OUT = "C:/Projects/AIProjects/AIRegulations/AIRegulation-DocAnalysis-Demo/team-report.pptx"; prs.writeFile({ fileName: OUT }) .then(() => console.log("✅ 生成完成:", OUT)) .catch(e => { console.error("❌ 生成失败:", e); process.exit(1); });