gitlink-cli/scripts/gen-ppt.js

446 lines
31 KiB
JavaScript
Raw 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.

const pptxgen = require("pptxgenjs");
const fs = require("fs");
const pres = new pptxgen();
pres.layout = "LAYOUT_16x9";
pres.author = "GitLink CLI Team";
pres.title = "GitLink 智能化能力提升项目汇报";
// ===== Color Palette =====
const C = {
navy: "1E2761",
blue: "2B579A",
lightBlue: "CADCFC",
teal: "028090",
accent: "F96167",
white: "FFFFFF",
offWhite: "F5F7FA",
dark: "1A1A2E",
gray: "64748B",
lightGray: "E2E8F0",
green: "22C55E",
orange: "F59E0B",
purple: "8B5CF6",
};
// ===== Helper: icon in colored circle =====
function iconCircle(slide, icon, x, y, color) {
slide.addShape(pres.shapes.OVAL, { x, y, w: 0.5, h: 0.5, fill: { color } });
slide.addText(icon, { x, y, w: 0.5, h: 0.5, align: "center", valign: "middle", fontSize: 18, color: "FFFFFF" });
}
function demoBtn(slide, x, y) {
slide.addShape(pres.shapes.ROUNDED_RECTANGLE, { x, y, w: 1.6, h: 0.3, fill: { color: "F96167" }, line: { color: "F96167", width: 1 } });
slide.addText("▶ 现场演示", { x, y, w: 1.6, h: 0.3, fontSize: 9, color: "FFFFFF", fontFace: "Arial", align: "center", valign: "middle" });
}
function card(slide, title, desc, x, y, w, h, icon, accent) {
slide.addShape(pres.shapes.ROUNDED_RECTANGLE, {
x, y, w, h, fill: { color: C.white },
line: { color: C.lightGray, width: 1 },
shadow: { type: "outer", blur: 6, offset: 2, color: "000000", opacity: 0.08 }
});
if (icon) iconCircle(slide, icon, x + 0.2, y + 0.2, accent || C.teal);
slide.addText(title, { x: x + 0.85, y: y + 0.15, w: w - 1.1, h: 0.4, fontSize: 14, bold: true, color: C.navy, fontFace: "Arial" });
slide.addText(desc, { x: x + 0.85, y: y + 0.55, w: w - 1.1, h: h - 0.7, fontSize: 11, color: C.gray, fontFace: "Arial", valign: "top" });
}
// ===== Slide 1: Cover =====
let s1 = pres.addSlide();
s1.background = { fill: C.navy };
s1.addShape(pres.shapes.RECTANGLE, { x: 0, y: 0, w: 10, h: 5.625, fill: { color: C.navy } });
// Decorative circle
s1.addShape(pres.shapes.OVAL, { x: 6.5, y: -1.5, w: 5, h: 5, fill: { color: "24397A", transparency: 50 } });
s1.addShape(pres.shapes.OVAL, { x: 7.5, y: 3, w: 3.5, h: 3.5, fill: { color: "2B579A", transparency: 60 } });
s1.addText("《软件演化与运维》", { x: 0.8, y: 1.0, w: 8, h: 0.5, fontSize: 16, color: C.lightBlue, fontFace: "Arial" });
s1.addText("GitLink 智能化能力提升项目", { x: 0.8, y: 1.6, w: 8, h: 0.6, fontSize: 36, bold: true, color: C.white, fontFace: "Arial" });
s1.addText("gitlink-cli 命令行工具 · AI Agent Skills · 工作流自动化 · 科研辅助", { x: 0.8, y: 2.4, w: 8, h: 0.4, fontSize: 14, color: C.lightBlue, fontFace: "Arial" });
s1.addShape(pres.shapes.RECTANGLE, { x: 0.8, y: 3.0, w: 1.5, h: 0.04, fill: { color: C.accent } });
s1.addText("刘焱 · 赵昌 · 曾蔚然\n2026-06-30", { x: 0.8, y: 3.3, w: 8, h: 0.6, fontSize: 13, color: C.gray, fontFace: "Arial" });
// ===== Slide 2: 目录 =====
let s2 = pres.addSlide();
s2.background = { fill: C.white };
s2.addText("目 录", { x: 0.8, y: 0.4, w: 5, h: 0.6, fontSize: 28, bold: true, color: C.navy, fontFace: "Arial" });
s2.addShape(pres.shapes.RECTANGLE, { x: 0.8, y: 1.0, w: 1.2, h: 0.04, fill: { color: C.teal } });
s2.addNotes("目录页。\n我们将从项目背景开始逐一介绍每个子任务的完成情况\n最后进行现场演示和总结。");
const tocItems = [
["01", "项目背景与目标", "CLI 能力扩展的背景与四大子任务概览"],
["02", "子任务一CLI 能力扩展", "31 命令组 · 181+ 命令 · 20 测试 · 包管理"],
["03", "子任务二AI Agent Skills", "11 个 Claude Code Skills · 端到端验证"],
["04", "子任务三:端到端工作流", "社区运营自动化 · 代码质量看门人"],
["05", "子任务四:科研辅助", "科研项目洞悉 · 热点追踪与知识图谱"],
["06", "团队贡献与总结", "成员分工 · 交付统计 · Q&A"],
];
tocItems.forEach((item, i) => {
const y = 1.3 + i * 0.65;
s2.addShape(pres.shapes.ROUNDED_RECTANGLE, { x: 0.8, y, w: 8.4, h: 0.5, fill: { color: i % 2 === 0 ? C.offWhite : C.white } });
s2.addText(item[0], { x: 1.0, y, w: 0.6, h: 0.5, fontSize: 16, bold: true, color: C.teal, fontFace: "Arial", valign: "middle", align: "center" });
s2.addText(item[1], { x: 1.7, y, w: 2.5, h: 0.5, fontSize: 13, bold: true, color: C.navy, fontFace: "Arial", valign: "middle" });
s2.addText(item[2], { x: 4.3, y, w: 4.7, h: 0.5, fontSize: 10, color: C.gray, fontFace: "Arial", valign: "middle" });
});
// ===== Slide 3: 项目背景 =====
let s3 = pres.addSlide();
s3.background = { fill: C.navy };
s3.addText("项目背景与目标", { x: 0.8, y: 0.4, w: 8, h: 0.6, fontSize: 28, bold: true, color: C.white, fontFace: "Arial" });
s3.addShape(pres.shapes.RECTANGLE, { x: 0.8, y: 1.0, w: 1.2, h: 0.04, fill: { color: C.accent } });
s3.addNotes("gitlink-cli 是 GitLink 官方命令行工具,用 Go 语言开发。\n随着 AI 编程智能体的兴起,我们需要扩展 CLI 的能力,让它可以被 AI Agent 调用。\n四大子任务分别是CLI 扩展、Skills 开发、工作流自动化以及科研辅助。");
s3.addText("gitlink-cli 是 GitLink 平台的官方命令行工具,采用 Go 语言开发。\n随着 AI 编程智能体的兴起,我们需要从\"手动操作\"转向\"Agent 驱动开发\"。", { x: 0.8, y: 1.3, w: 8.4, h: 0.8, fontSize: 13, color: C.lightBlue, fontFace: "Arial" });
// 4 cards
const cards3 = [
["CLI 扩展", "补齐 Shortcut 命令\n优化交互体验\n跨平台兼容", C.teal],
["Skills 生态", "AI Agent 结构化\n调用知识库\nClaude Code 兼容", C.blue],
["工作流自动化", "串联 ≥3 命令/Skill\n可复现脚本\n端到端场景", C.purple],
["科研辅助", "仓库分析洞察\n热点追踪\n知识图谱可视化", C.accent],
];
cards3.forEach((c, i) => {
const x = 0.5 + i * 2.35;
s3.addShape(pres.shapes.ROUNDED_RECTANGLE, { x, y: 2.3, w: 2.1, h: 2.6, fill: { color: "24397A" }, line: { color: c[2], width: 2 } });
s3.addText(c[0], { x, y: 2.5, w: 2.1, h: 0.4, fontSize: 16, bold: true, color: c[2], fontFace: "Arial", align: "center" });
s3.addText(c[1], { x: x + 0.15, y: 3.0, w: 1.8, h: 1.6, fontSize: 11, color: C.lightBlue, fontFace: "Arial", align: "center", valign: "top" });
});
// ===== Slide 4: 子任务一 - 概览 =====
let s4 = pres.addSlide();
s4.background = { fill: C.white };
s4.addText("子任务一CLI 能力扩展", { x: 0.8, y: 0.3, w: 8, h: 0.6, fontSize: 26, bold: true, color: C.navy, fontFace: "Arial" });
s4.addShape(pres.shapes.RECTANGLE, { x: 0.8, y: 0.85, w: 1.2, h: 0.04, fill: { color: C.blue } });
// Big numbers
const stats = [
["31", "命令组", C.blue],
["181+", "子命令", C.teal],
["20", "测试文件", C.green],
["23", "Shortcut 组", C.accent],
["4", "包管理平台", C.purple],
];
stats.forEach((s, i) => {
const x = 0.4 + i * 1.9;
s4.addText(s[0], { x, y: 1.2, w: 1.7, h: 0.7, fontSize: 36, bold: true, color: s[2], fontFace: "Arial", align: "center" });
s4.addText(s[1], { x, y: 1.85, w: 1.7, h: 0.3, fontSize: 11, color: C.gray, fontFace: "Arial", align: "center" });
});
// Command groups showcase
s4.addShape(pres.shapes.ROUNDED_RECTANGLE, { x: 0.4, y: 2.4, w: 9.2, h: 2.9, fill: { color: C.offWhite } });
s4.addNotes("子任务一是 CLI 能力扩展,占总分的 50%。\n我们新增了 23 个 Shortcut 命令组、181 个子命令、20 个单元测试,覆盖了 4 个包管理平台。\n这里列出了所有命令组及其子命令数量。");
s4.addText("关键新增命令组", { x: 0.6, y: 2.5, w: 4, h: 0.35, fontSize: 13, bold: true, color: C.navy, fontFace: "Arial" });
const groups = ["repo(29)","issue(12)","pr(15)","user(24)","branch(9)","ci(12)","release(6)","webhook(8)","wiki(7)","snippet(4)","commit(5)","file(11)","milestone(6)","collaborator(6)","org(7)","search(2)","label(7)","tag(3)","dataset(4)","template(5)"];
groups.forEach((g, i) => {
const x = 0.6 + (i % 5) * 1.8;
const y = 3.0 + Math.floor(i / 5) * 0.65;
s4.addShape(pres.shapes.ROUNDED_RECTANGLE, { x, y, w: 1.65, h: 0.45, fill: { color: C.white }, line: { color: C.lightGray, width: 0.5 } });
s4.addText(g, { x, y, w: 1.65, h: 0.45, fontSize: 9, color: C.navy, fontFace: "Arial", align: "center", valign: "middle" });
});
// ===== Slide 5: 子任务一 - 架构 =====
let s5 = pres.addSlide();
s5.background = { fill: C.navy };
s5.addNotes("CLI 采用经典的三层架构:\n第一层 Shortcuts 提供高频操作的快捷接口;\n第二层 API Commands 负责统一的认证和错误处理;\n第三层 Raw API 可以直接访问任意平台端点,灵活扩展。");
s5.addText("CLI 三层架构", { x: 0.8, y: 0.3, w: 8, h: 0.6, fontSize: 26, bold: true, color: C.white, fontFace: "Arial" });
s5.addShape(pres.shapes.RECTANGLE, { x: 0.8, y: 0.85, w: 1.2, h: 0.04, fill: { color: C.teal } });
const layers = [
["Shortcuts", "gitlink-cli <group> +<verb>", "高频操作快捷接口23 组 181+ 命令", C.teal, 0.5],
["API Commands", "元数据驱动封装", "统一认证/错误/输出格式处理", C.blue, 0.4],
["Raw API", "gitlink-cli api <METHOD> <PATH>", "直接访问任意端点,灵活扩展", C.purple, 0.3],
];
layers.forEach((l, i) => {
const y = 1.3 + i * 1.3;
s5.addShape(pres.shapes.ROUNDED_RECTANGLE, { x: 0.5, y, w: 9.0, h: 1.0, fill: { color: "24397A" }, line: { color: l[3], width: 2 } });
s5.addText(l[0], { x: 0.8, y, w: 2, h: 1.0, fontSize: 16, bold: true, color: l[3], fontFace: "Arial", valign: "middle" });
s5.addText(l[1], { x: 3.0, y, w: 3, h: 1.0, fontSize: 12, color: C.white, fontFace: "Arial", valign: "middle" });
s5.addText(l[2], { x: 6.2, y, w: 3, h: 1.0, fontSize: 10, color: C.lightBlue, fontFace: "Arial", valign: "middle" });
// Arrow
if (i < 2) s5.addShape(pres.shapes.LINE, { x: 5, y: y + 1.0, w: 0, h: 0.3, line: { color: l[3], width: 2, dashType: "dash" } });
});
// ===== Slide 6: REPL & 输出优化 =====
let s6 = pres.addSlide();
s6.background = { fill: C.navy };
s6.addNotes("我们还新增了 REPL 交互模式,支持命令面板、滚动视口,以及三种输出格式。\n表格渲染优化让嵌套数据可以直观展示。");
s6.addText("REPL 交互模式 & 输出优化", { x: 0.8, y: 0.3, w: 8, h: 0.6, fontSize: 26, bold: true, color: C.white, fontFace: "Arial" });
s6.addShape(pres.shapes.RECTANGLE, { x: 0.8, y: 0.85, w: 1.2, h: 0.04, fill: { color: C.accent } });
const replFeats = [
["命令面板", "Ctrl+/ 触发模糊搜索", C.teal],
["命令执行器", "stdout 捕获 + Flag 解析", C.blue],
["滚动视口", "长输出滚动查看", C.purple],
["表格渲染", "嵌套数据表格化输出", C.green],
["JSON/Table/YAML", "三种输出格式", C.orange],
["颜色支持", "跨平台颜色检测", C.accent],
];
replFeats.forEach((f, i) => {
const x = 0.4 + (i % 3) * 3.2;
const y = 1.3 + Math.floor(i / 3) * 2.0;
s6.addShape(pres.shapes.ROUNDED_RECTANGLE, { x, y, w: 2.9, h: 1.7, fill: { color: "24397A" }, line: { color: f[2], width: 1.5 } });
s6.addText(f[0], { x, y: y + 0.15, w: 2.9, h: 0.4, fontSize: 14, bold: true, color: f[2], fontFace: "Arial", align: "center" });
s6.addText(f[1], { x: x + 0.2, y: y + 0.6, w: 2.5, h: 0.9, fontSize: 10, color: C.lightBlue, fontFace: "Arial", align: "center" });
});
// ===== Slide 7: 子任务二 - Skills =====
let s7 = pres.addSlide();
s7.background = { fill: C.white };
s7.addNotes("子任务二是 AI Agent Skills占总分的 20%。\n我们开发了 11 个 Claude Code Skills覆盖了项目管理的各个场景。\n所有 Skill 都在 Claude Code 平台上做了端到端实测验证。\n这里展示了 6 个核心 Skill每个 Skill 都包含完整的命令参考和工作流示例。");
s7.addText("子任务二AI Agent Skills", { x: 0.8, y: 0.3, w: 8, h: 0.6, fontSize: 26, bold: true, color: C.navy, fontFace: "Arial" });
s7.addShape(pres.shapes.RECTANGLE, { x: 0.8, y: 0.85, w: 1.2, h: 0.04, fill: { color: C.purple } });
s7.addText("11 个 Claude Code Skills · 29 个官方 Skills · Claude Code 端到端验证", { x: 0.8, y: 1.0, w: 8, h: 0.3, fontSize: 11, color: C.gray, fontFace: "Arial" });
const skills = [
["Issue Triage", "自动分类/打标签/分配\n关键词权重+紧急度评估\nClaude Code 验证", C.accent],
["Code Review", "PR 深度审查\n设计一致性检查\n跨模块影响分析", C.blue],
["Project Health", "健康度评分/趋势\nIssue/PR/贡献者\n里程碑多维度", C.teal],
["Release Auto", "语义化版本推荐\nConventional Commits\n自动 Release Notes", C.green],
["Compliance", "许可证合规检查\n敏感信息扫描\n开源规范检测", C.orange],
["Newcomer Guide", "good-first-issue 引导\n自动评论模板\n降低贡献门槛", C.purple],
];
skills.forEach((sk, i) => {
const x = 0.4 + (i % 3) * 3.2;
const y = 1.5 + Math.floor(i / 3) * 1.9;
card(s7, sk[0], sk[1], x, y, 2.9, 1.6, "→", sk[2]);
});
// ===== Slide 8: Skills 架构 =====
let s8 = pres.addSlide();
s8.background = { fill: C.navy };
s8.addNotes("Skills 框架采用四层架构:\n共享层、领域层、智能层和编排层。\n这种分层设计让每个 Skill 职责清晰,同时可以灵活组合。");
s8.addText("Skills 框架分层架构", { x: 0.8, y: 0.3, w: 8, h: 0.6, fontSize: 26, bold: true, color: C.white, fontFace: "Arial" });
s8.addShape(pres.shapes.RECTANGLE, { x: 0.8, y: 0.85, w: 1.2, h: 0.04, fill: { color: C.green } });
const sLayers = [
["共享层", "gitlink-shared", "认证 · 全局参数 · 安全规则 · API 注意事项", C.teal],
["领域层", "repo/issue/pr/release/ci", "各功能领域命令参考", C.blue],
["智能层", "code-review/triage/health", "AI 驱动分析工作流", C.purple],
["编排层", "workflow/community-ops/quality-gate", "端到端场景串联", C.accent],
];
sLayers.forEach((l, i) => {
const y = 1.2 + i * 1.1;
s8.addShape(pres.shapes.ROUNDED_RECTANGLE, { x: 0.5, y, w: 9.0, h: 0.85, fill: { color: "24397A" }, line: { color: l[3], width: 2 } });
s8.addText(l[0], { x: 0.7, y, w: 1.3, h: 0.85, fontSize: 13, bold: true, color: l[3], fontFace: "Arial", valign: "middle" });
s8.addText(l[1], { x: 2.2, y, w: 2.0, h: 0.85, fontSize: 11, color: C.white, fontFace: "Consolas", valign: "middle" });
s8.addText(l[2], { x: 4.5, y, w: 4.5, h: 0.85, fontSize: 10, color: C.lightBlue, fontFace: "Arial", valign: "middle" });
if (i < 3) s8.addShape(pres.shapes.LINE, { x: 5, y: y + 0.85, w: 0, h: 0.25, line: { color: l[3], width: 2, dashType: "dash" } });
});
// ===== Slide 9: 子任务三 - 工作流 =====
let s9 = pres.addSlide();
s9.background = { fill: C.white };
s9.addNotes("子任务三是端到端自动化工作流,占总分的 20%。\n我们实现了两个场景\n场景 A 是社区运营自动化,从 Issue 分拣到周报生成再到 Release Notes 发布;\n场景 B 是代码质量看门人,从 PR 审查到 CI 检查再到自动合并决策。");
s9.addText("子任务三:端到端自动化工作流", { x: 0.8, y: 0.3, w: 8, h: 0.6, fontSize: 26, bold: true, color: C.navy, fontFace: "Arial" });
s7.addShape(pres.shapes.RECTANGLE, { x: 0.8, y: 0.85, w: 1.2, h: 0.04, fill: { color: C.orange } });
// Scenario A
s9.addShape(pres.shapes.ROUNDED_RECTANGLE, { x: 0.4, y: 1.2, w: 9.2, h: 1.8, fill: { color: C.offWhite } });
s9.addShape(pres.shapes.ROUNDED_RECTANGLE, { x: 0.5, y: 1.3, w: 0.06, h: 1.6, fill: { color: C.teal } });
s9.addText("场景A社区运营自动化", { x: 0.8, y: 1.25, w: 4, h: 0.35, fontSize: 14, bold: true, color: C.navy, fontFace: "Arial" });
const flowA = ["Issue 分拣", "周报生成", "Release Notes"];
flowA.forEach((f, i) => {
const x = 0.8 + i * 2.9;
s9.addShape(pres.shapes.ROUNDED_RECTANGLE, { x, y: 1.7, w: 2.4, h: 0.5, fill: { color: C.white }, line: { color: C.teal, width: 1 } });
s9.addText(f, { x, y: 1.7, w: 2.4, h: 0.5, fontSize: 11, bold: true, color: C.teal, fontFace: "Arial", align: "center", valign: "middle" });
if (i < 2) s9.addText("→", { x: x + 2.35, y: 1.7, w: 0.5, h: 0.5, fontSize: 16, color: C.gray, fontFace: "Arial", align: "center", valign: "middle" });
});
s9.addText("关键词权重评分 · 健康度4维评分 · Conventional Commits分类", { x: 0.8, y: 2.3, w: 8, h: 0.3, fontSize: 9, color: C.gray, fontFace: "Arial" });
// Scenario B
s9.addShape(pres.shapes.ROUNDED_RECTANGLE, { x: 0.4, y: 3.2, w: 9.2, h: 2.0, fill: { color: C.offWhite } });
s9.addShape(pres.shapes.ROUNDED_RECTANGLE, { x: 0.5, y: 3.3, w: 0.06, h: 1.8, fill: { color: C.accent } });
s9.addText("场景B代码质量看门人", { x: 0.8, y: 3.25, w: 4, h: 0.35, fontSize: 14, bold: true, color: C.navy, fontFace: "Arial" });
const flowB = ["PR 采集", "深度审查", "CI 检查", "门禁决策"];
flowB.forEach((f, i) => {
const x = 0.8 + i * 2.2;
s9.addShape(pres.shapes.ROUNDED_RECTANGLE, { x, y: 3.7, w: 1.8, h: 0.5, fill: { color: C.white }, line: { color: C.accent, width: 1 } });
s9.addText(f, { x, y: 3.7, w: 1.8, h: 0.5, fontSize: 11, bold: true, color: C.accent, fontFace: "Arial", align: "center", valign: "middle" });
if (i < 3) s9.addText("→", { x: x + 1.7, y: 3.7, w: 0.5, h: 0.5, fontSize: 16, color: C.gray, fontFace: "Arial", align: "center", valign: "middle" });
});
s9.addText("评分模型CodeReview×40% + CI×30% + 设计一致性×30% 门槛≥70分", { x: 0.8, y: 4.4, w: 8, h: 0.3, fontSize: 10, bold: true, color: C.accent, fontFace: "Arial" });
// ===== Slide 11: 工作流真实输出 =====
let s11 = pres.addSlide();
s11.background = { fill: C.navy };
s11.addText("工作流真实输出数据", { x: 0.8, y: 0.3, w: 8, h: 0.6, fontSize: 26, bold: true, color: C.white, fontFace: "Arial" });
s11.addShape(pres.shapes.RECTANGLE, { x: 0.8, y: 0.85, w: 1.2, h: 0.04, fill: { color: C.accent } });
demoBtn(s11, 7.5, 0.9);
s11.addText("以下数据通过对 z2_cc/gitlink-cli 仓库运行工作流脚本实际采集", { x: 0.8, y: 1.0, w: 8, h: 0.3, fontSize: 10, color: C.gray, fontFace: "Arial" });
const outputs = [
["社区周报", "综合评分3.5/10\nIssue 19 (关闭 4)\nPR 2 · 贡献者 1", C.teal],
["Release Notes", "100 次提交 · 204 文件\n+16483 / -3644 行\n7 位贡献者 · v0.1.0", C.blue],
["科研洞察", "综合评分4.8/10\n贡献者 16 人\nGo 93.8% · 19 Issues", C.purple],
["热点追踪", "33 个仓库 · 19 主题\n11 种语言 · 27 组织\npython 30% · C++ 21%", C.green],
];
outputs.forEach((o, i) => {
const x = 0.3 + i * 2.45;
s11.addShape(pres.shapes.ROUNDED_RECTANGLE, { x, y: 1.5, w: 2.2, h: 3.3, fill: { color: "24397A" }, line: { color: o[2], width: 2 } });
s11.addText(o[0], { x, y: 1.65, w: 2.2, h: 0.35, fontSize: 13, bold: true, color: o[2], fontFace: "Arial", align: "center" });
s11.addText(o[1], { x: x + 0.15, y: 2.15, w: 1.9, h: 2.4, fontSize: 11, color: C.lightBlue, fontFace: "Consolas", align: "left" });
});
// ===== Slide 12: 终端输出 - 周报 =====
let s12r = pres.addSlide();
s12r.background = { fill: C.navy };
s12r.addNotes("这是社区周报的实际输出数据。\\n综合评分 3.5/10因为项目较新、Star 较少、且未检测到开源许可证。");
s12r.addText("社区周报 · 实际输出", { x: 0.8, y: 0.3, w: 8, h: 0.5, fontSize: 22, bold: true, color: C.white, fontFace: "Consolas" });
s12r.addShape(pres.shapes.RECTANGLE, { x: 0.8, y: 0.8, w: 1.2, h: 0.04, fill: { color: C.teal } });
s12r.addText("$ cat _output/weekly-health-report.md", { x: 0.8, y: 1.0, w: 8, h: 0.3, fontSize: 10, color: C.gray, fontFace: "Consolas" });
// Terminal box
s12r.addShape(pres.shapes.ROUNDED_RECTANGLE, { x: 0.5, y: 1.4, w: 9.0, h: 3.8, fill: { color: "0A0E17" }, line: { color: "1E293B", width: 1 } });
// Title bar dots
[["FF5F57","FFBD2E","28C840"],["1E2A3A","1E2A3A","1E2A3A"]].forEach((row,ri) => row.forEach((c,ci) => {
s12r.addShape(pres.shapes.OVAL, { x: 0.7 + ci*0.2, y: 1.55 + ri*0.01, w: 0.1, h: 0.1, fill: { color: c } });
}));
const rptLines = [
["# 综合评分3.5/10 🔴 堪忧", "F96167"],
["", ""],
["| 指标 | 数据 |","94A3B8"],
["|---------------|-----------------------|","94A3B8"],
["| Issue 总数 | 19关闭 4/打开 15 |","94A3B8"],
["| 关闭率 | 21% 🔴 偏低 |","EF4444"],
["| PR 总数 | 2合并 0 |","94A3B8"],
["| 贡献者数 | 1 人 |","94A3B8"],
["| 平均响应 | 24.3 天 🟡 正常 |","F59E0B"],
["", ""],
["# Issue 分析评分3/10","3B82F6"],
["# PR 分析评分3/10","3B82F6"],
["# 贡献者活跃度评分3/10","3B82F6"],
];
rptLines.forEach((l, i) => {
if (l[0]) s12r.addText(l[0], { x: 0.8, y: 1.8 + i*0.22, w: 8, h: 0.22, fontSize: 9, color: l[1], fontFace: "Consolas", margin: 0 });
});
// ===== Slide 13: 终端输出 - Release Notes =====
let s13r = pres.addSlide();
s13r.background = { fill: C.navy };
s13r.addNotes("Release Notes 从提交历史自动生成。\\n100 次提交、7 位贡献者、204 个文件变更。\\n版本推荐v0.1.0(有 feat 次版本+1。");
s13r.addText("Release Notes · 实际输出", { x: 0.8, y: 0.3, w: 8, h: 0.5, fontSize: 22, bold: true, color: C.white, fontFace: "Consolas" });
s13r.addShape(pres.shapes.RECTANGLE, { x: 0.8, y: 0.8, w: 1.2, h: 0.04, fill: { color: C.blue } });
s13r.addText("$ cat _output/release-notes-v0.1.0.md", { x: 0.8, y: 1.0, w: 8, h: 0.3, fontSize: 10, color: C.gray, fontFace: "Consolas" });
s13r.addShape(pres.shapes.ROUNDED_RECTANGLE, { x: 0.5, y: 1.4, w: 9.0, h: 3.8, fill: { color: "0A0E17" }, line: { color: "1E293B", width: 1 } });
[["FF5F57","FFBD2E","28C840"],["1E2A3A","1E2A3A","1E2A3A"]].forEach((row,ri) => row.forEach((c,ci) => {
s13r.addShape(pres.shapes.OVAL, { x: 0.7 + ci*0.2, y: 1.55 + ri*0.01, w: 0.1, h: 0.1, fill: { color: c } });
}));
const rnLines = [
["## v0.1.0 (2026-06-30)", "22C55E"],
["", ""],
["### 版本概览","3B82F6"],
["- 基于 v0.0.0,包含 100 次提交","94A3B8"],
["- 涉及 204 个文件","94A3B8"],
["- 新增 +16483 / 删除 -3644 行","94A3B8"],
["- 贡献者7 人","94A3B8"],
["", ""],
["### 分类统计","F59E0B"],
["✨ 新功能 20 次 (20%)","22C55E"],
["🐛 Bug 修复 19 次 (19%)","EF4444"],
["📝 文档 44 次 (44%)","3B82F6"],
["✅ 测试 3 次 (3%) ","A78BFA"],
["🔧 工程 2 次 (2%) ","F59E0B"],
["📦 其他 11 次 (11%)","94A3B8"],
];
rnLines.forEach((l, i) => {
if (l[0]) s13r.addText(l[0], { x: 0.8, y: 1.8 + i*0.22, w: 8, h: 0.22, fontSize: 9, color: l[1], fontFace: "Consolas", margin: 0 });
});
// ===== Slide 14: 子任务四 - 科研 =====
let s12 = pres.addSlide();
s12.background = { fill: C.white };
s12.addNotes("子任务四是科研辅助,是加分项。\n模块 C 是科研项目洞悉,可以采集 8 维仓库数据,从成熟度、文档质量、贡献模式和社区健康度四个维度进行评分。\n模块 D 是热点追踪与知识图谱,支持多关键词搜索并自动构建交互式知识图谱。");
s12.addText("子任务四:科研辅助", { x: 0.8, y: 0.3, w: 8, h: 0.6, fontSize: 26, bold: true, color: C.navy, fontFace: "Arial" });
s12.addShape(pres.shapes.RECTANGLE, { x: 0.8, y: 0.85, w: 1.2, h: 0.04, fill: { color: C.green } });
card(s12, "模块C科研项目洞悉", "8维数据采集\n4维度评分模型\n自动生成 HTML 报告", 0.4, 1.2, 4.5, 2.0, "📊", C.teal);
card(s12, "模块D热点追踪与知识图谱", "多关键词搜索\n实体关系提取\n交互式 HTML 可视化", 5.1, 1.2, 4.5, 2.0, "🔍", C.purple);
// Scoring model
s12.addShape(pres.shapes.ROUNDED_RECTANGLE, { x: 0.4, y: 3.5, w: 9.2, h: 1.8, fill: { color: C.offWhite } });
s12.addText("科研洞察评分模型", { x: 0.6, y: 3.6, w: 4, h: 0.3, fontSize: 12, bold: true, color: C.navy, fontFace: "Arial" });
const dims = [
["成熟度", "25%", "年龄/Star/Fork/更新", C.blue],
["文档质量", "20%", "README/License/CI", C.teal],
["贡献模式", "30%", "贡献者数/提交频率", C.green],
["社区健康", "25%", "Issue/PR 关闭率", C.orange],
];
dims.forEach((d, i) => {
const x = 0.6 + i * 2.3;
s8.addShape(pres.shapes.ROUNDED_RECTANGLE, { x, y: 4.0, w: 2.0, h: 1.1, fill: { color: C.white }, line: { color: d[3], width: 1.5 } });
s8.addText(d[0], { x, y: 4.1, w: 2.0, h: 0.3, fontSize: 12, bold: true, color: d[3], fontFace: "Arial", align: "center" });
s8.addText(d[1], { x, y: 4.35, w: 2.0, h: 0.3, fontSize: 14, bold: true, color: C.navy, fontFace: "Arial", align: "center" });
s8.addText(d[2], { x, y: 4.6, w: 2.0, h: 0.3, fontSize: 8, color: C.gray, fontFace: "Arial", align: "center" });
});
// ===== Slide 14: 知识图谱可视化 =====
let s14 = pres.addSlide();
s14.background = { fill: C.navy };
s14.addText("知识图谱可视化", { x: 0.8, y: 0.3, w: 8, h: 0.6, fontSize: 26, bold: true, color: C.white, fontFace: "Arial" });
s14.addShape(pres.shapes.RECTANGLE, { x: 0.8, y: 0.85, w: 1.2, h: 0.04, fill: { color: C.green } });
demoBtn(s14, 7.5, 0.9);
s14.addText("热点追踪 Skill 自动构建多关键词搜索结果的知识图谱", { x: 0.8, y: 1.0, w: 8, h: 0.3, fontSize: 10, color: C.gray, fontFace: "Arial" });
const kgNodes = [
["研究项目", "4 个", C.blue, 0.5],
["主题标签", "19 个", C.purple, 1.0],
["技术栈", "11 种", C.teal, 1.5],
["组织", "27 个", C.orange, 2.0],
["关系边", "30+ 条", C.accent, 2.5],
];
kgNodes.forEach(n => {
s14.addShape(pres.shapes.ROUNDED_RECTANGLE, { x: 0.5 + n[3] * 2.0, y: 1.5, w: 1.7, h: 1.5, fill: { color: "24397A" }, line: { color: n[2], width: 2 } });
s14.addText(n[1], { x: 0.5 + n[3] * 2.0, y: 1.6, w: 1.7, h: 0.5, fontSize: 16, bold: true, color: n[2], fontFace: "Arial", align: "center" });
s14.addText(n[0], { x: 0.5 + n[3] * 2.0, y: 2.15, w: 1.7, h: 0.3, fontSize: 10, color: C.lightBlue, fontFace: "Arial", align: "center" });
});
s14.addText("关系topic主题归属· uses技术使用· belongs_to组织归属· related项目关联", { x: 0.5, y: 3.3, w: 9, h: 0.4, fontSize: 11, color: C.gray, fontFace: "Arial", align: "center" });
s14.addShape(pres.shapes.ROUNDED_RECTANGLE, { x: 0.5, y: 3.8, w: 9.0, h: 1.3, fill: { color: "24397A" } });
s14.addText("交互式 HTML 知识图谱功能", { x: 0.7, y: 3.9, w: 4, h: 0.3, fontSize: 12, bold: true, color: C.white, fontFace: "Arial" });
s14.addText("✅ 滚轮缩放 ✅ 拖拽平移 ✅ 点击高亮 ✅ SVG 导出 ✅ 深色主题 ✅ 侧栏项目列表", { x: 0.7, y: 4.3, w: 8.5, h: 0.5, fontSize: 11, color: C.lightBlue, fontFace: "Arial" });
// ===== Slide 15: 演示展示 =====
let s15 = pres.addSlide();
s15.background = { fill: C.navy };
s15.addNotes("现在是现场演示环节,我们将展示四个核心功能:\n1. 社区运营自动化(一键式三阶段流水线)\n2. 科研项目洞悉8 维数据采集与 4 维评分)\n3. 热点追踪与知识图谱(交互式 HTML 可视化)\n4. 质量门禁PR 审查与自动评分)\n\n演示脚本详见 doc/演示脚本.md综合演示页详见 doc/demo.html");
s15.addText("演示展示", { x: 0.8, y: 0.3, w: 8, h: 0.6, fontSize: 28, bold: true, color: C.white, fontFace: "Arial" });
s15.addShape(pres.shapes.RECTANGLE, { x: 0.8, y: 0.85, w: 1.2, h: 0.04, fill: { color: C.accent } });
// Terminals
const demos = [
["社区运营自动化", "DRY_RUN=true bash community-ops-full.sh", "Issue 分拣 → 周报 → Release Notes"],
["科研项目洞悉", "bash research-insight-full.sh", "8维采集 → 4维评分 → 结构化报告"],
["热点追踪与知识图谱", "bash hotspot-tracker-full.sh", "搜索 → 知识图谱 → HTML 交互式可视化"],
["质量门禁", "DRY_RUN=true bash quality-gate-full.sh", "PR 审查 → CI 检查 → 质量评分"],
];
demos.forEach((d, i) => {
const y = 1.2 + i * 1.05;
s15.addShape(pres.shapes.ROUNDED_RECTANGLE, { x: 0.5, y, w: 9.0, h: 0.85, fill: { color: "24397A" } });
s15.addText(d[0], { x: 0.8, y, w: 2.5, h: 0.85, fontSize: 13, bold: true, color: C.accent, fontFace: "Arial", valign: "middle" });
s15.addText(d[1], { x: 3.5, y, w: 3.5, h: 0.5, fontSize: 10, color: C.lightBlue, fontFace: "Consolas", valign: "middle" });
s15.addText(d[2], { x: 3.5, y: y + 0.4, w: 5.5, h: 0.4, fontSize: 9, color: C.gray, fontFace: "Arial", valign: "middle" });
});
// ===== Slide 16: 团队贡献 =====
let s16 = pres.addSlide();
s16.background = { fill: C.white };
s16.addNotes("最后介绍一下团队贡献。\n刘焱负责 CLI 底层架构和大部分 Shortcut 实现;\n赵昌负责命令实现、Skills 开发、工作流编排和科研模块;\n曾蔚然作为组长负责 DevOps 流水线、代码审查和项目统筹。\n\n项目共交付 47 个文件、约 5,800 行代码,全部验证通过。\n感谢各位聆听欢迎提问");
s16.addText("团队贡献", { x: 0.8, y: 0.3, w: 8, h: 0.6, fontSize: 26, bold: true, color: C.navy, fontFace: "Arial" });
s16.addShape(pres.shapes.RECTANGLE, { x: 0.8, y: 0.85, w: 1.2, h: 0.04, fill: { color: C.teal } });
const members = [
["刘焱", "78 commits", "CLI 架构、23 组 Shortcut、REPL、测试、Skills", "40%"],
["赵昌", "46 commits", "Webhook/Wiki/Snippet 命令、Skills、工作流、科研模块、报告", "30%"],
["曾蔚然(组长)", "9 commits", "DevOps 流水线、PR 审查 Skills、代码合并", "30%"],
];
members.forEach((m, i) => {
const y = 1.2 + i * 1.3;
s16.addShape(pres.shapes.ROUNDED_RECTANGLE, { x: 0.5, y, w: 9.0, h: 1.1, fill: { color: C.offWhite } });
s16.addShape(pres.shapes.OVAL, { x: 0.7, y: y + 0.2, w: 0.7, h: 0.7, fill: { color: [C.blue, C.teal, C.accent][i] } });
s16.addText(m[0], { x: 0.7, y: y + 0.2, w: 0.7, h: 0.7, fontSize: 10, bold: true, color: C.white, fontFace: "Arial", align: "center", valign: "middle" });
s16.addText(m[1], { x: 1.6, y: y + 0.1, w: 2, h: 0.35, fontSize: 13, bold: true, color: C.navy, fontFace: "Arial", valign: "middle" });
s16.addText(m[2], { x: 1.6, y: y + 0.45, w: 5, h: 0.4, fontSize: 10, color: C.gray, fontFace: "Arial", valign: "middle" });
// Progress bar
s16.addShape(pres.shapes.ROUNDED_RECTANGLE, { x: 7.0, y: y + 0.35, w: 2.2, h: 0.35, fill: { color: C.lightGray } });
s16.addShape(pres.shapes.ROUNDED_RECTANGLE, { x: 7.0, y: y + 0.35, w: 2.2 * parseFloat(m[3]) / 100, h: 0.35, fill: { color: [C.blue, C.teal, C.accent][i] } });
s16.addText(m[3], { x: 7.0, y: y + 0.35, w: 2.2, h: 0.35, fontSize: 10, bold: true, color: C.white, fontFace: "Arial", align: "center", valign: "middle" });
});
s16.addShape(pres.shapes.ROUNDED_RECTANGLE, { x: 0.5, y: 4.6, w: 9.0, h: 0.7, fill: { color: C.offWhite } });
s16.addText("总计47 个交付文件 · 5,800 行代码 · 14 轮迭代 · 全部验证通过", { x: 0.5, y: 4.6, w: 9.0, h: 0.7, fontSize: 13, bold: true, color: C.navy, fontFace: "Arial", align: "center", valign: "middle" });
// ===== Slide 17: Q&A =====
let s17 = pres.addSlide();
s17.background = { fill: C.navy };
s17.addShape(pres.shapes.OVAL, { x: -2, y: -1, w: 6, h: 6, fill: { color: "24397A", transparency: 50 } });
s17.addShape(pres.shapes.OVAL, { x: 7, y: 3, w: 4, h: 4, fill: { color: "2B579A", transparency: 60 } });
s17.addNotes("问答环节。\n可以准备以下问题的回答\n1. CLI 如何保证向后兼容?——新增 Shortcut 不影响已有命令\n2. 工作流脚本安全吗?——默认 dry-run 模式,不会修改数据\n3. 科研模块数据来源?——全部通过 gitlink-cli 从 GitLink API 实时采集\n4. 知识图谱是如何构建的?——多关键词搜索 → 实体关系提取 → Mermaid 可视化");
s17.addText("Q & A", { x: 0, y: 1.5, w: 10, h: 1.2, fontSize: 48, bold: true, color: C.white, fontFace: "Arial", align: "center" });
s17.addText("感谢聆听 · 欢迎提问", { x: 0, y: 2.8, w: 10, h: 0.5, fontSize: 16, color: C.lightBlue, fontFace: "Arial", align: "center" });
// ===== Save =====
const outPath = "e:/gitlink-cli/gitlink-cli/tmp_ppt.pptx";
pres.writeFile({ fileName: outPath }).then(() => console.log("Done: " + outPath));