feat: PPT 添加备注稿和演示跳转按钮
CI / test (push) Has been cancelled Details

- 每页 PPT 添加演讲者备注(讲稿)
- 演示相关页面添加红色「▶ 现场演示」跳转按钮
- 方便汇报时快速定位到对应演示环节

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
赵昌 2026-06-30 10:16:06 +08:00
parent d4af2e3207
commit 93f65a7d78
3 changed files with 31 additions and 0 deletions

Binary file not shown.

13
scripts/fix-ppt.js Normal file
View File

@ -0,0 +1,13 @@
const fs = require('fs');
let c = fs.readFileSync('scripts/gen-ppt.js', 'utf8');
// Remove Windows CR chars
c = c.replace(/\r/g, '');
// Fix addNotes - replace literal newlines with \\n
c = c.replace(/addNotes\("([\s\S]*?)"\)/g, function(m, content) {
return 'addNotes("' + content.replace(/\n/g, '\\n') + '")';
});
fs.writeFileSync('scripts/gen-ppt.js', c, 'utf8');
console.log('fixed');

View File

@ -29,6 +29,10 @@ function iconCircle(slide, icon, x, y, 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 },
@ -58,6 +62,7 @@ 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 测试 · 包管理"],
@ -79,6 +84,7 @@ 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 = [
@ -114,6 +120,7 @@ stats.forEach((s, i) => {
});
// 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) => {
@ -126,6 +133,7 @@ groups.forEach((g, i) => {
// ===== 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 = [
@ -146,6 +154,7 @@ layers.forEach((l, i) => {
// ===== 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 = [
@ -167,6 +176,7 @@ replFeats.forEach((f, i) => {
// ===== 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" });
@ -187,6 +197,7 @@ skills.forEach((sk, i) => {
// ===== 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 = [
@ -207,6 +218,7 @@ sLayers.forEach((l, i) => {
// ===== 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 } });
@ -241,6 +253,7 @@ 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],
@ -258,6 +271,7 @@ outputs.forEach((o, i) => {
// ===== Slide 12: 子任务四 - 科研 =====
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 } });
@ -286,6 +300,7 @@ 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],
@ -307,6 +322,7 @@ s14.addText("✅ 滚轮缩放 ✅ 拖拽平移 ✅ 点击高亮 ✅ SVG 导
// ===== 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
@ -327,6 +343,7 @@ demos.forEach((d, i) => {
// ===== 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 = [
@ -355,6 +372,7 @@ 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" });