feat: 同步全部系统改动与文档

This commit is contained in:
2026-07-28 10:29:56 +08:00
parent 62f7632fc6
commit 1fa1ece06d
487 changed files with 267645 additions and 144 deletions

View File

@@ -0,0 +1,223 @@
param([string]$OutputDirectory = '')
$ErrorActionPreference = 'Stop'
$root = (Resolve-Path (Join-Path $PSScriptRoot '..\..')).Path
$outDir = if ($OutputDirectory) { (Resolve-Path $OutputDirectory).Path } else { Join-Path $root 'doc' }
$base = '大连元利流体技术有限公司MES系统标准设计文档_V1.1_2026-07-24'
$docxPath = Join-Path $outDir ($base + '.docx')
$pdfPath = Join-Path $outDir ($base + '.pdf')
$assetDir = Join-Path $root 'work\system-technical-document\assets'
New-Item -ItemType Directory -Force -Path $outDir, $assetDir | Out-Null
Add-Type -AssemblyName System.Drawing
function New-DiagramCanvas { param([int]$Width,[int]$Height)
$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 Save-Diagram { param($Bitmap,$Graphics,[string]$Path) $Graphics.Dispose(); $Bitmap.Save($Path,[System.Drawing.Imaging.ImageFormat]::Png); $Bitmap.Dispose() }
function Draw-Entity { param($Graphics,[int]$X,[int]$Y,[int]$W,[int]$H,[string]$Title,[string[]]$Fields,[System.Drawing.Color]$Fill)
$rect=New-Object System.Drawing.Rectangle $X,$Y,$W,$H; $Graphics.FillRectangle((New-Object System.Drawing.SolidBrush $Fill),$rect); $Graphics.DrawRectangle((New-Object System.Drawing.Pen ([System.Drawing.Color]::FromArgb(51,65,85)),3),$rect)
$titleFont=New-Object System.Drawing.Font 'Microsoft YaHei',20,([System.Drawing.FontStyle]::Bold); $fieldFont=New-Object System.Drawing.Font 'Microsoft YaHei',14; $brush=New-Object System.Drawing.SolidBrush ([System.Drawing.Color]::FromArgb(30,41,59)); $fmt=New-Object System.Drawing.StringFormat; $fmt.Alignment=[System.Drawing.StringAlignment]::Center
$Graphics.DrawString($Title,$titleFont,$brush,(New-Object System.Drawing.RectangleF ($X+8),($Y+8),($W-16),34),$fmt); $fmt.Alignment=[System.Drawing.StringAlignment]::Near
for($i=0;$i -lt $Fields.Count;$i++){ $Graphics.DrawString($Fields[$i],$fieldFont,$brush,(New-Object System.Drawing.RectangleF ($X+14),($Y+52+($i*25)),($W-28),22),$fmt) }
$fmt.Dispose(); $brush.Dispose(); $fieldFont.Dispose(); $titleFont.Dispose()
}
function Draw-Relation { param($Graphics,[int]$X1,[int]$Y1,[int]$X2,[int]$Y2,[string]$Label)
$pen=New-Object System.Drawing.Pen ([System.Drawing.Color]::FromArgb(71,85,105)),3; $pen.CustomEndCap=New-Object System.Drawing.Drawing2D.AdjustableArrowCap 5,6; $Graphics.DrawLine($pen,$X1,$Y1,$X2,$Y2); $font=New-Object System.Drawing.Font 'Microsoft YaHei',13; $brush=New-Object System.Drawing.SolidBrush ([System.Drawing.Color]::FromArgb(71,85,105)); $Graphics.DrawString($Label,$font,$brush,(($X1+$X2)/2),(($Y1+$Y2)/2-20)); $brush.Dispose(); $font.Dispose(); $pen.Dispose()
}
function Build-DesignDiagrams {
$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); $red=[System.Drawing.Color]::FromArgb(254,226,226)
$c=New-DiagramCanvas 1800 1060; $b=$c[0]; $g=$c[1]
Draw-Entity $g 60 90 360 220 '订单 Order' @('PK 订单编号 + 行号','拆分内码 / 物料 / 数量','交期 / 订单状态') $blue
Draw-Entity $g 720 70 380 240 '工艺版本 Process' @('PK 工艺编号 + 版本','工序顺序 / 工艺要求','启用状态 / 资源') $teal
Draw-Entity $g 1370 90 360 220 '生产任务 Task' @('PK TaskAID','订单工序 / 计划数量','工位 / 指派对象 / 状态') $amber
Draw-Entity $g 90 670 360 220 '操作记录 Operation' @('PK 操作记录ID','开始 / 暂停 / 恢复 / 结束','操作人 / 设备 / 原因') $green
Draw-Entity $g 720 700 380 220 '质量任务 Quality' @('PK 检验任务ID','标准 / 实测值 / 判定','返工 / 让步 / 报废') $red
Draw-Entity $g 1370 670 360 220 '工时与报工 Hours' @('PK 报工记录ID','完成数量 / 生产工时','校验 / 修正 / 结算') $blue
Draw-Relation $g 420 180 720 180 '生成/引用'; Draw-Relation $g 1100 180 1370 180 '展开工序'; Draw-Relation $g 1550 310 900 700 '送检'; Draw-Relation $g 1370 780 1100 800 '产生结果'; Draw-Relation $g 720 800 450 780 '执行事实'; Draw-Relation $g 1370 800 1100 820 '报工/结算'
Save-Diagram $b $g (Join-Path $assetDir 'design-er-model.png')
$c=New-DiagramCanvas 1800 980; $b=$c[0]; $g=$c[1]; $actors=@('浏览器','MES服务','业务过程','SQL Server','外部系统'); $xs=@(150,500,850,1200,1550); $font=New-Object System.Drawing.Font 'Microsoft YaHei',18,([System.Drawing.FontStyle]::Bold); $brush=New-Object System.Drawing.SolidBrush ([System.Drawing.Color]::FromArgb(30,41,59)); $pen=New-Object System.Drawing.Pen ([System.Drawing.Color]::FromArgb(148,163,184)),2; $pen.DashStyle=[System.Drawing.Drawing2D.DashStyle]::Dash
for($i=0;$i -lt $actors.Count;$i++){ $g.DrawString($actors[$i],$font,$brush,$xs[$i]-45,35); $g.DrawLine($pen,$xs[$i],85,$xs[$i],900) }
$font.Dispose(); $brush.Dispose(); $pen.Dispose(); $events=@(@(150,500,130,'1.提交查询/操作'),@(500,850,220,'2.鉴权与参数校验'),@(850,1200,310,'3.执行事务/过程'),@(1200,1550,400,'4.必要时调用外部系统'),@(1550,1200,490,'5.返回外部结果'),@(1200,850,580,'6.提交或回滚'),@(850,500,670,'7.返回业务结果'),@(500,150,760,'8.刷新页面与审计'))
foreach($e in $events){$p=New-Object System.Drawing.Pen ([System.Drawing.Color]::FromArgb(51,65,85)),3; $p.CustomEndCap=New-Object System.Drawing.Drawing2D.AdjustableArrowCap 5,6; $g.DrawLine($p,$e[0],$e[2],$e[1],$e[2]); $f=New-Object System.Drawing.Font 'Microsoft YaHei',15; $br=New-Object System.Drawing.SolidBrush ([System.Drawing.Color]::FromArgb(51,65,85)); $g.DrawString($e[3],$f,$br,(($e[0]+$e[1])/2-55),($e[2]-28)); $br.Dispose(); $f.Dispose(); $p.Dispose() }
Save-Diagram $b $g (Join-Path $assetDir 'design-sequence-order-task.png')
$c=New-DiagramCanvas 1800 950; $b=$c[0]; $g=$c[1]; $states=@(@(80,360,260,120,'未排产',$blue),@(430,170,260,120,'已排产',$amber),@(780,80,260,120,'可执行',$teal),@(1130,170,260,120,'进行中',$green),@(1460,360,260,120,'完成',$blue),@(1130,590,260,120,'送检/处置',$red),@(780,690,260,120,'暂停',$amber)); foreach($s in $states){$r=New-Object System.Drawing.Rectangle $s[0],$s[1],$s[2],$s[3]; $g.FillRectangle((New-Object System.Drawing.SolidBrush $s[5]),$r); $g.DrawRectangle((New-Object System.Drawing.Pen ([System.Drawing.Color]::FromArgb(51,65,85)),3),$r); $f=New-Object System.Drawing.Font 'Microsoft YaHei',21,([System.Drawing.FontStyle]::Bold); $br=New-Object System.Drawing.SolidBrush ([System.Drawing.Color]::FromArgb(30,41,59)); $g.DrawString($s[4],$f,$br,(New-Object System.Drawing.RectangleF ($s[0]),($s[1]+35),$s[2],45),(New-Object System.Drawing.StringFormat)); $br.Dispose(); $f.Dispose() }
Draw-Relation $g 340 420 430 230 '确认排产'; Draw-Relation $g 690 230 780 140 '下发'; Draw-Relation $g 1040 140 1130 230 '收料/开工'; Draw-Relation $g 1390 230 1460 420 '合格/完成'; Draw-Relation $g 1260 290 1260 590 '送检'; Draw-Relation $g 1130 650 1040 750 '暂停'; Draw-Relation $g 780 690 650 290 '取消/重排'; Draw-Relation $g 1460 420 1390 230 '返工/重检'
Save-Diagram $b $g (Join-Path $assetDir 'design-task-state-machine.png')
}
Build-DesignDiagrams
$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.2)
$section.PageSetup.BottomMargin = $word.CentimetersToPoints(2.0)
$section.PageSetup.LeftMargin = $word.CentimetersToPoints(2.3)
$section.PageSetup.RightMargin = $word.CentimetersToPoints(2.1)
$normal.Font.NameFarEast = '宋体'; $normal.Font.Name = 'Arial'; $normal.Font.Size = 10.5
$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 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]$Indent=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($Indent)
$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)
$selection.Style=$normal; $selection.Range.ListFormat.ApplyBulletDefault(); $selection.ParagraphFormat.LeftIndent=$word.CentimetersToPoints(0.75); $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[]]$Widths=@(),[double]$Size=8.7)
$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=$Size; $table.Range.ParagraphFormat.SpaceAfter=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 $Widths.Count -and $c -lt $table.Columns.Count;$c++){ $table.Columns.Item($c+1).Width=$word.CentimetersToPoints($Widths[$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
$selection.SetRange($table.Range.End,$table.Range.End); $selection.TypeParagraph()
}
function Add-Note { param([string]$Title,[string]$Text,[string]$Kind='info')
$shade = switch($Kind) { 'risk' { 0xD9E2F3 } 'warn' { 0xD9F2FF } default { 0xEAF4E4 } }; $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.Size=9.5; $cell.Range.ParagraphFormat.SpaceAfter=0; $cell.Shading.BackgroundPatternColor=$shade; $selection.SetRange($table.Range.End,$table.Range.End); $selection.TypeParagraph()
}
function Add-Image { param([string]$Path,[double]$Width=16,[string]$Caption='')
if(Test-Path $Path){$selection.ParagraphFormat.Alignment=1; $selection.ParagraphFormat.FirstLineIndent=0; $shape=$selection.InlineShapes.AddPicture($Path,$false,$true); $shape.LockAspectRatio=-1; $shape.Width=$word.CentimetersToPoints($Width); $selection.TypeParagraph(); if($Caption){Add-Text $Caption 9 $false 1 0 0 8 0}}
}
function Add-PageBreak { $selection.InsertBreak(7) }
function Move-End { $selection.SetRange($doc.Content.End-1,$doc.Content.End-1) }
# 封面和文档控制
Add-Text '大连元利流体技术有限公司' 18 $true 1 0x8F4A31 58 12 0
Add-Text 'MES 系统标准设计文档' 28 $true 1 0x51352A 68 16 0
Add-Text 'System Design Specification' 15 $false 1 0x6B594F 0 58 0
Add-Table @(@('设计基线','内容'),@('文档编号','YL-MES-DESIGN-001'),@('系统版本','V1.1.0'),@('文档版本','V1.1'),@('基线日期','2026-07-24'),@('设计性质','系统总体设计与详细设计基线'),@('适用对象','架构、开发、实施、测试、运维和业务负责人')) @(4.0,11.0) 9.5
Add-Text '本文档描述 MES 系统的目标、边界、设计决策、业务域、数据模型、接口契约、状态机、非功能指标和验收基线。实现技术细节、现有过程名称和源码定位以《标准技术文档》为准。' 10 $false 1 0x666666 20 0 0
Add-PageBreak
Add-Heading '1 设计总则' 1
Add-Heading '1.1 设计目标' 2
foreach($x in @('以订单、物料、工艺、资源、任务、质量和工时为核心对象,形成可追溯的制造执行闭环。','将业务规则集中在服务端过程和领域边界内,前端负责交互、校验提示和视图编排。','通过角色、菜单、按钮和数据范围实现最小权限,所有关键变更可审计、可回退。','在不改变 SAP B1 主数据权威性的前提下,建立 MES 车间执行状态和异常反馈能力。')){Add-Bullet $x}
Add-Heading '1.2 设计原则' 2
Add-Table @(@('原则','设计要求','验收证据'),@('单一事实源','订单和物料以 SAP/接口主数据为源,执行事实以 MES 记录为源','主数据对账、字段映射表'),@('状态可追溯','状态变更必须有前置状态、操作人、时间和来源','操作日志、状态流转测试'),@('边界清晰','模块通过稳定对象和过程契约协作,不直接修改他域数据','依赖矩阵、接口清单'),@('可恢复','数据库、文件、配置和发布包均有备份和回退路径','恢复演练记录'),@('默认安全','服务端鉴权、参数校验、白名单和审计优先于前端限制','权限穿透测试、审计记录')) @(3.0,8.2,5.0)
Add-Heading '1.3 范围与不在范围' 2
Add-Table @(@('范围','纳入内容','不纳入内容'),@('纳入','MES Web、MESCommonBase、SQL Server、文件服务、SAP B1/TM/AGV/设备集成','MES 之外系统内部实现'),@('纳入','生产计划、工艺、生产执行、质量、工时、设备、研发和看板','ERP 财务总账和人力资源主系统'),@('约束','正式环境只按审批后的脚本和发布包变更','直接在正式库手工改业务数据')) @(3.0,8.2,5.0)
Add-PageBreak
Add-Heading '2 需求与业务域设计' 1
Add-Heading '2.1 业务域划分' 2
Add-Table @(@('业务域','职责边界','核心对象','输出'),@('主数据与权限','人员、角色、菜单、工位、设备和基础参数','人员、角色、资源','可访问菜单和资源上下文'),@('工艺工程','标准工艺、生产工艺、工序、图纸和工艺任务','工序、工艺版本、图纸','可下发的订单工艺路线'),@('计划排产','按工艺和资源安排数量、工位、人员、日期','订单、工序任务、排产记录','未排产/已排产计划'),@('生产执行','收料、开工、暂停、报工、送检、完工','任务、操作记录、报工记录','实时生产状态和完成数量'),@('质量管理','检验标准、实测值、不合格处置和质量统计','检验任务、结果、处置单','合格/返工/让步/报废结论'),@('工时与成本','操作工时、辅助工时、校验、修正、结算','工时记录、校验记录','可信工时和成本数据'),@('集成与交付','ERP、库存、AGV、设备、文件和发货状态协同','接口消息、附件、交付状态','对账结果和交付视图')) @(3.0,6.0,4.0,3.2)
Add-Heading '2.2 角色与责任' 2
Add-Table @(@('角色','允许的设计范围','关键责任'),@('系统管理员','账号、角色、菜单、工位和基础配置','权限审批、账号生命周期、审计'),@('工艺工程师','工序、标准工艺、生产工艺、图纸','工艺版本、启用状态、变更说明'),@('计划员','排产、派工、计划时间和外协分组','资源冲突、计划冻结和调整原因'),@('班组长/操作员','任务执行、报工、送检和异常说明','真实记录现场事实,不代录他人'),@('质量人员','标准、检验、判定和不合格处置','检验结论、复检和质量追溯'),@('运维/开发','部署、接口、数据库和故障处理','变更评审、备份恢复和技术支持')) @(3.5,6.0,6.7)
Add-Heading '2.3 关键业务规则' 2
foreach($x in @('标准工艺是可复用模板,生产工艺是订单或物料的执行版本;只有通过启用和完整性检查的工艺才可下发任务。','同一订单工序的排产数量不得超过可计划数量;计划时间、工位和指派对象变更必须保留操作记录。','生产任务状态必须遵循状态机;已完成或已关闭任务不得通过普通编辑入口回退。','检验不合格必须进入处置分支,不能仅修改显示状态绕过返工、让步或报废流程。')){Add-Bullet $x}
Add-PageBreak
Add-Heading '3 总体架构设计' 1
Add-Heading '3.1 逻辑架构' 2
Add-Image (Join-Path $assetDir 'logical-architecture.png') 16 '图3-1 MES逻辑架构'
Add-Text '系统采用浏览器、MES Web 服务、统一数据库过程层和外部适配器分层。浏览器不直接连接数据库业务请求携带用户和页面上下文经服务端鉴权、参数处理和过程执行后返回结果。SAP B1、TM、AGV、设备和文件服务通过适配器隔离协议差异。'
Add-Heading '3.2 分层职责' 2
Add-Table @(@('层次','职责','禁止事项'),@('表示层','页面、表格、弹窗、交互校验、分页和导出','不在前端伪造最终业务状态'),@('应用服务层','身份上下文、请求编排、过程调用、异常和审计','不绕过权限直接暴露任意过程'),@('领域过程层','状态转换、事务、校验、幂等、聚合查询','不依赖页面字段名称作为唯一契约'),@('数据层','表、视图、索引、约束、日志和备份','正式环境手工修改业务表'),@('集成适配层','SAP/TM/AGV/设备/文件协议转换与重试','把外部凭据下发到浏览器')) @(3.0,7.0,6.2)
Add-Heading '3.3 设计决策记录' 2
Add-Table @(@('编号','决策','原因','影响'),@('ADR-001','常规 MES 查询统一走过程调用','集中权限、事务和数据规则','需要维护过程契约和版本'),@('ADR-002','外部系统通过适配器访问','隔离 SAP/TM/AGV 协议与凭据','需建设重试、超时和对账'),@('ADR-003','附件采用元数据+文件实体','便于权限、版本和生命周期管理','禁止仅凭原始文件名定位'),@('ADR-004','状态事实与统计视图分离','避免报表直接改生产状态','统计延迟和数据质量需监控')) @(2.0,5.0,6.0,4.0)
Add-PageBreak
Add-Heading '4 业务流程与状态设计' 1
Add-Heading '4.1 订单到交付主流程' 2
Add-Image (Join-Path $assetDir 'business-flow.png') 16 '图4-1 订单到交付业务主流程'
Add-Number '接收订单和物料主数据,建立订单行、拆分内码及可视范围。'
Add-Number '维护或选择标准工艺,生成订单生产工艺并校验工序顺序、数量和资源。'
Add-Number '计划员为工序安排工位、人员、数量、计划开始和计划完成时间。'
Add-Number '下发生产任务,任务进入可执行队列;执行过程中记录收料、开工、暂停、报工和送检。'
Add-Number '质量结果和工时校验反馈任务状态,完成任务进入订单关闭、入库或发货协同。'
Add-Heading '4.2 生产任务状态机' 2
Add-Image (Join-Path $assetDir 'design-task-state-machine.png') 16 '图4-2 生产任务状态机'
Add-Table @(@('状态','允许前置','触发动作','允许后续'),@('未排产','新建/计划调整','保存排产信息','已排产、取消'),@('已排产','未排产','确认排产/派工','可执行、重排'),@('可执行','已排产且工艺下发','收料或开工','进行中、异常'),@('进行中','可执行/暂停','开始、恢复、报工','暂停、送检、完成'),@('暂停','进行中','暂停并填写原因','进行中、取消'),@('送检','进行中/报工完成','提交检验任务','完成、返工、让步、报废'),@('完成','检验合格/无需检验','完成确认','关闭/入库')) @(2.7,4.2,5.0,4.0)
Add-Heading '4.3 质量与工时闭环' 2
Add-Text '生产事实、检验事实和工时事实分别记录,再由状态规则和统计视图汇总。工时结算不得直接把页面显示值当作事实;必须使用可校验的开始/结束记录、报工数量、辅助工时和修正原因。质量不合格结果必须保留检验依据及处置结论。'
Add-PageBreak
Add-Heading '5 数据设计' 1
Add-Heading '5.1 核心实体关系' 2
Add-Image (Join-Path $assetDir 'design-er-model.png') 16 '图5-1 MES核心实体关系图ER'
Add-Table @(@('实体','主标识','关键关系','生命周期'),@('订单','订单编号+订单行号+拆分内码','包含物料、工艺和任务','接收、执行、关闭'),@('工艺版本','工艺编号/版本/启用状态','由多个工序组成','草稿、启用、停用'),@('生产任务','任务标识+订单工序','关联工位、人员、计划和报工','未排产至完成'),@('操作记录','记录标识','关联任务和操作人','开始、暂停、恢复、结束'),@('质量任务','检验任务标识','关联任务、标准和结果','待检、检验、处置、关闭'),@('附件','文件标识/哈希','关联订单、物料、工艺或检验','上传、启用、归档')) @(3.0,4.5,6.0,3.5)
Add-Heading '5.2 数据一致性设计' 2
foreach($x in @('所有跨域写入必须由一个明确的业务过程完成,过程内控制事务边界和失败回滚。','查询结果必须明确粒度;一对多关联用于展示时要通过聚合、去重或明确版本条件避免任务行膨胀。','工艺库、任务表和统计视图应定义当前启用记录规则,禁止仅按订单号和工序号无条件关联多个版本。','接口重试必须具备业务幂等键,避免重复创建任务、重复发料、重复报工或重复检验。','删除优先采用停用、关闭或归档,保留历史记录和审计链。')){Add-Bullet $x}
Add-Heading '5.3 数据字典基线' 2
Add-Table @(@('数据域','必须定义的字段','质量规则'),@('订单','订单编号、行号、拆分内码、物料、数量、交期','组合标识唯一,数量非负'),@('工艺','工艺编号、顺序、工艺要求、资源、启用、版本','同一范围仅一个当前启用版本'),@('排产','计划数量、工位、指派对象、开始/完成时间、排产状态','计划数量不超可计划量,时间先后合法'),@('执行','收料、开工、暂停、报工、完成数量','状态与操作记录一致'),@('质量','检验类型、标准、实测值、判定、处置','结果可追溯至任务和人员'),@('审计','用户、角色、页面、动作、参数摘要、结果、时间','禁止记录密码和敏感凭据')) @(3.0,7.4,5.1)
Add-PageBreak
Add-Heading '6 接口与集成设计' 1
Add-Heading '6.1 订单到任务接口时序' 2
Add-Image (Join-Path $assetDir 'design-sequence-order-task.png') 16 '图6-1 订单到生产任务的接口时序图'
Add-Heading '6.2 MES 通用接口契约' 2
Add-Table @(@('部分','设计约束','失败处理'),@('请求上下文','用户标识、页面模块、动作类型、过程名、参数和分页信息','缺失身份或模块上下文直接拒绝'),@('查询响应','数据、总数、错误码、错误消息和关联标识','分页总数必须与结果粒度一致'),@('写入响应','成功标识、业务主键、状态和可重试提示','失败回滚并记录原因'),@('权限','服务端校验菜单、按钮和数据范围','前端隐藏不等于授权'),@('幂等','请求号或业务组合键可重复提交而不重复落库','重复请求返回原结果或明确冲突')) @(3.0,7.3,5.2)
Add-Heading '6.3 外部集成边界' 2
Add-Table @(@('系统','方向','数据','设计要求'),@('SAP B1','SAP→MES为主','订单、物料、BOM、采购和库存','明确主数据权威方、同步窗口和对账'),@('TM/库存','双向按场景','领料、库存、拣配和搬运','超时重试、幂等和人工补偿'),@('AGV','MES→AGV并回传','ContainerTransportOrder及任务状态','避免重复下发,记录外部任务号'),@('设备/MQTT','设备→MES受控写入','变量、状态和设备命令','Tag白名单、范围校验和审计'),@('文件服务','MES↔文件服务','图纸、工艺附件、检验附件','权限一致、哈希校验、版本化')) @(3.0,3.0,5.0,5.0)
Add-Heading '6.4 超时、重试和对账' 2
Add-Text '同步查询和写入采用分类超时外部调用失败不得直接伪造成功状态。可重试错误使用指数退避和幂等键业务不可重试错误进入人工处理队列。每日对订单、任务、库存、AGV和文件实体执行数量及状态对账差异生成可关闭的问题单。'
Add-PageBreak
Add-Heading '7 安全与权限设计' 1
Add-Image (Join-Path $assetDir 'permission-flow.png') 16 '图7-1 身份与权限设计'
Add-Heading '7.1 权限模型' 2
Add-Table @(@('控制点','设计'),@('身份认证','账号、密码、会话和登录失败控制;禁止共享账号'),@('角色授权','用户可关联多个角色,权限取角色授权集合并按数据范围收敛'),@('菜单/按钮','菜单决定入口,按钮决定动作;查询、编辑、确认、删除分别授权'),@('数据范围','按组织、工位、班组、订单或资源限制可见和可操作数据'),@('审计','记录登录、权限变更、关键写入、接口调用、设备写入和异常')) @(4.0,12.0)
Add-Heading '7.2 安全基线' 2
foreach($x in @('正式凭据只保存在服务端配置或密钥系统,前端包、日志和文档不得出现密码。','SQL、文件路径、设备 Tag、外部命令和过程调用采用白名单与参数化策略。','图纸和附件下载必须经过业务权限校验,不能依赖公开目录地址。','设备写入、AGV下发、订单关闭和质量处置属于高风险动作应二次确认并记录前后值。','安全事件按账号、请求号、页面、时间、IP和业务主键关联支持追溯。')){Add-Bullet $x}
Add-PageBreak
Add-Heading '8 部署与运行设计' 1
Add-Image (Join-Path $assetDir 'deployment-topology.png') 16 '图8-1 正式环境部署拓扑'
Add-Heading '8.1 环境划分' 2
Add-Table @(@('环境','用途','数据策略','发布要求'),@('开发','功能开发和单元调试','脱敏或模拟数据','允许快速迭代'),@('测试/预发布','集成、回归、性能和权限验证','接近正式结构的测试数据','必须有版本化构建包'),@('正式','生产执行和经营数据','正式备份、审批和审计','变更窗口、回退包和应急联系人齐备')) @(3.0,5.0,5.0,3.0)
Add-Heading '8.2 发布设计' 2
foreach($x in @('构建阶段锁定依赖、生成版本号和校验文件;发布包包含 dist、运行时配置模板和回退包。','数据库脚本先在测试库执行并验证,再按审批顺序执行正式脚本;脚本必须可重复检查、可审计。','发布前备份数据库、配置、文件索引和当前前端包,发布后执行登录、查询、关键写入、外部接口和回退冒烟。','发布失败时先停止继续变更,依据故障范围选择前端回退、脚本回退或数据补偿,并保留现场日志。')){Add-Number $x}
Add-Heading '8.3 可用性和恢复目标' 2
Add-Table @(@('指标','设计基线','验证方式'),@('RPO','核心数据库按备份策略可恢复;日志和附件纳入备份范围','备份恢复演练'),@('RTO','按故障等级定义恢复时限,关键生产入口优先','故障演练记录'),@('查询性能','常用列表在目标数据量下满足页面交互时延','代表性数据压测'),@('并发控制','同一任务的排产、报工、关闭和质量处置避免并发覆盖','冲突测试、版本校验'),@('容量','每月记录数据库、附件、日志和核心表增长率','容量趋势报告')) @(3.5,8.0,4.5)
Add-PageBreak
Add-Heading '9 测试与验收设计' 1
Add-Heading '9.1 测试层次' 2
Add-Table @(@('层次','对象','通过标准'),@('单元/过程测试','校验、状态转换、计算和异常分支','规则边界和回滚正确'),@('接口测试','MES通用、SAP/TM、AGV、设备和文件接口','契约、超时、重试和幂等通过'),@('集成测试','订单→工艺→排产→执行→质量→交付','主链路和失败链路可追踪'),@('权限测试','角色、按钮、数据范围和越权路径','无越权、无水平或垂直越权'),@('性能/恢复','并发、慢查询、备份恢复和发布回退','达到指标且演练可重复'),@('用户验收','计划员、工艺、班组、质量、管理人员场景','关键岗位签字确认')) @(3.0,7.0,6.0)
Add-Heading '9.2 核心验收场景' 2
foreach($x in @('订单导入后生成标准工艺和生产工艺,验证保存、启用、下发、编辑和版本边界。','机加件和装配件分别排产,验证工位、人员、数量、计划时间、外协分组和已/未排产查询粒度。','执行收料、开工、暂停、恢复、报工、送检和完成,验证状态机、数量和工时记录。','质量合格、不合格、返工、让步和报废分别验证下游状态和追溯。','外部接口成功、超时、重复提交和部分成功分别验证重试、对账和人工补偿。','权限矩阵逐角色验证查询、编辑、确认、删除、设备写入和附件下载。')){Add-Bullet $x}
Add-Heading '9.3 验收交付物' 2
Add-Table @(@('交付物','内容','责任方'),@('设计基线','架构、数据、接口、状态和非功能要求','架构/产品'),@('测试证据','用例、结果、缺陷、性能和恢复记录','测试/运维'),@('变更证据','版本号、审批、脚本、备份和回退记录','开发/实施'),@('运行证据','监控、告警、权限、审计和对账结果','运维/业务')) @(3.5,9.0,3.5)
Add-PageBreak
Add-Heading '10 设计风险与演进路线' 1
Add-Table @(@('优先级','设计风险','影响','演进动作'),@('P0','前端上下文不足或服务端权限不强制','越权和审计失效','统一服务端鉴权、权限穿透测试和审计关联'),@('P1','过程与页面字段耦合,缺少版本化契约','升级回归和接口兼容风险','建立接口契约、过程版本和自动化回归'),@('P1','工艺版本一对多关联导致任务结果膨胀','计划数量、报表和排产判断失真','明确当前启用版本,查询按版本去重并建立数据质量检查'),@('P1','外部接口缺乏统一幂等与补偿','重复任务或状态不一致','统一请求号、对账任务和人工补偿队列'),@('P2','大页面和大过程维护成本高','变更影响面大','按业务域拆分服务、查询和前端页面'),@('P2','统计和事实数据边界不清','报表与现场状态不一致','建立数据产品层和指标口径管理')) @(2.0,5.5,4.2,5.8)
Add-Heading '10.1 分阶段演进' 2
Add-Table @(@('阶段','重点','完成标志'),@('阶段一:基线治理','权限、凭据、过程契约、工艺版本和备份恢复','风险项有负责人和验证记录'),@('阶段二:稳定性提升','接口幂等、对账、监控、慢查询和自动化回归','关键链路可观测、可恢复'),@('阶段三:领域演进','按业务域拆分、统一状态服务、数据产品和容量治理','新功能不依赖跨域直接改表'),@('阶段四:智能优化','负荷预测、异常推荐、设备分析和工艺成本优化','模型结果可解释且不绕过业务审批')) @(4.0,8.0,5.5)
Add-PageBreak
Add-Heading '附录A 设计追踪矩阵' 1
Add-Table @(@('需求/目标','设计章节','实现/验证对象','验收证据'),@('订单可追溯','2、4、5','订单、任务、操作、质量和附件','全流程主键追踪'),@('工艺可复用','2、4、5','标准工艺、生产工艺、启用版本','工艺生成和版本测试'),@('计划可执行','4、5','工序任务、资源、计划时间','排产冲突和状态测试'),@('生产可核算','4、5','操作记录、报工、工时校验','工时计算和修正记录'),@('质量可闭环','4、5、6','检验任务、结果、处置和交付','不合格处置链路'),@('系统可运营','7、8、9、10','权限、日志、监控、备份和回退','演练、审计和验收清单')) @(4.0,4.0,5.8,4.0)
Add-Heading '附录B 设计输入与输出' 1
Add-Table @(@('类别','输入','输出'),@('业务输入','订单、工艺、资源、质量和交付规则','业务域模型、状态机和流程'),@('技术输入','前端源码、服务接口、数据库对象、运行配置','分层架构、接口边界和部署拓扑'),@('运营输入','权限矩阵、备份策略、监控和应急要求','安全、恢复、运维和验收设计'),@('变更输入','缺陷、需求、数据质量和容量趋势','ADR、风险项和演进路线')) @(3.5,7.0,5.5)
$header=$section.Headers.Item(1); $header.Range.Text='大连元利流体技术有限公司 MES 系统标准设计文档'; $header.Range.Font.NameFarEast='微软雅黑'; $header.Range.Font.Size=8; $header.Range.ParagraphFormat.Alignment=2
$footer=$section.Footers.Item(1); $footer.Range.Text='内部设计基线 | YL-MES-DESIGN-001'; $footer.Range.Font.NameFarEast='宋体'; $footer.Range.Font.Size=8; $footer.Range.ParagraphFormat.Alignment=1
try { $doc.BuiltInDocumentProperties.Item('Title').Value='大连元利流体技术有限公司MES系统标准设计文档'; $doc.BuiltInDocumentProperties.Item('Subject').Value='MES系统总体设计基线' } catch { }
$doc.SaveAs2($docxPath,16)
$doc.ExportAsFixedFormat($pdfPath,17)
}
finally {
if($doc){try{$doc.Close($false)}catch{}; try{[void][Runtime.InteropServices.Marshal]::ReleaseComObject($doc)}catch{}}
if($word){try{$word.Quit()}catch{}; try{[void][Runtime.InteropServices.Marshal]::ReleaseComObject($word)}catch{}}
[GC]::Collect(); [GC]::WaitForPendingFinalizers()
}
Write-Output "已生成:$docxPath"
Write-Output "已生成:$pdfPath"

View File

@@ -0,0 +1,51 @@
param(
[string]$OutputDirectory = ''
)
$ErrorActionPreference = 'Stop'
$scriptRoot = $PSScriptRoot
$root = (Resolve-Path (Join-Path $scriptRoot '..\..')).Path
$outputDir = if ($OutputDirectory) { (Resolve-Path $OutputDirectory).Path } else { Join-Path $root 'doc' }
$technicalBuilder = Join-Path $root 'work\system-technical-document\build-standard-technical-document.ps1'
$tempDir = Join-Path $scriptRoot 'source-build'
$technicalBase = '大连元利流体技术有限公司MES系统标准技术文档_V1.0_2026-07-24'
$designBase = '大连元利流体技术有限公司MES系统标准设计文档_V1.0_2026-07-24'
$sourceDocx = Join-Path $tempDir ($technicalBase + '.docx')
$targetDocx = Join-Path $outputDir ($designBase + '.docx')
$targetPdf = Join-Path $outputDir ($designBase + '.pdf')
New-Item -ItemType Directory -Force -Path $outputDir, $tempDir | Out-Null
# 在源构建脚本中替换文档基线名称,再由原有生成器一次性生成 DOCX/PDF。
# 这样可以保留封面、页眉、修订记录和文档属性的一致性。
$sourceScript = Join-Path $tempDir 'build-design-source.ps1'
$sourceText = [IO.File]::ReadAllText($technicalBuilder, [Text.Encoding]::UTF8)
$replacements = @(
@('大连元利流体技术有限公司MES系统标准技术文档_V1.0_2026-07-24', '大连元利流体技术有限公司MES系统标准设计文档_V1.0_2026-07-24'),
@('MES 系统标准技术文档', 'MES 系统标准设计文档'),
@('MES系统标准技术文档', 'MES系统标准设计文档'),
@('System Technical Specification', 'System Design Specification'),
@('首次形成系统级标准技术文档', '首次形成系统级标准设计文档'),
@('本文档定义 MES 系统当前技术实现基线', '本文档定义 MES 系统当前系统设计基线')
)
foreach ($pair in $replacements) {
$sourceText = $sourceText.Replace($pair[0], $pair[1])
}
$utf8Bom = New-Object Text.UTF8Encoding($true)
[IO.File]::WriteAllText($sourceScript, $sourceText, $utf8Bom)
Copy-Item -LiteralPath (Join-Path $root 'work\system-technical-document\assets') -Destination (Join-Path $tempDir 'assets') -Recurse -Force
& powershell.exe -NoProfile -ExecutionPolicy Bypass -File $sourceScript -OutputDirectory $tempDir
$generatedDocx = Join-Path $tempDir ($designBase + '.docx')
$generatedPdf = Join-Path $tempDir ($designBase + '.pdf')
if (-not (Test-Path -LiteralPath $generatedDocx)) {
throw "未找到标准设计文档 DOCX$generatedDocx"
}
if (-not (Test-Path -LiteralPath $generatedPdf)) {
throw "未找到标准设计文档 PDF$generatedPdf"
}
Copy-Item -LiteralPath $generatedDocx -Destination $targetDocx -Force
Copy-Item -LiteralPath $generatedPdf -Destination $targetPdf -Force
Write-Output "已生成:$targetDocx"
Write-Output "已生成:$targetPdf"

Binary file not shown.

After

Width:  |  Height:  |  Size: 38 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 54 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 58 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 47 KiB

View File

@@ -0,0 +1,843 @@
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.0_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 1800 930; $b = $canvas[0]; $g = $canvas[1]
$steps = @(
@('ERP 订单', '销售/生产订单、物料、BOM', $blue),
@('工艺准备', '标准工艺、生产工艺、图纸', $teal),
@('计划排产', '工位、人员、数量与时间', $amber),
@('任务下发', '形成工序任务并进入执行队列', $green),
@('生产执行', '收料、开工、暂停、报工、送检', $blue),
@('质量闭环', '首检、序检、收检、终检、不合格处置', $red),
@('完工交付', '工时校验、订单关闭、入库与发货', $green)
)
for ($i = 0; $i -lt $steps.Count; $i++) {
$x = 65 + ($i % 4) * 430; $y = if ($i -lt 4) { 130 } else { 540 }
Draw-Box $g $x $y 335 170 $steps[$i][0] $steps[$i][1] $steps[$i][2]
if ($i -lt 3) { Draw-Arrow $g ($x + 335) ($y + 85) ($x + 430) ($y + 85) }
if ($i -eq 3) { Draw-Arrow $g ($x + 165) ($y + 170) ($x + 165) 455 '进入执行' }
if ($i -ge 4 -and $i -lt 6) { Draw-Arrow $g ($x + 335) ($y + 85) ($x + 430) ($y + 85) }
}
Draw-Arrow $g 1510 540 1510 410; Draw-Arrow $g 1510 410 280 410 '异常、返工、计划调整反馈'
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 '应用服务' '10101MES 通用服务`n9996B1/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 Design Specification' 15 $false 1 0x6B594F 0 70 0
$coverRows = @(
@('文档编号', 'YL-MES-TECH-001'),
@('系统版本', 'V1.1.0'),
@('文档版本', 'V1.0'),
@('基线日期', '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', '首次形成系统级标准设计文档,覆盖现状架构、部署、权限、数据、接口、运维与验收规范', '正式基线')
) @(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.json1.1.0'),
@('功能范围', '9个一级业务模块75个正式启用功能页面'),
@('前端规模', '99个 Vue 页面文件、28个 API 脚本、8个共享 Vue 组件'),
@('数据库', 'YL_MESDBSQL 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.jsAGV 使用 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 读取或写入 TagListMQTT 用于实时数据订阅。写设备命令属于高风险操作必须限制目标客户端、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
}

View File

@@ -0,0 +1,58 @@
开始生成 2026-07-24 17:13:31
17:13:31 已生成四张技术架构与流程图
17:13:32 写入表格6行 x 2列首项=文档编号
17:13:33 写入表格2行 x 4列首项=版本
17:13:33 写入表格5行 x 3列首项=角色
17:13:33 写入表格4行 x 3列首项=标识
17:13:33 写入表格9行 x 2列首项=项目
17:13:34 写入表格6行 x 3列首项=系统/域
17:13:34 写入表格10行 x 4列首项=模块
17:13:34 写入表格6行 x 3列首项=层次
17:13:35 写入表格12行 x 4列首项=类别
17:13:35 写入表格9行 x 3列首项=路径
17:13:35 写入表格7行 x 3列首项=目录
17:13:36 写入表格7行 x 3列首项=用途
17:13:36 写入表格6行 x 3列首项=内容
17:13:36 写入表格8行 x 3列首项=配置类别
17:13:37 写入表格7行 x 3列首项=环节
17:13:37 写入表格6行 x 3列首项=级别
17:13:37 写入表格7行 x 3列首项=字段
17:13:38 写入表格5行 x 4列首项=接口族
17:13:38 写入表格9行 x 3列首项=项目
17:13:38 写入表格8行 x 3列首项=数据域
17:13:38 写入表格6行 x 3列首项=对象
17:13:39 写入表格6行 x 3列首项=项目
17:13:39 写入表格7行 x 3列首项=阶段
17:13:40 写入表格5行 x 2列首项=项目
17:13:41 写入表格5行 x 2列首项=项目
17:13:41 写入表格5行 x 2列首项=项目
17:13:41 写入表格5行 x 2列首项=项目
17:13:42 写入表格5行 x 2列首项=项目
17:13:42 写入表格5行 x 2列首项=项目
17:13:42 写入表格5行 x 2列首项=项目
17:13:43 写入表格5行 x 2列首项=项目
17:13:43 写入表格5行 x 2列首项=项目
17:13:43 写入表格5行 x 3列首项=环节
17:13:44 写入表格6行 x 3列首项=日志
17:13:44 写入表格5行 x 3列首项=级别
17:13:44 写入表格6行 x 3列首项=场景
17:13:45 写入表格5行 x 2列首项=频率
17:13:45 写入表格7行 x 3列首项=现象
17:13:45 写入表格5行 x 2列首项=阶段
17:13:45 写入表格7行 x 3列首项=层次
17:13:46 写入表格9行 x 4列首项=优先级
17:13:46 写入表格6行 x 3列首项=序号
17:13:46 写入表格5行 x 3列首项=序号
17:13:47 写入表格6行 x 3列首项=序号
17:13:47 写入表格10行 x 3列首项=序号
17:13:47 写入表格14行 x 3列首项=序号
17:13:48 写入表格22行 x 3列首项=序号
17:13:48 写入表格5行 x 3列首项=序号
17:13:48 写入表格14行 x 3列首项=序号
17:13:48 写入表格2行 x 3列首项=序号
17:13:49 写入表格8行 x 3列首项=类别
17:13:51 写入表格8行 x 2列首项=文件
17:13:51 写入表格10行 x 4列首项=编号
17:14:07 当前 Office 兼容层不支持写入内置文档属性,已跳过属性写入
17:14:12 已生成 DOCX 和 PDF共 32 页
17:14:13 Office 进程已退出,但 Quit 调用返回 RPC 兼容层异常