$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