$ErrorActionPreference = "Stop" $outputPath = Join-Path $PSScriptRoot "订单与供应监测模块架构汇报.pptx" $buildDir = Join-Path $PSScriptRoot "pptx-build" if (Test-Path $outputPath) { Remove-Item -LiteralPath $outputPath -Force } if (Test-Path $buildDir) { Remove-Item -LiteralPath $buildDir -Recurse -Force } New-Item -ItemType Directory -Force -Path $buildDir | Out-Null New-Item -ItemType Directory -Force -Path (Join-Path $buildDir "_rels") | Out-Null New-Item -ItemType Directory -Force -Path (Join-Path $buildDir "docProps") | Out-Null New-Item -ItemType Directory -Force -Path (Join-Path $buildDir "ppt") | Out-Null New-Item -ItemType Directory -Force -Path (Join-Path $buildDir "ppt\_rels") | Out-Null New-Item -ItemType Directory -Force -Path (Join-Path $buildDir "ppt\slides") | Out-Null New-Item -ItemType Directory -Force -Path (Join-Path $buildDir "ppt\slides\_rels") | Out-Null New-Item -ItemType Directory -Force -Path (Join-Path $buildDir "ppt\slideMasters") | Out-Null New-Item -ItemType Directory -Force -Path (Join-Path $buildDir "ppt\slideMasters\_rels") | Out-Null New-Item -ItemType Directory -Force -Path (Join-Path $buildDir "ppt\slideLayouts") | Out-Null New-Item -ItemType Directory -Force -Path (Join-Path $buildDir "ppt\slideLayouts\_rels") | Out-Null New-Item -ItemType Directory -Force -Path (Join-Path $buildDir "ppt\theme") | Out-Null $emu = 9525 $shapeId = 1 function XmlEscape($value) { return [System.Security.SecurityElement]::Escape([string]$value) } function Emu($px) { return [int64]([double]$px * $emu) } function Rgb($hex) { return $hex.TrimStart("#").ToUpperInvariant() } function Write-Utf8($path, $content) { $utf8 = New-Object System.Text.UTF8Encoding($false) [System.IO.File]::WriteAllText($path, $content, $utf8) } function TextShape($text, $x, $y, $w, $h, $fontSize, $color, $bold) { $script:shapeId++ $b = if ($bold) { ' b="1"' } else { "" } $paras = @() foreach ($line in ([string]$text -split "`r?`n")) { $paras += @" $(XmlEscape $line) "@ } return @" $($paras -join "") "@ } function RectShape($x, $y, $w, $h, $fill, $line = "FFFFFF", $radius = $false) { $script:shapeId++ $geom = if ($radius) { "roundRect" } else { "rect" } return @" "@ } function Card($title, $body, $x, $y, $w, $h, $accent) { return (RectShape $x $y $w $h "FFFFFF" "DDDDDD" $true) + (RectShape $x $y 8 $h $accent $accent $false) + (TextShape $title ($x + 22) ($y + 16) ($w - 35) 34 17 "17304A" $true) + (TextShape $body ($x + 22) ($y + 58) ($w - 35) ($h - 68) 13 "555555" $false) } function Node($text, $x, $y, $w, $h, $fill, $line) { return (RectShape $x $y $w $h $fill $line $true) + (TextShape $text ($x + 10) ($y + 15) ($w - 20) ($h - 20) 14 "17304A" $true) } function Title($title, $subtitle) { $xml = (TextShape $title 70 42 980 52 30 "17304A" $true) if ($subtitle -ne "") { $xml += TextShape $subtitle 72 92 980 30 14 "666666" $false } $xml += RectShape 70 128 1140 3 "2B74B1" "2B74B1" $false return $xml } $slides = @() $slides += @{ Bg = "FBFAF7" Body = (TextShape "订单监测与供应监测" 90 170 900 58 38 "17304A" $true) + (TextShape "模块架构、功能逻辑与系统关联汇报" 92 238 880 38 20 "666666" $false) + (TextShape "面向管理层的简版说明" 94 300 420 28 15 "2B74B1" $true) + (Card "汇报重点" "1. 两个模块分别解决什么问题`n2. 数据如何进入系统并形成分析结果`n3. 与库存、产品、生命周期等模块如何关联" 760 170 390 250 "2B74B1") } $slides += @{ Bg = "FFFFFF" Body = (Title "一页总览" "两个模块都采用:数据接入 -> 数据入库 -> 后端聚合 -> 前端看板展示") + (Card "订单监测" "关注销售侧:订单金额、商品贡献、渠道/平台表现、支付效率、退款漏损、连带购买。`n`n当前数据库已有核心表,具备较完整的数据分析基础。" 80 170 500 320 "2B74B1") + (Card "供应监测" "关注采购侧:供应商履约、采购订单、入库金额、账期、准交率、付款计划。`n`n当前数据库只有部分基础数据,需补齐采购订单、账期和交付匹配数据。" 700 170 500 320 "449B7A") } $slides += @{ Bg = "FFFFFF" Body = (Title "整体模块架构" "前端页面保持稳定,后端逐步将文件依赖切换为数据库驱动") + (Node "数据文件上传`nCSV / Excel" 70 220 180 78 "DAE7F4" "2B74B1") + (TextShape "→" 268 234 50 50 28 "666666" $true) + (Node "导入服务`n解析 / 清洗 / 校验" 330 220 210 78 "EAF5EC" "449B7A") + (TextShape "→" 558 234 50 50 28 "666666" $true) + (Node "业务数据库`n订单 / 供应 / 库存" 620 220 210 78 "F7F1E8" "E88B3A") + (TextShape "→" 848 234 50 50 28 "666666" $true) + (Node "分析服务`nMapper / 聚合逻辑" 910 220 210 78 "F5F5F5" "666666") + (TextShape "↓" 995 305 50 50 26 "666666" $true) + (Node "管理看板`n图表 / 报表 / 对比" 910 370 210 78 "FFFFFF" "2B74B1") + (Card "架构原则" "接口尽量保持不变,减少前端改造;数据统一入库,避免依赖本地路径;分析逻辑集中在 Service 和 Mapper 层。" 120 500 1030 105 "2B74B1") } $slides += @{ Bg = "FFFFFF" Body = (Title "订单监测:功能逻辑" "订单监测已经具备数据库化基础,重点是持续完善导入和统计口径") + (Card "核心功能" "订单价值分析:GMV、成交金额、退款金额`n商品分析:Top 商品、连带购买`n渠道分析:平台、渠道、业务单元贡献`n支付分析:平均支付耗时、支付漏斗`n经营报表:按日/月/年聚合" 70 165 360 370 "2B74B1") + (Card "实现逻辑" "1. 订单和店铺价值数据进入数据库`n2. Mapper 查询订单主表和店铺价值明细表`n3. Service 聚合指标并返回统一结构`n4. 前端看板按日期范围展示结果" 460 165 360 370 "449B7A") + (Card "当前基础" "dtm_order_main:订单主表`ndtm_shop_value_main:店铺价值明细表`n`n当前数据库中两张核心表已有较多数据,可支撑订单监测主要分析。" 850 165 360 370 "E88B3A") } $slides += @{ Bg = "FFFFFF" Body = (Title "供应监测:功能逻辑" "供应监测目标是从 Excel 文件读取升级为数据库驱动") + (Card "核心功能" "供应商统计:订单金额、入库金额、完成率、准交率`n供应商对比:多个供应商横向比较`n付款计划:账期 + 验收/入库日期计算预计付款`n数据导入:账期、订单、入库、匹配结果" 70 165 360 370 "449B7A") + (Card "实现逻辑" "1. 上传供应监测相关 Excel`n2. 解析供应商、订单、入库、账期字段`n3. 写入供应监测数据表`n4. Service 从数据库聚合供应商指标`n5. 前端继续使用现有查询接口" 460 165 360 370 "2B74B1") + (Card "当前缺口" "数据库已有:供应商基础表、采购入库基础表。`n`n仍缺:采购订单、供应商账期、计划交货日期、实际验收日期、订单入库匹配结果。" 850 165 360 370 "E88B3A") } $slides += @{ Bg = "FFFFFF" Body = (Title "模块关联关系" "两个监测模块不是孤立看板,而是与基础数据和分析模块共享数据资产") + (Card "订单监测关联" "产品模块:通过 SKU 关联商品、SPU、产品信息。`n生命周期模块:复用订单销售数据做热销、趋势、生命周期分析。`n店铺模块:复用平台、渠道、业务单元维度。" 90 170 500 280 "2B74B1") + (Card "供应监测关联" "库存模块:复用采购入库和库存流转数据。`n产品模块:通过 SKU 关联采购产品。`n供应商资料:复用供应商编号和名称,扩展账期和履约指标。" 690 170 500 280 "449B7A") + (Card "通用关联" "系统权限和操作日志可统一管理导入权限、导入记录和异常追踪;导入批次设计可在订单和供应两个模块复用。" 190 495 900 95 "E88B3A") } $slides += @{ Bg = "FFFFFF" Body = (Title "数据入库建设重点" "管理层需要关注的是数据完整性、稳定性和可追踪性") + (Card "订单监测" "建设重点:完善导入批次、重复数据处理、异常行反馈。`n`n收益:订单看板稳定、历史数据可追溯、跨模块复用能力强。" 90 170 500 300 "2B74B1") + (Card "供应监测" "建设重点:补齐采购订单、账期、计划交货日期、实际验收日期、匹配结果。`n`n收益:供应商履约分析和付款计划可以稳定落地。" 690 170 500 300 "449B7A") } $slides += @{ Bg = "FFFFFF" Body = (Title "推进路径" "建议分阶段推进,先稳定数据,再扩展分析能力") + (Node "阶段一`n确认数据源和字段口径" 80 220 210 85 "DAE7F4" "2B74B1") + (TextShape "→" 308 240 50 50 28 "666666" $true) + (Node "阶段二`n建设导入和入库表" 370 220 210 85 "EAF5EC" "449B7A") + (TextShape "→" 598 240 50 50 28 "666666" $true) + (Node "阶段三`n切换 Service 查询数据库" 660 220 230 85 "F7F1E8" "E88B3A") + (TextShape "→" 908 240 50 50 28 "666666" $true) + (Node "阶段四`n完善看板和管理报表" 970 220 210 85 "FFFFFF" "2B74B1") + (Card "结论" "订单监测已有较好的数据库基础,重点是规范化导入和追踪。供应监测需要先补齐核心数据表,再将现有 Excel 分析迁移到数据库查询。" 120 430 1040 130 "2B74B1") } function SlideXml($slide) { $bg = Rgb $slide.Bg return @" $($slide.Body) "@ } $overrides = @( '', '', '', '', '', '' ) for ($i = 1; $i -le $slides.Count; $i++) { $overrides += "" Write-Utf8 (Join-Path $buildDir "ppt\slides\slide$i.xml") (SlideXml $slides[$i - 1]) Write-Utf8 (Join-Path $buildDir "ppt\slides\_rels\slide$i.xml.rels") @" "@ } Write-Utf8 (Join-Path $buildDir "[Content_Types].xml") @" $($overrides -join "`n ") "@ Write-Utf8 (Join-Path $buildDir "_rels\.rels") @" "@ $slideIds = @() $presentationRels = @( '' ) for ($i = 1; $i -le $slides.Count; $i++) { $relId = $i + 1 $slideDbId = 255 + $i $slideIds += "" $presentationRels += "" } Write-Utf8 (Join-Path $buildDir "ppt\presentation.xml") @" $($slideIds -join "") "@ Write-Utf8 (Join-Path $buildDir "ppt\_rels\presentation.xml.rels") @" $($presentationRels -join "`n ") "@ Write-Utf8 (Join-Path $buildDir "ppt\slideMasters\slideMaster1.xml") @" "@ Write-Utf8 (Join-Path $buildDir "ppt\slideMasters\_rels\slideMaster1.xml.rels") @" "@ Write-Utf8 (Join-Path $buildDir "ppt\slideLayouts\slideLayout1.xml") @" "@ Write-Utf8 (Join-Path $buildDir "ppt\slideLayouts\_rels\slideLayout1.xml.rels") @" "@ Write-Utf8 (Join-Path $buildDir "ppt\theme\theme1.xml") @" "@ $created = [DateTime]::UtcNow.ToString("s") + "Z" Write-Utf8 (Join-Path $buildDir "docProps\core.xml") @" 订单与供应监测模块架构汇报 Codex Codex $created $created "@ Write-Utf8 (Join-Path $buildDir "docProps\app.xml") @" Codex OpenXML Generator Widescreen $($slides.Count) DTM "@ Add-Type -AssemblyName System.IO.Compression.FileSystem [System.IO.Compression.ZipFile]::CreateFromDirectory($buildDir, $outputPath) Remove-Item -LiteralPath $buildDir -Recurse -Force Write-Output $outputPath