Files
star-erp/generate_pptx.cjs

217 lines
14 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 React = require("react");
const ReactDOMServer = require("react-dom/server");
const sharp = require("sharp");
const {
LayoutDashboard,
Mail,
Cpu,
Layout,
BellRing,
Factory,
ShieldAlert,
Target,
Zap
} = require("lucide-react");
let pres = new pptxgen();
pres.layout = 'LAYOUT_16x9';
pres.author = 'AI Assistant';
pres.title = '每週三的開發成果發表';
// Colors
const colors = {
primary: "36454F",
secondary: "F2F2F2",
accent: "028090",
textWhite: "FFFFFF",
textDark: "1E293B",
textMuted: "64748B"
};
// Icon rendering helper
function renderIconSvg(IconComponent, color = "#000000", size = 256) {
return ReactDOMServer.renderToStaticMarkup(
React.createElement(IconComponent, { color, size: String(size) })
);
}
async function iconToBase64Png(IconComponent, color, size = 256) {
const svg = renderIconSvg(IconComponent, color, size);
const pngBuffer = await sharp(Buffer.from(svg)).png().toBuffer();
return "image/png;base64," + pngBuffer.toString("base64");
}
pres.defineSlideMaster({
title: 'MASTER_TITLE', background: { color: colors.primary },
});
pres.defineSlideMaster({
title: 'MASTER_CONTENT', background: { color: colors.secondary },
});
async function generate() {
// ==========================================
// Slide 1: 封面 (Title Slide)
// ==========================================
let slide1 = pres.addSlide({ masterName: "MASTER_TITLE" });
slide1.addShape(pres.shapes.RECTANGLE, { x: 0, y: 2.8, w: 10, h: 0.1, fill: { color: colors.accent } });
slide1.addText("每週三的開發成果發表", {
x: 0.5, y: 1.5, w: 9, h: 1.2,
fontSize: 44, fontFace: "Arial Black", color: colors.textWhite,
align: "center", bold: true
});
slide1.addText("Star ERP & Star Cloud 核心功能、架構優化與系統穩定性提升", {
x: 0.5, y: 3.2, w: 9, h: 1,
fontSize: 20, fontFace: "Outfit", color: "CADCFC",
align: "center"
});
// ==========================================
// Slide 2: 本週核心亮點總覽 (Agenda)
// ==========================================
let slide2 = pres.addSlide({ masterName: "MASTER_CONTENT" });
slide2.addText("本週核心亮點總覽", { x: 0.5, y: 0.5, w: 9, h: 0.8, fontSize: 32, fontFace: "Arial Black", color: colors.primary, bold: true });
slide2.addShape(pres.shapes.RECTANGLE, { x: 0.5, y: 1.3, w: 7.5, h: 0.05, fill: { color: colors.accent } });
let card1Y = 2.2;
const cardShadow = { type: "outer", color: "000000", blur: 6, offset: 2, angle: 135, opacity: 0.1 };
// Card 1: UI
slide2.addShape(pres.shapes.RECTANGLE, { x: 0.5, y: card1Y, w: 2.8, h: 2.7, fill: { color: colors.textWhite }, shadow: cardShadow });
const iconCloud = await iconToBase64Png(LayoutDashboard, "#" + colors.accent);
slide2.addImage({ data: iconCloud, x: 1.5, y: card1Y + 0.2, w: 0.6, h: 0.6 });
slide2.addText("UI 視覺重構", { x: 0.7, y: card1Y + 0.9, w: 2.4, h: 0.4, fontSize: 18, fontFace: "Arial", color: colors.accent, bold: true, align: "center" });
slide2.addText("Star Cloud 系統日誌大改造,全面導入極簡奢華風 UI。", { x: 0.7, y: card1Y + 1.4, w: 2.4, h: 1.2, fontSize: 14, fontFace: "Calibri", color: colors.textDark, align: "center", valign: "top" });
// Card 2: ERP
slide2.addShape(pres.shapes.RECTANGLE, { x: 3.6, y: card1Y, w: 2.8, h: 2.7, fill: { color: colors.textWhite }, shadow: cardShadow });
const iconErp = await iconToBase64Png(Mail, "#" + colors.accent);
slide2.addImage({ data: iconErp, x: 4.6, y: card1Y + 0.2, w: 0.6, h: 0.6 });
slide2.addText("系統提醒機制", { x: 3.8, y: card1Y + 0.9, w: 2.4, h: 0.4, fontSize: 18, fontFace: "Arial", color: colors.accent, bold: true, align: "center" });
slide2.addText("Star ERP 公共事業費提醒與生產工單損耗產出管理。", { x: 3.8, y: card1Y + 1.4, w: 2.4, h: 1.2, fontSize: 14, fontFace: "Calibri", color: colors.textDark, align: "center", valign: "top" });
// Card 3: Arch
slide2.addShape(pres.shapes.RECTANGLE, { x: 6.7, y: card1Y, w: 2.8, h: 2.7, fill: { color: colors.textWhite }, shadow: cardShadow });
const iconArch = await iconToBase64Png(Cpu, "#" + colors.accent);
slide2.addImage({ data: iconArch, x: 7.7, y: card1Y + 0.2, w: 0.6, h: 0.6 });
slide2.addText("底層核心架構", { x: 6.9, y: card1Y + 0.9, w: 2.4, h: 0.4, fontSize: 18, fontFace: "Arial", color: colors.accent, bold: true, align: "center" });
slide2.addText("修正閉包變數地雷並導入 SQL select 效能優化與多租戶隔離。", { x: 6.9, y: card1Y + 1.4, w: 2.4, h: 1.2, fontSize: 14, fontFace: "Calibri", color: colors.textDark, align: "center", valign: "top" });
// ==========================================
// Slide 3: 亮點 1 - Star Cloud 視覺與架構升級
// ==========================================
let slide3 = pres.addSlide({ masterName: "MASTER_CONTENT" });
slide3.addText("亮點 1: Star Cloud 視覺與架構升級", { x: 0.5, y: 0.5, w: 9, h: 0.8, fontSize: 32, fontFace: "Arial Black", color: colors.primary, bold: true });
slide3.addShape(pres.shapes.RECTANGLE, { x: 0.5, y: 1.3, w: 6.5, h: 0.05, fill: { color: colors.accent } });
slide3.addText("本週開發功能與 Demo", { x: 0.5, y: 1.8, w: 4.5, h: 0.5, fontSize: 24, fontFace: "Arial", color: colors.accent, bold: true });
slide3.addText("儀表板與系統日誌介面大改造", { x: 0.5, y: 2.5, w: 4.5, h: 0.4, fontSize: 18, fontFace: "Calibri", color: colors.textDark, bullet: true });
slide3.addText("移除舊版復古風,全面導入極簡奢華風、深色模式及 Outfit 字型", { x: 0.5, y: 3.0, w: 4.5, h: 0.6, fontSize: 18, fontFace: "Calibri", color: colors.textDark, bullet: true });
slide3.addText("顯著提升 SaaS 系統高級感", { x: 0.5, y: 3.7, w: 4.5, h: 0.4, fontSize: 18, fontFace: "Calibri", color: colors.textDark, bullet: true });
slide3.addShape(pres.shapes.RECTANGLE, { x: 5.2, y: 1.8, w: 4.3, h: 3, fill: { color: colors.primary }, shadow: { ...cardShadow, opacity: 0.2 } });
const iconZap = await iconToBase64Png(Zap, "#FFFFFF");
slide3.addImage({ data: iconZap, x: 5.7, y: 2.0, w: 0.4, h: 0.4 });
slide3.addText("技術邏輯", { x: 6.2, y: 2.0, w: 3.5, h: 0.5, fontSize: 22, fontFace: "Arial", color: colors.textWhite, bold: true });
slide3.addText("建構 IoT 高併發機台通訊架構", { x: 5.7, y: 2.6, w: 3.5, h: 0.4, fontSize: 16, fontFace: "Calibri", color: colors.textWhite, bullet: true });
slide3.addText("全面改用 Redis Queue 異步處理海量機台心跳與日誌回報", { x: 5.7, y: 3.1, w: 3.5, h: 0.6, fontSize: 16, fontFace: "Calibri", color: colors.textWhite, bullet: true });
// ==========================================
// Slide 4: 亮點 2 - Star ERP 公共事業費發信機制
// ==========================================
let slide4 = pres.addSlide({ masterName: "MASTER_CONTENT" });
slide4.addText("亮點 2: Star ERP 公共事業費發信機制", { x: 0.5, y: 0.5, w: 9, h: 0.8, fontSize: 32, fontFace: "Arial Black", color: colors.primary, bold: true });
slide4.addShape(pres.shapes.RECTANGLE, { x: 0.5, y: 1.3, w: 6.5, h: 0.05, fill: { color: colors.accent } });
slide4.addText("本週開發功能", { x: 0.5, y: 1.6, w: 9, h: 0.5, fontSize: 24, fontFace: "Arial", color: colors.accent, bold: true });
const iconBell = await iconToBase64Png(BellRing, "#" + colors.accent);
slide4.addImage({ data: iconBell, x: 2.0, y: 1.65, w: 0.4, h: 0.4 });
slide4.addText("實作公共事業費逾期提醒機制、租戶自訂通知設定及發送測試信功能。", { x: 0.5, y: 2.1, w: 9, h: 0.5, fontSize: 18, fontFace: "Calibri", color: colors.textDark });
let timelineY = 3.5;
slide4.addShape(pres.shapes.LINE, { x: 1, y: timelineY, w: 8, h: 0, line: { color: colors.primary, width: 4 } });
slide4.addShape(pres.shapes.OVAL, { x: 1.5, y: timelineY - 0.2, w: 0.4, h: 0.4, fill: { color: colors.accent } });
slide4.addText("前 7 天", { x: 1.0, y: timelineY + 0.3, w: 1.4, h: 0.5, fontSize: 14, fontFace: "Arial", align: "center", bold: true, color: colors.textDark });
slide4.addShape(pres.shapes.OVAL, { x: 3.8, y: timelineY - 0.2, w: 0.4, h: 0.4, fill: { color: colors.accent } });
slide4.addText("前 3 天", { x: 3.3, y: timelineY + 0.3, w: 1.4, h: 0.5, fontSize: 14, fontFace: "Arial", align: "center", bold: true, color: colors.textDark });
slide4.addShape(pres.shapes.OVAL, { x: 6.1, y: timelineY - 0.2, w: 0.4, h: 0.4, fill: { color: colors.accent } });
slide4.addText("到期日 (0 天)", { x: 5.6, y: timelineY + 0.3, w: 1.4, h: 0.5, fontSize: 14, fontFace: "Arial", align: "center", bold: true, color: colors.textDark });
slide4.addShape(pres.shapes.OVAL, { x: 8.4, y: timelineY - 0.2, w: 0.4, h: 0.4, fill: { color: "990011" } });
slide4.addText("逾期 (每日)", { x: 7.9, y: timelineY + 0.3, w: 1.4, h: 0.5, fontSize: 14, fontFace: "Arial", align: "center", bold: true, color: "990011" });
slide4.addText("附件防呆:實作公共事業費憑證附件上傳管理與前端防呆機制", { x: 0.5, y: 4.5, w: 9, h: 0.5, fontSize: 18, fontFace: "Calibri", color: colors.textDark, align: "center", italic: true });
// ==========================================
// Slide 5: 亮點 3 - Star ERP 生產工單耗損與產出管理
// ==========================================
let slide5 = pres.addSlide({ masterName: "MASTER_CONTENT" });
slide5.addText("亮點 3: Star ERP 生產工單耗損與產出管理", { x: 0.5, y: 0.5, w: 9, h: 0.8, fontSize: 32, fontFace: "Arial Black", color: colors.primary, bold: true });
slide5.addShape(pres.shapes.RECTANGLE, { x: 0.5, y: 1.3, w: 6.5, h: 0.05, fill: { color: colors.accent } });
slide5.addText("本週開發功能", { x: 0.5, y: 1.6, w: 9, h: 0.5, fontSize: 24, fontFace: "Arial", color: colors.accent, bold: true });
const iconFactory = await iconToBase64Png(Factory, "#" + colors.accent);
slide5.addImage({ data: iconFactory, x: 2.0, y: 1.65, w: 0.4, h: 0.4 });
slide5.addText("新增生產工單「實際產量」填寫與「耗損原因」紀錄。", { x: 0.5, y: 2.1, w: 9, h: 0.5, fontSize: 18, fontFace: "Calibri", color: colors.textDark });
slide5.addShape(pres.shapes.RECTANGLE, { x: 0.5, y: 2.8, w: 4.2, h: 2.2, fill: { color: colors.textWhite }, shadow: cardShadow });
slide5.addText("後端設計", { x: 0.7, y: 2.9, w: 3.8, h: 0.5, fontSize: 20, fontFace: "Arial", color: colors.accent, bold: true });
slide5.addText([
{ text: "新增資料庫欄位以儲存實際產量與耗損原因", options: { bullet: true, breakLine: true } },
{ text: "完善 API 狀態推進與實際產量/成本的計算邏輯", options: { bullet: true, breakLine: true } },
{ text: "修正完工入庫金額未計算問題", options: { bullet: true } }
], { x: 0.7, y: 3.4, w: 3.8, h: 1.4, fontSize: 16, fontFace: "Calibri", color: colors.textDark, valign: "top" });
slide5.addShape(pres.shapes.RECTANGLE, { x: 5.3, y: 2.8, w: 4.2, h: 2.2, fill: { color: colors.textWhite }, shadow: cardShadow });
slide5.addText("前端優化", { x: 5.5, y: 2.9, w: 3.8, h: 0.5, fontSize: 20, fontFace: "Arial", color: colors.accent, bold: true });
slide5.addText([
{ text: "完工入庫實作原生數字輸入框", options: { bullet: true, breakLine: true } },
{ text: "支援 step=1 加減功能", options: { bullet: true, breakLine: true } },
{ text: "加入嚴謹的資料驗證", options: { bullet: true } }
], { x: 5.5, y: 3.4, w: 3.8, h: 1.4, fontSize: 16, fontFace: "Calibri", color: colors.textDark, valign: "top" });
// ==========================================
// Slide 6: 深層技術挑戰與解法
// ==========================================
let slide6 = pres.addSlide({ masterName: "MASTER_CONTENT" });
slide6.addText("深層技術挑戰與解法", { x: 0.5, y: 0.5, w: 9, h: 0.8, fontSize: 32, fontFace: "Arial Black", color: colors.primary, bold: true });
slide6.addShape(pres.shapes.RECTANGLE, { x: 0.5, y: 1.3, w: 1, h: 0.05, fill: { color: colors.accent } });
slide6.addShape(pres.shapes.RECTANGLE, { x: 0.5, y: 1.8, w: 4.2, h: 2.8, fill: { color: "990011" }, shadow: { ...cardShadow, opacity: 0.2 } });
slide6.addText("日漸增長的效能隱患與閉包變數地雷", { x: 0.7, y: 2.0, w: 3.8, h: 0.8, fontSize: 20, fontFace: "Arial", color: colors.textWhite, bold: true });
slide6.addShape(pres.shapes.LINE, { x: 0.7, y: 2.8, w: 3.8, h: 0, line: { color: colors.textWhite, width: 2 } });
slide6.addText("全站 Service/Controller 加入 SQL select 具體欄位限制,配置租戶資料表索引 (Index);修正 PHP InventoryService 閉包參考失效的潛藏 Bug。", { x: 0.7, y: 3.0, w: 3.8, h: 1.4, fontSize: 16, fontFace: "Calibri", color: colors.textWhite, valign: "top" });
slide6.addShape(pres.shapes.RECTANGLE, { x: 5.3, y: 1.8, w: 4.2, h: 2.8, fill: { color: colors.accent }, shadow: { ...cardShadow, opacity: 0.2 } });
slide6.addText("跨租戶管理的安全顧慮", { x: 5.5, y: 2.0, w: 3.8, h: 0.8, fontSize: 20, fontFace: "Arial", color: colors.textWhite, bold: true });
slide6.addShape(pres.shapes.LINE, { x: 5.5, y: 2.8, w: 3.8, h: 0, line: { color: colors.textWhite, width: 2 } });
slide6.addText("強化與整理了開發與 Git 規範文件,隔離多租戶目錄被誤推的風險。", { x: 5.5, y: 3.0, w: 3.8, h: 1.4, fontSize: 16, fontFace: "Calibri", color: colors.textWhite, valign: "top" });
// ==========================================
// Slide 7: 未來計畫
// ==========================================
let slide7 = pres.addSlide({ masterName: "MASTER_TITLE" });
const iconTarget = await iconToBase64Png(Target, "#" + colors.accent);
slide7.addImage({ data: iconTarget, x: 4.8, y: 0.8, w: 0.5, h: 0.5 });
slide7.addText("未來計畫 (Next Steps)", { x: 0.5, y: 1.5, w: 9, h: 1.0, fontSize: 36, fontFace: "Arial Black", color: colors.accent, align: "center", bold: true });
slide7.addText("開始開發 Star Cloud維護 ERP 系統", { x: 0.5, y: 2.8, w: 9, h: 1.5, fontSize: 28, fontFace: "Arial", color: colors.textWhite, align: "center" });
// Save
pres.writeFile({ fileName: "/home/mama/projects/demo_day_presentation.pptx" }).then(fileName => {
console.log(`created file: ${fileName}`);
});
}
generate().catch(err => {
console.error(err);
process.exit(1);
});