const pptxgen = require("pptxgenjs"); const fs = require("fs"); const pres = new pptxgen(); pres.layout = "LAYOUT_16x9"; pres.title = "Star Cloud Demo Day - Technical Edition"; pres.author = "許家偉"; // --- Theme Colors --- const COLORS = { bg: "0F172A", cardBg: "1E293B", highlight: "2DD4BF", secondary: "7DD3FC", text: "FFFFFF", muted: "94A3B8" }; const FONTS = { header: "Georgia", body: "Calibri" }; const makeShadow = (opacity = 0.2) => ({ type: "outer", blur: 8, offset: 3, angle: 135, color: "000000", opacity: opacity }); // --- Slide 1: Title --- const slide1 = pres.addSlide(); slide1.background = { color: COLORS.bg }; slide1.addShape(pres.shapes.RECTANGLE, { x: 0, y: 0, w: 0.15, h: "100%", fill: { color: COLORS.highlight } }); slide1.addText("Star Cloud Demo Day", { x: 1.0, y: 1.8, w: 8, h: 1, fontSize: 48, fontFace: FONTS.header, color: COLORS.text, bold: true, margin: 0 }); slide1.addText("2026-03-25 ~ 2026-03-31 成果發表", { x: 1.0, y: 2.8, w: 8, h: 0.5, fontSize: 24, fontFace: FONTS.body, color: COLORS.secondary, italic: true }); slide1.addShape(pres.shapes.RECTANGLE, { x: 7.5, y: 4.5, w: 2, h: 0.6, fill: { color: COLORS.highlight, transparency: 10 }, shadow: makeShadow() }); slide1.addText("演講者:許家偉", { x: 7.5, y: 4.5, w: 2, h: 0.6, fontSize: 14, fontFace: FONTS.body, color: COLORS.text, align: "center", valign: "middle", bold: true }); // --- Slide 2: Overview --- const slide2 = pres.addSlide(); slide2.background = { color: COLORS.bg }; slide2.addText("本週進度總覽 / Overview", { x: 0.5, y: 0.4, w: 9, h: 0.6, fontSize: 32, fontFace: FONTS.header, color: COLORS.highlight, bold: true }); slide2.addShape(pres.shapes.LINE, { x: 2, y: 3, w: 6, h: 0, line: { color: COLORS.highlight, width: 4 } }); const timelineItems = [ { title: "機台權限管理", desc: "模組獨立化與效能優化" }, { title: "商品管理整合", desc: "狀態整合與多語系修復" }, { title: "廣告隔離機制", desc: "多租戶素材歸屬強化" } ]; timelineItems.forEach((item, idx) => { const x = 2 + (idx * 3); slide2.addShape(pres.shapes.OVAL, { x: x - 0.2, y: 2.8, w: 0.4, h: 0.4, fill: { color: COLORS.secondary }, line: { color: COLORS.text, width: 2 } }); slide2.addText(item.title, { x: x - 1, y: 3.3, w: 2, h: 0.4, fontSize: 18, fontFace: FONTS.header, color: COLORS.text, align: "center", bold: true }); slide2.addText(item.desc, { x: x - 1, y: 3.7, w: 2, h: 0.6, fontSize: 12, fontFace: FONTS.body, color: COLORS.muted, align: "center" }); }); // --- Slide 3: Highlight 1 - Machine Permissions (WITH EAGER LOADING) --- const slide3 = pres.addSlide(); slide3.background = { color: COLORS.bg }; slide3.addText("亮點一:機台權限管理獨立化", { x: 0.5, y: 0.4, w: 9, h: 0.6, fontSize: 28, fontFace: FONTS.header, color: COLORS.highlight, bold: true }); const features = [ { title: "直覺檢索", text: "管理員可快速檢索、分配所屬帳號對應的機台清單。" }, { title: "即時過濾", text: "透過 Alpine.js 實作,輸入關鍵字即動態無刷新過濾。" }, { title: "效能關鍵:Eager Loading", text: "使用 with('machines') 解決 N+1 問題,萬筆資料秒開。" } ]; features.forEach((f, idx) => { const y = 1.2 + (idx * 1.3); slide3.addShape(pres.shapes.RECTANGLE, { x: 0.5, y: y, w: 4, h: 1.1, fill: { color: COLORS.cardBg }, line: { color: COLORS.secondary, width: 1 }, shadow: makeShadow() }); slide3.addText(f.title, { x: 0.7, y: y + 0.1, w: 3.5, h: 0.3, fontSize: 16, fontFace: FONTS.header, color: COLORS.highlight, bold: true }); slide3.addText(f.text, { x: 0.7, y: y + 0.45, w: 3.5, h: 0.5, fontSize: 12, fontFace: FONTS.body, color: COLORS.text }); }); slide3.addImage({ path: "/home/mama/.gemini/antigravity/brain/58a170d0-7144-4e9f-9396-3e753a0bf69a/machine_permissions_table_1774944648298.png", x: 4.8, y: 1.2, w: 4.8, h: 3.7, sizing: { type: 'contain' }, shadow: makeShadow(0.3) }); // --- Slide 4: Highlight 2 --- const slide4 = pres.addSlide(); slide4.background = { color: COLORS.bg }; slide4.addText("亮點二:商品管理整合與 UX 完善", { x: 0.5, y: 0.4, w: 9, h: 0.6, fontSize: 28, fontFace: FONTS.header, color: COLORS.highlight, bold: true }); const comparison = [ { title: "功能整合 (Integrated)", items: ["• 「商品狀態」納入主流程", "• 減少跳轉,提升管理效率"] }, { title: "細節優化 (Enhanced)", items: ["• 修復多語系(ZH/EN/JA)存取故障", "• 密碼欄位新增顯隱切換按鈕"] } ]; comparison.forEach((c, idx) => { const x = 0.5 + (idx * 4.75); slide4.addShape(pres.shapes.RECTANGLE, { x: x, y: 1.2, w: 4.25, h: 3.5, fill: { color: COLORS.cardBg }, line: { color: COLORS.highlight, width: 2 }, shadow: makeShadow(0.2) }); slide4.addText(c.title, { x: x + 0.2, y: 1.4, w: 3.8, h: 0.4, fontSize: 18, fontFace: FONTS.header, color: COLORS.highlight, bold: true, align: "center" }); slide4.addText(c.items.map(i => ({ text: i, options: { breakLine: true, bullet: true } })), { x: x + 0.3, y: 2.0, w: 3.6, h: 2.5, fontSize: 14, fontFace: FONTS.body, color: COLORS.text, margin: 0 }); }); // --- Slide 5: Highlight 3 --- const slide5 = pres.addSlide(); slide5.background = { color: COLORS.bg }; slide5.addText("亮點三:多租戶廣告素材隔離機制", { x: 1.0, y: 0.4, w: 8, h: 1, fontSize: 32, fontFace: FONTS.header, color: COLORS.highlight, bold: true, align: "center" }); slide5.addShape(pres.shapes.OVAL, { x: 4.25, y: 2.0, w: 1.5, h: 1.5, fill: { color: COLORS.highlight, transparency: 30 }, line: { color: COLORS.secondary, width: 2 } }); slide5.addText("安全性隔離\n(Shield)", { x: 4.25, y: 2.5, w: 1.5, h: 0.5, fontSize: 14, fontFace: FONTS.header, color: COLORS.text, align: "center", bold: true }); const isolations = [ { x: 1, y: 1.8, label: "公司 A\n廣告素材", color: "A8DADC" }, { x: 7.5, y: 1.8, label: "公司 B\n廣告素材", color: "A8DADC" }, { x: 1, y: 3.8, label: "公司 C\n廣告素材", color: "A8DADC" }, { x: 7.5, y: 3.8, label: "公司 D\n廣告素材", color: "A8DADC" } ]; isolations.forEach(i => { slide5.addShape(pres.shapes.ROUNDED_RECTANGLE, { x: i.x, y: i.y, w: 1.5, h: 0.8, fill: { color: COLORS.cardBg }, line: { color: COLORS.secondary, width: 1 }, rectRadius: 0.1 }); slide5.addText(i.label, { x: i.x, y: i.y, w: 1.5, h: 0.8, fontSize: 12, fontFace: FONTS.body, color: COLORS.text, align: "center", valign: "middle" }); slide5.addShape(pres.shapes.LINE, { x: i.x + (i.x < 5 ? 1.5 : 0), y: i.y + 0.4, w: i.x < 5 ? (4.25 - (i.x + 1.5)) : (7.5 - (i.x + 1.5)), h: 2.75 - (i.y + 0.4), line: { color: COLORS.secondary, width: 1, dashType: "dash" } }); }); slide5.addText("嚴格驗證 company_id,確保素材 100% 歸屬隔離。", { x: 0.5, y: 5.0, w: 9, h: 0.4, fontSize: 14, fontFace: FONTS.body, color: COLORS.muted, align: "center", italic: true }); // --- Slide 6: Future Roadmap --- const slide6 = pres.addSlide(); slide6.background = { color: COLORS.bg }; slide6.addText("未來計畫 / Roadmap", { x: 0.5, y: 0.4, w: 9, h: 1, fontSize: 36, fontFace: FONTS.header, color: COLORS.highlight, bold: true, align: "center" }); const roadmap = [ { icon: "Optim", title: "操作優化", text: "針對樂樂反饋優化操作流程與介面體驗。" }, { icon: "Sync", title: "API 對接", text: "與 Terry 配合,實現機台通訊穩定與對接。" }, { icon: "Remote", title: "遠端管理", text: "實作遠端控制與異常即時監控監管。" } ]; roadmap.forEach((r, idx) => { const x = 0.5 + (idx * 3.1); slide6.addShape(pres.shapes.RECTANGLE, { x: x, y: 2.0, w: 2.8, h: 2.5, fill: { color: COLORS.highlight, transparency: 85 }, line: { color: COLORS.highlight, width: 2 }, shadow: makeShadow() }); slide6.addText(r.title, { x: x, y: 2.3, w: 2.8, h: 0.5, fontSize: 20, fontFace: FONTS.header, color: COLORS.highlight, bold: true, align: "center" }); slide6.addText(r.text, { x: x + 0.2, y: 3.0, w: 2.4, h: 1.2, fontSize: 14, fontFace: FONTS.body, color: COLORS.text, align: "center" }); }); slide6.addText("Star Cloud 將持續進化,打造最領先的智能雲端平台。🚀", { x: 0.5, y: 5.0, w: 9, h: 0.4, fontSize: 14, fontFace: FONTS.body, color: COLORS.secondary, align: "center", bold: true }); pres.writeFile({ fileName: "star-cloud-demo-20260331.pptx" }) .then(fileName => console.log(`Presentation created: ${fileName}`)) .catch(err => { console.error("Error creating presentation:", err); process.exit(1); });