forked from Gitlink/gitlink-cli
446 lines
31 KiB
JavaScript
446 lines
31 KiB
JavaScript
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));
|