New modules: - Energy Quota Management (定额管理) - Cost/Expense Analysis with TOU pricing (费用分析) - Sub-item Energy Analysis (分项分析) - EV Charging Station Management (充电桩管理) — 8 models, 6 pages - Enhanced Energy Analysis — loss, YoY, MoM comparison - Alarm Analytics — trends, MTTR, top devices, rule toggle - Maintenance & Work Orders (运维管理) — inspections, repair orders, duty - Data Query Module (数据查询) - Equipment Topology (设备拓扑) - Management System (管理体系) — regulations, standards, processes Infrastructure: - Redis caching layer with decorator - Redis Streams data ingestion buffer - Hourly/daily/monthly aggregation engine - Rate limiting & request ID middleware - 6 Alembic migrations (003-008), 21 new tables - Extended seed data for all modules Stats: 120+ API routes, 12 pages, 27 tabs, 37 database tables Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
318 lines
22 KiB
JavaScript
318 lines
22 KiB
JavaScript
const pptxgen = require("pptxgenjs");
|
||
const path = require("path");
|
||
|
||
const pres = new pptxgen();
|
||
pres.layout = "LAYOUT_16x9";
|
||
pres.author = "Tianpu EMS Team";
|
||
pres.title = "天普EMS企业级功能增强 — 开发团队晨会";
|
||
|
||
// Color palette — Ocean Gradient theme for energy/tech
|
||
const C = {
|
||
navy: "0A1628",
|
||
darkBlue: "0F2440",
|
||
blue: "1565C0",
|
||
lightBlue: "42A5F5",
|
||
teal: "00897B",
|
||
green: "43A047",
|
||
white: "FFFFFF",
|
||
offWhite: "F5F7FA",
|
||
lightGray: "E8ECF1",
|
||
gray: "8898AA",
|
||
darkGray: "32325D",
|
||
accent: "FF6F00",
|
||
red: "E53935",
|
||
};
|
||
|
||
const makeShadow = () => ({ type: "outer", blur: 6, offset: 2, angle: 135, color: "000000", opacity: 0.12 });
|
||
|
||
// ============================================================
|
||
// SLIDE 1: Title
|
||
// ============================================================
|
||
let s1 = pres.addSlide();
|
||
s1.background = { color: C.navy };
|
||
|
||
// Top accent bar
|
||
s1.addShape(pres.shapes.RECTANGLE, { x: 0, y: 0, w: 10, h: 0.06, fill: { color: C.lightBlue } });
|
||
|
||
// Title block
|
||
s1.addText("天普零碳园区", { x: 0.8, y: 1.2, w: 8.4, h: 0.8, fontSize: 44, fontFace: "Microsoft YaHei", color: C.white, bold: true, margin: 0 });
|
||
s1.addText("智慧能源管理平台", { x: 0.8, y: 1.9, w: 8.4, h: 0.8, fontSize: 44, fontFace: "Microsoft YaHei", color: C.lightBlue, bold: true, margin: 0 });
|
||
s1.addText("企业级功能增强项目 — 开发团队晨会", { x: 0.8, y: 2.9, w: 8.4, h: 0.5, fontSize: 20, fontFace: "Microsoft YaHei", color: C.gray, margin: 0 });
|
||
|
||
// Bottom info bar
|
||
s1.addShape(pres.shapes.RECTANGLE, { x: 0, y: 4.8, w: 10, h: 0.825, fill: { color: C.darkBlue } });
|
||
s1.addText("React 19 + FastAPI + PostgreSQL/TimescaleDB + Redis", { x: 0.8, y: 4.85, w: 8.4, h: 0.7, fontSize: 14, fontFace: "Consolas", color: C.lightBlue, align: "left", valign: "middle" });
|
||
|
||
// ============================================================
|
||
// SLIDE 2: Project Overview
|
||
// ============================================================
|
||
let s2 = pres.addSlide();
|
||
s2.background = { color: C.offWhite };
|
||
s2.addShape(pres.shapes.RECTANGLE, { x: 0, y: 0, w: 10, h: 0.06, fill: { color: C.blue } });
|
||
|
||
s2.addText("项目概述", { x: 0.7, y: 0.3, w: 8.6, h: 0.6, fontSize: 32, fontFace: "Microsoft YaHei", color: C.darkGray, bold: true, margin: 0 });
|
||
|
||
// 4 KPI cards
|
||
const kpis = [
|
||
{ label: "增强阶段", value: "12", sub: "全部完成", color: C.green },
|
||
{ label: "新增API", value: "80+", sub: "端点", color: C.blue },
|
||
{ label: "新增页面", value: "16", sub: "前端组件", color: C.teal },
|
||
{ label: "数据库表", value: "37", sub: "总计", color: C.accent },
|
||
];
|
||
kpis.forEach((k, i) => {
|
||
const cx = 0.7 + i * 2.3;
|
||
s2.addShape(pres.shapes.RECTANGLE, { x: cx, y: 1.15, w: 2.0, h: 1.5, fill: { color: C.white }, shadow: makeShadow() });
|
||
s2.addShape(pres.shapes.RECTANGLE, { x: cx, y: 1.15, w: 2.0, h: 0.06, fill: { color: k.color } });
|
||
s2.addText(k.value, { x: cx, y: 1.35, w: 2.0, h: 0.7, fontSize: 36, fontFace: "Arial Black", color: k.color, align: "center", valign: "middle", bold: true, margin: 0 });
|
||
s2.addText(k.sub, { x: cx, y: 1.95, w: 2.0, h: 0.3, fontSize: 12, fontFace: "Microsoft YaHei", color: C.gray, align: "center", margin: 0 });
|
||
s2.addText(k.label, { x: cx, y: 2.3, w: 2.0, h: 0.3, fontSize: 11, fontFace: "Microsoft YaHei", color: C.darkGray, align: "center", bold: true, margin: 0 });
|
||
});
|
||
|
||
// Description bullets
|
||
s2.addText([
|
||
{ text: "参考系统: cp-ems-ruoyi (Java/Spring Boot 企业级EMS)", options: { bullet: true, breakLine: true, fontSize: 14 } },
|
||
{ text: "目标: 以现代Python/React技术栈实现同等企业级功能深度", options: { bullet: true, breakLine: true, fontSize: 14 } },
|
||
{ text: "技术优势保留: 3D可视化、多协议采集、TypeScript、i18n、暗色模式", options: { bullet: true, breakLine: true, fontSize: 14 } },
|
||
{ text: "全部编译验证通过: 后端0错误、前端0 TS错误、所有API已测试", options: { bullet: true, fontSize: 14 } },
|
||
], { x: 0.7, y: 2.9, w: 8.6, h: 2.5, fontFace: "Microsoft YaHei", color: C.darkGray, valign: "top" });
|
||
|
||
// ============================================================
|
||
// SLIDE 3: New Modules Overview (Table)
|
||
// ============================================================
|
||
let s3 = pres.addSlide();
|
||
s3.background = { color: C.offWhite };
|
||
s3.addShape(pres.shapes.RECTANGLE, { x: 0, y: 0, w: 10, h: 0.06, fill: { color: C.blue } });
|
||
s3.addText("新增功能模块一览", { x: 0.7, y: 0.2, w: 8.6, h: 0.55, fontSize: 28, fontFace: "Microsoft YaHei", color: C.darkGray, bold: true, margin: 0 });
|
||
|
||
const hdrOpts = { fill: { color: C.blue }, color: C.white, bold: true, fontSize: 11, fontFace: "Microsoft YaHei", align: "center", valign: "middle" };
|
||
const cellOpts = { fontSize: 10, fontFace: "Microsoft YaHei", color: C.darkGray, valign: "middle" };
|
||
const cellC = { ...cellOpts, align: "center" };
|
||
const altFill = { fill: { color: C.lightGray } };
|
||
|
||
const tableRows = [
|
||
[
|
||
{ text: "功能模块", options: hdrOpts },
|
||
{ text: "后端", options: hdrOpts },
|
||
{ text: "前端", options: hdrOpts },
|
||
{ text: "状态", options: hdrOpts },
|
||
],
|
||
[{ text: "基础设施 (Redis/队列/聚合)", options: cellOpts }, { text: "3 files", options: cellC }, { text: "-", options: cellC }, { text: "✅", options: cellC }],
|
||
[{ text: "定额管理", options: { ...cellOpts, ...altFill } }, { text: "model+API+service", options: { ...cellC, ...altFill } }, { text: "1 page (3 tabs)", options: { ...cellC, ...altFill } }, { text: "✅", options: { ...cellC, ...altFill } }],
|
||
[{ text: "费用分析", options: cellOpts }, { text: "model+API+service", options: cellC }, { text: "1 component", options: cellC }, { text: "✅", options: cellC }],
|
||
[{ text: "分项分析", options: { ...cellOpts, ...altFill } }, { text: "extended energy.py", options: { ...cellC, ...altFill } }, { text: "1 component", options: { ...cellC, ...altFill } }, { text: "✅", options: { ...cellC, ...altFill } }],
|
||
[{ text: "充电桩管理", options: cellOpts }, { text: "8 models + API", options: cellC }, { text: "6 pages", options: cellC }, { text: "✅", options: cellC }],
|
||
[{ text: "能耗分析增强 (损耗/同比/环比)", options: { ...cellOpts, ...altFill } }, { text: "extended energy.py", options: { ...cellC, ...altFill } }, { text: "3 components", options: { ...cellC, ...altFill } }, { text: "✅", options: { ...cellC, ...altFill } }],
|
||
[{ text: "告警分析", options: cellOpts }, { text: "extended alarms.py", options: cellC }, { text: "enhanced page", options: cellC }, { text: "✅", options: cellC }],
|
||
[{ text: "运维管理", options: { ...cellOpts, ...altFill } }, { text: "4 models + API", options: { ...cellC, ...altFill } }, { text: "1 page (5 tabs)", options: { ...cellC, ...altFill } }, { text: "✅", options: { ...cellC, ...altFill } }],
|
||
[{ text: "数据查询", options: cellOpts }, { text: "extended energy.py", options: cellC }, { text: "1 page", options: cellC }, { text: "✅", options: cellC }],
|
||
[{ text: "设备拓扑", options: { ...cellOpts, ...altFill } }, { text: "extended devices.py", options: { ...cellC, ...altFill } }, { text: "1 component", options: { ...cellC, ...altFill } }, { text: "✅", options: { ...cellC, ...altFill } }],
|
||
[{ text: "管理体系", options: cellOpts }, { text: "4 models + API", options: cellC }, { text: "1 page (4 tabs)", options: cellC }, { text: "✅", options: cellC }],
|
||
[{ text: "生产加固 (限流/幂等/请求ID)", options: { ...cellOpts, ...altFill } }, { text: "middleware.py", options: { ...cellC, ...altFill } }, { text: "-", options: { ...cellC, ...altFill } }, { text: "✅", options: { ...cellC, ...altFill } }],
|
||
];
|
||
|
||
s3.addTable(tableRows, { x: 0.5, y: 0.85, w: 9.0, colW: [3.8, 2.2, 1.8, 0.8], border: { pt: 0.5, color: "D0D5DD" }, rowH: [0.35, 0.32, 0.32, 0.32, 0.32, 0.32, 0.32, 0.32, 0.32, 0.32, 0.32, 0.32, 0.32, 0.32] });
|
||
|
||
// ============================================================
|
||
// SLIDE 4: Tech Architecture
|
||
// ============================================================
|
||
let s4 = pres.addSlide();
|
||
s4.background = { color: C.offWhite };
|
||
s4.addShape(pres.shapes.RECTANGLE, { x: 0, y: 0, w: 10, h: 0.06, fill: { color: C.blue } });
|
||
s4.addText("技术架构", { x: 0.7, y: 0.25, w: 8.6, h: 0.55, fontSize: 28, fontFace: "Microsoft YaHei", color: C.darkGray, bold: true, margin: 0 });
|
||
|
||
// Architecture layers as horizontal blocks
|
||
const layers = [
|
||
{ label: "前端展示层", tech: "React 19 + TypeScript + Ant Design 5 + ECharts + Three.js (3D)", color: C.lightBlue, y: 1.0 },
|
||
{ label: "API网关层", tech: "FastAPI + JWT Auth + RBAC + Rate Limiting + Request ID", color: C.blue, y: 1.85 },
|
||
{ label: "业务服务层", tech: "定额检查 | 费用计算 | 告警引擎 | 报表生成 | 数据聚合", color: C.teal, y: 2.7 },
|
||
{ label: "数据采集层", tech: "Modbus TCP + MQTT + HTTP API + Redis Streams Queue", color: C.green, y: 3.55 },
|
||
{ label: "存储层", tech: "PostgreSQL 16 (TimescaleDB) + Redis 7 + File Storage", color: C.accent, y: 4.4 },
|
||
];
|
||
|
||
layers.forEach(l => {
|
||
s4.addShape(pres.shapes.RECTANGLE, { x: 0.7, y: l.y, w: 2.2, h: 0.65, fill: { color: l.color } });
|
||
s4.addText(l.label, { x: 0.7, y: l.y, w: 2.2, h: 0.65, fontSize: 13, fontFace: "Microsoft YaHei", color: C.white, align: "center", valign: "middle", bold: true, margin: 0 });
|
||
s4.addShape(pres.shapes.RECTANGLE, { x: 3.0, y: l.y, w: 6.3, h: 0.65, fill: { color: C.white }, shadow: makeShadow() });
|
||
s4.addText(l.tech, { x: 3.2, y: l.y, w: 5.9, h: 0.65, fontSize: 12, fontFace: "Consolas", color: C.darkGray, valign: "middle", margin: 0 });
|
||
});
|
||
|
||
// ============================================================
|
||
// SLIDE 5: Frontend Team
|
||
// ============================================================
|
||
let s5 = pres.addSlide();
|
||
s5.background = { color: C.offWhite };
|
||
s5.addShape(pres.shapes.RECTANGLE, { x: 0, y: 0, w: 10, h: 0.06, fill: { color: C.lightBlue } });
|
||
s5.addText("前端开发组 — 代码Review清单", { x: 0.7, y: 0.2, w: 8.6, h: 0.5, fontSize: 26, fontFace: "Microsoft YaHei", color: C.darkGray, bold: true, margin: 0 });
|
||
s5.addText("Git: http://100.108.180.60:3300/tianpu/tianpu-ems | 目录: frontend/src/", { x: 0.7, y: 0.65, w: 8.6, h: 0.3, fontSize: 11, fontFace: "Consolas", color: C.blue, margin: 0 });
|
||
|
||
const feFiles = [
|
||
["pages/Quota/index.tsx", "定额管理 (3 tabs: 配置/监控/分析)"],
|
||
["pages/Charging/*", "充电管理 (Dashboard, Stations, Piles, Orders, Pricing)"],
|
||
["pages/Maintenance/index.tsx", "运维管理 (5 tabs: 概览/巡检/工单/值班)"],
|
||
["pages/DataQuery/index.tsx", "数据查询 (树形选择器 + 多参数查询)"],
|
||
["pages/Management/index.tsx", "管理体系 (4 tabs: 规章/标准/流程/预案)"],
|
||
["pages/Analysis/CostAnalysis.tsx", "费用分析组件"],
|
||
["pages/Analysis/SubitemAnalysis.tsx", "分项分析组件"],
|
||
["pages/Analysis/Loss|Yoy|Mom.tsx", "损耗/同比/环比分析 (3组件)"],
|
||
["pages/Alarms/index.tsx", "告警分析增强 + 规则Toggle"],
|
||
["pages/Devices/Topology.tsx", "设备拓扑树"],
|
||
["layouts/MainLayout.tsx", "菜单导航 (14项)"],
|
||
["App.tsx + services/api.ts", "路由配置 + API调用函数"],
|
||
];
|
||
|
||
const feHdr = [
|
||
{ text: "文件路径", options: hdrOpts },
|
||
{ text: "功能说明", options: hdrOpts },
|
||
];
|
||
const feRows = [feHdr];
|
||
feFiles.forEach((f, i) => {
|
||
const bg = i % 2 === 1 ? altFill : {};
|
||
feRows.push([
|
||
{ text: f[0], options: { fontSize: 10, fontFace: "Consolas", color: C.blue, valign: "middle", ...bg } },
|
||
{ text: f[1], options: { fontSize: 10, fontFace: "Microsoft YaHei", color: C.darkGray, valign: "middle", ...bg } },
|
||
]);
|
||
});
|
||
s5.addTable(feRows, { x: 0.5, y: 1.05, w: 9.0, colW: [3.8, 5.2], border: { pt: 0.5, color: "D0D5DD" }, rowH: 0.32 });
|
||
|
||
// ============================================================
|
||
// SLIDE 6: Backend Team
|
||
// ============================================================
|
||
let s6 = pres.addSlide();
|
||
s6.background = { color: C.offWhite };
|
||
s6.addShape(pres.shapes.RECTANGLE, { x: 0, y: 0, w: 10, h: 0.06, fill: { color: C.teal } });
|
||
s6.addText("后端开发组 — 代码Review清单", { x: 0.7, y: 0.2, w: 8.6, h: 0.5, fontSize: 26, fontFace: "Microsoft YaHei", color: C.darkGray, bold: true, margin: 0 });
|
||
s6.addText("Git: http://100.108.180.60:3300/tianpu/tianpu-ems | 目录: backend/app/", { x: 0.7, y: 0.65, w: 8.6, h: 0.3, fontSize: 11, fontFace: "Consolas", color: C.teal, margin: 0 });
|
||
|
||
// Three columns: Models | APIs | Services
|
||
const colW = 2.9;
|
||
const colGap = 0.15;
|
||
const colY = 1.1;
|
||
const colH = 4.3;
|
||
|
||
// Models column
|
||
s6.addShape(pres.shapes.RECTANGLE, { x: 0.5, y: colY, w: colW, h: colH, fill: { color: C.white }, shadow: makeShadow() });
|
||
s6.addShape(pres.shapes.RECTANGLE, { x: 0.5, y: colY, w: colW, h: 0.4, fill: { color: C.blue } });
|
||
s6.addText("数据模型 (6 files)", { x: 0.5, y: colY, w: colW, h: 0.4, fontSize: 13, fontFace: "Microsoft YaHei", color: C.white, align: "center", valign: "middle", bold: true, margin: 0 });
|
||
s6.addText([
|
||
{ text: "models/quota.py", options: { breakLine: true, fontSize: 9, fontFace: "Consolas", color: C.blue } },
|
||
{ text: " EnergyQuota, QuotaUsage", options: { breakLine: true, fontSize: 9, color: C.gray } },
|
||
{ text: "models/pricing.py", options: { breakLine: true, fontSize: 9, fontFace: "Consolas", color: C.blue } },
|
||
{ text: " Pricing, PricingPeriod", options: { breakLine: true, fontSize: 9, color: C.gray } },
|
||
{ text: "models/charging.py", options: { breakLine: true, fontSize: 9, fontFace: "Consolas", color: C.blue } },
|
||
{ text: " 8 charging models", options: { breakLine: true, fontSize: 9, color: C.gray } },
|
||
{ text: "models/maintenance.py", options: { breakLine: true, fontSize: 9, fontFace: "Consolas", color: C.blue } },
|
||
{ text: " Plan, Record, Order, Duty", options: { breakLine: true, fontSize: 9, color: C.gray } },
|
||
{ text: "models/management.py", options: { breakLine: true, fontSize: 9, fontFace: "Consolas", color: C.blue } },
|
||
{ text: " Regulation, Standard, etc.", options: { breakLine: true, fontSize: 9, color: C.gray } },
|
||
{ text: "models/energy.py", options: { breakLine: true, fontSize: 9, fontFace: "Consolas", color: C.blue } },
|
||
{ text: " EnergyCategory (new)", options: { fontSize: 9, color: C.gray } },
|
||
], { x: 0.65, y: colY + 0.5, w: colW - 0.3, h: colH - 0.6, valign: "top" });
|
||
|
||
// APIs column
|
||
const col2X = 0.5 + colW + colGap;
|
||
s6.addShape(pres.shapes.RECTANGLE, { x: col2X, y: colY, w: colW, h: colH, fill: { color: C.white }, shadow: makeShadow() });
|
||
s6.addShape(pres.shapes.RECTANGLE, { x: col2X, y: colY, w: colW, h: 0.4, fill: { color: C.teal } });
|
||
s6.addText("API接口 (7 files)", { x: col2X, y: colY, w: colW, h: 0.4, fontSize: 13, fontFace: "Microsoft YaHei", color: C.white, align: "center", valign: "middle", bold: true, margin: 0 });
|
||
s6.addText([
|
||
{ text: "api/v1/quota.py", options: { breakLine: true, fontSize: 9, fontFace: "Consolas", color: C.teal } },
|
||
{ text: " 定额管理 CRUD", options: { breakLine: true, fontSize: 9, color: C.gray } },
|
||
{ text: "api/v1/cost.py", options: { breakLine: true, fontSize: 9, fontFace: "Consolas", color: C.teal } },
|
||
{ text: " 费用分析 API", options: { breakLine: true, fontSize: 9, color: C.gray } },
|
||
{ text: "api/v1/charging.py", options: { breakLine: true, fontSize: 9, fontFace: "Consolas", color: C.teal } },
|
||
{ text: " 充电管理 20+ endpoints", options: { breakLine: true, fontSize: 9, color: C.gray } },
|
||
{ text: "api/v1/maintenance.py", options: { breakLine: true, fontSize: 9, fontFace: "Consolas", color: C.teal } },
|
||
{ text: " 运维管理 API", options: { breakLine: true, fontSize: 9, color: C.gray } },
|
||
{ text: "api/v1/management.py", options: { breakLine: true, fontSize: 9, fontFace: "Consolas", color: C.teal } },
|
||
{ text: " 管理体系 CRUD", options: { breakLine: true, fontSize: 9, color: C.gray } },
|
||
{ text: "api/v1/energy.py (扩展)", options: { breakLine: true, fontSize: 9, fontFace: "Consolas", color: C.teal } },
|
||
{ text: " 分类/损耗/同比/环比/参量", options: { breakLine: true, fontSize: 9, color: C.gray } },
|
||
{ text: "api/v1/alarms.py (扩展)", options: { breakLine: true, fontSize: 9, fontFace: "Consolas", color: C.teal } },
|
||
{ text: " 分析/排名/MTTR/Toggle", options: { fontSize: 9, color: C.gray } },
|
||
], { x: col2X + 0.15, y: colY + 0.5, w: colW - 0.3, h: colH - 0.6, valign: "top" });
|
||
|
||
// Services column
|
||
const col3X = col2X + colW + colGap;
|
||
s6.addShape(pres.shapes.RECTANGLE, { x: col3X, y: colY, w: colW, h: colH, fill: { color: C.white }, shadow: makeShadow() });
|
||
s6.addShape(pres.shapes.RECTANGLE, { x: col3X, y: colY, w: colW, h: 0.4, fill: { color: C.green } });
|
||
s6.addText("服务 + 中间件 (6 files)", { x: col3X, y: colY, w: colW, h: 0.4, fontSize: 13, fontFace: "Microsoft YaHei", color: C.white, align: "center", valign: "middle", bold: true, margin: 0 });
|
||
s6.addText([
|
||
{ text: "core/cache.py", options: { breakLine: true, fontSize: 9, fontFace: "Consolas", color: C.green } },
|
||
{ text: " Redis缓存层", options: { breakLine: true, fontSize: 9, color: C.gray } },
|
||
{ text: "core/middleware.py", options: { breakLine: true, fontSize: 9, fontFace: "Consolas", color: C.green } },
|
||
{ text: " 限流/幂等/请求ID", options: { breakLine: true, fontSize: 9, color: C.gray } },
|
||
{ text: "collectors/queue.py", options: { breakLine: true, fontSize: 9, fontFace: "Consolas", color: C.green } },
|
||
{ text: " Redis Streams消息队列", options: { breakLine: true, fontSize: 9, color: C.gray } },
|
||
{ text: "services/aggregation.py", options: { breakLine: true, fontSize: 9, fontFace: "Consolas", color: C.green } },
|
||
{ text: " 时/日/月数据聚合引擎", options: { breakLine: true, fontSize: 9, color: C.gray } },
|
||
{ text: "services/quota_checker.py", options: { breakLine: true, fontSize: 9, fontFace: "Consolas", color: C.green } },
|
||
{ text: " 定额合规检查", options: { breakLine: true, fontSize: 9, color: C.gray } },
|
||
{ text: "services/cost_calculator.py", options: { breakLine: true, fontSize: 9, fontFace: "Consolas", color: C.green } },
|
||
{ text: " 分时电价费用计算", options: { breakLine: true, fontSize: 9, color: C.gray } },
|
||
{ text: "alembic/versions/003-008", options: { breakLine: true, fontSize: 9, fontFace: "Consolas", color: C.green } },
|
||
{ text: " 6个新数据库迁移文件", options: { fontSize: 9, color: C.gray } },
|
||
], { x: col3X + 0.15, y: colY + 0.5, w: colW - 0.3, h: colH - 0.6, valign: "top" });
|
||
|
||
// ============================================================
|
||
// SLIDE 7: Next Steps
|
||
// ============================================================
|
||
let s7 = pres.addSlide();
|
||
s7.background = { color: C.offWhite };
|
||
s7.addShape(pres.shapes.RECTANGLE, { x: 0, y: 0, w: 10, h: 0.06, fill: { color: C.accent } });
|
||
s7.addText("下一步行动计划", { x: 0.7, y: 0.3, w: 8.6, h: 0.55, fontSize: 28, fontFace: "Microsoft YaHei", color: C.darkGray, bold: true, margin: 0 });
|
||
|
||
const steps = [
|
||
{ num: "1", title: "注册Gitea账号", desc: "访问 http://100.108.180.60:3300 注册开发者账号" },
|
||
{ num: "2", title: "Clone仓库", desc: "git clone http://100.108.180.60:3300/tianpu/tianpu-ems.git" },
|
||
{ num: "3", title: "阅读负责代码", desc: "前端组看Slide 5、后端组看Slide 6中列出的文件" },
|
||
{ num: "4", title: "本地运行项目", desc: "backend: uvicorn app.main:app --port 8000\nfrontend: npm install && npm run dev" },
|
||
{ num: "5", title: "登录体验", desc: "http://localhost:3000 账号: admin / admin123" },
|
||
{ num: "6", title: "API文档", desc: "http://localhost:8000/docs (Swagger自动生成)" },
|
||
];
|
||
|
||
steps.forEach((s, i) => {
|
||
const sy = 1.1 + i * 0.72;
|
||
// Number circle
|
||
s7.addShape(pres.shapes.OVAL, { x: 0.7, y: sy + 0.05, w: 0.45, h: 0.45, fill: { color: C.blue } });
|
||
s7.addText(s.num, { x: 0.7, y: sy + 0.05, w: 0.45, h: 0.45, fontSize: 18, fontFace: "Arial", color: C.white, align: "center", valign: "middle", bold: true, margin: 0 });
|
||
// Title + desc
|
||
s7.addText(s.title, { x: 1.35, y: sy, w: 2.0, h: 0.55, fontSize: 15, fontFace: "Microsoft YaHei", color: C.darkGray, valign: "middle", bold: true, margin: 0 });
|
||
s7.addText(s.desc, { x: 3.4, y: sy, w: 6.0, h: 0.55, fontSize: 11, fontFace: "Consolas", color: C.gray, valign: "middle", margin: 0 });
|
||
});
|
||
|
||
// ============================================================
|
||
// SLIDE 8: Verification Results
|
||
// ============================================================
|
||
let s8 = pres.addSlide();
|
||
s8.background = { color: C.navy };
|
||
s8.addShape(pres.shapes.RECTANGLE, { x: 0, y: 0, w: 10, h: 0.06, fill: { color: C.green } });
|
||
|
||
s8.addText("验证结果 — 全部通过", { x: 0.7, y: 0.3, w: 8.6, h: 0.6, fontSize: 28, fontFace: "Microsoft YaHei", color: C.white, bold: true, margin: 0 });
|
||
|
||
const checks = [
|
||
{ icon: "✅", label: "Backend", value: "120+ API routes, 0 errors" },
|
||
{ icon: "✅", label: "Frontend", value: "12 pages, 27 tabs, 0 TS errors" },
|
||
{ icon: "✅", label: "Database", value: "37 tables, seed data populated" },
|
||
{ icon: "✅", label: "API Test", value: "All 20 endpoint groups return real data" },
|
||
{ icon: "✅", label: "Modals", value: "Create / Edit / Delete all functional" },
|
||
{ icon: "✅", label: "Console", value: "0 runtime errors (only antd deprecation warnings)" },
|
||
];
|
||
|
||
checks.forEach((c, i) => {
|
||
const cy = 1.2 + i * 0.65;
|
||
s8.addShape(pres.shapes.RECTANGLE, { x: 0.7, y: cy, w: 8.6, h: 0.5, fill: { color: C.darkBlue } });
|
||
s8.addText(c.icon, { x: 0.9, y: cy, w: 0.5, h: 0.5, fontSize: 18, align: "center", valign: "middle", margin: 0 });
|
||
s8.addText(c.label, { x: 1.5, y: cy, w: 1.5, h: 0.5, fontSize: 14, fontFace: "Microsoft YaHei", color: C.lightBlue, valign: "middle", bold: true, margin: 0 });
|
||
s8.addText(c.value, { x: 3.2, y: cy, w: 6.0, h: 0.5, fontSize: 13, fontFace: "Consolas", color: C.white, valign: "middle", margin: 0 });
|
||
});
|
||
|
||
// Bottom tagline
|
||
s8.addText("准备就绪 — 开始代码Review!", { x: 0.7, y: 5.0, w: 8.6, h: 0.4, fontSize: 16, fontFace: "Microsoft YaHei", color: C.accent, align: "center", bold: true, margin: 0 });
|
||
|
||
// Save
|
||
const outPath = path.resolve("E:/AI_Projects/01.Tianpu_EMS/docs/天普EMS开发任务分配_晨会.pptx");
|
||
pres.writeFile({ fileName: outPath }).then(() => {
|
||
console.log("Presentation saved to: " + outPath);
|
||
}).catch(err => {
|
||
console.error("Error:", err);
|
||
});
|