653 lines
38 KiB
PowerShell
653 lines
38 KiB
PowerShell
$ErrorActionPreference = 'Stop'
|
||
|
||
Add-Type -AssemblyName System.Drawing
|
||
|
||
$root = (Resolve-Path (Join-Path $PSScriptRoot '..\..')).Path
|
||
$shots = Join-Path $PSScriptRoot 'screenshots'
|
||
$prepared = Join-Path $PSScriptRoot 'prepared'
|
||
$docDir = Join-Path $root 'doc'
|
||
$desktop = [Environment]::GetFolderPath('Desktop')
|
||
$fileName = '大连元利流体技术有限公司MES系统操作手册_系统管理篇_样稿'
|
||
$docxPath = Join-Path $docDir ($fileName + '.docx')
|
||
$pdfPath = Join-Path $docDir ($fileName + '.pdf')
|
||
$desktopDocx = Join-Path $desktop ($fileName + '.docx')
|
||
$desktopPdf = Join-Path $desktop ($fileName + '.pdf')
|
||
|
||
New-Item -ItemType Directory -Force -Path $prepared, $docDir | Out-Null
|
||
|
||
function New-Crop {
|
||
param(
|
||
[string]$Source,
|
||
[string]$Target,
|
||
[int]$X,
|
||
[int]$Y,
|
||
[int]$Width,
|
||
[int]$Height
|
||
)
|
||
$sourceImage = [System.Drawing.Bitmap]::FromFile($Source)
|
||
try {
|
||
$cropWidth = [Math]::Min($Width, $sourceImage.Width - $X)
|
||
$cropHeight = [Math]::Min($Height, $sourceImage.Height - $Y)
|
||
$targetImage = New-Object System.Drawing.Bitmap($cropWidth, $cropHeight)
|
||
try {
|
||
$graphics = [System.Drawing.Graphics]::FromImage($targetImage)
|
||
try {
|
||
$graphics.DrawImage(
|
||
$sourceImage,
|
||
(New-Object System.Drawing.Rectangle(0, 0, $cropWidth, $cropHeight)),
|
||
(New-Object System.Drawing.Rectangle($X, $Y, $cropWidth, $cropHeight)),
|
||
[System.Drawing.GraphicsUnit]::Pixel
|
||
)
|
||
} finally {
|
||
$graphics.Dispose()
|
||
}
|
||
$targetImage.Save($Target, [System.Drawing.Imaging.ImageFormat]::Png)
|
||
} finally {
|
||
$targetImage.Dispose()
|
||
}
|
||
} finally {
|
||
$sourceImage.Dispose()
|
||
}
|
||
}
|
||
|
||
Copy-Item (Join-Path $shots '01-personnel-list.png') (Join-Path $prepared 'personnel-list.png') -Force
|
||
Copy-Item (Join-Path $shots '03-menu-list.png') (Join-Path $prepared 'menu-list.png') -Force
|
||
Copy-Item (Join-Path $shots '03-menu-permission-panel.png') (Join-Path $prepared 'menu-permission.png') -Force
|
||
Copy-Item (Join-Path $shots '05-operation-log.png') (Join-Path $prepared 'operation-log.png') -Force
|
||
New-Crop (Join-Path $shots '01-personnel-add-dialog.png') (Join-Path $prepared 'personnel-add.png') 560 105 800 470
|
||
New-Crop (Join-Path $shots '02-role-list.png') (Join-Path $prepared 'role-list.png') 0 0 1020 940
|
||
New-Crop (Join-Path $shots '02-role-add-dialog.png') (Join-Path $prepared 'role-add.png') 560 105 800 390
|
||
New-Crop (Join-Path $shots '04-workstation-list.png') (Join-Path $prepared 'workstation-list.png') 0 0 1020 940
|
||
New-Crop (Join-Path $shots '04-workstation-add-dialog.png') (Join-Path $prepared 'workstation-add.png') 560 105 800 450
|
||
|
||
$word = $null
|
||
$doc = $null
|
||
$buildError = $null
|
||
|
||
try {
|
||
$word = New-Object -ComObject Word.Application
|
||
$word.Visible = $false
|
||
$word.DisplayAlerts = 0
|
||
$doc = $word.Documents.Add()
|
||
$selection = $word.Selection
|
||
|
||
$doc.PageSetup.PageWidth = $word.CentimetersToPoints(21)
|
||
$doc.PageSetup.PageHeight = $word.CentimetersToPoints(29.7)
|
||
$doc.PageSetup.TopMargin = $word.CentimetersToPoints(2.2)
|
||
$doc.PageSetup.BottomMargin = $word.CentimetersToPoints(2.0)
|
||
$doc.PageSetup.LeftMargin = $word.CentimetersToPoints(2.1)
|
||
$doc.PageSetup.RightMargin = $word.CentimetersToPoints(2.1)
|
||
|
||
$normal = $doc.Styles.Item(-1)
|
||
$normal.Font.NameFarEast = '宋体'
|
||
$normal.Font.Name = 'Arial'
|
||
$normal.Font.Size = 10.5
|
||
$normal.ParagraphFormat.LineSpacingRule = 1
|
||
$normal.ParagraphFormat.SpaceAfter = 6
|
||
|
||
function Move-End {
|
||
$end = $doc.Content.End - 1
|
||
$selection.SetRange($end, $end)
|
||
}
|
||
|
||
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
|
||
)
|
||
$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)
|
||
$styleId = switch ($Level) { 1 { -2 } 2 { -3 } default { -4 } }
|
||
$selection.Style = $doc.Styles.Item($styleId)
|
||
$selection.Font.NameFarEast = '微软雅黑'
|
||
$selection.Font.Name = 'Arial'
|
||
$selection.Font.Color = 0x8F4A31
|
||
$selection.Font.Bold = 1
|
||
$selection.ParagraphFormat.KeepWithNext = -1
|
||
$selection.TypeText($Text)
|
||
$selection.TypeParagraph()
|
||
$selection.Style = $normal
|
||
}
|
||
|
||
function Add-StepList {
|
||
param([string[]]$Items)
|
||
for ($i = 0; $i -lt $Items.Count; $i++) {
|
||
Add-Text (('{0}. {1}' -f ($i + 1), $Items[$i])) 10.5 $false 0 0 0 4 0
|
||
}
|
||
}
|
||
|
||
function Add-ItemList {
|
||
param([string[]]$Items)
|
||
foreach ($item in $Items) {
|
||
Add-Text ('(' + ([array]::IndexOf($Items, $item) + 1) + ')' + $item) 10.5 $false 0 0 0 4 0
|
||
}
|
||
}
|
||
|
||
function Add-Table {
|
||
param([object[]]$Rows, [double[]]$WidthsCm = @())
|
||
$range = $selection.Range
|
||
$table = $doc.Tables.Add($range, $Rows.Count, $Rows[0].Count)
|
||
$table.Borders.Enable = 1
|
||
$table.Range.Font.NameFarEast = '宋体'
|
||
$table.Range.Font.Name = 'Arial'
|
||
$table.Range.Font.Size = 9
|
||
$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++) {
|
||
$table.Cell($r + 1, $c + 1).Range.Text = [string]$Rows[$r][$c]
|
||
$table.Cell($r + 1, $c + 1).VerticalAlignment = 1
|
||
if ($WidthsCm.Count -gt $c) {
|
||
$table.Cell($r + 1, $c + 1).Width = $word.CentimetersToPoints($WidthsCm[$c])
|
||
}
|
||
}
|
||
}
|
||
$table.Rows.Item(1).Range.Bold = 1
|
||
$table.Rows.Item(1).Shading.BackgroundPatternColor = 0xE6D8D0
|
||
$table.Rows.Item(1).Range.ParagraphFormat.Alignment = 1
|
||
$table.AllowAutoFit = -1
|
||
Move-End
|
||
$selection.TypeParagraph()
|
||
}
|
||
|
||
function Add-Note {
|
||
param([string]$Title, [string]$Text, [string]$Kind = 'info')
|
||
$range = $selection.Range
|
||
$table = $doc.Tables.Add($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.Font.Bold = 0
|
||
$cell.Range.ParagraphFormat.SpaceAfter = 0
|
||
if ($Kind -eq 'warn') {
|
||
$cell.Shading.BackgroundPatternColor = 0xD9F2FF
|
||
} elseif ($Kind -eq 'danger') {
|
||
$cell.Shading.BackgroundPatternColor = 0xD9E2F3
|
||
} else {
|
||
$cell.Shading.BackgroundPatternColor = 0xF4F1EE
|
||
}
|
||
Move-End
|
||
$selection.TypeParagraph()
|
||
}
|
||
|
||
function Add-Figure {
|
||
param([string]$Path, [string]$Caption, [double]$MaxWidthCm = 16.4)
|
||
$selection.ParagraphFormat.Alignment = 1
|
||
$shape = $selection.InlineShapes.AddPicture($Path, $false, $true, $selection.Range)
|
||
$shape.LockAspectRatio = -1
|
||
$maxWidth = $word.CentimetersToPoints($MaxWidthCm)
|
||
if ($shape.Width -gt $maxWidth) { $shape.Width = $maxWidth }
|
||
$selection.SetRange($shape.Range.End, $shape.Range.End)
|
||
$selection.TypeParagraph()
|
||
Add-Text $Caption 9 $false 1 0x777777 0 8 0
|
||
}
|
||
|
||
function Add-PageBreak {
|
||
$selection.InsertBreak(7)
|
||
}
|
||
|
||
# Cover
|
||
Add-Text '' 12 $false 1 0 0 20 0
|
||
Add-Text '大连元利流体技术有限公司' 22 $true 1 0x8F4A31 0 12 0
|
||
Add-Text 'MES 系统用户操作手册' 30 $true 1 0x8F4A31 0 16 0
|
||
Add-Text '系统管理篇(样稿)' 24 $true 1 0x4D4D4D 0 30 0
|
||
Add-Text '版本:V1.0' 12 $false 1 0 0 8 0
|
||
Add-Text '编制日期:2026年7月23日' 12 $false 1 0 0 8 0
|
||
Add-Text '适用系统:大连元利 MES 正式环境' 12 $false 1 0 0 28 0
|
||
Add-Note '编制说明' '本样稿依据现有项目操作手册、当前前端程序、正式菜单配置及数据库只读核对结果编写。截图过程仅登录、查询、打开并取消弹窗,未执行任何新增、修改、删除或保存操作。' 'warn'
|
||
Add-PageBreak
|
||
|
||
Add-Heading '文档修订记录' 1
|
||
Add-Table @(
|
||
@('版本', '日期', '修订内容', '说明'),
|
||
@('V1.0', '2026-07-23', '首次编制系统管理篇样稿', '覆盖当前正式菜单中的五个功能')
|
||
) @(2, 3, 7, 4)
|
||
|
||
Add-Heading '阅读说明' 1
|
||
Add-ItemList @(
|
||
'本手册中的【按钮名称】表示页面可点击按钮,“字段名称”表示输入框、下拉框或表格列。',
|
||
'截图中的业务数据来自正式环境,只用于说明界面;本次编制没有创建测试数据。',
|
||
'涉及新增、编辑、删除、重置密码、菜单分配的步骤均为操作说明,编制时未实际提交。',
|
||
'当前正式菜单以数据库配置为准,包括人员管理、菜单管理、角色管理、工位管理、报工操作记录。参考手册中的“节假日设定”不在当前正式菜单,本样稿不纳入。'
|
||
)
|
||
Add-PageBreak
|
||
|
||
Add-Text '目 录' 20 $true 1 0x8F4A31 0 12 0
|
||
$tocRange = $selection.Range
|
||
$toc = $doc.TablesOfContents.Add($tocRange, $true, 1, 3, $true, '', $true, $true, '', $true, $true, $true)
|
||
Move-End
|
||
Add-PageBreak
|
||
|
||
Add-Heading '1 系统管理概述' 1
|
||
Add-Text '系统管理用于维护登录账号、角色、角色可见菜单、生产工位主数据,并查询生产报工操作轨迹。该模块中的主数据会被计划排产、生产执行、质量、设备、工时和审计功能共同使用,因此操作人员应具备系统管理员权限,并在修改前确认影响范围。' 10.5 $false 0 0 0 6 0.74
|
||
|
||
Add-Heading '1.1 功能范围' 2
|
||
Add-Table @(
|
||
@('序号', '功能', '主要用途', '是否会写入数据'),
|
||
@('1', '人员管理', '维护账号、姓名、角色、班组及密码', '查询不写入;新增/编辑/重置/删除会写入'),
|
||
@('2', '角色管理', '维护角色名称', '查询不写入;新增/编辑/删除会写入'),
|
||
@('3', '菜单管理', '按角色分配或移除一级、二级菜单', '过滤不写入;分配/移除会写入'),
|
||
@('4', '工位管理', '维护生产工位名称和工位号', '查询不写入;新增/编辑/删除会写入'),
|
||
@('5', '报工操作记录', '按订单或操作人查询生产操作轨迹', '只读查询')
|
||
) @(1.2, 3, 7.6, 4.2)
|
||
|
||
Add-Heading '1.2 数据关系总览' 2
|
||
Add-Table @(
|
||
@('上游/主数据', '本模块关系', '下游使用位置', '变更影响'),
|
||
@('角色主数据', '角色管理创建角色;菜单管理为角色分配页面', '用户登录后的左侧菜单和页面访问范围', '角色改名会同步显示;菜单变更通常需重新登录后验证'),
|
||
@('人员主数据 + 人员角色关系', '人员管理把账号关联到一个角色,并可维护班组', '登录、排产指派、人员绑定、班次、工时、报工操作人', '更换角色会改变菜单;删除角色关系后账号不再出现在人员列表'),
|
||
@('MES资源主数据(工位)', '工位管理维护工位号和工位名称', '排产、加工中心、人员绑定、设备/工位查询、工时记录', '新增/改名还会调用 SAP B1 Resources;删除当前仅删除MES记录'),
|
||
@('生产执行动作', '开始、结束、报工、辅助等动作形成操作记录', '报工操作记录页面用于追溯订单、人员、工位和工时', '本页面不反向修改生产数据')
|
||
) @(3.5, 4.5, 5.2, 4.4)
|
||
Add-Note '推荐顺序' '新增账号时,先确认角色,再配置角色菜单,最后新增人员并验证登录;新增工位时,先确认工位号和名称,再维护工位,随后到人员绑定或计划相关页面完成下游配置。' 'info'
|
||
|
||
Add-Heading '1.3 通用查询与安全原则' 2
|
||
Add-ItemList @(
|
||
'空白查询条件通常表示不限制该字段;多个条件同时填写时按“并且”组合。',
|
||
'带“×”或清除图标的输入框可先清空,再点击【查询】恢复全量或默认结果。',
|
||
'分页页面可切换每页10、20、30、40条;切换每页条数后从第1页重新查询。',
|
||
'红色【删除】和所有确认弹窗均属于写操作。正式环境中应先确认下游占用和回退方案。',
|
||
'本手册不要求使用示例数据验证写操作;如需验证,应在测试环境完成。'
|
||
)
|
||
|
||
Add-PageBreak
|
||
Add-Heading '2 人员管理' 1
|
||
Add-Text '入口:左侧菜单【系统管理】→【人员管理】。该页面用于维护能够登录MES的人员账号,以及账号对应的角色和班组。人员角色关系直接决定登录后的可见菜单;人员姓名、工号和班组还会被排产、生产、人员绑定、班次、工时等功能引用。' 10.5 $false 0 0 0 6 0.74
|
||
Add-Figure (Join-Path $prepared 'personnel-list.png') '图2-1 人员管理列表(正式环境只读截图)'
|
||
|
||
Add-Heading '2.1 页面字段' 2
|
||
Add-Table @(
|
||
@('区域', '字段/按钮', '说明'),
|
||
@('查询区', '姓名', '按姓名关键字模糊匹配,可输入完整姓名或其中一部分'),
|
||
@('查询区', '角色', '从现有角色中选择,按角色编号精确过滤'),
|
||
@('列表', '姓名、工号、密码、角色、班组', '密码固定显示为“******”,页面不展示明文'),
|
||
@('操作', '重置密码、编辑、删除', '分别重置初始密码、维护人员资料、解除人员登录角色关系'),
|
||
@('分页', '总数、每页条数、页码、跳页', '默认每页10条,可选10/20/30/40条')
|
||
) @(2.3, 4.2, 10.5)
|
||
|
||
Add-Heading '2.2 搜索与过滤' 2
|
||
Add-StepList @(
|
||
'在“姓名”中输入关键字;不填写表示不限制姓名。',
|
||
'在“角色”下拉框中选择一个角色;不选择表示不限制角色。',
|
||
'点击【查询】。姓名和角色同时填写时,系统只显示同时满足两个条件的人员。',
|
||
'如无结果,先清空一个条件再查询,并确认当前页码;必要时返回第1页。'
|
||
)
|
||
Add-Table @(
|
||
@('条件示例', '匹配方式', '结果说明'),
|
||
@('姓名=“张”', '包含匹配', '姓名中包含“张”的人员'),
|
||
@('角色=“计划员”', '精确匹配角色', '关联到计划员角色的人员'),
|
||
@('姓名=“张” 且 角色=“计划员”', '两个条件取交集', '同时满足姓名关键字和角色的人员'),
|
||
@('两个条件均为空', '不限制', '按人员内部编号倒序分页显示')
|
||
) @(5, 4, 8)
|
||
|
||
Add-Heading '2.3 新增人员' 2
|
||
Add-Figure (Join-Path $prepared 'personnel-add.png') '图2-2 新增人员弹窗'
|
||
Add-StepList @(
|
||
'点击【新增】打开“增加人员”弹窗。',
|
||
'填写“姓名”和“工号”,并从“角色”下拉框选择角色。三项均为必填。',
|
||
'核对工号未被其他账号使用后,点击【确定】。点击【取消】不会产生数据。',
|
||
'新增成功后列表回到第1页,并按默认每页10条重新查询。'
|
||
)
|
||
Add-Note '初始密码' '新增人员的初始密码由系统固定为 123456,弹窗不显示密码输入框。应通知本人首次登录后按公司密码管理要求处理,避免长期使用初始密码。' 'warn'
|
||
Add-Note '数据关系' '保存时同时创建人员基本记录和“人员—角色”关联。新增弹窗不能维护班组;如需班组,新增后使用【编辑】补充。工号已存在时新增失败。' 'info'
|
||
|
||
Add-Heading '2.4 编辑人员' 2
|
||
Add-StepList @(
|
||
'在目标人员行点击【编辑】。',
|
||
'可修改姓名、班组和角色;工号为只读,不能在编辑弹窗中更换。',
|
||
'班组可选装配、电气、机加、质检、技术、计划、库房、采购、销售、售后、工艺、其他,也可清空。',
|
||
'点击【确定】写入人员资料并更新该人员的角色关联;点击【取消】放弃修改。'
|
||
)
|
||
Add-Note '影响范围' '修改角色后,该账号下一次登录加载的新菜单以目标角色的菜单配置为准;修改姓名或班组会影响后续页面中的人员显示和筛选,但历史业务记录通常保留原记录内容。' 'warn'
|
||
|
||
Add-Heading '2.5 重置密码' 2
|
||
Add-StepList @(
|
||
'在目标人员行点击【重置密码】。',
|
||
'核对人员姓名和工号,在确认框点击【确定】。',
|
||
'系统将密码重置为 123456,并提示“密码重置成功”。点击【取消】不做任何修改。'
|
||
)
|
||
|
||
Add-Heading '2.6 删除人员' 2
|
||
Add-StepList @(
|
||
'先确认该人员不再需要登录,并完成在办任务、工位绑定、班次和责任事项交接。',
|
||
'点击该行【删除】,在“当前人员将永久删除”确认框中再次核对。',
|
||
'点击【确定】后,系统移除人员与角色的关联,列表提示“人员离职成功”;点击【取消】不做修改。'
|
||
)
|
||
Add-Note '重要说明' '当前实现不是物理删除全部人员历史,而是移除人员角色关联,使其不再出现在本页联查结果中。已有报工、工时、检验等历史业务记录不会随此操作级联删除。' 'danger'
|
||
|
||
Add-PageBreak
|
||
Add-Heading '3 角色管理' 1
|
||
Add-Text '入口:左侧菜单【系统管理】→【角色管理】。角色是人员和菜单之间的中间层:人员选择角色,菜单管理再为角色分配页面。角色名称用于界面展示,角色编号用于保持人员、菜单关联。' 10.5 $false 0 0 0 6 0.74
|
||
Add-Figure (Join-Path $prepared 'role-list.png') '图3-1 角色管理列表(右侧空白为当前页面布局)' 15
|
||
|
||
Add-Heading '3.1 搜索与分页' 2
|
||
Add-StepList @(
|
||
'在“角色功能”输入角色名称关键字。',
|
||
'点击【查询】;系统按包含关系模糊匹配角色名称。',
|
||
'清空输入框后再次查询可恢复全部普通角色。',
|
||
'列表默认每页10条,可选10/20/30/40条并支持跳页。'
|
||
)
|
||
Add-Note '系统保留角色' '超级管理员(角色编号1)被查询逻辑排除,不会显示在角色管理列表和人员页面的角色下拉框中,避免通过普通维护误改。' 'info'
|
||
|
||
Add-Heading '3.2 新增角色' 2
|
||
Add-Figure (Join-Path $prepared 'role-add.png') '图3-2 新增角色弹窗'
|
||
Add-StepList @(
|
||
'点击【新增】。',
|
||
'填写唯一的“角色功能”名称,如岗位或职责名称。该字段必填。',
|
||
'点击【确定】创建角色;存在同名角色时系统提示失败。点击【取消】不产生数据。',
|
||
'角色创建后还没有菜单权限,应进入【菜单管理】完成分配,再用于人员账号。'
|
||
)
|
||
|
||
Add-Heading '3.3 编辑角色' 2
|
||
Add-StepList @(
|
||
'在目标角色行点击【编辑】。',
|
||
'修改角色名称后点击【确定】。系统校验不能与其他角色重名。',
|
||
'编辑只修改显示名称,角色编号不变,因此原有人员关联和菜单配置仍保留。'
|
||
)
|
||
|
||
Add-Heading '3.4 删除角色' 2
|
||
Add-StepList @(
|
||
'先在人员管理中把该角色下的人员调整到其他角色。',
|
||
'再到菜单管理逐项移除该角色下的二级菜单,最后移除一级菜单。',
|
||
'返回角色管理点击【删除】,确认后完成删除。'
|
||
)
|
||
Add-Table @(
|
||
@('系统提示', '原因', '处理方法'),
|
||
@('当前角色已经分配了菜单', '角色仍有关联菜单记录', '到菜单管理先移除子菜单,再移除一级菜单'),
|
||
@('当前角色已经分配了人员', '仍有人员使用该角色', '到人员管理把相关人员改为其他角色'),
|
||
@('删除成功', '菜单和人员关联均已解除', '角色从角色主数据中删除')
|
||
) @(5.2, 5.2, 6.6)
|
||
|
||
Add-PageBreak
|
||
Add-Heading '4 菜单管理' 1
|
||
Add-Text '入口:左侧菜单【系统管理】→【菜单管理】。当前正式页面用于“给角色分配菜单”,不是维护菜单名称、路径或页面代码。菜单数据在用户登录时转换为动态路由,因此分配结果决定该角色登录后左侧导航栏显示哪些模块。' 10.5 $false 0 0 0 6 0.74
|
||
Add-Figure (Join-Path $prepared 'menu-list.png') '图4-1 菜单管理初始页面(尚未选择角色)'
|
||
|
||
Add-Heading '4.1 三栏布局与过滤' 2
|
||
Add-Table @(
|
||
@('位置', '内容', '过滤规则'),
|
||
@('顶部角色下拉框', '选择待配置的普通角色', '支持在下拉框中输入关键字筛选角色'),
|
||
@('左栏:一级模块', '系统管理、计划排产、生产管理等一级菜单模板', '输入关键字后按模块名称包含匹配'),
|
||
@('中栏:已分配菜单树', '当前角色已拥有的一级和二级菜单', '输入关键字后按树节点名称包含匹配'),
|
||
@('右栏:二级菜单', '全部页面菜单及其所属一级模块路径', '输入关键字后按二级模块名称包含匹配')
|
||
) @(3.5, 7, 6.5)
|
||
Add-Note '过滤性质' '三栏关键字过滤均在当前已加载列表中即时执行,不会修改权限,也不需要点击查询按钮。清空关键字即可恢复该栏全部内容。' 'info'
|
||
|
||
Add-Figure (Join-Path $prepared 'menu-permission.png') '图4-2 选择“管理员”后的已分配菜单树'
|
||
|
||
Add-Heading '4.2 分配一级菜单' 2
|
||
Add-StepList @(
|
||
'在顶部选择目标角色,中栏随即加载该角色现有菜单。',
|
||
'在左栏勾选一个或多个一级模块。已分配的一级模块复选框不可重复选择。',
|
||
'点击左栏与中栏之间的向右箭头。',
|
||
'在确认框核对角色和选择项,点击【确定】完成分配;点击【取消】不写入。'
|
||
)
|
||
Add-Note '数据关系' '一级菜单以超级管理员的菜单模板为来源,分配时复制到目标角色的菜单配置中。一级菜单只是目录;要看到具体页面,还需继续分配二级菜单。' 'info'
|
||
|
||
Add-Heading '4.3 分配二级菜单' 2
|
||
Add-StepList @(
|
||
'在中栏仅勾选一个一级菜单,作为二级菜单的归属目录。',
|
||
'在右栏勾选一个或多个二级菜单。已分配的二级菜单不可重复选择。',
|
||
'点击中栏与右栏之间的向左箭头。',
|
||
'确认后,所选页面加入目标角色的目标一级目录。'
|
||
)
|
||
Add-Note '校验规则' '必须且只能选择一个中栏一级菜单;选中二级节点或同时选多个节点时,箭头不可用或系统提示“只可以分配给一个一级菜单”。' 'warn'
|
||
|
||
Add-Heading '4.4 移除菜单' 2
|
||
Add-StepList @(
|
||
'在中栏找到要撤回的二级菜单,必要时使用顶部关键字过滤。',
|
||
'点击该二级菜单右侧【移除】,在确认框点击【确定】。',
|
||
'如需移除一级菜单,必须先移除其全部二级菜单;有子节点时一级菜单的【移除】不可用。',
|
||
'全部子菜单移除后,再移除空的一级菜单。'
|
||
)
|
||
Add-Note '生效验证' '菜单变更后,应让目标账号退出并重新登录,核对左侧导航。移除菜单会影响页面入口,但不删除该页面产生的历史业务数据。' 'danger'
|
||
|
||
Add-Heading '4.5 当前页面边界' 2
|
||
Add-ItemList @(
|
||
'当前页面未提供可见的“新增菜单、编辑菜单名称、修改路径、删除菜单模板”入口。',
|
||
'页面代码中的查询/新增/编辑/删除按钮级权限控件处于停用状态,当前只分配页面级菜单。',
|
||
'因此正式操作中不要把本页理解为菜单结构设计器;新页面上线需由开发/实施人员维护模板和路由。'
|
||
)
|
||
|
||
Add-PageBreak
|
||
Add-Heading '5 工位管理' 1
|
||
Add-Text '入口:左侧菜单【系统管理】→【工位管理】。工位是生产任务、设备、人员绑定和工时记录的共同基础数据。列表只显示有效的机加工资源,以及名称为“外协”的特殊资源。' 10.5 $false 0 0 0 6 0.74
|
||
Add-Figure (Join-Path $prepared 'workstation-list.png') '图5-1 工位管理列表(右侧空白为当前页面布局)' 15
|
||
|
||
Add-Heading '5.1 列表与查询' 2
|
||
Add-Table @(
|
||
@('字段/按钮', '说明'),
|
||
@('工位名称', '业务人员识别工位的显示名称'),
|
||
@('工位号', '工位唯一业务编码,供MES与SAP B1资源关联'),
|
||
@('编辑', '只允许修改工位名称,工位号保持不变'),
|
||
@('删除', '从MES资源主数据删除该工位'),
|
||
@('查询', '当前版本刷新全部工位列表')
|
||
) @(5, 12)
|
||
Add-Note '当前限制' '页面虽然显示“工位名称”输入框,但当前查询请求没有传递该字段。无论输入什么内容,点击【查询】都会重新加载全部工位,不能按名称过滤。' 'warn'
|
||
|
||
Add-Heading '5.2 新增工位' 2
|
||
Add-Figure (Join-Path $prepared 'workstation-add.png') '图5-2 新增工位弹窗'
|
||
Add-StepList @(
|
||
'点击【新增】。',
|
||
'填写“工位名称”和“工位号”,两项均为必填。工位号应沿用公司现有编码规则。',
|
||
'确认名称未重复、工位号未占用后点击【确定】;点击【取消】不产生数据。',
|
||
'MES新增成功后,前端同时向 SAP B1 Resources 创建类型为 rtMachine 的资源。'
|
||
)
|
||
Add-Note '保存前检查' '正式环境不得用临时名称或测试编码尝试保存。新增会同时影响MES和SAP B1,失败时应分别核对两端是否一致,避免重复创建。' 'danger'
|
||
|
||
Add-Heading '5.3 编辑工位' 2
|
||
Add-StepList @(
|
||
'在目标工位行点击【编辑】。',
|
||
'修改工位名称。工位号作为关联键不在编辑弹窗中开放修改。',
|
||
'点击【确定】后,MES更新资源名称,并调用 SAP B1 Resources 按同一工位号更新名称。',
|
||
'如新名称已被其他工位使用,系统提示“存在同名工位”。'
|
||
)
|
||
|
||
Add-Heading '5.4 删除工位' 2
|
||
Add-StepList @(
|
||
'先确认工位没有未完排产、在制任务、人员绑定、设备关联和进行中的工时记录。',
|
||
'记录工位号和名称,确认已具备可恢复依据。',
|
||
'点击【删除】,在确认框点击【确定】后从MES资源主数据删除。'
|
||
)
|
||
Add-Note '高风险操作' '当前删除过程没有启用菜单/人员等占用校验,也没有调用 SAP B1 删除资源。删除可能造成MES与SAP B1不一致,并影响历史关联查询。未经业务负责人和系统管理员确认,不应执行。' 'danger'
|
||
|
||
Add-Heading '5.5 下游数据关系' 2
|
||
Add-Table @(
|
||
@('下游功能', '使用方式', '变更影响'),
|
||
@('计划排产/工位计划', '作为指派对象或工位维度', '改名后新查询显示新名称;删除会使后续选择缺失'),
|
||
@('生产执行/加工中心', '定位任务执行工位并形成操作记录', '错误工位会影响报工归属和工时统计'),
|
||
@('人员绑定/班次', '建立人员与工位的可执行关系', '删除前必须解除或确认绑定'),
|
||
@('设备与工时', '关联设备状态、人员工时、设备工时', '删除可能导致历史或在制数据无法正常联查'),
|
||
@('SAP B1 Resources', '新增和改名时以工位号同步资源', '两端应使用同一编码和名称')
|
||
) @(4, 6, 7)
|
||
|
||
Add-PageBreak
|
||
Add-Heading '6 报工操作记录' 1
|
||
Add-Text '入口:左侧菜单【系统管理】→【报工操作记录】。该页面是只读审计页面,用于追溯生产执行产生的操作轨迹,不提供新增、编辑、删除或导出。进入页面后自动加载最新记录。' 10.5 $false 0 0 0 6 0.74
|
||
Add-Figure (Join-Path $prepared 'operation-log.png') '图6-1 报工操作记录(正式环境只读截图)'
|
||
|
||
Add-Heading '6.1 搜索与过滤' 2
|
||
Add-StepList @(
|
||
'按订单追溯时,在“订单编号”输入完整订单编号。',
|
||
'按人员追溯时,在“操作人”输入完整姓名。',
|
||
'两个条件可同时填写,系统只返回订单编号和操作人均完全相同的记录。',
|
||
'点击【查询】;清空两个条件后查询,恢复最新100条记录。'
|
||
)
|
||
Add-Table @(
|
||
@('条件', '匹配方式', '注意事项'),
|
||
@('订单编号', '精确相等', '不支持包含匹配;少字符、多空格或编号不完整均可能无结果'),
|
||
@('操作人', '精确相等', '应使用系统记录中的完整姓名'),
|
||
@('订单编号 + 操作人', '两个条件取交集', '适合核对某人在指定订单上的操作'),
|
||
@('均为空', '最新记录', '按记录内部编号倒序,仅返回前100条')
|
||
) @(4.5, 4, 8.5)
|
||
Add-Note '当前限制' '页面分页控件已停用,后端每次最多返回最新100条。较早记录如不在最近100条内,必须填写准确订单编号或操作人缩小范围,但同一条件仍只返回该结果集最新100条。' 'warn'
|
||
|
||
Add-Heading '6.2 表格字段说明' 2
|
||
Add-Table @(
|
||
@('字段组', '字段', '业务含义'),
|
||
@('业务定位', '订单编号、合同号、物料编号、物料描述', '定位生产订单及对应产品/零件'),
|
||
@('工艺与资源', '工序名称、工位名称', '说明在哪一道工序、哪个工位发生操作'),
|
||
@('人员与动作', '操作人、操作类别、操作数值、操作描述', '说明谁执行了什么动作及数量/补充说明'),
|
||
@('时间与工时', '开始时间、结束时间、人员工时、设备工时', '用于核对动作区间及工时结果'),
|
||
@('审计信息', '最后编辑人、最后编辑时间', '识别记录后续调整责任人和时间')
|
||
) @(3, 6, 8)
|
||
|
||
Add-Heading '6.3 前后数据关系' 2
|
||
Add-Table @(
|
||
@('前序动作', '形成的记录信息', '本页用途'),
|
||
@('开始加工/辅助开始', '操作类别、订单、工序、工位、操作人、开始时间', '核对任务是否启动、由谁启动'),
|
||
@('报工/辅助结束/加工结束', '结束时间、操作数值、人员工时、设备工时', '核对报工数量和工时结果'),
|
||
@('后续编辑', '最后编辑人、最后编辑时间、操作描述', '追溯调整人员和调整时间')
|
||
) @(5, 7, 5)
|
||
Add-Note '审计原则' '本页数据来自生产执行操作记录表,只用于查询展示。发现异常时应回到对应生产任务、工时或业务处理页面核对,不能在本页直接更改记录。' 'info'
|
||
|
||
Add-PageBreak
|
||
Add-Heading '7 典型业务链路' 1
|
||
Add-Heading '7.1 新增可登录人员' 2
|
||
Add-StepList @(
|
||
'在角色管理确认目标角色存在;没有时创建唯一角色名称。',
|
||
'在菜单管理选择该角色,先分配一级菜单,再分配二级页面。',
|
||
'在人员管理新增姓名、工号和角色;系统使用初始密码123456。',
|
||
'如需班组,新增成功后编辑人员补充班组。',
|
||
'让本人登录验证菜单范围,禁止使用正式业务写操作做权限测试。'
|
||
)
|
||
|
||
Add-Heading '7.2 下线一个角色' 2
|
||
Add-StepList @(
|
||
'在人员管理按角色筛选,逐一把人员调整到其他有效角色。',
|
||
'在菜单管理选择原角色,先移除所有二级菜单,再移除一级菜单。',
|
||
'在角色管理删除角色。若仍提示占用,返回前两步继续核对。',
|
||
'保留变更审批或操作记录,以便追溯权限调整。'
|
||
)
|
||
|
||
Add-Heading '7.3 新增生产工位' 2
|
||
Add-StepList @(
|
||
'由生产、设备、计划和系统管理员共同确认工位号、工位名称及SAP B1资源规则。',
|
||
'在工位管理一次性准确填写并保存,避免用测试编码试录。',
|
||
'核对MES工位列表和SAP B1 Resources是否一致。',
|
||
'再到人员绑定、设备或计划页面完成下游关系配置。',
|
||
'使用只读查询验证可选项,不创建正式生产任务作为测试。'
|
||
)
|
||
|
||
Add-Heading '7.4 追溯一次报工操作' 2
|
||
Add-StepList @(
|
||
'优先取得完整订单编号,在报工操作记录中精确查询。',
|
||
'如需进一步缩小范围,再填写完整操作人姓名。',
|
||
'横向滚动核对合同、物料、工序、工位、开始/结束时间和工时。',
|
||
'结合最后编辑人、最后编辑时间判断是否发生后续调整。',
|
||
'需要纠正时转到对应业务页面,并按审批流程处理。'
|
||
)
|
||
|
||
Add-Heading '8 常见问题' 1
|
||
Add-Table @(
|
||
@('问题', '原因判断', '处理建议'),
|
||
@('人员查询不到', '姓名/角色组合无匹配,或人员角色关联已移除', '清空条件并回到第1页;确认人员是否已执行删除/离职'),
|
||
@('新账号登录后没有菜单', '角色尚未配置一级/二级菜单,或登录会话未刷新', '菜单管理补充分配后退出并重新登录'),
|
||
@('角色删除失败', '角色仍分配菜单或人员', '先转移人员,再按“二级→一级”顺序移除菜单'),
|
||
@('工位名称输入后仍显示全部', '当前版本未把名称条件传给查询接口', '按列表滚动查找;不要反复输入或保存测试数据'),
|
||
@('工位编辑提示同名', '目标名称已被资源主数据占用', '核对现有工位名称,使用经审批的唯一名称'),
|
||
@('报工记录查询不到', '页面使用精确匹配,且最多返回最新100条', '输入完整订单编号/操作人,检查空格和编号格式'),
|
||
@('菜单无法移除一级模块', '一级模块仍有子菜单', '先逐个移除二级菜单,再移除一级模块')
|
||
) @(5, 6, 6)
|
||
|
||
Add-Heading '9 正式环境操作红线' 1
|
||
Add-ItemList @(
|
||
'不得使用“测试、test、临时”等数据在正式环境验证新增功能。',
|
||
'不得通过新增后删除的方式验证操作流程;删除不一定能恢复全部上下游关系。',
|
||
'不得直接删除仍有关联任务、人员、菜单、设备或工时的角色和工位。',
|
||
'重置密码、分配菜单、人员换角色均应取得授权,并通知受影响人员。',
|
||
'涉及SAP B1同步的工位新增/改名,必须核对两端结果;异常时停止重复提交。',
|
||
'所有截图、查询和核对优先使用只读操作;写操作应按审批、备份和回退方案执行。'
|
||
)
|
||
|
||
Add-Heading '附录A 技术数据关系(供管理员核对)' 1
|
||
Add-Table @(
|
||
@('功能', '主要数据对象', '关系说明'),
|
||
@('人员管理', '登录基础数据_人员信息;登录基础数据_人员权限角色', '人员主记录通过人员编号关联角色编号'),
|
||
@('角色管理', '登录基础数据_角色信息', '角色编号被人员关系和菜单配置引用'),
|
||
@('菜单管理', '登录基础数据_二级菜单', '同一菜单模板按角色编号形成角色菜单配置'),
|
||
@('工位管理', 'MES_资源主数据;View_基础数据_工位;SAP B1 Resources', '工位号/VisCode为跨系统关联键,名称用于显示'),
|
||
@('报工操作记录', 'YL_加工中心_操作记录表', '生产动作写入,本页按订单或操作人只读查询')
|
||
) @(4, 7, 6)
|
||
|
||
Add-Text '—— 系统管理篇结束 ——' 11 $true 1 0x777777 18 0 0
|
||
Write-Output 'PROGRESS=content-complete'
|
||
|
||
# Header and footer
|
||
foreach ($section in $doc.Sections) {
|
||
$header = $section.Headers.Item(1).Range
|
||
$header.Text = '大连元利流体技术有限公司 MES系统操作手册 | 系统管理篇'
|
||
$header.Font.NameFarEast = '微软雅黑'
|
||
$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.Size = 8.5
|
||
$footer.Font.Color = 0x777777
|
||
$footer.ParagraphFormat.Alignment = 1
|
||
$footer.Collapse(0)
|
||
$footer.Fields.Add($footer, 33) | Out-Null
|
||
}
|
||
|
||
Write-Output 'PROGRESS=headers-complete'
|
||
foreach ($item in $doc.TablesOfContents) { $item.Update() }
|
||
$doc.Fields.Update() | Out-Null
|
||
$doc.Repaginate()
|
||
Write-Output 'PROGRESS=fields-complete'
|
||
|
||
if (Test-Path $docxPath) { Remove-Item -LiteralPath $docxPath -Force }
|
||
if (Test-Path $pdfPath) { Remove-Item -LiteralPath $pdfPath -Force }
|
||
$doc.SaveAs($docxPath, 12)
|
||
Write-Output 'PROGRESS=docx-saved'
|
||
$doc.ExportAsFixedFormat($pdfPath, 17)
|
||
Write-Output 'PROGRESS=pdf-saved'
|
||
$pageCount = $doc.ComputeStatistics(2)
|
||
$doc.Close(0)
|
||
$doc = $null
|
||
|
||
Copy-Item -LiteralPath $docxPath -Destination $desktopDocx -Force
|
||
Copy-Item -LiteralPath $pdfPath -Destination $desktopPdf -Force
|
||
|
||
Write-Output ('DOCX=' + $docxPath)
|
||
Write-Output ('PDF=' + $pdfPath)
|
||
Write-Output ('DESKTOP_DOCX=' + $desktopDocx)
|
||
Write-Output ('DESKTOP_PDF=' + $desktopPdf)
|
||
Write-Output ('PAGES=' + $pageCount)
|
||
} catch {
|
||
$buildError = $_
|
||
Write-Output ('BUILD_ERROR=' + $_.Exception.Message)
|
||
Write-Output ('BUILD_ERROR_LINE=' + $_.InvocationInfo.ScriptLineNumber)
|
||
} finally {
|
||
if ($doc -ne $null) { try { $doc.Close(0) } catch {} }
|
||
if ($word -ne $null) { try { $word.Quit() } catch {} }
|
||
[GC]::Collect()
|
||
[GC]::WaitForPendingFinalizers()
|
||
}
|
||
|
||
if ($buildError -ne $null) { throw $buildError }
|