Files
MES_Manage_View_V20/work/system-design-document/build-independent-system-design.ps1

224 lines
35 KiB
PowerShell
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
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"