843 lines
64 KiB
PowerShell
843 lines
64 KiB
PowerShell
param(
|
||
[string]$OutputDirectory = ''
|
||
)
|
||
|
||
$ErrorActionPreference = 'Stop'
|
||
Add-Type -AssemblyName System.Drawing
|
||
|
||
$scriptRoot = $PSScriptRoot
|
||
$root = (Resolve-Path (Join-Path $scriptRoot '..\..')).Path
|
||
$docDir = if ($OutputDirectory) { $OutputDirectory } else { Join-Path $root 'doc' }
|
||
$assetDir = Join-Path $scriptRoot 'assets'
|
||
$fileBase = '大连元利流体技术有限公司MES系统标准技术文档_V1.1_2026-07-24'
|
||
$docxPath = Join-Path $docDir ($fileBase + '.docx')
|
||
$pdfPath = Join-Path $docDir ($fileBase + '.pdf')
|
||
$buildLog = Join-Path $scriptRoot 'build.log'
|
||
|
||
New-Item -ItemType Directory -Force -Path $docDir, $assetDir | Out-Null
|
||
[IO.File]::WriteAllText($buildLog, "开始生成 $(Get-Date -Format 'yyyy-MM-dd HH:mm:ss')`r`n", [Text.Encoding]::UTF8)
|
||
|
||
function Write-ProgressLog {
|
||
param([string]$Message)
|
||
[IO.File]::AppendAllText($buildLog, "$(Get-Date -Format 'HH:mm:ss') $Message`r`n", [Text.Encoding]::UTF8)
|
||
}
|
||
|
||
function New-Canvas {
|
||
param([int]$Width = 1800, [int]$Height = 980)
|
||
$bitmap = New-Object System.Drawing.Bitmap $Width, $Height
|
||
$graphics = [System.Drawing.Graphics]::FromImage($bitmap)
|
||
$graphics.SmoothingMode = [System.Drawing.Drawing2D.SmoothingMode]::AntiAlias
|
||
$graphics.TextRenderingHint = [System.Drawing.Text.TextRenderingHint]::AntiAliasGridFit
|
||
$graphics.Clear([System.Drawing.Color]::FromArgb(248, 250, 252))
|
||
return @($bitmap, $graphics)
|
||
}
|
||
|
||
function Draw-Box {
|
||
param(
|
||
[System.Drawing.Graphics]$Graphics,
|
||
[int]$X,
|
||
[int]$Y,
|
||
[int]$Width,
|
||
[int]$Height,
|
||
[string]$Title,
|
||
[string]$Detail,
|
||
[System.Drawing.Color]$Fill,
|
||
[System.Drawing.Color]$Border = [System.Drawing.Color]::FromArgb(64, 80, 96)
|
||
)
|
||
$rect = New-Object System.Drawing.Rectangle $X, $Y, $Width, $Height
|
||
$brush = New-Object System.Drawing.SolidBrush $Fill
|
||
$pen = New-Object System.Drawing.Pen $Border, 3
|
||
$Graphics.FillRectangle($brush, $rect)
|
||
$Graphics.DrawRectangle($pen, $rect)
|
||
$titleFont = New-Object System.Drawing.Font 'Microsoft YaHei', 21, ([System.Drawing.FontStyle]::Bold), ([System.Drawing.GraphicsUnit]::Pixel)
|
||
$detailFont = New-Object System.Drawing.Font 'Microsoft YaHei', 16, ([System.Drawing.FontStyle]::Regular), ([System.Drawing.GraphicsUnit]::Pixel)
|
||
$textBrush = New-Object System.Drawing.SolidBrush ([System.Drawing.Color]::FromArgb(30, 41, 59))
|
||
$format = New-Object System.Drawing.StringFormat
|
||
$format.Alignment = [System.Drawing.StringAlignment]::Center
|
||
$format.LineAlignment = [System.Drawing.StringAlignment]::Center
|
||
$titleRect = New-Object System.Drawing.RectangleF ($X + 12), ($Y + 8), ($Width - 24), ([Math]::Min(48, $Height * 0.36))
|
||
$detailRect = New-Object System.Drawing.RectangleF ($X + 14), ($Y + 48), ($Width - 28), ($Height - 54)
|
||
$Graphics.DrawString($Title, $titleFont, $textBrush, $titleRect, $format)
|
||
$Graphics.DrawString($Detail, $detailFont, $textBrush, $detailRect, $format)
|
||
$format.Dispose(); $textBrush.Dispose(); $detailFont.Dispose(); $titleFont.Dispose(); $pen.Dispose(); $brush.Dispose()
|
||
}
|
||
|
||
function Draw-Arrow {
|
||
param([System.Drawing.Graphics]$Graphics, [int]$X1, [int]$Y1, [int]$X2, [int]$Y2, [string]$Label = '')
|
||
$pen = New-Object System.Drawing.Pen ([System.Drawing.Color]::FromArgb(71, 85, 105)), 4
|
||
$pen.CustomEndCap = New-Object System.Drawing.Drawing2D.AdjustableArrowCap 6, 7
|
||
$Graphics.DrawLine($pen, $X1, $Y1, $X2, $Y2)
|
||
if ($Label) {
|
||
$font = New-Object System.Drawing.Font 'Microsoft YaHei', 14, ([System.Drawing.FontStyle]::Regular), ([System.Drawing.GraphicsUnit]::Pixel)
|
||
$brush = New-Object System.Drawing.SolidBrush ([System.Drawing.Color]::FromArgb(71, 85, 105))
|
||
$Graphics.DrawString($Label, $font, $brush, (($X1 + $X2) / 2 - 40), (($Y1 + $Y2) / 2 - 25))
|
||
$brush.Dispose(); $font.Dispose()
|
||
}
|
||
$pen.Dispose()
|
||
}
|
||
|
||
function Save-Canvas {
|
||
param([System.Drawing.Bitmap]$Bitmap, [System.Drawing.Graphics]$Graphics, [string]$Path)
|
||
$Graphics.Dispose()
|
||
$Bitmap.Save($Path, [System.Drawing.Imaging.ImageFormat]::Png)
|
||
$Bitmap.Dispose()
|
||
}
|
||
|
||
function Build-Diagrams {
|
||
$blue = [System.Drawing.Color]::FromArgb(219, 234, 254)
|
||
$teal = [System.Drawing.Color]::FromArgb(204, 251, 241)
|
||
$amber = [System.Drawing.Color]::FromArgb(254, 243, 199)
|
||
$green = [System.Drawing.Color]::FromArgb(220, 252, 231)
|
||
$gray = [System.Drawing.Color]::FromArgb(226, 232, 240)
|
||
$red = [System.Drawing.Color]::FromArgb(254, 226, 226)
|
||
|
||
$canvas = New-Canvas 1800 960; $b = $canvas[0]; $g = $canvas[1]
|
||
Draw-Box $g 60 80 270 150 '用户访问层' 'Chrome / Edge`nPC 与车间终端' $blue
|
||
Draw-Box $g 420 80 350 150 'MES 前端' 'Vue 2.7 + Element UI`n动态菜单、业务交互、报表' $teal
|
||
Draw-Box $g 860 80 380 150 'MES 通用服务' 'HTTPS / MESCommonBase.ashx`n过程调用、上传下载、日志' $amber
|
||
Draw-Box $g 1330 80 390 150 'SQL Server' 'YL_MESDB`n业务数据、视图、存储过程' $green
|
||
Draw-Arrow $g 330 155 420 155 'HTTPS'; Draw-Arrow $g 770 155 860 155 'JSON'; Draw-Arrow $g 1240 155 1330 155 'T-SQL'
|
||
Draw-Box $g 420 380 350 140 'SAP B1 代理服务' 'B1 Service Layer`nGET / POST / PATCH' $blue
|
||
Draw-Box $g 860 380 380 140 'TM 开放接口' '领料、库存及相关业务接口' $teal
|
||
Draw-Box $g 1330 380 390 140 '文件服务' '图纸、附件上传与下载' $gray
|
||
Draw-Arrow $g 595 230 595 380 '业务集成'; Draw-Arrow $g 1050 230 1050 380 '业务集成'; Draw-Arrow $g 1525 230 1525 380 '文件'
|
||
Draw-Box $g 420 680 350 140 'AGV / 物流接口' '搬运任务下发与状态维护' $amber
|
||
Draw-Box $g 860 680 380 140 '设备 / MQTT' '设备变量读取、写入与状态采集' $red
|
||
Draw-Box $g 1330 680 390 140 '质量与看板接口' 'SPC、趋势图、实时监控' $blue
|
||
Draw-Arrow $g 595 520 595 680; Draw-Arrow $g 1050 520 1050 680; Draw-Arrow $g 1525 520 1525 680
|
||
Save-Canvas $b $g (Join-Path $assetDir 'logical-architecture.png')
|
||
|
||
$canvas = New-Canvas 1900 820; $b = $canvas[0]; $g = $canvas[1]
|
||
$steps = @(
|
||
@('ERP 订单', '销售订单、物料、BOM', $blue),
|
||
@('工艺准备', '标准工艺、生产工艺、图纸', $teal),
|
||
@('计划排产', '工位、人员、数量、时间', $amber),
|
||
@('任务下发', '创建工序任务、进入执行队列', $green),
|
||
@('生产执行', '收料、开工、报工、送检', $blue),
|
||
@('质量闭环', '检验、判定、不合格处置', $red),
|
||
@('完工交付', '工时校验、关闭、入库、发货', $green)
|
||
)
|
||
$xPositions = @(30, 300, 570, 840, 1110, 1380, 1650); $y = 220; $boxWidth = 220; $boxHeight = 165
|
||
for ($i = 0; $i -lt $steps.Count; $i++) { Draw-Box $g $xPositions[$i] $y $boxWidth $boxHeight $steps[$i][0] $steps[$i][1] $steps[$i][2] }
|
||
$labels = @('生成', '排产', '下发', '执行', '检验', '交付')
|
||
for ($i = 0; $i -lt $labels.Count; $i++) { Draw-Arrow $g ($xPositions[$i] + $boxWidth) ($y + 82) $xPositions[$i + 1] ($y + 82) $labels[$i] }
|
||
Draw-Arrow $g ($xPositions[6] + 110) ($y + $boxHeight) ($xPositions[6] + 110) 560
|
||
Draw-Arrow $g ($xPositions[6] + 110) 560 ($xPositions[0] + 110) 560 '异常、返工、计划调整反馈'
|
||
Save-Canvas $b $g (Join-Path $assetDir 'business-flow.png')
|
||
|
||
$canvas = New-Canvas 1800 900; $b = $canvas[0]; $g = $canvas[1]
|
||
Draw-Box $g 80 100 300 150 '账号登录' '用户名、密码验证' $blue
|
||
Draw-Box $g 500 100 300 150 '角色选择' '一个账号可对应多个角色' $teal
|
||
Draw-Box $g 920 100 360 150 '菜单权限读取' '按角色加载菜单及增删改查权限' $amber
|
||
Draw-Box $g 1400 100 300 150 '动态路由' '仅挂载可访问页面' $green
|
||
Draw-Arrow $g 380 175 500 175; Draw-Arrow $g 800 175 920 175; Draw-Arrow $g 1280 175 1400 175
|
||
Draw-Box $g 300 500 360 160 '页面业务请求' '携带 UserID、UserName、ModularID' $blue
|
||
Draw-Box $g 800 500 360 160 '服务端校验与执行' '校验身份、参数与业务规则' $teal
|
||
Draw-Box $g 1300 500 360 160 '审计与结果' '记录操作上下文并返回结果' $gray
|
||
Draw-Arrow $g 1550 250 480 500 '进入业务页面'; Draw-Arrow $g 660 580 800 580; Draw-Arrow $g 1160 580 1300 580
|
||
Save-Canvas $b $g (Join-Path $assetDir 'permission-flow.png')
|
||
|
||
$canvas = New-Canvas 1800 900; $b = $canvas[0]; $g = $canvas[1]
|
||
Draw-Box $g 80 110 330 170 '浏览器终端' '访问 MES Web 站点`n建议统一受管浏览器版本' $blue
|
||
Draw-Box $g 530 110 340 170 'Web 静态资源' 'index.html、JS、CSS`nstatic/config.js 环境配置' $teal
|
||
Draw-Box $g 990 110 340 170 '应用服务' '10101:MES 通用服务`n9996:B1/TM 代理服务' $amber
|
||
Draw-Box $g 1410 110 310 170 '数据库服务' '192.168.2.92`nSQL Server / YL_MESDB' $green
|
||
Draw-Arrow $g 410 195 530 195 'HTTPS'; Draw-Arrow $g 870 195 990 195 'HTTPS'; Draw-Arrow $g 1330 195 1410 195 '内网'
|
||
Draw-Box $g 300 570 360 150 'SAP B1' 'ERP 主数据、订单、库存' $blue
|
||
Draw-Box $g 800 570 360 150 '文件与图纸' '上传、下载、在线预览' $gray
|
||
Draw-Box $g 1300 570 360 150 'AGV / 设备侧' '9981 AGV 接口及设备通信' $red
|
||
Draw-Arrow $g 1160 280 480 570; Draw-Arrow $g 1160 280 980 570; Draw-Arrow $g 1160 280 1480 570
|
||
Save-Canvas $b $g (Join-Path $assetDir 'deployment-topology.png')
|
||
}
|
||
|
||
Build-Diagrams
|
||
Write-ProgressLog '已生成四张技术架构与流程图'
|
||
|
||
$modulePages = [ordered]@{
|
||
'系统管理' = @('人员管理', '角色管理', '菜单管理', '工位管理', '报工操作记录')
|
||
'设备管理' = @('设备信息维护', '设备数据', '设备历史数据', '实时数据')
|
||
'研发管理' = @('设计任务', '设计报工', '设计工时校验', '设计工时报表', '研发财务工时')
|
||
'工艺管理' = @('工序管理', '制定标准工艺', '生产工艺', '工艺查询', '工艺任务', '图纸维护', '工艺维护', '查看图纸', '采购图纸查询')
|
||
'计划排产' = @('机加件排产', '装配件排产', '机加件已排产', '机加件未排产', '优先装配', '计划用表', '装配未排产', '生产订单关闭', '工位任务汇总', '装配已排产', '系统类装配任务', '阀类装配任务', '及时齐套跟踪结果')
|
||
'生产管理' = @('生产计划跟踪', '加工中心', '过程异常管控', '工时校验', '外协管理', '人员绑定', '装配中心', '班次管理', '工时报表', '加急件管理', '拣配任务', '采购外协管理', '工时查询', '机加正在进行中', '装配状态', '外协报表', '工时修正', '物料机器人', '手续确认报表', '发货通知列表', '结算工时')
|
||
'异常提醒' = @('机加及时开工', '外协及时开工', '加急任务列表', '装配及时送检')
|
||
'质量管理' = @('终检', '采购入库检', '销售退货检', '原材料退库检', '序检收检', '质量检验标准', '其他入库检', '质检明细', '不合格品处置', '质检报工', '测试装配任务', '及时检验报表', '产品合格率(工位)')
|
||
'销售订单管理' = @('销售订单状态')
|
||
}
|
||
|
||
$moduleDesign = @(
|
||
@('系统管理', '账号、角色、菜单、工位及操作审计', '人员/角色/菜单基础数据', '全部业务模块的登录与权限基础'),
|
||
@('设备管理', '维护设备台账并查看实时与历史数据', '设备、工位、采集变量', '生产执行、设备看板和设备分析'),
|
||
@('研发管理', '设计任务分派、报工、校验与财务工时', '研发项目、任务、人员、报工记录', '工时统计、成本核算和项目复盘'),
|
||
@('工艺管理', '维护工序、标准工艺、订单工艺及图纸', '物料、工序、标准工艺、订单工艺、图纸', '计划排产、任务下发、生产执行和检验标准'),
|
||
@('计划排产', '将订单工艺分配到工位、人员和时间', '生产订单、工艺路线、资源与日历', '生产任务、齐套跟踪、工位负荷和异常提醒'),
|
||
@('生产管理', '执行收料、开工、暂停、报工、送检和工时闭环', '工序任务、人员、设备、物料和操作记录', '质量检验、完工关闭、工时报表和交付状态'),
|
||
@('异常提醒', '识别未及时开工、未及时送检和加急事项', '计划时间、实际时间、任务状态', '计划调整、现场督办和管理看板'),
|
||
@('质量管理', '执行质量标准、检验、判定与不合格处置', '检验任务、标准、实测值、量具和处置记录', '任务流转、入库、返工/让步/报废和质量统计'),
|
||
@('销售订单管理', '汇总订单从计划到交付的全流程状态', 'SAP 销售订单与 MES 生产/质量/交付数据', '交付协调、客户响应和经营分析')
|
||
)
|
||
|
||
$techStack = @(
|
||
@('前端框架', 'Vue.js', '2.7.16', '单页应用与组件体系'),
|
||
@('UI 组件', 'Element UI', '2.15.14', '表单、表格、弹窗、分页'),
|
||
@('路由', 'Vue Router', '3.6.5', '动态权限路由'),
|
||
@('状态管理', 'Vuex', '3.6.2', '用户、角色、标签页等全局状态'),
|
||
@('HTTP', 'Axios', '0.21.4', 'MES、SAP B1、TM 与其他服务调用'),
|
||
@('图表', 'ECharts', '5.4.3', '看板和统计图'),
|
||
@('日历排程', 'FullCalendar', '6.1.x', '计划日历与排产交互'),
|
||
@('设备通信', 'MQTT.js', '4.3.7', '设备与实时数据通信'),
|
||
@('文档与报表', 'xlsx / jsPDF / pdfjs / docxtemplater', '见 package.json', '导入导出、PDF预览和模板生成'),
|
||
@('构建工具', 'Webpack', '5.89.0', '开发服务、生产构建和代码分包'),
|
||
@('数据库', 'Microsoft SQL Server', '2019 / 兼容级别150', 'YL_MESDB 业务数据与过程层')
|
||
)
|
||
|
||
$word = $null; $doc = $null
|
||
try {
|
||
$word = New-Object -ComObject Word.Application
|
||
$word.Visible = $false
|
||
$word.DisplayAlerts = 0
|
||
$doc = $word.Documents.Add()
|
||
$selection = $word.Selection
|
||
$normal = $doc.Styles.Item(-1)
|
||
|
||
$section = $doc.Sections.Item(1)
|
||
$section.PageSetup.PaperSize = 7
|
||
$section.PageSetup.TopMargin = $word.CentimetersToPoints(2.3)
|
||
$section.PageSetup.BottomMargin = $word.CentimetersToPoints(2.0)
|
||
$section.PageSetup.LeftMargin = $word.CentimetersToPoints(2.4)
|
||
$section.PageSetup.RightMargin = $word.CentimetersToPoints(2.1)
|
||
$section.PageSetup.HeaderDistance = $word.CentimetersToPoints(1.0)
|
||
$section.PageSetup.FooterDistance = $word.CentimetersToPoints(1.0)
|
||
$section.PageSetup.DifferentFirstPageHeaderFooter = -1
|
||
|
||
$normal.Font.NameFarEast = '宋体'; $normal.Font.Name = 'Arial'; $normal.Font.Size = 10.5
|
||
$normal.ParagraphFormat.LineSpacingRule = 1
|
||
$normal.ParagraphFormat.LineSpacing = 18
|
||
$normal.ParagraphFormat.SpaceAfter = 6
|
||
|
||
foreach ($item in @(@(-2, 16, 0x8F4A31), @(-3, 13, 0x8F4A31), @(-4, 11, 0x6B594F))) {
|
||
$style = $doc.Styles.Item($item[0])
|
||
$style.Font.NameFarEast = '微软雅黑'; $style.Font.Name = 'Arial'; $style.Font.Size = $item[1]
|
||
$style.Font.Bold = 1; $style.Font.Color = $item[2]
|
||
$style.ParagraphFormat.KeepWithNext = -1; $style.ParagraphFormat.SpaceBefore = 10; $style.ParagraphFormat.SpaceAfter = 6
|
||
}
|
||
|
||
function Move-End { $selection.SetRange($doc.Content.End - 1, $doc.Content.End - 1) }
|
||
function Add-Text {
|
||
param([string]$Text, [double]$Size = 10.5, [bool]$Bold = $false, [int]$Align = 0, [int]$Color = 0, [double]$Before = 0, [double]$After = 6, [double]$FirstIndentCm = 0.74)
|
||
$selection.Style = $normal
|
||
$selection.Font.NameFarEast = '宋体'; $selection.Font.Name = 'Arial'; $selection.Font.Size = $Size
|
||
$selection.Font.Bold = [int]$Bold; $selection.Font.Color = $Color
|
||
$selection.ParagraphFormat.Alignment = $Align; $selection.ParagraphFormat.SpaceBefore = $Before; $selection.ParagraphFormat.SpaceAfter = $After
|
||
$selection.ParagraphFormat.FirstLineIndent = $word.CentimetersToPoints($FirstIndentCm)
|
||
$selection.TypeText($Text); $selection.TypeParagraph()
|
||
}
|
||
function Add-Heading {
|
||
param([string]$Text, [int]$Level = 1)
|
||
$styleId = switch ($Level) { 1 { -2 } 2 { -3 } default { -4 } }
|
||
$selection.Style = $doc.Styles.Item($styleId)
|
||
$selection.TypeText($Text); $selection.TypeParagraph(); $selection.Style = $normal
|
||
}
|
||
function Add-Bullet {
|
||
param([string]$Text, [int]$Level = 1)
|
||
$selection.Style = $normal
|
||
$selection.Range.ListFormat.ApplyBulletDefault()
|
||
$selection.ParagraphFormat.LeftIndent = $word.CentimetersToPoints(0.75 + (($Level - 1) * 0.65))
|
||
$selection.ParagraphFormat.FirstLineIndent = $word.CentimetersToPoints(-0.5)
|
||
$selection.TypeText($Text); $selection.TypeParagraph(); $selection.Range.ListFormat.RemoveNumbers()
|
||
$selection.ParagraphFormat.LeftIndent = 0; $selection.ParagraphFormat.FirstLineIndent = 0
|
||
}
|
||
function Add-Number {
|
||
param([string]$Text)
|
||
$selection.Style = $normal
|
||
$selection.Range.ListFormat.ApplyNumberDefault(); $selection.ParagraphFormat.LeftIndent = $word.CentimetersToPoints(0.75)
|
||
$selection.TypeText($Text); $selection.TypeParagraph(); $selection.Range.ListFormat.RemoveNumbers(); $selection.ParagraphFormat.LeftIndent = 0
|
||
}
|
||
function Add-Table {
|
||
param([object[]]$Rows, [double[]]$WidthsCm = @(), [double]$FontSize = 8.7)
|
||
if ($Rows.Count -eq 0) { return }
|
||
Write-ProgressLog ("写入表格:{0}行 x {1}列,首项={2}" -f $Rows.Count, $Rows[0].Count, [string]$Rows[0][0])
|
||
$table = $doc.Tables.Add($selection.Range, $Rows.Count, $Rows[0].Count)
|
||
$table.Borders.Enable = 1; $table.AllowAutoFit = -1
|
||
$table.Range.Font.NameFarEast = '宋体'; $table.Range.Font.Name = 'Arial'; $table.Range.Font.Size = $FontSize
|
||
$table.Range.ParagraphFormat.SpaceAfter = 0; $table.Range.ParagraphFormat.LineSpacingRule = 0
|
||
for ($r = 0; $r -lt $Rows.Count; $r++) {
|
||
for ($c = 0; $c -lt $Rows[$r].Count; $c++) {
|
||
$cell = $table.Cell($r + 1, $c + 1)
|
||
$cell.Range.Text = [string]$Rows[$r][$c]
|
||
$cell.VerticalAlignment = 1
|
||
}
|
||
}
|
||
for ($c = 0; $c -lt $WidthsCm.Count -and $c -lt $table.Columns.Count; $c++) {
|
||
$table.Columns.Item($c + 1).Width = $word.CentimetersToPoints($WidthsCm[$c])
|
||
}
|
||
$table.Rows.Item(1).Range.Bold = 1
|
||
$table.Rows.Item(1).Range.Font.NameFarEast = '微软雅黑'
|
||
$table.Rows.Item(1).Range.ParagraphFormat.Alignment = 1
|
||
$table.Rows.Item(1).Shading.BackgroundPatternColor = 0xE6D8D0
|
||
$table.Rows.Item(1).HeadingFormat = -1
|
||
$table.Rows.AllowBreakAcrossPages = 0
|
||
if ($Rows.Count -le 6) {
|
||
for ($rowIndex = 1; $rowIndex -lt $table.Rows.Count; $rowIndex++) {
|
||
$table.Rows.Item($rowIndex).Range.ParagraphFormat.KeepWithNext = -1
|
||
}
|
||
}
|
||
$selection.SetRange($table.Range.End, $table.Range.End); $selection.TypeParagraph()
|
||
}
|
||
function Add-Note {
|
||
param([string]$Title, [string]$Text, [string]$Kind = 'info')
|
||
$table = $doc.Tables.Add($selection.Range, 1, 1)
|
||
$table.Borders.Enable = 1
|
||
$cell = $table.Cell(1, 1); $cell.Range.Text = "$Title:$Text"
|
||
$cell.Range.Font.NameFarEast = '微软雅黑'; $cell.Range.Font.Name = 'Arial'; $cell.Range.Font.Size = 9.5
|
||
$cell.Range.ParagraphFormat.SpaceAfter = 0
|
||
$cell.Shading.BackgroundPatternColor = switch ($Kind) { 'warn' { 0xD9F2FF } 'risk' { 0xD9E2F3 } default { 0xEAF4E4 } }
|
||
$selection.SetRange($table.Range.End, $table.Range.End); $selection.TypeParagraph()
|
||
}
|
||
function Add-Image {
|
||
param([string]$Path, [double]$WidthCm = 16.0, [string]$Caption = '')
|
||
$selection.ParagraphFormat.Alignment = 1; $selection.ParagraphFormat.FirstLineIndent = 0
|
||
$shape = $selection.InlineShapes.AddPicture($Path, $false, $true)
|
||
$shape.LockAspectRatio = -1; $shape.Width = $word.CentimetersToPoints($WidthCm)
|
||
$selection.TypeParagraph()
|
||
if ($Caption) { Add-Text $Caption 9 $false 1 0 0 8 0 }
|
||
}
|
||
function Add-PageBreak { $selection.InsertBreak(7) }
|
||
|
||
# 封面
|
||
Add-Text '大连元利流体技术有限公司' 18 $true 1 0x8F4A31 65 12 0
|
||
Add-Text 'MES 系统标准技术文档' 28 $true 1 0x51352A 70 16 0
|
||
Add-Text 'System Technical Specification' 15 $false 1 0x6B594F 0 70 0
|
||
$coverRows = @(
|
||
@('文档编号', 'YL-MES-TECH-001'),
|
||
@('系统版本', 'V1.1.0'),
|
||
@('文档版本', 'V1.1'),
|
||
@('基线日期', '2026-07-24'),
|
||
@('文档属性', '内部技术资料'),
|
||
@('适用范围', 'MES 实施、开发、测试、运维及审计')
|
||
)
|
||
Add-Table $coverRows @(4.2, 9.0) 10
|
||
Add-Text '编制依据:当前前端源代码、正式菜单配置、正式数据库只读元数据及现有业务技术资料' 9.5 $false 1 0x666666 55 0 0
|
||
Add-PageBreak
|
||
|
||
Add-Heading '文档控制' 1
|
||
Add-Heading '修订记录' 2
|
||
Add-Table @(
|
||
@('版本', '日期', '修订内容', '状态'),
|
||
@('V1.0', '2026-07-24', '首次形成系统级标准技术文档,覆盖现状架构、部署、权限、数据、接口、运维与验收规范', '正式基线'),
|
||
@('V1.1', '2026-07-24', '修订核心业务流程图,消除主流程与异常回流线重叠并明确箭头方向', '图形修订')
|
||
) @(2.0, 2.8, 10.0, 2.2)
|
||
Add-Heading '审批与分发' 2
|
||
Add-Table @(
|
||
@('角色', '职责', '签署/日期'),
|
||
@('业务负责人', '确认业务边界和关键流程', ''),
|
||
@('技术负责人', '确认架构、接口、数据与变更方案', ''),
|
||
@('运维负责人', '确认部署、备份、监控和应急流程', ''),
|
||
@('质量/测试负责人', '确认测试范围与验收证据', '')
|
||
) @(3.2, 9.2, 4.6)
|
||
Add-Note '保密要求' '本文档包含正式环境拓扑、内部接口约定和数据库对象信息,仅限授权的实施、开发、测试、运维及审计人员使用。账号、口令、私钥和 SAP 会话信息不得写入正文或版本库。' 'warn'
|
||
Add-PageBreak
|
||
|
||
Add-Heading '目录' 1
|
||
$tocRange = $selection.Range
|
||
[void]$doc.TablesOfContents.Add($tocRange, $true, 1, 3)
|
||
Move-End; Add-PageBreak
|
||
|
||
Add-Heading '1 文档说明' 1
|
||
Add-Heading '1.1 目的' 2
|
||
Add-Text '本文档定义 MES 系统当前技术实现基线,并给出部署、配置、权限、数据、接口、运维、变更和验收的统一要求。它用于技术交接和持续维护,不替代面向最终用户的操作手册。'
|
||
Add-Heading '1.2 适用对象' 2
|
||
foreach ($t in @('实施人员:确认网络、服务、数据库、外部系统和上线条件。','开发人员:理解代码结构、请求约定、模块边界、数据链路和变更规则。','测试人员:依据关键状态、接口契约和验收清单设计测试。','运维人员:执行部署、监控、备份、恢复、故障定位和应急处置。','审计与管理人员:核对权限、日志、变更记录和数据保护措施。')) { Add-Bullet $t }
|
||
Add-Heading '1.3 事实与规范的区分' 2
|
||
Add-Table @(
|
||
@('标识', '含义', '使用方式'),
|
||
@('当前实现', '由代码、配置或正式数据库只读元数据确认的现状', '用于复现和维护当前系统'),
|
||
@('标准要求', '后续建设、变更和运维应遵循的控制要求', '作为评审和验收依据'),
|
||
@('改进建议', '现状可运行但存在安全、可维护性或恢复能力风险', '纳入版本计划,评估后实施')
|
||
) @(3.0, 7.0, 7.0)
|
||
Add-Heading '1.4 基线与范围' 2
|
||
Add-Table @(
|
||
@('项目', '基线值'),
|
||
@('项目目录', 'MES_Manage_View_V20'),
|
||
@('前端版本', 'package.json:1.1.0'),
|
||
@('功能范围', '9个一级业务模块,75个正式启用功能页面'),
|
||
@('前端规模', '99个 Vue 页面文件、28个 API 脚本、8个共享 Vue 组件'),
|
||
@('数据库', 'YL_MESDB,SQL Server 2019,兼容级别150'),
|
||
@('数据库规模', '61张用户表、27个视图、425个存储过程、2个函数'),
|
||
@('数据库容量', '约19.44 GB,其中数据约16.62 GB、日志约2.82 GB'),
|
||
@('统计日期', '2026-07-24,只读采集')
|
||
) @(4.2, 12.8)
|
||
|
||
Add-Heading '2 系统概述' 1
|
||
Add-Heading '2.1 建设目标' 2
|
||
Add-Text 'MES 连接 SAP 业务订单与车间执行过程,以工艺和计划为主线,将生产任务落实到工位、设备和人员,记录物料流转、生产操作、工时与质量结果,并向管理侧提供异常、齐套、进度、质量和交付视图。'
|
||
Add-Heading '2.2 系统边界' 2
|
||
Add-Table @(
|
||
@('系统/域', 'MES 负责', '外部系统负责'),
|
||
@('订单与主数据', '接收并使用订单、物料、BOM、供应商等信息', 'SAP B1 维护 ERP 主数据、财务和库存权威记录'),
|
||
@('工艺与计划', '标准/生产工艺、排产、任务下发、工位和时间安排', '外部系统提供订单需求和部分资源信息'),
|
||
@('生产执行', '收料、开工、暂停、报工、送检、人员/设备工时', '设备侧提供状态或执行反馈'),
|
||
@('质量', '检验任务、标准、实测值、判定及不合格处置', 'SAP/库存侧承接入库、退货等结果'),
|
||
@('物流与交付', '拣配、AGV任务、发货通知及订单状态汇总', 'SAP/仓储侧完成库存和交付凭证')
|
||
) @(3.2, 7.1, 6.7)
|
||
Add-Heading '2.3 功能模块' 2
|
||
$rows = @()
|
||
$rows += ,@('模块', '核心职责', '主要输入', '主要输出')
|
||
foreach ($moduleRow in $moduleDesign) { $rows += ,$moduleRow }
|
||
Add-Table $rows @(2.6, 4.8, 4.9, 4.8) 8.2
|
||
Add-Heading '2.4 核心业务主线' 2
|
||
Add-Image (Join-Path $assetDir 'business-flow.png') 16.3 '图2-1 MES 核心业务闭环'
|
||
Add-Note '状态控制原则' '任何会改变订单、工艺、任务、工时、检验或库存状态的操作,都必须在服务端再次校验当前状态和数量边界;前端按钮可见性不能代替业务校验。' 'warn'
|
||
|
||
Add-Heading '3 总体技术架构' 1
|
||
Add-Heading '3.1 逻辑架构' 2
|
||
Add-Image (Join-Path $assetDir 'logical-architecture.png') 16.3 '图3-1 系统逻辑架构'
|
||
Add-Text '浏览器加载 Vue 单页应用。常规 MES 请求经统一 Axios 实例发送到 MESCommonBase.ashx;前端通过统一请求载荷指定执行类型、过程名称、参数、分页和操作上下文。SAP B1、TM、文件、AGV和设备数据通过独立接口访问。'
|
||
Add-Heading '3.2 分层职责' 2
|
||
Add-Table @(
|
||
@('层次', '职责', '主要实现'),
|
||
@('表现层', '查询、表格、表单、弹窗、状态提示和报表', 'Vue / Element UI / ECharts / FullCalendar'),
|
||
@('前端业务层', '页面状态、输入校验、交互编排、路由与权限菜单', 'views、store、router、utils、api'),
|
||
@('应用服务层', '身份上下文、请求解析、过程调用、上传下载、外部系统代理', 'MESCommonBase.ashx、B1/TM代理、文件服务'),
|
||
@('数据逻辑层', '业务校验、状态流转、事务、查询和聚合', 'SQL Server 存储过程、视图、函数'),
|
||
@('集成层', 'SAP、TM、AGV、设备/PLC、文件与质量数据交换', 'HTTPS/JSON、Service Layer、MQTT及专用接口')
|
||
) @(3.0, 7.2, 6.8)
|
||
Add-Heading '3.3 架构约束' 2
|
||
foreach ($t in @('正式环境页面只能通过受控服务访问业务数据,不允许浏览器直连数据库。','写操作必须在数据库事务或等效原子边界内完成,并返回明确的成功、失败和业务原因。','跨系统操作应定义幂等键或重复提交校验,避免任务、报工、检验和库存记录重复。','前端不得持久化数据库密码、SAP密码、服务私钥或其他长期凭据。','所有外部接口失败都应保留可定位的业务编号、请求时间和错误摘要。')) { Add-Bullet $t }
|
||
|
||
Add-Heading '4 技术栈与代码结构' 1
|
||
Add-Heading '4.1 技术栈基线' 2
|
||
$techRows = @()
|
||
$techRows += ,@('类别', '技术', '版本', '用途')
|
||
foreach ($techRow in $techStack) { $techRows += ,$techRow }
|
||
Add-Table $techRows @(3.0, 4.0, 3.0, 7.0)
|
||
Add-Heading '4.2 源码目录' 2
|
||
Add-Table @(
|
||
@('路径', '职责', '变更注意事项'),
|
||
@('src/views', '业务页面和模块组件', '大型页面改动需覆盖状态、权限和接口回归'),
|
||
@('src/api', '封装登录、基础数据、B1、TM及专项接口', '保持请求参数和返回结构兼容'),
|
||
@('src/router', '基础路由、动态菜单树和组件映射', '菜单 component 必须能解析到真实页面'),
|
||
@('src/store', '用户、角色、权限、标签页和应用状态', '登出时清理身份与缓存'),
|
||
@('src/utils', '统一请求、认证 Cookie、CRUD、PDF和设备工具', '共享工具变更需扩大回归范围'),
|
||
@('static/config.js', '运行时环境地址', '按环境发布,不写入账号口令'),
|
||
@('config / build', '开发代理与 Webpack 构建', '生产构建关闭 source map,核对资源路径'),
|
||
@('db_backups', '数据库变更和回退证据', '一事一脚本,具备前置检查、事务和验证')
|
||
) @(4.0, 6.0, 7.0)
|
||
Add-Heading '4.3 模块代码规模' 2
|
||
Add-Table @(
|
||
@('目录', 'Vue 文件数', '说明'),
|
||
@('ProductionManagement', '36', '生产、工时、外协、物流及研发相关页面,复杂度最高'),
|
||
@('QualityManagement', '15', '检验、标准、处置和统计'),
|
||
@('PlanManagement', '13', '机加与装配排产、齐套、关闭及汇总'),
|
||
@('ProcessManagement', '9', '工序、工艺、图纸与工艺任务'),
|
||
@('SystemMaintenance', '6', '人员、角色、菜单、工位和日志'),
|
||
@('Device/Anomalous/Sale 等', '20', '设备、异常提醒、销售状态及框架页面')
|
||
) @(6.0, 3.0, 8.0)
|
||
Add-Heading '4.4 编码与提交规范' 2
|
||
foreach ($t in @('所有源文件统一使用 UTF-8;发现乱码注释或字符串时在独立变更中修复并回归。','新增页面必须同时完成页面组件、菜单配置、权限配置、接口契约和用户/技术文档。','共享组件和全局工具不承载单一页面的特殊规则;跨三个以上页面的稳定重复逻辑才考虑抽取。','禁止在代码中提交正式密码、个人令牌、数据库连接串和私钥。','数据库脚本必须包含对象存在性检查、事务边界、错误回滚、影响说明和只读验证语句。')) { Add-Bullet $t }
|
||
|
||
Add-Heading '5 部署架构与环境配置' 1
|
||
Add-Heading '5.1 正式环境拓扑' 2
|
||
Add-Image (Join-Path $assetDir 'deployment-topology.png') 16.3 '图5-1 当前部署与集成拓扑'
|
||
Add-Heading '5.2 当前运行时端点' 2
|
||
Add-Table @(
|
||
@('用途', '当前配置', '来源/说明'),
|
||
@('MES 通用接口', 'https://192.168.2.92:10101/submit/MESCommonBase.ashx', 'static/config.js:常规业务请求'),
|
||
@('MES 服务根地址', 'https://192.168.2.92:10101', '文件上传下载等'),
|
||
@('SAP B1 代理', 'https://192.168.2.92:9996/b1s', '前端 b1s.js 统一 POST 代理'),
|
||
@('TM 代理', 'https://192.168.2.92:9996/openapi', '前端 tm.js 统一 POST 代理'),
|
||
@('AGV 搬运接口', 'http://192.168.2.92:9981/api/zk/call_agv_move_web', '物料机器人页面当前实现'),
|
||
@('数据库', '192.168.2.92 / YL_MESDB', '凭据单独保管,不进入文档和代码')
|
||
) @(4.0, 8.3, 4.7) 8.4
|
||
Add-Note '安全边界' '上表用于技术维护和网络检查,不代表对所有终端开放。应通过服务器防火墙、反向代理和访问控制限制来源;AGV 当前为 HTTP 地址,应评估升级为 HTTPS 或限定在隔离网络。' 'risk'
|
||
Add-Heading '5.3 前端构建与发布' 2
|
||
Add-Number '安装 Node.js 20 及 npm 9 或更高兼容版本,执行 npm ci 安装锁定依赖。'
|
||
Add-Number '在目标环境准备 static/config.js;只配置服务地址,不加入账号和密码。'
|
||
Add-Number '执行 npm run build,生成 dist 目录。构建脚本会清理 dist/static/config.js,因此发布包中必须由环境配置步骤补回该文件。'
|
||
Add-Number '将 dist 发布至 Web 服务,启用 HTTPS、正确 MIME 类型、静态缓存和 index.html 回退。'
|
||
Add-Number '使用非管理员账号完成登录、菜单、查询、写操作权限和附件访问冒烟测试。'
|
||
Add-Heading '5.4 发布目录要求' 2
|
||
Add-Table @(
|
||
@('内容', '缓存策略', '发布要求'),
|
||
@('index.html', '不缓存或短缓存', '确保新版本入口及时生效'),
|
||
@('带 contenthash 的 JS/CSS', '长期缓存', '文件名变化自动失效'),
|
||
@('static/config.js', '不缓存或短缓存', '按环境独立管理,发布后检查端点'),
|
||
@('图片、字体和图标', '长期缓存', '检查跨域、MIME和中文文件名'),
|
||
@('图纸/附件', '按业务权限', '不得以公共静态目录绕过鉴权')
|
||
) @(4.2, 4.2, 8.6)
|
||
Add-Heading '5.5 回退条件' 2
|
||
foreach ($t in @('登录或动态菜单无法正常加载。','核心查询、保存、下发、报工或检验出现批量失败。','数据库脚本验证失败或数据状态不一致。','SAP、TM、文件、AGV等关键集成产生不可接受的业务中断。','出现越权、敏感信息泄露或无法审计的写操作。')) { Add-Bullet $t }
|
||
|
||
Add-Heading '6 配置管理' 1
|
||
Add-Heading '6.1 配置分类' 2
|
||
Add-Table @(
|
||
@('配置类别', '位置', '管理要求'),
|
||
@('前端运行时地址', 'static/config.js', '环境独立、发布时注入、禁止密码'),
|
||
@('开发代理', 'config/index.js', '仅开发使用,不作为正式环境反向代理依据'),
|
||
@('菜单与页面权限', '登录基础数据_二级菜单', '按角色维护,变更需校验动态路由'),
|
||
@('人员与角色', '系统管理相关基础数据', '最小权限、离职停用、定期复核'),
|
||
@('工位、班次和字典', '业务基础数据', '变更前评估对排产、工时和统计的影响'),
|
||
@('数据库连接与服务凭据', '服务端安全配置', '密钥库/受限配置,不写入前端或文档'),
|
||
@('外部系统端点', '前端运行时配置或服务端配置', '区分开发、测试、正式,纳入连通性检查')
|
||
) @(4.0, 5.5, 7.5)
|
||
Add-Heading '6.2 配置变更控制' 2
|
||
foreach ($t in @('配置变更必须记录变更人、时间、原值、新值、原因、验证结果和回退值。','正式环境配置不得直接从开发环境复制覆盖,必须逐项比对。','菜单路径、组件路径和权限位变更后,需要清除登录缓存并使用目标角色重新登录验证。','工位、班次、字典和状态类配置变更应验证历史数据展示不受破坏。')) { Add-Bullet $t }
|
||
|
||
Add-Heading '7 身份、权限与安全' 1
|
||
Add-Heading '7.1 权限流程' 2
|
||
Add-Image (Join-Path $assetDir 'permission-flow.png') 16.3 '图7-1 登录、菜单与业务请求权限链路'
|
||
Add-Heading '7.2 当前实现' 2
|
||
Add-Table @(
|
||
@('环节', '当前机制', '控制重点'),
|
||
@('登录', '用户名和密码由统一 MES 接口验证', '必须使用可信 HTTPS 证书'),
|
||
@('角色', '账号可关联多个角色;角色编号写入 Admin-Token Cookie', '角色选择后重新加载菜单'),
|
||
@('菜单', '按角色读取菜单数据,getTreeData 构建树并动态 addRoutes', '组件路径必须受白名单/构建产物约束'),
|
||
@('页面权限', '菜单记录含 AddData/DeleteData/EditData/SearchData 权限位', '按钮权限与后端写权限保持一致'),
|
||
@('请求上下文', '公共请求包含 UserID、UserName、ModularID', '服务端不可只信任前端传值'),
|
||
@('登出', '清理用户、账号、角色 Cookie', '同时使服务端会话或令牌失效')
|
||
) @(3.2, 7.4, 6.4)
|
||
Add-Heading '7.3 标准安全要求' 2
|
||
foreach ($t in @('前端权限只用于界面控制,服务端必须对每次查询和写操作校验身份、角色、模块和数据范围。','Cookie 应设置 Secure、SameSite 和合理有效期;如架构允许,应使用 HttpOnly 会话令牌。','密码不得出现在日志、异常消息、浏览器存储、截图和文档中。','所有写操作记录操作人、模块、业务主键、动作、时间、结果和必要的变更摘要。','高风险操作包括删除、订单关闭、任务重置、工时修正、批量下发和质量放行,应增加二次确认与权限分离。','定期复核停用账号、重复角色、过宽菜单和长期未使用权限。')) { Add-Bullet $t }
|
||
Add-Heading '7.4 当前风险与改进优先级' 2
|
||
Add-Table @(
|
||
@('级别', '现状观察', '建议'),
|
||
@('高', '角色编号存于可由前端读取的 Cookie,前端路由守卫将 roles 固定为 admin', '确保服务端基于可信会话重新鉴权;评估更安全的令牌与 Cookie 属性'),
|
||
@('高', '正式端点直接写在 static/config.js,AGV 使用 HTTP', '端点环境化并限制网络来源;AGV 使用 HTTPS 或隔离网络'),
|
||
@('中', 'MES 通用 Axios 超时为1,500,000毫秒(25分钟)', '按业务分类设置超时、取消请求和服务端作业化'),
|
||
@('中', '部分源码中文注释显示编码异常', '统一 UTF-8,禁止乱码进入新提交'),
|
||
@('中', '页面与数据库过程高度耦合', '建立接口契约、回归测试和变更影响清单')
|
||
) @(1.8, 7.1, 8.1) 8.2
|
||
|
||
Add-Heading '8 请求与接口设计' 1
|
||
Add-Heading '8.1 MES 通用请求' 2
|
||
Add-Text '常规页面通过统一服务地址 POST JSON。CreateData 将过程执行所需信息序列化,并补充当前用户和页面上下文。不同历史模块存在多个 type 编号,维护时应以对应服务端实现和现有页面为准,不得仅凭编号推断读写性质。'
|
||
Add-Table @(
|
||
@('字段', '含义', '标准要求'),
|
||
@('type', '后端执行/返回策略标识', '新增类型必须形成接口契约'),
|
||
@('name', '服务端过程或业务命令名称', '禁止由最终用户自由输入'),
|
||
@('param', '参数数组序列化结果', '参数化执行,禁止拼接 SQL'),
|
||
@('pageSize / pageList', '分页和页码信息', '大数据查询必须分页'),
|
||
@('UserID / UserName', '操作用户上下文', '服务端从可信身份核验,不可盲信'),
|
||
@('ModularID', '当前页面路由/模块标识', '用于权限和审计,必须与授权菜单匹配')
|
||
) @(3.5, 6.0, 7.5)
|
||
Add-Heading '8.2 SAP B1 与 TM 代理' 2
|
||
Add-Text 'b1s.js 和 tm.js 将外部 GET、POST、PATCH 统一封装为对代理服务的 POST,请求体包含 func、cmd 和序列化 content。代理层负责与真正外部接口通信并返回结果。该设计避免浏览器直接保存 SAP 凭据,但仍需在代理层实施命令白名单、权限、超时和日志。'
|
||
Add-Table @(
|
||
@('接口族', '超时', '成功返回', '失败处理'),
|
||
@('B1 代理', '100秒', '{ success: true, data }', '提取 SAP error.message 或网络错误'),
|
||
@('TM 代理', '100秒', '{ success: true, data }', '复用相同错误提取逻辑'),
|
||
@('MES 通用接口', '1500秒', 'Axios response', '当前统一实例未集中定义响应拦截器'),
|
||
@('AGV', '页面 Axios 默认行为', '校验返回 ids 包含任务号', '失败后不应更新 MES 任务为 RUNNING')
|
||
) @(3.0, 2.4, 5.5, 6.1)
|
||
Add-Heading '8.3 接口标准' 2
|
||
foreach ($t in @('所有写接口必须定义业务主键、幂等规则、允许状态、数量边界和事务范围。','统一返回结构至少包含 success/code/message/data/traceId;业务失败不使用模糊的“操作失败”。','查询接口明确分页、排序、最大导出量和日期范围;导出应与查询权限一致。','跨系统调用记录请求时间、目标系统、业务编号、结果码和耗时,但对密码、令牌、个人敏感信息脱敏。','对网络超时、重复提交和外部系统成功但 MES 更新失败定义补偿或人工对账流程。')) { Add-Bullet $t }
|
||
|
||
Add-Heading '9 数据架构' 1
|
||
Add-Heading '9.1 正式数据库基线' 2
|
||
Add-Table @(
|
||
@('项目', '当前值', '说明'),
|
||
@('数据库', 'YL_MESDB', 'MES 主业务数据库'),
|
||
@('数据库引擎', 'SQL Server 2019 RTM 15.0.2000.5', '建议评估累计更新补丁'),
|
||
@('兼容级别', '150', 'SQL Server 2019'),
|
||
@('排序规则', 'Chinese_PRC_CI_AS', '中文、不区分大小写、不区分重音'),
|
||
@('恢复模式', 'SIMPLE', '当前不支持日志链上的时间点恢复'),
|
||
@('用户表 / 视图', '61 / 27', '只读元数据统计'),
|
||
@('存储过程 / 函数', '425 / 2', '业务逻辑主要集中在过程层'),
|
||
@('容量', '总计约19.44 GB', '数据约16.62 GB、日志约2.82 GB')
|
||
) @(4.0, 5.4, 7.6)
|
||
Add-Heading '9.2 核心数据域' 2
|
||
Add-Table @(
|
||
@('数据域', '代表性对象', '关键关系'),
|
||
@('订单与任务', 'MES_接口_生产计划、生产任务、子任务', '订单拆分为工序任务,任务关联工艺、工位、人员和数量'),
|
||
@('工艺与图纸', '基础表_工序、标准工艺库、生产工艺库、零件/工艺图纸', '标准工艺可生成订单工艺,订单工艺下发任务'),
|
||
@('生产与工时', '操作记录、报工记录、工时校验表', '开始/暂停/结束形成时段,报工和校验形成结算依据'),
|
||
@('质量', '质检记录、检测零件、检测数据、检验标准、不合格处置', '任务产生检验,检验结果影响后续流转和统计'),
|
||
@('资源', '设备台账、资源主数据、工位人员绑定、班次', '排产和执行以有效工位、设备、人员和班次为约束'),
|
||
@('权限与审计', '人员、角色、人员角色、二级菜单、操作日志', '账号经角色获得菜单与操作权限,业务请求留痕'),
|
||
@('集成与缓存', '物料、BOM、设备实时缓存、历史状态、附件', '承接 SAP、设备、文件等外部数据')
|
||
) @(3.2, 6.6, 7.2) 8.2
|
||
Add-Heading '9.3 关键状态模型' 2
|
||
Add-Table @(
|
||
@('对象', '典型状态/动作', '控制要求'),
|
||
@('生产订单', '未准备工艺 → 已准备工艺 → 已排产 → 执行中 → 完工/关闭', '状态转换需检查工艺、任务、数量和未完成工时'),
|
||
@('工序任务', '待下发/可执行 → 已开工 → 暂停/恢复 → 已报工/完成', '重复开始、越量报工和跨状态操作必须拦截'),
|
||
@('工艺', '生成/编辑 → 保存启用 → 下发任务', '字段即时保存与整条启用要区分;结构变更后重新启用'),
|
||
@('质检任务', '待检 → 检验中 → 合格/不合格 → 处置/放行', '实测值、判定、数量和处置结果保持一致'),
|
||
@('工时', '操作记录 → 计算工时 → 校验/修正 → 结算', '原始记录保留,修正需审计并可追溯')
|
||
) @(3.2, 7.0, 6.8)
|
||
Add-Heading '9.4 数据完整性与事务' 2
|
||
Add-Note '现状观察' '61张用户表仅检测到8个外键约束,较多关联完整性可能由存储过程和业务代码维护。技术变更必须核对逻辑外键、孤儿数据和删除影响。' 'risk'
|
||
foreach ($t in @('订单、任务、工艺、操作记录、报工和检验之间使用稳定业务主键关联。','批量下发、报工、检验保存、订单关闭等跨表写入在同一事务中完成。','数量字段统一精度和单位,写入前校验非负、累计不超计划及合格/不合格合计关系。','删除优先采用业务停用或软删除;确需物理删除时先检查下游引用并记录审计。','时间统一保存完整日期时间,明确计划时间、操作时间、服务器时间和班次边界。')) { Add-Bullet $t }
|
||
Add-Heading '9.5 备份与恢复' 2
|
||
Add-Table @(
|
||
@('项目', '最低要求', '验证证据'),
|
||
@('全量备份', '每日一次,保留周期按公司制度', '备份作业日志与文件校验'),
|
||
@('差异/日志备份', '若要求时间点恢复,将数据库切换为 FULL 并建立日志备份链', '恢复演练可定位到目标时间'),
|
||
@('异地副本', '至少一份与数据库主机故障域隔离', '抽查可读与保留周期'),
|
||
@('恢复演练', '季度或重大版本前执行', '恢复耗时、数据校验、问题清单'),
|
||
@('变更前备份', '数据库结构/过程或批量数据变更前执行', '脚本、备份和回退编号互相引用')
|
||
) @(4.0, 8.0, 5.0)
|
||
|
||
Add-Heading '10 关键业务技术设计' 1
|
||
Add-Heading '10.1 工艺到任务下发' 2
|
||
Add-Number '维护工序基础数据和物料标准工艺。标准工艺是后续订单生成生产工艺的来源。'
|
||
Add-Number '为生产订单生成订单专用生产工艺;调整工序顺序、工时、车间、设备和说明。'
|
||
Add-Number '保存当前订单工艺,使其进入可用于计划和任务生成的启用状态。字段即时保存不等同于整条工艺启用。'
|
||
Add-Number '整单下发按工艺路线生成全部工序任务;单工序下发仅用于补发目标工序。必须防止重复任务。'
|
||
Add-Number '任务进入计划和生产执行后,工艺结构变更必须评估已排产、已开工、工时和质量记录。'
|
||
Add-Heading '10.2 计划排产到生产执行' 2
|
||
Add-Table @(
|
||
@('阶段', '写入/改变', '下游影响'),
|
||
@('排产', '工位、人员、数量、计划开始/完成、外协分组等', '工位负荷、任务可执行时间、物料准备和异常判断'),
|
||
@('收料/领料', '物料接收或领用状态', '允许后续开始并形成物料追踪'),
|
||
@('开工', '任务进入执行状态并形成开始记录', '设备/人员占用、在制进度和工时开始'),
|
||
@('暂停/恢复', '记录暂停区间和原因', '净工时、设备状态和异常统计'),
|
||
@('报工/结束', '完成数量、工时、操作记录和任务进度', '质量送检、后工序、完工判断和工时报表'),
|
||
@('送检/收检', '检验任务或跨工序接收结果', '质量闭环及后续工序可执行性')
|
||
) @(3.1, 6.8, 7.1)
|
||
Add-Heading '10.3 工时闭环' 2
|
||
Add-Text '系统以操作记录为原始事实,结合开始、暂停、恢复和结束时间计算生产/辅助工时;报工记录承载完成数量和确认信息;工时校验和工时修正用于处理异常。任何修正都应保留原值、修正值、原因、操作人和时间,结算工时只使用已满足校验规则的数据。'
|
||
Add-Heading '10.4 质量闭环' 2
|
||
Add-Text '质量任务从生产送检、采购入库、销售退货、原材料退库或其他入库场景产生。检验标准提供项目、上下限、比例和量具要求;检验结果记录实测值、合格/不合格数量和判定。非合格结果进入返工、让步、报废或其他处置,并反馈生产、库存和统计。'
|
||
Add-Heading '10.5 异常与交付' 2
|
||
Add-Text '异常提醒依据计划与实际时间、任务状态和加急标记形成。销售订单状态页面汇总 SAP 和 MES 的计划、齐套、拣配、发料、装配、送检、入库和发货状态。汇总页面原则上只读展示,不应成为绕过原业务模块直接改状态的入口。'
|
||
|
||
Add-Heading '11 模块技术边界' 1
|
||
foreach ($m in $moduleDesign) {
|
||
Add-Heading ("11.{0} {1}" -f ([array]::IndexOf($moduleDesign, $m) + 1), $m[0]) 2
|
||
Add-Table @(
|
||
@('项目', '说明'),
|
||
@('核心职责', $m[1]),
|
||
@('主要输入', $m[2]),
|
||
@('主要输出/影响', $m[3]),
|
||
@('页面范围', ($modulePages[$m[0]] -join '、'))
|
||
) @(3.5, 13.5) 8.4
|
||
}
|
||
|
||
Add-Heading '12 文件、设备与外部集成' 1
|
||
Add-Heading '12.1 图纸与附件' 2
|
||
Add-Table @(
|
||
@('环节', '实现', '控制要求'),
|
||
@('上传', 'MESUploadFile.ashx', '校验扩展名、MIME、大小、病毒和业务归属'),
|
||
@('存储', '文件服务目录与数据库元数据', '文件名不可作为唯一标识,保留哈希/版本/上传人'),
|
||
@('下载/预览', 'webpage/part/ 与 PDF 预览组件', '与业务记录权限一致,避免目录遍历'),
|
||
@('删除', '业务删除记录或状态', '保留审计,防止已下发工艺失去依据')
|
||
) @(3.0, 6.0, 8.0)
|
||
Add-Heading '12.2 AGV' 2
|
||
Add-Text '物料机器人页面先在 MES 创建搬运任务,再调用 AGV 接口下发 ContainerTransportOrder;只有接口返回任务号成功后才将 MES 状态更新为 RUNNING。应补充超时后的任务查询、重复下发幂等和“AGV成功但MES更新失败”的对账补偿。'
|
||
Add-Heading '12.3 设备与 MQTT' 2
|
||
Add-Text '公共工具支持 Cmd_Opc_Read 和 Cmd_Opc_Write,通过设备 API 读取或写入 TagList;MQTT 用于实时数据订阅。写设备命令属于高风险操作,必须限制目标客户端、Tag 白名单、数值范围和操作权限,并记录请求与设备响应。'
|
||
Add-Heading '12.4 SAP B1' 2
|
||
Add-Text 'SAP B1 是订单、物料、BOM、采购、库存等数据的重要外部来源。MES 通过代理执行 Service Layer 请求。集成设计必须明确主数据权威方、同步方向、时间窗口、失败重试、重复数据判定和日常对账。'
|
||
|
||
Add-Heading '13 日志、监控与审计' 1
|
||
Add-Heading '13.1 日志分类' 2
|
||
Add-Table @(
|
||
@('日志', '内容', '用途'),
|
||
@('用户操作日志', '用户、模块、动作、业务主键、结果、时间', '责任追溯和安全审计'),
|
||
@('API 请求/响应日志', '命令、参数摘要、耗时、结果码、traceId', '接口故障定位;敏感字段脱敏'),
|
||
@('数据库作业日志', '备份、同步、清理和计划任务结果', '运维检查和恢复依据'),
|
||
@('外部集成日志', 'SAP/TM/AGV/设备调用状态和业务编号', '跨系统对账和补偿'),
|
||
@('前端错误', '页面、用户、版本、错误栈和时间', '定位浏览器端异常')
|
||
) @(3.8, 8.0, 5.2)
|
||
Add-Heading '13.2 监控指标' 2
|
||
foreach ($t in @('站点与接口可用率、证书有效期、HTTP 5xx 和超时率。','MES 通用接口、B1、TM、AGV接口的P50/P95响应时间和失败率。','数据库 CPU、内存、数据/日志空间、阻塞、死锁、慢查询和备份状态。','订单同步延迟、待下发任务、超时任务、未闭环工时、待检和不合格处置积压。','文件服务容量、上传失败率和无业务引用文件。')) { Add-Bullet $t }
|
||
Add-Heading '13.3 告警分级' 2
|
||
Add-Table @(
|
||
@('级别', '示例', '响应目标'),
|
||
@('P1', '系统不可用、数据破坏、越权或批量错误写入', '立即响应,停止相关写入并启动应急'),
|
||
@('P2', '核心模块不可用、SAP/AGV关键链路中断', '30分钟内响应并给出绕行/恢复方案'),
|
||
@('P3', '单一报表、导出或非核心页面异常', '工作时间内响应并纳入修复计划'),
|
||
@('P4', '体验、文案或低风险数据展示问题', '按版本排期')
|
||
) @(2.0, 10.0, 5.0)
|
||
|
||
Add-Heading '14 性能与容量' 1
|
||
Add-Heading '14.1 查询规范' 2
|
||
foreach ($t in @('列表查询默认分页,日期范围和导出量设置上限。','常用筛选字段建立与查询计划匹配的索引,避免对列进行不可搜索的函数包装。','页面首次加载不并发请求无关的大数据字典和全部明细;明细按需展开。','导出超过同步阈值时转后台任务,并提供下载状态。','对25分钟的通用超时进行业务分类,避免浏览器长期占用连接。')) { Add-Bullet $t }
|
||
Add-Heading '14.2 容量基线与趋势' 2
|
||
Add-Text '当前数据库约19.44 GB。运维应每月记录数据文件、日志文件、核心大表行数、附件容量和增长率;当预计剩余空间不足三个月时提前扩容或归档。归档必须保持订单、任务、工时、质量和审计记录之间的可追溯性。'
|
||
Add-Heading '14.3 性能验收建议' 2
|
||
Add-Table @(
|
||
@('场景', '建议目标', '备注'),
|
||
@('登录与菜单', '正常内网条件下5秒内完成', '包含动态路由构建'),
|
||
@('普通分页查询', 'P95不超过5秒', '合理筛选范围'),
|
||
@('复杂统计报表', 'P95不超过15秒', '超过阈值采用异步'),
|
||
@('保存/状态操作', 'P95不超过5秒', '不含不可控外部系统等待'),
|
||
@('关键外部接口', '定义独立超时、重试和熔断', '避免整页无期限等待')
|
||
) @(4.0, 5.0, 8.0)
|
||
|
||
Add-Heading '15 运维与故障处理' 1
|
||
Add-Heading '15.1 日常检查' 2
|
||
Add-Table @(
|
||
@('频率', '检查项'),
|
||
@('每日', '站点/API可用、数据库空间、备份结果、同步/作业、P1/P2告警、待处理外部接口失败'),
|
||
@('每周', '慢查询、阻塞/死锁、异常日志趋势、菜单权限变更、附件增长和关键业务积压'),
|
||
@('每月', '容量趋势、账号权限复核、证书/密码到期、依赖漏洞、恢复点与监控覆盖'),
|
||
@('每季度', '恢复演练、应急演练、技术债评审和关键业务全链路回归')
|
||
) @(3.0, 14.0)
|
||
Add-Heading '15.2 故障定位顺序' 2
|
||
Add-Number '确认影响范围:单用户、单角色、单页面、单接口、单数据库对象或全系统。'
|
||
Add-Number '记录时间、用户、页面、业务编号、操作和错误信息,不要求用户重复高风险操作。'
|
||
Add-Number '检查浏览器网络请求、服务可用性、外部系统状态和数据库阻塞/错误。'
|
||
Add-Number '使用 traceId、业务主键和操作人关联前端、服务、数据库与外部接口日志。'
|
||
Add-Number '需要数据修复时先备份和评估影响,使用经评审脚本,完成后验证上下游一致性。'
|
||
Add-Heading '15.3 常见故障矩阵' 2
|
||
Add-Table @(
|
||
@('现象', '优先检查', '禁止做法'),
|
||
@('登录后无菜单', '角色、菜单启用、组件路径、Cookie和getInfo返回', '直接给管理员权限绕过'),
|
||
@('页面一直加载', '网络请求、25分钟超时、数据库阻塞和返回规模', '连续刷新并重复写操作'),
|
||
@('保存成功但列表未变', '返回结果、事务提交、查询条件、缓存和刷新逻辑', '未核对数据就再次新增'),
|
||
@('SAP/AGV失败', '外部接口日志、业务编号、幂等状态和MES本地状态', '盲目重复下发'),
|
||
@('工时/数量不一致', '操作记录、报工、检验、修正审计和累计边界', '直接覆盖原始记录'),
|
||
@('图纸打不开', '文件元数据、物理文件、权限、MIME和路径', '将目录改为匿名公开')
|
||
) @(4.0, 8.5, 4.5) 8.2
|
||
|
||
Add-Heading '16 变更、发布与回退' 1
|
||
Add-Heading '16.1 标准变更流程' 2
|
||
Add-Number '提出变更:说明问题、范围、业务规则、数据影响、权限影响和验收标准。'
|
||
Add-Number '技术分析:定位页面、共享工具、接口、过程、表、视图、菜单和外部系统影响。'
|
||
Add-Number '实施:代码和数据库脚本分离管理;正式凭据不进入版本库。'
|
||
Add-Number '验证:静态检查、单元/定向测试、接口测试、数据库只读验证和关键链路回归。'
|
||
Add-Number '发布:备份、窗口确认、脚本执行、前端发布、配置核对和冒烟测试。'
|
||
Add-Number '观察与回退:监控错误率和业务状态;达到回退条件时按预案恢复。'
|
||
Add-Heading '16.2 数据库脚本规范' 2
|
||
foreach ($t in @('文件名包含动作、模块、日期;不覆盖历史脚本。','先备份被修改对象定义;脚本使用 TRY/CATCH、事务和 XACT_ABORT。','对象创建/修改具备前置检查,重复执行不会产生重复业务数据。','禁止在同一脚本中混入无关结构变更和业务数据修复。','附带只读验证查询和明确回退方案;正式执行结果写入变更记录。')) { Add-Bullet $t }
|
||
Add-Heading '16.3 前端发布检查' 2
|
||
Add-Table @(
|
||
@('阶段', '检查项'),
|
||
@('构建前', '锁文件一致、Node/npm版本、ESLint、git diff --check、无敏感信息'),
|
||
@('构建后', 'index、JS/CSS、图标字体、懒加载页面、static/config.js'),
|
||
@('发布后', 'HTTPS、缓存、登录、目标角色菜单、核心查询/写入、附件、导出'),
|
||
@('观察期', '前端错误、接口失败、数据库阻塞和用户反馈')
|
||
) @(3.5, 13.5)
|
||
|
||
Add-Heading '17 测试与验收' 1
|
||
Add-Heading '17.1 测试层次' 2
|
||
Add-Table @(
|
||
@('层次', '覆盖重点', '证据'),
|
||
@('静态检查', 'ESLint、编码、敏感信息、脚本语法', '命令输出与检查报告'),
|
||
@('组件/函数', '校验、状态计算、导出字段和共享工具', '自动化测试结果'),
|
||
@('接口', '参数、权限、分页、错误、幂等和事务', '请求响应样例与数据库核对'),
|
||
@('业务链路', '工艺→排产→下发→生产→质量→关闭/交付', '测试记录和状态截图'),
|
||
@('角色权限', '不同角色的菜单、按钮和数据范围', '权限矩阵'),
|
||
@('非功能', '性能、恢复、安全、兼容性和容量', '压测/演练/扫描报告')
|
||
) @(3.2, 8.0, 5.8)
|
||
Add-Heading '17.2 核心回归场景' 2
|
||
foreach ($t in @('登录、单/多角色选择、菜单加载和退出。','标准工艺生成生产工艺、编辑、保存启用、整单和单工序下发。','机加与装配排产、计划时间/工位/人员/数量调整及已排产查询。','收料、开工、暂停、恢复、报工、送检和工时计算。','采购/过程/终检、实测值保存、不合格处置及下游状态。','订单关闭、齐套、发货通知和销售订单全流程状态。','SAP、TM、图纸附件、AGV和设备接口的成功与失败分支。')) { Add-Bullet $t }
|
||
Add-Heading '17.3 上线验收门槛' 2
|
||
Add-Note '上线条件' 'P1/P2缺陷为0;核心链路通过;数据库脚本、回退和备份验证完成;权限矩阵通过目标角色验证;监控和应急联系人就绪;文档与变更记录已更新。' 'warn'
|
||
|
||
Add-Heading '18 风险与技术债' 1
|
||
Add-Table @(
|
||
@('优先级', '风险/技术债', '影响', '建议行动'),
|
||
@('P0', '正式凭据与权限完全依赖前端将造成越权风险', '数据安全与审计', '确认服务端强制鉴权,开展权限穿透测试'),
|
||
@('P1', '数据库为 SIMPLE 恢复模式', '无法时间点恢复', '依据RPO/RTO决定是否切换FULL并建立日志备份'),
|
||
@('P1', 'SQL Server 2019 RTM 未体现累计更新', '稳定性与安全补丁', '测试后升级到受支持CU'),
|
||
@('P1', 'AGV接口使用HTTP且地址硬编码', '传输安全与环境切换', '服务端代理/HTTPS/配置化'),
|
||
@('P1', '通用请求超时25分钟', '资源占用与用户重复操作', '分类超时、取消、异步任务和幂等'),
|
||
@('P2', '大型单文件页面和过程耦合度高', '维护成本与回归风险', '按业务域拆分并建立契约测试'),
|
||
@('P2', '外键较少,关系主要靠过程维护', '孤儿数据和删除风险', '补充数据质量检查,逐步增加约束'),
|
||
@('P2', '源码存在编码异常', '可读性和误改风险', '统一UTF-8并加入检查')
|
||
) @(2.0, 5.4, 4.0, 5.6) 8.0
|
||
|
||
Add-Heading '19 附录A:正式功能页面清单' 1
|
||
$moduleNo = 1
|
||
foreach ($key in $modulePages.Keys) {
|
||
Add-Heading ("A.{0} {1}" -f $moduleNo, $key) 2
|
||
$rows = @()
|
||
$rows += ,@('序号', '页面名称', '技术归属')
|
||
for ($i = 0; $i -lt $modulePages[$key].Count; $i++) {
|
||
$rows += ,@(($i + 1).ToString(), $modulePages[$key][$i], $key)
|
||
}
|
||
Add-Table $rows @(2.0, 9.0, 6.0)
|
||
$moduleNo++
|
||
}
|
||
|
||
Add-Heading '20 附录B:关键对象参考' 1
|
||
Add-Heading 'B.1 代表性数据库对象' 2
|
||
Add-Table @(
|
||
@('类别', '代表对象', '用途'),
|
||
@('生产计划', 'MES_接口_生产计划、MES_接口_生产计划_生产任务', '订单和工序任务主数据'),
|
||
@('工艺', '基础表_工序、标准工艺库、生产工艺库', '工序与路线'),
|
||
@('工时', 'YL_加工中心_操作记录表、YL_加工中心_报工记录', '开始、暂停、结束和报工事实'),
|
||
@('质量', 'YL_质量检验_质检记录及检测明细', '检验结果与实测数据'),
|
||
@('资源', 'MES_资源主数据、设备台账、工位人员绑定表、班次表', '工位设备与人员班次'),
|
||
@('权限', '登录基础数据_人员信息、角色信息、人员权限角色、二级菜单', '身份、角色和菜单权限'),
|
||
@('日志', '_日志、记录_日志_项目运行日志', '用户操作与接口请求响应')
|
||
) @(3.0, 8.0, 6.0) 8.2
|
||
Add-Heading 'B.2 关键前端入口' 2
|
||
Add-Table @(
|
||
@('文件', '职责'),
|
||
@('src/main.js', '注册 Vue、Element UI、公共指令、CRUD、图表和根实例'),
|
||
@('src/permission.js', '登录白名单、动态菜单加载和路由守卫'),
|
||
@('src/router/getTreeData.js', '将数据库菜单转换为路由树'),
|
||
@('src/utils/request.js', 'MES 通用 Axios 实例和文件地址'),
|
||
@('src/utils/curd.js', '统一请求载荷、通用表格操作和设备读写辅助'),
|
||
@('src/api/b1s.js / tm.js', 'SAP B1 与 TM 代理封装'),
|
||
@('static/config.js', '正式运行时服务地址')
|
||
) @(6.0, 11.0)
|
||
|
||
Add-Heading '21 附录C:上线与运维检查表' 1
|
||
Add-Table @(
|
||
@('编号', '检查项', '结果', '责任人/日期'),
|
||
@('C-01', '前端构建、版本号、资源和 static/config.js 正确', '□通过 □不通过', ''),
|
||
@('C-02', 'HTTPS证书、端口、防火墙和DNS/地址可用', '□通过 □不通过', ''),
|
||
@('C-03', '数据库备份完成且可读取,回退脚本已准备', '□通过 □不通过', ''),
|
||
@('C-04', '数据库脚本执行与只读验证完成', '□通过 □不通过', ''),
|
||
@('C-05', '目标角色菜单、按钮与数据权限验证完成', '□通过 □不通过', ''),
|
||
@('C-06', '核心业务链路与外部接口冒烟通过', '□通过 □不通过', ''),
|
||
@('C-07', '日志、监控、告警和应急联系人就绪', '□通过 □不通过', ''),
|
||
@('C-08', '变更记录、技术文档和用户文档已更新', '□通过 □不通过', ''),
|
||
@('C-09', '观察期和回退决策人已明确', '□通过 □不通过', '')
|
||
) @(1.8, 9.4, 3.4, 3.0) 8.2
|
||
|
||
# 页眉页脚
|
||
$header = $section.Headers.Item(1).Range
|
||
$header.Text = '大连元利流体技术有限公司 MES 系统标准技术文档'
|
||
$header.Font.NameFarEast = '微软雅黑'; $header.Font.Name = 'Arial'; $header.Font.Size = 8.5; $header.Font.Color = 0x777777
|
||
$header.ParagraphFormat.Alignment = 2
|
||
$footer = $section.Footers.Item(1).Range
|
||
$footer.Text = '内部技术资料 | '
|
||
$footer.Font.NameFarEast = '微软雅黑'; $footer.Font.Name = 'Arial'; $footer.Font.Size = 8.5; $footer.Font.Color = 0x777777
|
||
$footer.ParagraphFormat.Alignment = 1
|
||
$footer.Collapse(0)
|
||
[void]$footer.Fields.Add($footer, 33)
|
||
|
||
foreach ($toc in $doc.TablesOfContents) { $toc.Update() }
|
||
[void]$doc.Fields.Update()
|
||
$doc.Repaginate()
|
||
try {
|
||
$doc.BuiltInDocumentProperties.Item('Title').Value = '大连元利流体技术有限公司MES系统标准技术文档'
|
||
$doc.BuiltInDocumentProperties.Item('Subject').Value = 'MES系统架构、部署、数据、接口、权限、运维与验收技术基线'
|
||
$doc.BuiltInDocumentProperties.Item('Author').Value = 'MESWORK'
|
||
} catch {
|
||
Write-ProgressLog '当前 Office 兼容层不支持写入内置文档属性,已跳过属性写入'
|
||
}
|
||
$doc.SaveAs2($docxPath, 16)
|
||
$doc.ExportAsFixedFormat($pdfPath, 17)
|
||
$pages = $doc.ComputeStatistics(2)
|
||
Write-ProgressLog "已生成 DOCX 和 PDF,共 $pages 页"
|
||
try { $doc.Close($false) } catch { Write-ProgressLog 'Office 已保存文档,但关闭文档时返回兼容层异常' }
|
||
$doc = $null
|
||
try { $word.Quit() } catch { Write-ProgressLog 'Office 进程已退出,但 Quit 调用返回 RPC 兼容层异常' }
|
||
$word = $null
|
||
[GC]::Collect(); [GC]::WaitForPendingFinalizers()
|
||
|
||
[pscustomobject]@{
|
||
Docx = $docxPath
|
||
Pdf = $pdfPath
|
||
Pages = $pages
|
||
Modules = $modulePages.Count
|
||
PagesInScope = ($modulePages.Values | ForEach-Object { $_.Count } | Measure-Object -Sum).Sum
|
||
} | Format-List
|
||
}
|
||
catch {
|
||
Write-ProgressLog ("生成失败:" + $_.Exception.Message)
|
||
if ($null -ne $doc) { try { $doc.Close($false) } catch {} }
|
||
if ($null -ne $word) { try { $word.Quit() } catch {} }
|
||
[GC]::Collect(); [GC]::WaitForPendingFinalizers()
|
||
throw
|
||
}
|
||
|
||
|