diff --git a/.gitignore b/.gitignore index 0ec9630..14e595e 100644 --- a/.gitignore +++ b/.gitignore @@ -25,6 +25,7 @@ selenium-debug.log **/.idea/ .vscode/ **/.vscode/ +~$*.docx *.suo *.ntvs* *.njsproj diff --git a/MES_Manage_View_V20/MacroinfManage_MES.code-workspace b/MES_Manage_View_V20/MacroinfManage_MES.code-workspace new file mode 100644 index 0000000..2a0ed79 --- /dev/null +++ b/MES_Manage_View_V20/MacroinfManage_MES.code-workspace @@ -0,0 +1,7 @@ +{ + "folders": [ + { + "path": ".." + } + ] +} \ No newline at end of file diff --git a/MES_Manage_View_V20/今后开发计划_2026-05-27.md b/MES_Manage_View_V20/今后开发计划_2026-05-27.md new file mode 100644 index 0000000..8a5bdc5 --- /dev/null +++ b/MES_Manage_View_V20/今后开发计划_2026-05-27.md @@ -0,0 +1,77 @@ +# 今后开发计划与新增需求分析记录 + +生成日期:2026-05-27 +项目:MES_Manage_View_V20 + +## 一、排期口径 + +- 按“最终调整”数字从小到大排序。 +- 从 2026-05-28 开始排期。 +- 按工作日递推,跳过周六、周日。 +- 跳过端午节、中秋节、国庆节法定放假日期。 +- 调休日按工作日处理。 +- 暂按单开发线串行排期。 + +节假日口径: + +- 端午节:2026-06-19 至 2026-06-21。 +- 中秋节:2026-09-25 至 2026-09-27。 +- 国庆节:2026-10-01 至 2026-10-07。 +- 调休上班日:2026-09-20、2026-10-10。 + +## 二、开发计划排期 + +| 顺序 | 需求 | 预估 | 开始 | 结束 | 备注 | +|---:|---|---:|---|---|---| +| 1 | 及时开工报表 | 1天 | 5.28 | 5.29 | 增加正选/反选查询 | +| 2 | 机加件排产-表单 | 4天 | 5.29 | 6.04 | 日期筛选优化 + 历史工时查询;SAP新增字段不算MES开发 | +| 3 | 装配已排产需求 | 12天 | 6.04 | 6.23 | 大需求,建议分阶段交付 | +| 4 | 生产日报-送检(机加/装配) | 3天 | 6.23 | 6.26 | 建议统一报表,部门做筛选维度 | +| 5 | 及时齐套跟踪结果报表 | 5天 | 6.26 | 7.03 | 依赖SAP缺件明细实时接口 | +| 6 | 生产计划跟踪 | 3天 | 7.03 | 7.08 | 工序状态、颜色、标准工时、订单状态 | +| 7 | 外协任务检验 | 3天 | 7.08 | 7.13 | 增加指派对象、供应商、SAP采购收货单号 | +| 8 | 异常管控 | 5天 | 7.13 | 7.20 | 报工页面直接报异常,多审批人可见一人处理 | +| 9 | 机加班次产量表 | 3天 | 7.20 | 7.23 | 新增报表 | +| 10 | 发货通知列表 | 1天 | 7.23 | 7.24 | SAP数据已提供,可新增查询报表 | +| 11 | 质检任务早知道 | 1天 | 7.24 | 7.27 | 依赖“装配已排产需求”的装配完成时间 | +| 12 | 生产工艺 | 2天 | 7.27 | 7.29 | 无生产工艺时自动带出标准工艺 | +| 13 | 工时报表 + 备注类小改 | 2天 | 7.29 | 7.31 | 指派对象、机加领料备注、机加/装配退库备注、保存提示等合并处理 | +| 14 | 生产订单关闭 | 4天 | 7.31 | 8.06 | 批量更新SAP订单状态,风险较高 | +| 15 | 及时检验报表 | 4天 | 8.06 | 8.12 | 报工超过2天未检验 | +| 16 | 工序流转卡 | 1天 | 8.12 | 8.13 | 增加打印原料编码 | +| 17 | 一楼质检大屏幕 | 4天 | 8.13 | 8.19 | 及时率、关键工序 | +| 18 | 机加现场大屏幕 | 3天 | 8.19 | 8.24 | 缺勤、关键工序 | +| 19 | 装配现场大屏幕 | 4天 | 8.24 | 8.28 | 缺勤、及时送检 | +| 20 | 编程任务清单 | 4天 | 8.28 | 9.03 | 按装配类似逻辑做编程报工 | +| 21 | 设备档案管理 | 2天 | 9.03 | 9.07 | 需先确认字段归属 | +| 22 | 设备数据采集 | 8天 | 9.07 | 9.17 | 采集接口、落库、状态汇总 | +| 23 | 设备指标/OEE | 6天 | 9.17 | 9.24 | 依赖设备采集和标准工时口径 | +| 24 | 工时查询-设备采集联动 | 2天 | 9.24 | 9.29 | 程序工时字段对接采集数据 | +| 25 | 手续确认报表 | 3天 | 9.29 | 10.09 | 装配/电气齐套列表 + 手续确认 | +| 26 | 产品合格率(工位) | 3天 | 10.09 | 10.13 | 需确认良品/总产量口径 | +| 27 | 让步接收记录 | 2天 | 10.13 | 10.15 | 新增查询页面 | +| 28 | 设计任务报工模块 | 6天 | 10.15 | 10.23 | MES自建设计任务、设计工时 | +| 29 | 工时异常报表 | 2天 | 10.23 | 10.27 | 依赖标准工时和实际单件工时 | +| 30 | 正在加工状态 | 1天 | 10.27 | 10.28 | 机加正在进行中状态 | + +## 三、暂不直接排期 / 需等前置条件 + +| 需求 | 原因 | +|---|---| +| 及时拣配(机加)MES | 等SAP数据、条码规则、状态写回规则 | +| 及时拣配(装配)MES | 等SAP数据、条码规则、状态写回规则 | +| 及时送检报表 | 需确认发料齐套时间/SAP字段是否稳定;若SAP数据已到,可插入0.5天 | +| 工艺内容修改 | 已开工任务怎么处理未定 | +| 标牌打印操作 | 需求未确定 | +| 首检、巡检 | 需求内容为空,无法估时 | +| 外协采购订单收检结果 | 需求内容为空,无法估时 | +| 不合格品单据打印 | 需求内容为空,无法估时 | + +## 四、排期结论 + +按以上单线工作日计划,已明确可做事项预计到 2026-10-28 完成。 + +实际执行建议先做 5.28 到 6.23 的前三项,因为它们优先级最高,且“装配已排产需求”会影响后面的质检早知道、日计划、及时送检等需求。 + +## 五、新增需求分析与开发记录原文 + diff --git a/MES_Manage_View_V20/今后开发计划与新增需求分析记录_2026-05-27.docx b/MES_Manage_View_V20/今后开发计划与新增需求分析记录_2026-05-27.docx new file mode 100644 index 0000000..10399e1 Binary files /dev/null and b/MES_Manage_View_V20/今后开发计划与新增需求分析记录_2026-05-27.docx differ diff --git a/MES_Manage_View_V20/元利项目详细用户使用说明书.md b/MES_Manage_View_V20/元利项目详细用户使用说明书.md index eafa154..e293efd 100644 --- a/MES_Manage_View_V20/元利项目详细用户使用说明书.md +++ b/MES_Manage_View_V20/元利项目详细用户使用说明书.md @@ -1090,8 +1090,7 @@ 9. 看板:生产、装配、质检、机加、综合大屏。 10. 新增需求页面:手续确认、及时检验、装配已排产需求、齐套跟踪等。 -## 二十一、逐页详细操作说明(按 src/views 页面) - +## 二十一、逐页详细操作说明 本章按源码页面逐页编写。每个页面都从实际 `v-model`、表格列、按钮、弹窗、页签、存储过程和 SAP/WMS 调用中提取操作线索,转换成用户可执行的步骤。 通用阅读方法: diff --git a/MES_Manage_View_V20/技术开发详细方案_2026-05-27.docx b/MES_Manage_View_V20/技术开发详细方案_2026-05-27.docx new file mode 100644 index 0000000..6eb6961 Binary files /dev/null and b/MES_Manage_View_V20/技术开发详细方案_2026-05-27.docx differ diff --git a/MES_Manage_View_V20/技术开发详细方案_2026-05-27.md b/MES_Manage_View_V20/技术开发详细方案_2026-05-27.md new file mode 100644 index 0000000..f0c69a3 --- /dev/null +++ b/MES_Manage_View_V20/技术开发详细方案_2026-05-27.md @@ -0,0 +1,3441 @@ +# MES 新增需求技术开发详细方案 + +生成日期:2026-05-27 +依据文档: + +- `今后开发计划与新增需求分析记录_2026-05-27.docx` +- `今后开发计划_2026-05-27.md` +- `新增需求分析与开发记录_2026-05-23.md` +- `新增需求界面原型设计_2026-05-25.md` +- `隐性需求综合分析_2026-05-25.md` +- `MES_功能列表_页面_存储过程映射.md` +- `项目功能技术路线数据库分析报告_2026-05-22.md` +- `script.sql` + +## 1. 项目技术现状 + +### 1.1 前端技术栈 + +主系统目录:`MES_Manage_View_V20` + +技术栈: + +- Vue 2.7.16 +- Vue Router 3.6.5 +- Vuex 3.6.2 +- Element UI 2.15.14 +- Webpack 5 +- Axios 0.21.4 +- xlsx / xlsx-style 用于导出 +- vue-print-nb 用于打印 +- pdfjs-dist 用于图纸预览 +- mqtt 用于设备或网关通信 + +主业务页面位置: + +- `src/views/PlanManagement`:计划、排产、订单关闭。 +- `src/views/ProductionManagement`:生产中心、装配中心、工时、外协、异常、班次。 +- `src/views/QualityManagement`:质检中心、质检任务、质检明细、不合格品。 +- `src/views/ProcessManagement`:标准工艺、生产工艺、工序、图纸。 +- `src/views/DeviceManagement`:设备台账、设备实时数据、设备历史数据。 +- `src/views/SystemMaintenance`:工位、人员、权限等基础维护。 +- `src/views/AnomalousManagement/PunctualWork`:及时开工报表。 + +### 1.2 后端调用方式 + +系统现有模式不是 REST API,而是前端统一传存储过程名给 `.ashx` 网关执行。 + +调用方式: + +```text +Vue 页面 + -> this.CreateData(type, procedureName, params, pageSize, pageCurrent) + -> this.ExecDatabase(data) + -> MESCommonBase.ashx + -> SQL Server 存储过程 +``` + +常用 type: + +| type | 用途 | 说明 | +|---|---|---| +| `11` | 查询 | 返回列表或分页数据 | +| `12` | 新增、修改、删除 | 返回执行结果 | +| `7` | JSON 批量 | 用于批量排产等 | +| `2001` | 导出 | 现有导出相关逻辑使用 | + +参数格式: + +```js +const param = [] +param.push(['订单号', this.query.订单号]) +param.push(['合同号', this.query.合同号]) +const data = this.CreateData('11', '存储过程名', param, this.pageSize, this.pageCurrent) +this.ExecDatabase(data).then(res => { ... }) +``` + +### 1.3 核心数据库对象 + +本轮开发必须优先复用以下核心表和视图。 + +#### 生产计划主表 + +表:`MES_接口_生产计划` + +关键字段: + +| 字段 | 类型 | 说明 | +|---|---|---| +| `订单编号` | int | 生产订单号,主键 | +| `合同号` | nvarchar(50) | 合同维度 | +| `订单状态` | nvarchar(50) | SAP/MES 订单状态 | +| `物料编号` | nvarchar(500) | 主物料编码 | +| `物料描述` | nvarchar(500) | 主物料名称 | +| `计划数量` | decimal(16,2) | 订单计划数量 | +| `计划开始` | datetime | 订单计划开始 | +| `计划完成` | datetime | 订单计划完成 | +| `同步时间` | datetime | SAP/MES 同步时间 | +| `任务状态` | int | 订单任务状态 | +| `齐套` | float | 齐套状态或齐套比例 | +| `预计齐套时间` | datetime | 现有预计齐套时间 | +| `齐套时间` | datetime | 现有齐套时间 | +| `发料状态` | nvarchar(50) | 发料状态 | +| `拣配状态` | nvarchar(50) | 拣配状态 | +| `发货状态` | nvarchar(50) | 发货状态 | +| `要求发货日期` | datetime | 发货要求日期 | +| `入库数量` | decimal(19,6) | 入库数量 | +| `确认状态` | nvarchar(50) | 现有确认状态 | + +#### 生产任务表 + +表:`MES_接口_生产计划_生产任务` + +关键字段: + +| 字段 | 类型 | 说明 | +|---|---|---| +| `AID` | bigint | TaskAID,任务主键 | +| `订单编号` | int | 生产订单号 | +| `订单行号` | int | SAP/MES 行号 | +| `订单拆分内码` | int | 拆分内码 | +| `物料编码` | nvarchar(500) | 任务物料编码 | +| `物料名称` | nvarchar(500) | 任务物料名称 | +| `工序名称` | nvarchar(50) | 工序 | +| `顺序编号` | int | 工序顺序 | +| `总工时` | decimal(16,2) | 任务总工时,现有字段 | +| `指派对象编号` | nvarchar(50) | 指派对象编号 | +| `指派对象` | nvarchar(50) | 设备/工位/外协/装配等 | +| `指派数量` | decimal(16,2) | 指派数量 | +| `计划开始时间` | datetime | 任务计划开始 | +| `计划完成时间` | datetime | 任务计划完成 | +| `派工时间` | datetime | 现有派工时间 | +| `任务状态` | int | 任务状态 | +| `开工时间` | datetime | 开工时间 | +| `完工时间` | datetime | 完工时间 | +| `完成数量` | int | 完成数 | +| `合格数量` | int | 合格数 | +| `不合格数量` | int | 不合格数 | +| `让步放行数量` | int | 让步放行数 | +| `报废数量` | int | 报废数 | +| `外协通知` | int | 外协通知状态 | +| `外协备注` | nvarchar(500) | 外协备注 | +| `外协分组` | nvarchar(50) | 外协分组 | + +#### 生产订单视图 + +视图:`View_生产订单_MES` + +说明:目前多数计划、排产、生产任务查询均基于该视图。新增报表优先从该视图读取生产订单和任务基础信息。 + +#### 生产操作记录 + +表:`YL_加工中心_操作记录表` + +用途: + +- 现场开工、暂停、报工、辅助开始/结束、异常等操作记录。 +- 及时检验起算时间。 +- 历史工时查询。 +- 班次产量表。 +- 当前对应人员和当前对应内容。 + +现有字段从视图和过程可见: + +| 字段 | 说明 | +|---|---| +| `TaskAID` | 关联生产任务 | +| `操作类别` | 开始加工、报工、辅助结束、异常等 | +| `操作人` | 人员 | +| `工位编号` / `工位名称` | 工位/设备 | +| `开始时间` / `结束时间` | 操作时间段 | +| `工时` | 秒或分钟,现有过程按 `工时 > 0` 汇总 | +| `操作数值` | 数量或工时数值 | +| `操作内容` | 工作内容 | +| `操作描述` / `异常说明` | 说明 | + +#### 质检记录 + +表:`YL_质量检验_质检记录` + +用途: + +- 及时检验报表。 +- 生产日报-送检。 +- 让步接收记录。 +- 外协任务检验字段补充。 +- 产品合格率。 + +关键字段: + +| 字段 | 说明 | +|---|---| +| `QT_AID` | 质检主键 | +| `TaskAID` | 关联生产任务 | +| `计划号` | 生产订单 | +| `零件编码` / `零件名称` | 物料 | +| `工序名称` | 工序 | +| `质检类型` / `检测类型编号` | 首检、巡检、序检、收检、终检等 | +| `检验数量` | 检验数 | +| `合格数` | 合格数 | +| `不合格数` | 不合格数 | +| `检测人` | 检验人 | +| `检测时间` | 检验时间 | +| `检测说明` | 说明 | + +#### 设备采集相关表 + +| 表 | 说明 | +|---|---| +| `CaChe_Var` | 设备变量当前缓存 | +| `历史_设备数据_定时` | 设备历史采集点位数据 | +| `历史_工位设备状态每分钟记录` | 工位状态每分钟快照 | +| `YL_设备管理_设备台账` | 设备台账 | +| `YL_设备管理_工时记录` | 设备循环时间采集记录 | + +## 2. 总体开发原则 + +### 2.1 页面开发原则 + +1. 保持现有 Element UI 风格:顶部筛选区、中间按钮区、下方表格、弹窗明细。 +2. 报表页面只做查询、导出、打印、钻取,不承担基础主数据维护。 +3. 待办类页面可以做状态确认,例如手续确认。 +4. 能扩展现有页面的,不新建孤立维护页面。 +5. 所有新增页面必须同步菜单、按钮权限、路由组件、操作日志。 +6. 所有新增表格都要支持分页,避免一次性查全量。 +7. 时间筛选全部统一为闭区间:开始日 `00:00:00` 到结束日 `23:59:59`。 +8. 导出字段必须与页面字段一致。 + +### 2.2 数据库开发原则 + +1. 优先复用现有表和视图。 +2. 新增字段优先加在业务主表或扩展表,不能只存在报表 SQL 中。 +3. 人工维护字段必须有维护人、维护时间、原值、新值或日志。 +4. SAP 来源字段必须有同步时间和同步状态。 +5. 设备采集数据必须先落原始数据,再做汇总,不直接覆盖业务结果。 +6. 报表公共口径优先做视图或公共存储过程,不允许每个报表各写一套算法。 +7. 看板类过程必须可传统计日期;实时看板默认 `GETDATE()`。 +8. 写操作过程必须返回 `result`、`message`,批量操作要返回每行结果。 + +### 2.3 命名规范 + +新增表建议命名: + +```text +业务域_模块_对象 +例:生产管理_装配已排产需求_维护字段 +例:生产管理_设计任务 +例:生产管理_编程任务 +``` + +新增存储过程建议命名: + +```text +业务域_页面_动作 +例:生产管理_装配已排产需求_查询 +例:生产管理_装配已排产需求_维护字段保存 +例:质量管理_及时检验报表_查询 +``` + +如复用原有 MES 前缀,也可以使用: + +```text +MES_AssemblyPlannedDemand_Query +MES_AssemblyPlannedDemand_SaveManualFields +``` + +本项目已有大量中文过程名,建议新增需求优先用中文业务名,便于现场维护。 + +## 3. 通用新增基础表 + +以下表建议作为多需求共用基础能力,避免每个需求重复建字段。 + +### 3.1 SAP 调用日志表 + +表名:`系统集成_SAP调用日志` + +用途: + +- 批量关闭 SAP 订单。 +- 外协采购收货单号追踪。 +- 发货通知、缺件明细、派工时间、合同交货期同步。 +- 后续 SAP 失败重试和对账。 + +建议 SQL: + +```sql +CREATE TABLE dbo.系统集成_SAP调用日志 ( + AID bigint IDENTITY(1,1) PRIMARY KEY, + 业务类型 nvarchar(50) NOT NULL, + 业务主键 nvarchar(100) NULL, + 生产订单 int NULL, + TaskAID bigint NULL, + SAP对象类型 nvarchar(50) NULL, + SAP单据号 nvarchar(100) NULL, + 请求地址 nvarchar(500) NULL, + 请求方法 nvarchar(20) NULL, + 请求内容 nvarchar(max) NULL, + 返回内容 nvarchar(max) NULL, + 执行结果 nvarchar(20) NOT NULL, + 失败原因 nvarchar(max) NULL, + 请求人 nvarchar(50) NULL, + 请求时间 datetime NOT NULL DEFAULT GETDATE(), + 完成时间 datetime NULL, + 是否可重试 bit NOT NULL DEFAULT 0, + 重试次数 int NOT NULL DEFAULT 0 +); +``` + +索引: + +```sql +CREATE INDEX IX_系统集成_SAP调用日志_生产订单 ON dbo.系统集成_SAP调用日志(生产订单); +CREATE INDEX IX_系统集成_SAP调用日志_业务类型_时间 ON dbo.系统集成_SAP调用日志(业务类型, 请求时间); +``` + +### 3.2 业务字段维护日志表 + +表名:`系统管理_业务字段维护日志` + +用途: + +- 装配完成时间人工修改。 +- 钣金预达、钣金到达、泵预达、泵到达维护。 +- 预计总工时维护。 +- 预计可执行时间维护。 +- 手续确认等人工确认字段。 + +建议 SQL: + +```sql +CREATE TABLE dbo.系统管理_业务字段维护日志 ( + AID bigint IDENTITY(1,1) PRIMARY KEY, + 业务模块 nvarchar(100) NOT NULL, + 业务表名 nvarchar(100) NULL, + 业务主键 nvarchar(100) NOT NULL, + 字段名 nvarchar(100) NOT NULL, + 原值 nvarchar(max) NULL, + 新值 nvarchar(max) NULL, + 维护说明 nvarchar(500) NULL, + 维护人 nvarchar(50) NOT NULL, + 维护时间 datetime NOT NULL DEFAULT GETDATE() +); +``` + +索引: + +```sql +CREATE INDEX IX_系统管理_业务字段维护日志_业务 ON dbo.系统管理_业务字段维护日志(业务模块, 业务主键); +``` + +### 3.3 统一异常关联表 + +现有已有异常管控页面和异常工时逻辑,但本轮要求所有报工页面选中任务直接报异常,且审批人多选。建议在不推翻现有异常管控的前提下增加关联表。 + +表名:`生产管理_异常管控_任务异常` + +```sql +CREATE TABLE dbo.生产管理_异常管控_任务异常 ( + 异常AID bigint IDENTITY(1,1) PRIMARY KEY, + 异常编号 nvarchar(50) NOT NULL, + 来源模块 nvarchar(50) NOT NULL, + 生产订单 int NULL, + TaskAID bigint NULL, + 工序名称 nvarchar(50) NULL, + 指派对象 nvarchar(50) NULL, + 异常类型 nvarchar(50) NULL, + 异常说明 nvarchar(1000) NULL, + 附件ID nvarchar(500) NULL, + 状态 nvarchar(20) NOT NULL DEFAULT N'待处理', + 发起人 nvarchar(50) NOT NULL, + 发起时间 datetime NOT NULL DEFAULT GETDATE(), + 实际处理人 nvarchar(50) NULL, + 处理时间 datetime NULL, + 处理意见 nvarchar(1000) NULL, + 是否关闭 bit NOT NULL DEFAULT 0 +); + +CREATE TABLE dbo.生产管理_异常管控_审批人 ( + AID bigint IDENTITY(1,1) PRIMARY KEY, + 异常AID bigint NOT NULL, + 审批人编号 int NULL, + 审批人姓名 nvarchar(50) NOT NULL, + 是否已处理 bit NOT NULL DEFAULT 0, + 处理时间 datetime NULL +); +``` + +索引: + +```sql +CREATE INDEX IX_生产管理_异常管控_任务异常_TaskAID ON dbo.生产管理_异常管控_任务异常(TaskAID, 是否关闭); +CREATE INDEX IX_生产管理_异常管控_审批人_人员 ON dbo.生产管理_异常管控_审批人(审批人姓名, 是否已处理); +``` + +## 4. 需求 1:及时开工报表 + +### 4.1 现有页面 + +页面:`src/views/AnomalousManagement/PunctualWork/index.vue` + +现状: + +- 当前按指派对象过滤偏向反选逻辑。 +- 需求要求增加正选页面或正选模式。 +- 真实目标不是重做及时开工算法,只改筛选方式。 + +### 4.2 页面方案 + +在查询区新增: + +| 控件 | 类型 | 默认值 | 说明 | +|---|---|---|---| +| 指派对象 | `el-select multiple` | 全部 | 复用现有设备/工位下拉 | +| 查询模式 | `el-radio-group` 或 `el-select` | 排除 | 包含、排除 | + +页面展示: + +```text +指派对象:[多选] 查询模式:[包含/排除] [查询] [重置] [导出] +``` + +交互规则: + +- 查询模式=包含:只查选中指派对象。 +- 查询模式=排除:排除选中指派对象。 +- 未选择指派对象:不增加指派对象条件。 +- 默认保留原逻辑,避免影响现场使用习惯。 + +### 4.3 存储过程 + +建议扩展现有及时开工过程,增加参数: + +```sql +@指派对象 nvarchar(max) = N'', +@指派对象查询模式 nvarchar(10) = N'排除' +``` + +过滤逻辑: + +```sql +IF ISNULL(@指派对象, '') <> '' +BEGIN + IF @指派对象查询模式 = N'包含' + SET @where = @where + N' AND 指派对象 IN (SELECT value FROM STRING_SPLIT(@指派对象, '',''))' + ELSE + SET @where = @where + N' AND 指派对象 NOT IN (SELECT value FROM STRING_SPLIT(@指派对象, '',''))' +END +``` + +注意: + +- 现有很多过程使用字符串拼接动态 SQL,后续应尽量用 `sp_executesql` 参数化,降低注入风险。 +- 如果 `.ashx` 传参不支持 `nvarchar(max)`,可用 `nvarchar(4000)`。 + +### 4.4 不需要新增表 + +该需求只改页面和存储过程参数,不新增表。 + +## 5. 需求 2:机加件排产-表单 + +包含两件事: + +1. 已排产页面日期筛选优化。 +2. 新增历史工时查询,总工时列和明细弹窗。 + +### 5.1 现有页面 + +页面:`src/views/PlanManagement/SelfMakePlandone/index.vue` + +现有查询过程:`MES_OrderPlanned_Query` + +现有过程参数: + +```sql +@计划开始1 nvarchar(50)='', +@计划开始2 nvarchar(50)='', +@计划完成1 nvarchar(50)='', +@计划完成2 nvarchar(50)='' +``` + +### 5.2 页面日期筛选 + +改造前: + +- 计划开始时间为时间段。 +- 计划完成时间为时间段。 + +改造后: + +| 字段 | 控件 | 参数传递 | +|---|---|---| +| 计划开始日期 | `el-date-picker type="date"` | 传 `计划开始日期` | +| 计划完成日期 | `el-date-picker type="date"` | 传 `计划完成日期` | + +前端传参方式: + +```js +if (this.query.计划开始日期) { + param.push(['计划开始日期', this.query.计划开始日期]) +} +if (this.query.计划完成日期) { + param.push(['计划完成日期', this.query.计划完成日期]) +} +``` + +兼容方案: + +- 为减少影响,可以继续传旧参数: + - `计划开始1 = yyyy-MM-dd 00:00:00` + - `计划开始2 = yyyy-MM-dd 23:59:59` + - `计划完成1 = yyyy-MM-dd 00:00:00` + - `计划完成2 = yyyy-MM-dd 23:59:59` +- 存储过程也可新增单日期参数,旧参数保留。 + +### 5.3 存储过程改造 + +建议扩展 `MES_OrderPlanned_Query`: + +```sql +ALTER PROCEDURE dbo.MES_OrderPlanned_Query + @订单号 int = 0, + ... + @计划开始日期 nvarchar(50) = '', + @计划完成日期 nvarchar(50) = '', + @指派对象查询模式 nvarchar(10) = N'包含' +AS +BEGIN + ... + IF (@计划开始日期 <> '') + SET @selectStrWhere = @selectStrWhere + + ' AND [计划开始时间] >= ''' + @计划开始日期 + ' 00:00:00'' + AND [计划开始时间] < DATEADD(DAY, 1, ''' + @计划开始日期 + ''')' + + IF (@计划完成日期 <> '') + SET @selectStrWhere = @selectStrWhere + + ' AND [计划完成时间] >= ''' + @计划完成日期 + ' 00:00:00'' + AND [计划完成时间] < DATEADD(DAY, 1, ''' + @计划完成日期 + ''')' +END +``` + +更稳妥写法是把日期转成 `date` 类型后参数化。 + +### 5.4 总工时列 + +表格新增列: + +| 列名 | 字段 | 交互 | +|---|---|---| +| 总工时 | `历史总工时` | 蓝色可点击,点击打开明细 | + +总工时口径: + +- 数据来源:`YL_加工中心_操作记录表` +- 过滤:`TaskAID = 当前任务 TaskAID`,`工时 > 0` +- 默认包含:报工、辅助结束、加班等正向工时。 +- 默认排除:异常负工时、未结束记录。 +- 单位:建议统一显示小时,保留 2 位小数。 + +### 5.5 新增存储过程 + +#### 5.5.1 总工时汇总 + +过程名:`生产管理_机加已排产_历史工时汇总` + +参数: + +| 参数 | 类型 | 说明 | +|---|---|---| +| `@TaskAID` | bigint | 可选,单任务 | +| `@订单号` | int | 可选,订单 | +| `@开始日期` | date | 可选 | +| `@结束日期` | date | 可选 | + +返回字段: + +| 字段 | 说明 | +|---|---| +| `TaskAID` | 任务 | +| `订单编号` | 订单 | +| `工序名称` | 工序 | +| `总工时分钟` | 分钟 | +| `总工时小时` | 小时 | + +SQL 示例: + +```sql +CREATE PROCEDURE dbo.生产管理_机加已排产_历史工时汇总 + @TaskAID bigint = NULL, + @订单号 int = NULL, + @开始日期 date = NULL, + @结束日期 date = NULL +AS +BEGIN + SET NOCOUNT ON; + + SELECT + o.TaskAID, + MAX(t.订单编号) AS 订单编号, + MAX(o.工序名称) AS 工序名称, + SUM(ISNULL(o.工时, 0)) AS 总工时分钟, + CAST(SUM(ISNULL(o.工时, 0)) / 60.0 AS decimal(18,2)) AS 总工时小时 + FROM dbo.YL_加工中心_操作记录表 o + LEFT JOIN dbo.MES_接口_生产计划_生产任务 t ON o.TaskAID = t.AID + WHERE ISNULL(o.工时, 0) > 0 + AND (@TaskAID IS NULL OR o.TaskAID = @TaskAID) + AND (@订单号 IS NULL OR t.订单编号 = @订单号) + AND (@开始日期 IS NULL OR o.开始时间 >= @开始日期) + AND (@结束日期 IS NULL OR o.开始时间 < DATEADD(DAY, 1, @结束日期)) + GROUP BY o.TaskAID; +END +``` + +#### 5.5.2 历史工时明细 + +过程名:`生产管理_机加已排产_历史工时明细` + +参数: + +| 参数 | 类型 | 说明 | +|---|---|---| +| `@TaskAID` | bigint | 必填 | + +返回字段: + +| 字段 | 说明 | +|---|---| +| `设备名称` | 工位名称 | +| `日期` | 开始时间日期 | +| `生产订单` | 订单编号 | +| `物料编码` | 物料编码 | +| `物料名称` | 物料名称 | +| `工序名称` | 工序 | +| `操作人` | 操作人 | +| `开始时间` | 开始 | +| `结束时间` | 结束 | +| `工时分钟` | 分钟 | +| `工时小时` | 小时 | +| `设备日期小计小时` | 前端可展示分组合计 | + +SQL 示例: + +```sql +CREATE PROCEDURE dbo.生产管理_机加已排产_历史工时明细 + @TaskAID bigint +AS +BEGIN + SET NOCOUNT ON; + + SELECT + o.工位名称 AS 设备名称, + CONVERT(date, o.开始时间) AS 日期, + t.订单编号 AS 生产订单, + t.物料编码, + t.物料名称, + o.工序名称, + o.操作人, + o.开始时间, + o.结束时间, + ISNULL(o.工时, 0) AS 工时分钟, + CAST(ISNULL(o.工时, 0) / 60.0 AS decimal(18,2)) AS 工时小时, + CAST(SUM(ISNULL(o.工时, 0)) OVER (PARTITION BY o.工位名称, CONVERT(date, o.开始时间)) / 60.0 AS decimal(18,2)) AS 设备日期小计小时 + FROM dbo.YL_加工中心_操作记录表 o + LEFT JOIN dbo.MES_接口_生产计划_生产任务 t ON o.TaskAID = t.AID + WHERE o.TaskAID = @TaskAID + AND ISNULL(o.工时, 0) > 0 + ORDER BY o.工位名称, CONVERT(date, o.开始时间), o.开始时间; +END +``` + +### 5.6 前端弹窗 + +弹窗名:历史工时明细 + +结构: + +```text +设备:CNC-01 小计:12.50小时 + 日期:2026-05-28 小计:8.00小时 + 任务明细表 + 日期:2026-05-29 小计:4.50小时 + 任务明细表 +``` + +Element UI 实现建议: + +- 用 `el-dialog`。 +- 明细用 `el-table` 展示,按设备、日期排序。 +- 如需要折叠效果,使用前端 computed 分组。 +- 总工时列点击时调用 `生产管理_机加已排产_历史工时明细`。 + +### 5.7 不建议新增表 + +本需求只需要新增两个查询过程,不需要新增表。 + +## 6. 需求 3:装配已排产需求 + +### 6.1 定位 + +这是本轮最大的独立子项目,不是简单报表。 + +页面目标: + +- 基于装配已排产数据。 +- 整合 SAP 字段、MES 报工、工时、异常、齐套时间、装配完成时间、日计划。 +- 支持部分人工维护字段。 + +建议页面路径: + +```text +src/views/ProductionManagement/AssemblyPlannedDemand/index.vue +``` + +菜单建议: + +```text +生产管理 -> 装配管理 -> 装配已排产需求 +``` + +### 6.2 页面布局 + +页面结构: + +```text +查询区: +系统分类[全部/系统/非系统] 合同号 生产订单 物料编码/名称 +发料齐套时间[起止] 装配完成时间[起止] 状态[全部] +[查询] [重置] [导出] [日计划] [打印] + +主表: +生产订单 合同号 物料编码 物料名称 系统/非系统 派工时间 合同交货期 +发料齐套时间 装配完成时间 当前对应人员 当前对应内容 +生产订单累计工时 合同工时汇总 合同进度参考 预计总工时 预计剩余工时 +钣金预达 钣金到达 泵 生产异常 历史工序说明 操作 + +操作列: +[维护] [工时明细] [异常明细] [历史工序] [日计划] +``` + +### 6.3 字段口径 + +| 字段 | 来源 | 维护方式 | 说明 | +|---|---|---|---| +| 生产订单 | `MES_接口_生产计划.订单编号` | 只读 | 主键 | +| 合同号 | `MES_接口_生产计划.合同号` | 只读 | 合同维度 | +| 物料编码 | `MES_接口_生产计划.物料编号` | 只读 | 主物料 | +| 物料名称 | `MES_接口_生产计划.物料描述` | 只读 | 主物料名称 | +| 系统/非系统 | 规则计算 | 只读 | 高压冷却为系统,阀类非高压冷却为非系统 | +| 派工时间 | SAP 或任务表 `派工时间` | 只读 | 以 SAP 提供为准;现任务表已有派工时间 | +| 合同交货期 | SAP | 只读 | 需同步字段 | +| 发料齐套时间 | SAP/MES 齐套字段 | 可必要维护 | 优先使用 `齐套时间` 或后续 SAP 字段 | +| 装配完成时间 | 发料齐套时间 + 3 天 | 可维护 | 人工修改需记录日志 | +| 钣金预达 | 人工维护 | 可维护 | 过程字段 | +| 钣金到达 | 人工维护 | 可维护 | 过程字段 | +| 泵 | 人工维护 | 可维护 | 建议拆成泵预达/泵到达或说明 | +| 当前对应人员 | 操作记录 | 只读 | 开始未结束的人,多个合并 | +| 当前对应内容 | 操作记录/新增字段 | 只读/维护 | 装配开始时输入的工作内容 | +| 生产订单累计工时 | 工时汇总 | 只读 | 按生产订单分类汇总装配、质量、设计 | +| 历史工序说明 | 报工结束说明 | 只读 | 多条合并或明细弹窗 | +| 预计总工时 | 人工维护 | 可维护 | 订单级 | +| 合同工时汇总 | 工时汇总 | 只读 | 合同下所有订单 | +| 合同进度参考 | 计算 | 只读 | 累计工时 / 预计总工时 | +| 预计剩余工时 | 计算 | 只读 | 预计总工时 - 累计工时 | +| 生产异常 | 异常表 | 只读 | 未关闭异常数和明细 | + +### 6.4 建议新增字段 + +优先不要直接无限扩展主表。建议建订单扩展表。 + +表名:`生产管理_装配已排产需求_扩展` + +```sql +CREATE TABLE dbo.生产管理_装配已排产需求_扩展 ( + AID bigint IDENTITY(1,1) PRIMARY KEY, + 订单编号 int NOT NULL, + 发料齐套时间 datetime NULL, + 发料齐套时间来源 nvarchar(50) NULL, + 装配完成时间 datetime NULL, + 装配完成时间是否人工修改 bit NOT NULL DEFAULT 0, + SAP派工时间 datetime NULL, + 合同交货期 datetime NULL, + 钣金预达 datetime NULL, + 钣金到达 datetime NULL, + 泵预达 datetime NULL, + 泵到达 datetime NULL, + 泵说明 nvarchar(500) NULL, + 预计总工时 decimal(18,2) NULL, + 备注 nvarchar(1000) NULL, + 最后维护人 nvarchar(50) NULL, + 最后维护时间 datetime NULL, + 创建时间 datetime NOT NULL DEFAULT GETDATE() +); + +CREATE UNIQUE INDEX UX_生产管理_装配已排产需求_扩展_订单编号 +ON dbo.生产管理_装配已排产需求_扩展(订单编号); +``` + +### 6.5 当前对应内容 + +当前系统 `MES_人员工时记录_开始` 和装配中心已有人员工时逻辑。需求要求“装配开始时输入工作内容”。如果现有开始记录没有工作内容字段,应补字段到对应记录表。由于实际装配人员工时表名需从存储过程确认,建议先通过 `MES_人员工时记录_开始` 的落表对象确认。 + +建议新增字段: + +```sql +ALTER TABLE dbo.YL_加工中心_操作记录表 ADD 当前工作内容 nvarchar(1000) NULL; +``` + +如果装配人员工时独立表存在,应加在装配人员工时表,而不是操作记录表。 + +前端改造: + +- `AssemblyCenter` 开始装配弹窗增加 `工作内容`。 +- 调用 `MES_人员工时记录_开始` 时增加参数 `@工作内容`。 +- 未结束记录的人员和工作内容在装配已排产需求页展示。 + +### 6.6 工时汇总视图 + +建议新增统一工时视图,供装配已排产需求、合同工时、工时报表复用。 + +视图名:`View_统一工时明细` + +字段: + +| 字段 | 说明 | +|---|---| +| `来源模块` | 机加、装配、质量、设计、编程、设备 | +| `工时类型` | 装配、质量、设计等 | +| `生产订单` | 订单 | +| `合同号` | 合同 | +| `TaskAID` | 任务,可空 | +| `工序名称` | 工序 | +| `操作人` | 人员 | +| `开始时间` | 开始 | +| `结束时间` | 结束 | +| `工时分钟` | 分钟 | +| `工时小时` | 小时 | + +第一阶段可只接入: + +- 装配:`MES_人员工时记录_*` 对应表或 `YL_加工中心_操作记录表` +- 质量:质检中心人员工时记录或操作记录 +- 设计:设计任务报工表,等设计模块完成后接入 + +### 6.7 查询存储过程 + +过程名:`生产管理_装配已排产需求_查询` + +参数: + +| 参数 | 类型 | +|---|---| +| `@系统分类` | nvarchar(20),全部/系统/非系统 | +| `@合同号` | nvarchar(50) | +| `@订单编号` | int | +| `@物料` | nvarchar(100) | +| `@发料齐套开始` | date | +| `@发料齐套结束` | date | +| `@装配完成开始` | date | +| `@装配完成结束` | date | +| `@状态` | nvarchar(50) | + +核心 SQL 口径: + +```sql +SELECT + p.订单编号, + p.合同号, + p.物料编号, + p.物料描述, + CASE + WHEN p.物料描述 LIKE N'%高压冷却%' THEN N'系统' + ELSE N'非系统' + END AS 系统分类, + ISNULL(e.SAP派工时间, MAX(t.派工时间)) AS 派工时间, + e.合同交货期, + COALESCE(e.发料齐套时间, p.齐套时间, p.预计齐套时间) AS 发料齐套时间, + COALESCE(e.装配完成时间, DATEADD(DAY, 3, COALESCE(e.发料齐套时间, p.齐套时间, p.预计齐套时间))) AS 装配完成时间, + e.钣金预达, + e.钣金到达, + e.泵预达, + e.泵到达, + e.泵说明, + e.预计总工时, + wh.生产订单累计工时, + chw.合同工时汇总, + CASE WHEN ISNULL(e.预计总工时,0) = 0 THEN NULL + ELSE CAST(wh.生产订单累计工时 / e.预计总工时 AS decimal(18,4)) + END AS 合同进度参考, + ISNULL(e.预计总工时,0) - ISNULL(wh.生产订单累计工时,0) AS 预计剩余工时, + cur.当前对应人员, + cur.当前对应内容, + abn.未关闭异常数 +FROM dbo.MES_接口_生产计划 p +LEFT JOIN dbo.MES_接口_生产计划_生产任务 t ON p.订单编号 = t.订单编号 +LEFT JOIN dbo.生产管理_装配已排产需求_扩展 e ON p.订单编号 = e.订单编号 +LEFT JOIN (...) wh ON p.订单编号 = wh.生产订单 +LEFT JOIN (...) chw ON p.合同号 = chw.合同号 +LEFT JOIN (...) cur ON p.订单编号 = cur.生产订单 +LEFT JOIN (...) abn ON p.订单编号 = abn.生产订单 +WHERE p.自制件属性 LIKE N'%装配%' +GROUP BY ... +``` + +### 6.8 保存维护字段过程 + +过程名:`生产管理_装配已排产需求_维护字段保存` + +参数: + +- `@订单编号 int` +- `@发料齐套时间 datetime = NULL` +- `@装配完成时间 datetime = NULL` +- `@钣金预达 datetime = NULL` +- `@钣金到达 datetime = NULL` +- `@泵预达 datetime = NULL` +- `@泵到达 datetime = NULL` +- `@泵说明 nvarchar(500) = NULL` +- `@预计总工时 decimal(18,2) = NULL` +- `@备注 nvarchar(1000) = NULL` +- `@维护人 nvarchar(50)` + +逻辑: + +1. 如果扩展表不存在订单记录,插入。 +2. 如果存在,更新。 +3. 对每个字段写 `系统管理_业务字段维护日志`。 +4. 返回 `result=1`。 + +### 6.9 工时明细过程 + +过程名:`生产管理_装配已排产需求_工时明细` + +参数: + +- `@订单编号 int` +- `@合同号 nvarchar(50)` +- `@工时类型 nvarchar(50)`,全部/装配/质量/设计 + +返回: + +- 来源模块 +- 工时类型 +- 生产订单 +- 合同号 +- TaskAID +- 工序名称 +- 操作人 +- 开始时间 +- 结束时间 +- 工时小时 +- 工作内容 +- 结束说明 + +### 6.10 异常明细过程 + +过程名:`生产管理_装配已排产需求_异常明细` + +数据来源: + +- 优先:`生产管理_异常管控_任务异常` +- 兼容:现有异常管控表或 `YL_加工中心_操作记录表` 中 `操作类别='异常'` + +返回: + +- 异常编号 +- 异常类型 +- 异常说明 +- 发起人 +- 发起时间 +- 状态 +- 处理人 +- 处理时间 + +### 6.11 日计划 + +页面按钮:`日计划` + +规则: + +- 按装配完成时间分组。 +- 未完成、未入库、未关闭的任务进入计划。 +- 支持导出、打印。 + +过程名:`生产管理_装配已排产需求_日计划` + +参数: + +- `@计划日期 date` +- `@系统分类 nvarchar(20)` + +返回字段: + +- 计划日期 +- 生产订单 +- 合同号 +- 物料编码 +- 物料名称 +- 装配完成时间 +- 当前对应人员 +- 当前对应内容 +- 异常状态 +- 备注 + +打印: + +- 使用 `vue-print-nb`。 +- 打印区域为日计划表格。 +- 标题:`装配日计划 YYYY-MM-DD`。 + +## 7. 需求 4:生产日报-送检 + +### 7.1 页面定位 + +建议新增页面: + +```text +src/views/ReportManagement/InspectionDaily/index.vue +``` + +如果项目没有 `ReportManagement`,可放在: + +```text +src/views/ProductionManagement/InspectionDaily/index.vue +``` + +菜单建议: + +```text +报表中心 -> 生产日报 -> 生产日报-送检 +``` + +页面采用两个页签: + +- 机加送检日报 +- 装配送检日报 + +### 7.2 页面布局 + +```text +页签:[机加送检日报] [装配送检日报] + +查询区: +日期[单日/日期范围] 部门[全部] 生产订单 物料 工序 状态 +[查询] [重置] [导出] + +汇总区: +送检数量 已检数量 合格数量 不合格数量 未检数量 及时率 + +表格: +日期 部门 生产订单 物料编码 物料名称 工序名称 送检数量 +已检数量 合格数量 不合格数量 未检数量 送检时间 检验时间 状态 +``` + +### 7.3 需要确认的数据 + +| 数据 | 需要确认 | +|---|---| +| 送检记录来源 | 装配送检是否来自 `MES_ProductTask_SendInspection` 写入的记录,机加送检是否来自质检任务或操作记录 | +| 部门归属 | 按操作人部门、工位部门、任务部门还是物料/订单类型 | +| 送检数量 | 取操作记录 `操作数值`,还是质检记录 `检验数量` | +| 已检数量 | 质检记录合计 | +| 状态 | 未检、部分检验、已检、超期 | + +### 7.4 建议视图 + +视图名:`View_生产日报_送检明细` + +字段: + +| 字段 | 来源 | +|---|---| +| 日期 | 送检时间日期 | +| 送检类型 | 机加/装配 | +| 部门 | 人员部门或工位部门 | +| 生产订单 | 任务订单 | +| TaskAID | 任务 | +| 物料编码 | 任务物料 | +| 物料名称 | 任务物料 | +| 工序名称 | 任务工序 | +| 指派对象 | 任务指派对象 | +| 送检数量 | 送检记录 | +| 已检数量 | 质检记录 | +| 合格数量 | 质检记录 | +| 不合格数量 | 质检记录 | +| 未检数量 | 送检数量 - 已检数量 | +| 送检时间 | 送检记录时间 | +| 检验时间 | 最后检验时间 | +| 状态 | 计算 | + +### 7.5 存储过程 + +过程名:`生产日报_送检_查询` + +参数: + +| 参数 | 类型 | +|---|---| +| `@送检类型` | nvarchar(20),机加/装配 | +| `@开始日期` | date | +| `@结束日期` | date | +| `@部门` | nvarchar(50) | +| `@生产订单` | int | +| `@物料` | nvarchar(100) | +| `@状态` | nvarchar(20) | + +核心逻辑: + +```sql +SELECT + 日期, + 部门, + 生产订单, + 物料编码, + 物料名称, + 工序名称, + SUM(送检数量) AS 送检数量, + SUM(已检数量) AS 已检数量, + SUM(合格数量) AS 合格数量, + SUM(不合格数量) AS 不合格数量, + SUM(未检数量) AS 未检数量, + MIN(送检时间) AS 最早送检时间, + MAX(检验时间) AS 最后检验时间, + CASE + WHEN SUM(已检数量) = 0 THEN N'未检' + WHEN SUM(未检数量) > 0 THEN N'部分检验' + ELSE N'已检' + END AS 状态 +FROM dbo.View_生产日报_送检明细 +WHERE 日期 >= @开始日期 + AND 日期 < DATEADD(DAY, 1, @结束日期) + AND (@送检类型 = N'全部' OR 送检类型 = @送检类型) +GROUP BY 日期, 部门, 生产订单, 物料编码, 物料名称, 工序名称 +ORDER BY 日期, 部门, 生产订单; +``` + +### 7.6 是否新增表 + +第一阶段不新增表,使用视图 + 存储过程。 + +如果客户要求日报定版,需要新增快照表: + +```sql +CREATE TABLE dbo.生产日报_送检_日报快照 ( + AID bigint IDENTITY(1,1) PRIMARY KEY, + 统计日期 date NOT NULL, + 送检类型 nvarchar(20) NOT NULL, + 部门 nvarchar(50) NULL, + 生产订单 int NULL, + TaskAID bigint NULL, + 物料编码 nvarchar(100) NULL, + 物料名称 nvarchar(500) NULL, + 工序名称 nvarchar(100) NULL, + 送检数量 decimal(18,2) NULL, + 已检数量 decimal(18,2) NULL, + 合格数量 decimal(18,2) NULL, + 不合格数量 decimal(18,2) NULL, + 未检数量 decimal(18,2) NULL, + 状态 nvarchar(20) NULL, + 生成时间 datetime NOT NULL DEFAULT GETDATE(), + 生成人 nvarchar(50) NULL +); +``` + +## 8. 需求 5:及时齐套跟踪结果报表 + +### 8.1 页面定位 + +新增页面: + +```text +src/views/ProductionManagement/KitTrackingResult/index.vue +``` + +菜单建议: + +```text +报表中心 -> 齐套报表 -> 及时齐套跟踪结果报表 +``` + +### 8.2 页面布局 + +```text +查询区: +主生产订单 合同号 物料 齐套状态 预计可执行时间 SAP同步时间 +[查询] [重置] [导出] + +主表: +主生产订单 合同号 物料编码 物料名称 计划数量 齐套状态 +缺件数 当前进度 预计可执行时间 SAP同步时间 操作 + +展开明细: +缺料生产订单 缺料物料编码 缺料物料名称 缺件数量 属性 +对应单据号 当前进度 全序展示 单条预计完成时间 预计可执行时间 操作 +``` + +### 8.3 数据来源 + +| 数据 | 来源 | 方式 | +|---|---|---| +| 主表订单 | `MES_接口_生产计划` / `View_生产订单_MES` | MES 查询 | +| 齐套状态 | `齐套`、`齐套时间`、`发料状态`、`拣配状态` | MES 字段 | +| 缺件明细 | SAP 实时接口 | 点击展开时查 | +| 主子订单关系 | SAP 或 MES 人工维护 | 建议落 MES 表 | +| 预计可执行时间 | 人工维护 | 报表内维护,写日志 | + +### 8.4 建议新增表 + +#### 8.4.1 主子订单关系表 + +表名:`生产管理_齐套跟踪_主子订单关系` + +```sql +CREATE TABLE dbo.生产管理_齐套跟踪_主子订单关系 ( + AID bigint IDENTITY(1,1) PRIMARY KEY, + 主生产订单 int NOT NULL, + 缺料生产订单 int NOT NULL, + 缺料物料编码 nvarchar(100) NULL, + 缺料物料名称 nvarchar(500) NULL, + 关系来源 nvarchar(50) NOT NULL DEFAULT N'人工维护', + 是否有效 bit NOT NULL DEFAULT 1, + 创建人 nvarchar(50) NULL, + 创建时间 datetime NOT NULL DEFAULT GETDATE(), + 最后维护人 nvarchar(50) NULL, + 最后维护时间 datetime NULL +); + +CREATE INDEX IX_生产管理_齐套跟踪_主子订单关系_主单 +ON dbo.生产管理_齐套跟踪_主子订单关系(主生产订单, 是否有效); +``` + +#### 8.4.2 缺件预计信息表 + +表名:`生产管理_齐套跟踪_缺件预计信息` + +```sql +CREATE TABLE dbo.生产管理_齐套跟踪_缺件预计信息 ( + AID bigint IDENTITY(1,1) PRIMARY KEY, + 主生产订单 int NOT NULL, + 缺料生产订单 int NULL, + 缺料物料编码 nvarchar(100) NOT NULL, + 对应单据号 nvarchar(100) NULL, + 预计可执行时间 datetime NULL, + 预计可执行说明 nvarchar(500) NULL, + 维护人 nvarchar(50) NULL, + 维护时间 datetime NOT NULL DEFAULT GETDATE() +); + +CREATE INDEX IX_生产管理_齐套跟踪_缺件预计信息_主单 +ON dbo.生产管理_齐套跟踪_缺件预计信息(主生产订单); +``` + +#### 8.4.3 SAP 缺件缓存表 + +如果 SAP 实时查询压力大,新增缓存表: + +```sql +CREATE TABLE dbo.系统集成_SAP缺件明细缓存 ( + AID bigint IDENTITY(1,1) PRIMARY KEY, + 主生产订单 int NOT NULL, + 查询时间 datetime NOT NULL DEFAULT GETDATE(), + 缺料生产订单 int NULL, + 物料编码 nvarchar(100) NULL, + 物料名称 nvarchar(500) NULL, + 缺件数量 decimal(18,2) NULL, + 属性 nvarchar(20) NULL, + 对应单据号 nvarchar(100) NULL, + 当前进度 nvarchar(500) NULL, + 全序展示 nvarchar(max) NULL, + 单条预计完成时间 datetime NULL, + 原始JSON nvarchar(max) NULL +); +``` + +### 8.5 存储过程 + +主表查询: + +```text +生产管理_齐套跟踪结果_主表查询 +``` + +参数: + +- `@主生产订单 int` +- `@合同号 nvarchar(50)` +- `@物料 nvarchar(100)` +- `@齐套状态 nvarchar(50)` +- `@预计开始 date` +- `@预计结束 date` + +展开明细: + +```text +生产管理_齐套跟踪结果_缺件明细查询 +``` + +说明: + +- 第一优先:点击展开时前端调用 SAP 接口,再把结果展示并可缓存。 +- 如果后端 `.ashx` 只能执行 SQL,SAP 查询需要前端现有 SAP/B1 接口或后端新增封装接口。 +- 如果不能实时查 SAP,先读取 `系统集成_SAP缺件明细缓存`。 + +预计可执行时间保存: + +```text +生产管理_齐套跟踪结果_预计时间保存 +``` + +参数: + +- 主生产订单 +- 缺料生产订单 +- 缺料物料编码 +- 对应单据号 +- 预计可执行时间 +- 预计可执行说明 +- 维护人 + +同时写 `系统管理_业务字段维护日志`。 + +## 9. 需求 6:生产计划跟踪 + +### 9.1 现有页面 + +页面: + +```text +src/views/ProductionManagement/ProductionPlanTrack/index.vue +``` + +现有调用: + +```text +生产管理_生产计划跟踪 +``` + +页面现状已经有外协状态处理、工序子表、颜色等基础逻辑。 + +### 9.2 页面改造 + +新增/调整: + +| 内容 | 实现 | +|---|---| +| 当前序显示完整工艺路线 | 主表列改为路线组件 | +| 工序文字按状态变色 | 前端根据状态 class | +| 进度文案 | `打磨中`、`打磨毕待淬火` | +| 标准工时 | 表格列 | +| 订单状态 | 表格列 | + +工艺路线显示: + +```text +打磨(张三) -> 淬火(外协) -> 精磨(李四) +``` + +颜色规则: + +| 状态 | 样式 | +|---|---| +| 正在加工 | 蓝色或绿色高亮 | +| 已完成 | 灰色 | +| 等待加工 | 默认 | +| 异常 | 红色 | + +### 9.3 后端返回字段 + +过程 `生产管理_生产计划跟踪` 需要返回每道工序: + +| 字段 | 说明 | +|---|---| +| 生产订单 | +| 合同号 | +| 订单状态 | +| 物料编码 | +| 物料名称 | +| TaskAID | +| 工序名称 | +| 顺序编号 | +| 指派对象 | +| 任务状态 | +| 加工状态 | +| 开工时间 | +| 完工时间 | +| 标准工时 | +| 外协结束时间 | + +### 9.4 SQL 逻辑 + +标准工时来源: + +- 优先 `车间生产管理工艺_零件生产工艺_工艺库.标准工时` +- 通过 `订单编号 + 工艺顺序/订单行号` 关联 + +订单状态来源: + +- `MES_接口_生产计划.订单状态` +- 如果 SAP 同步了单据状态,也可增加 `单据状态` + +过程示例逻辑: + +```sql +SELECT + p.订单编号, + p.合同号, + p.订单状态, + t.AID AS TaskAID, + t.工序名称, + t.顺序编号, + t.指派对象, + t.任务状态, + t.加工状态, + t.开工时间, + t.完工时间, + ISNULL(g.标准工时, 0) AS 标准工时 +FROM dbo.MES_接口_生产计划 p +JOIN dbo.MES_接口_生产计划_生产任务 t ON p.订单编号 = t.订单编号 +LEFT JOIN dbo.车间生产管理工艺_零件生产工艺_工艺库 g + ON t.订单编号 = g.订单编号 + AND t.订单行号 = g.工艺顺序 +WHERE ... +ORDER BY p.订单编号, t.顺序编号; +``` + +### 9.5 前端算法 + +将后端明细按订单分组: + +```js +const groups = {} +rows.forEach(row => { + if (!groups[row.订单编号]) groups[row.订单编号] = [] + groups[row.订单编号].push(row) +}) +``` + +每个工序状态: + +```js +function getStepStatus(step) { + if (step.任务状态 === 4 || step.完工时间) return 'done' + if (step.加工状态 === 2 || step.开工时间) return 'doing' + return 'waiting' +} +``` + +进度文案: + +```js +function getProgressText(steps) { + const doing = steps.find(x => getStepStatus(x) === 'doing') + if (doing) return `${doing.工序名称}中` + const lastDoneIndex = findLastDoneIndex(steps) + if (lastDoneIndex >= 0 && steps[lastDoneIndex + 1]) { + return `${steps[lastDoneIndex].工序名称}毕待${steps[lastDoneIndex + 1].工序名称}` + } + if (lastDoneIndex === steps.length - 1) return '已完成' + return '待开工' +} +``` + +## 10. 需求 7:外协任务检验 + +### 10.1 现有页面 + +相关页面: + +```text +src/views/QualityManagement/CheckTask/processReceive.vue +src/views/ProductionManagement/OutsourceMange/index.vue +src/views/ProductionManagement/OutsourceSheet/index.vue +``` + +现有视图: + +- `View_质量检验_质检记录_外协收检` +- `View_外协质检` +- `View_外协报表视图` + +### 10.2 需求字段 + +| 字段 | 来源 | +|---|---| +| 指派对象 | 任务表 `MES_接口_生产计划_生产任务.指派对象` | +| 供应商 | SAP 采购/外协单据,或外协任务维护 | +| SAP采购收货单号 | SAP 采购收货成功后返回 | + +### 10.3 建议新增字段 + +优先加在质检记录扩展表,避免直接改大表影响历史。 + +表名:`质量管理_外协收检_扩展` + +```sql +CREATE TABLE dbo.质量管理_外协收检_扩展 ( + AID bigint IDENTITY(1,1) PRIMARY KEY, + QT_AID bigint NOT NULL, + TaskAID bigint NULL, + 指派对象 nvarchar(50) NULL, + 供应商编码 nvarchar(100) NULL, + 供应商名称 nvarchar(200) NULL, + SAP采购收货单号 nvarchar(100) NULL, + SAP采购收货行号 nvarchar(50) NULL, + SAP同步状态 nvarchar(20) NULL, + SAP返回信息 nvarchar(max) NULL, + 创建时间 datetime NOT NULL DEFAULT GETDATE(), + 最后维护时间 datetime NULL +); + +CREATE UNIQUE INDEX UX_质量管理_外协收检_扩展_QT +ON dbo.质量管理_外协收检_扩展(QT_AID); +``` + +如果客户明确要在质检主记录中查询导出,也可直接加字段到 `YL_质量检验_质检记录`: + +```sql +ALTER TABLE dbo.YL_质量检验_质检记录 ADD + 指派对象 nvarchar(50) NULL, + 供应商编码 nvarchar(100) NULL, + 供应商名称 nvarchar(200) NULL, + SAP采购收货单号 nvarchar(100) NULL; +``` + +推荐扩展表,查询视图再拼接。 + +### 10.4 页面改造 + +序检收检页面: + +- 收检表格增加:指派对象、供应商、SAP采购收货单号。 +- 收检详情弹窗增加只读展示。 +- 外协收检成功后,保存 SAP 返回的采购收货单号。 + +外协报表: + +- 增加供应商、SAP采购收货单号列。 +- 后续供应商合格率按供应商分组。 + +### 10.5 存储过程 + +新增或扩展: + +| 过程 | 说明 | +|---|---| +| `质量管理_外协收检_扩展保存` | 收检完成后保存供应商和 SAP 单号 | +| `质量管理_外协收检_查询` | 查询外协收检扩展字段 | +| `生产管理_外协任务报表_查询` | 扩展供应商、SAP采购收货单号、采购到货期说明 | + +## 11. 需求 8:异常管控 + +### 11.1 现有页面 + +异常页面: + +```text +src/views/ProductionManagement/AbnormalControl/index.vue +``` + +需要加入口的页面: + +- `ProductionManagement/MachiningCenter/index.vue` +- `ProductionManagement/AssemblyCenter/index.vue` +- `QualityManagement/QualityCenter/index.vue` +- `QualityManagement/CheckTask/processReceive.vue` +- 后续设计任务报工页面 +- 后续编程任务清单页面 + +### 11.2 页面交互 + +在任务操作区增加按钮: + +```text +[报异常] +``` + +点击前校验: + +- 必须选中任务。 +- 必须有 TaskAID 或生产订单。 +- 已关闭/已入库任务不允许新报异常,除非角色有权限。 + +异常弹窗字段: + +| 字段 | 控件 | +|---|---| +| 生产订单 | 只读 | +| TaskAID | 隐藏 | +| 工序名称 | 只读 | +| 指派对象 | 只读 | +| 异常类型 | 下拉 | +| 异常说明 | 多行文本 | +| 附件 | 上传 | +| 审批人 | 人员多选 | + +### 11.3 数据表 + +使用第 3.3 节建议表: + +- `生产管理_异常管控_任务异常` +- `生产管理_异常管控_审批人` + +### 11.4 存储过程 + +#### 11.4.1 异常提交 + +过程名:`生产管理_异常管控_任务异常提交` + +参数: + +- 来源模块 +- 生产订单 +- TaskAID +- 工序名称 +- 指派对象 +- 异常类型 +- 异常说明 +- 附件ID +- 审批人JSON +- 发起人 + +逻辑: + +1. 生成异常编号,例如 `YC202605280001`。 +2. 插入 `生产管理_异常管控_任务异常`。 +3. 解析审批人 JSON,插入 `生产管理_异常管控_审批人`。 +4. 返回异常编号。 + +#### 11.4.2 待办查询 + +过程名:`生产管理_异常管控_待办查询` + +参数: + +- `@审批人姓名` +- `@状态` + +逻辑: + +- 审批人被选中即可看到任务。 +- 任一审批人处理后,异常进入下一状态或关闭。 + +#### 11.4.3 异常处理 + +过程名:`生产管理_异常管控_任务异常处理` + +参数: + +- 异常AID +- 处理人 +- 处理意见 +- 处理结果 + +逻辑: + +1. 更新异常主表实际处理人、处理时间、状态。 +2. 当前审批人记录标记已处理。 +3. 同一异常其他审批人不再待办。 + +## 12. 需求 9:机加班次产量表 + +### 12.1 页面定位 + +新增页面: + +```text +src/views/ProductionManagement/MachiningShiftOutput/index.vue +``` + +菜单: + +```text +报表中心 -> 生产报表 -> 机加班次产量表 +``` + +### 12.2 页面布局 + +```text +查询区: +日期范围 班次 设备 操作人 生产订单 物料 +[查询] [重置] [导出] + +汇总卡: +总数量 总工时 设备数 班次数 + +分组表: +设备 -> 日期 -> 班次 -> 任务明细 +``` + +### 12.3 数据来源 + +| 数据 | 来源 | +|---|---| +| 报工数量 | `YL_加工中心_操作记录表.操作数值` | +| 工时 | `YL_加工中心_操作记录表.工时` | +| 设备 | `工位名称` 或任务 `指派对象` | +| 生产订单/物料 | `MES_接口_生产计划_生产任务` | +| 班次 | `班次表` + 时间匹配 | + +现有函数: + +```text +dbo.计算班次重叠秒数 +``` + +可用于跨天班次工时计算。 + +### 12.4 存储过程 + +过程名:`生产报表_机加班次产量表_查询` + +参数: + +- 开始日期 +- 结束日期 +- 班次 +- 设备 +- 操作人 +- 生产订单 +- 物料 + +返回: + +- 设备名称 +- 日期 +- 班次 +- 生产订单 +- 物料编码 +- 物料名称 +- 工序名称 +- 开始时间 +- 结束时间 +- 工时小时 +- 数量 +- 操作人 +- 设备日期班次小计数量 +- 设备日期班次小计工时 + +SQL 逻辑: + +1. 取 `操作类别='报工'` 且 `操作数值 > 0` 的记录。 +2. 按 `开始时间` 匹配班次。 +3. 关联任务表补订单、物料、工序。 +4. 按设备、日期、班次排序。 + +### 12.5 是否新增表 + +第一阶段不新增表。 + +如果班次规则不足,需要扩展 `班次表`: + +```sql +ALTER TABLE dbo.班次表 ADD + 是否跨天 bit NULL, + 是否启用 bit NULL, + 班次日期归属 nvarchar(20) NULL; -- 开始日/结束日 +``` + +## 13. 需求 10:发货通知列表 + +### 13.1 页面定位 + +新增页面: + +```text +src/views/ProductionManagement/ShippingNoticeList/index.vue +``` + +菜单: + +```text +报表中心 -> 交付报表 -> 发货通知列表 +``` + +### 13.2 数据来源 + +客户说明:SAP 已提供数据,大屏已显示。 + +需要先查新分析: + +1. 大屏当前发货通知读取哪个过程。 +2. `装配中心任务看板_发货状态查询` 是否已经包含发货通知字段。 +3. `MES_接口_生产计划` 中 `发货状态`、`要求发货日期` 是否够用。 +4. 是否有 SAP 发货通知同步落地表。 + +### 13.3 建议新增表 + +若当前没有发货通知落地表,建议建: + +```sql +CREATE TABLE dbo.系统集成_SAP发货通知 ( + AID bigint IDENTITY(1,1) PRIMARY KEY, + 发货通知号 nvarchar(100) NOT NULL, + 合同号 nvarchar(50) NULL, + 客户编码 nvarchar(100) NULL, + 客户名称 nvarchar(200) NULL, + 生产订单 int NULL, + 物料编码 nvarchar(100) NULL, + 物料名称 nvarchar(500) NULL, + 数量 decimal(18,2) NULL, + 要求发货日期 datetime NULL, + 发货状态 nvarchar(50) NULL, + SAP同步时间 datetime NULL, + 原始JSON nvarchar(max) NULL, + 创建时间 datetime NOT NULL DEFAULT GETDATE() +); + +CREATE INDEX IX_系统集成_SAP发货通知_合同号 ON dbo.系统集成_SAP发货通知(合同号); +CREATE INDEX IX_系统集成_SAP发货通知_生产订单 ON dbo.系统集成_SAP发货通知(生产订单); +``` + +如果已有大屏同步表,则不建新表,直接复用。 + +### 13.4 存储过程 + +过程名:`报表_发货通知列表_查询` + +参数: + +- 发货通知号 +- 合同号 +- 客户 +- 状态 +- 要求发货开始 +- 要求发货结束 + +返回: + +- 发货通知号 +- 合同号 +- 客户 +- 生产订单 +- 物料编码 +- 物料名称 +- 数量 +- 要求发货日期 +- 发货状态 +- SAP同步时间 + +## 14. 需求 11:质检任务早知道 + +### 14.1 依赖 + +强依赖: + +- `生产管理_装配已排产需求_查询` +- 装配完成时间字段可用 + +### 14.2 页面定位 + +新增页面: + +```text +src/views/QualityManagement/QualityTaskPreview/index.vue +``` + +菜单: + +```text +质量管理 -> 质量报表 -> 质检任务早知道 +``` + +### 14.3 查询规则 + +过滤: + +- 装配完成时间在查询范围内。 +- 排除已完成质检。 +- 排除订单关闭、取消、整单已入库。 +- 按装配完成时间分组。 + +### 14.4 存储过程 + +过程名:`质量管理_质检任务早知道_查询` + +参数: + +- 装配完成开始 +- 装配完成结束 +- 合同号 +- 生产订单 +- 物料 + +返回: + +- 预计质检日期 +- 生产订单 +- 合同号 +- 物料编码 +- 物料名称 +- 装配完成时间 +- 当前对应人员 +- 当前对应内容 +- 累计工时 +- 异常状态 +- 质检状态 + +SQL 逻辑: + +```sql +-- 基于装配已排产需求结果,再排除已检/关闭/取消/入库 +``` + +### 14.5 不新增表 + +本需求不新增表,只新增查询过程和页面。 + +## 15. 需求 12:生产工艺自动带出标准工艺 + +### 15.1 现有页面 + +相关页面: + +```text +src/views/ProcessManagement/ProcessProduct/index.vue +src/views/ProcessManagement/ProcessesDevelop/index.vue +``` + +### 15.2 页面交互 + +点击编辑生产工艺: + +1. 查询是否已有生产工艺。 +2. 如果有,正常打开。 +3. 如果没有,提示: + +```text +当前订单未找到生产工艺,是否按物料标准工艺带出草稿? +[带出标准工艺] [取消] +``` + +4. 带出后只在页面显示,不直接落库。 +5. 用户点击保存后,写入生产工艺。 + +### 15.3 存储过程 + +新增: + +| 过程 | 用途 | +|---|---| +| `工艺管理_生产工艺_是否存在` | 按订单号查询是否已有生产工艺 | +| `工艺管理_生产工艺_标准工艺草稿查询` | 按物料编码查标准工艺并映射成生产工艺字段 | + +保存仍复用现有生产工艺保存过程。 + +### 15.4 字段映射 + +需要查新分析: + +- 标准工艺表:`车间生产管理工艺_零件工序_工艺库` +- 生产工艺表:`车间生产管理工艺_零件生产工艺_工艺库` +- 两者字段差异。 + +至少映射: + +| 标准工艺 | 生产工艺 | +|---|---| +| 物料编号 | 物料编号 | +| 工序名称 | 工序名称 | +| 工艺顺序 | 工艺顺序 | +| 标准工时 | 标准工时 | +| 工序说明 | 工序说明 | +| 指派对象默认值 | 指派对象 | + +### 15.5 不建议新增表 + +该需求只改页面和过程,不新增表。 + +## 16. 需求 13:工时报表 + 备注类小改 + +### 16.1 工时报表新增指派对象 + +现有页面: + +```text +src/views/ProductionManagement/Timesheet/index.vue +``` + +现有过程: + +```text +工时统计_作业者工时_查询 +工时统计_作业者工时_查询_导出 +``` + +改造: + +- 查询区增加指派对象筛选。 +- 表格增加指派对象列。 +- 导出增加指派对象列。 + +SQL 来源: + +- `YL_加工中心_操作记录表.工位名称` +- 或关联任务表取 `MES_接口_生产计划_生产任务.指派对象` + +推荐使用任务表指派对象,工位名称作为实际操作工位,两者都可展示: + +| 字段 | 说明 | +|---|---| +| 指派对象 | 任务被派给谁 | +| 实际工位 | 操作记录发生在哪个工位 | + +### 16.2 机加领料备注 + +需求: + +- 生产领料(机加)增加备注字段。 + +需要先定位现有领料表。如果无独立表,可能通过 SAP 或操作记录保存。 + +建议: + +```sql +ALTER TABLE dbo.MES_接口_生产计划_生产任务 ADD 机加领料备注 nvarchar(500) NULL; +``` + +如领料已有专表,应加在领料单表。 + +过程: + +- `生产管理_机加领料_备注保存` +- `生产管理_机加领料_查询` 返回备注 + +### 16.3 机加退库备注、装配退库备注 + +建议如果退库已有业务表,在退库表增加: + +```sql +备注 nvarchar(500) NULL, +最后维护人 nvarchar(50) NULL, +最后维护时间 datetime NULL +``` + +如果没有退库表,先不要加到任务表,建议建退库单扩展表: + +```sql +CREATE TABLE dbo.生产管理_退库单_扩展 ( + AID bigint IDENTITY(1,1) PRIMARY KEY, + 退库单号 nvarchar(100) NOT NULL, + 退库类型 nvarchar(20) NOT NULL, -- 机加/装配 + 生产订单 int NULL, + TaskAID bigint NULL, + 备注 nvarchar(500) NULL, + 最后维护人 nvarchar(50) NULL, + 最后维护时间 datetime NULL +); +``` + +### 16.4 外协任务报表采购到货期说明 + +现有页面: + +```text +src/views/ProductionManagement/OutsourceSheet/index.vue +src/views/ProductionManagement/OutsourceMange/index.vue +``` + +建议字段: + +```sql +ALTER TABLE dbo.MES_接口_生产计划_生产任务 ADD 采购到货期说明 nvarchar(500) NULL; +``` + +如果采购到货期说明来自 SAP,则不允许手工覆盖,改为扩展表: + +```sql +CREATE TABLE dbo.生产管理_外协任务_采购扩展 ( + AID bigint IDENTITY(1,1) PRIMARY KEY, + TaskAID bigint NOT NULL, + 采购到货期说明 nvarchar(500) NULL, + SAP采购订单号 nvarchar(100) NULL, + SAP采购收货单号 nvarchar(100) NULL, + 供应商编码 nvarchar(100) NULL, + 供应商名称 nvarchar(200) NULL, + 最后维护人 nvarchar(50) NULL, + 最后维护时间 datetime NULL +); +``` + +### 16.5 制定标准工艺保存提示 + +页面: + +```text +src/views/ProcessManagement/ProcessesDevelop/index.vue +``` + +改造: + +- 保存成功显示“标准工艺保存成功”。 +- 保存失败显示后端 message。 +- 如果字段缺失,提示具体字段。 + +不涉及数据库。 + +## 17. 需求 14:生产订单关闭批量更新 SAP 状态 + +### 17.1 现有页面 + +页面: + +```text +src/views/PlanManagement/PlannOrderClose/index.vue +``` + +### 17.2 页面改造 + +表格增加多选列: + +```html + +``` + +新增按钮: + +```text +[批量关闭 SAP 订单] +``` + +点击后: + +1. 校验已选择订单。 +2. 弹出二次确认: + +```text +即将批量关闭 N 个 SAP 生产订单。该操作会写入 SAP,可能部分成功部分失败,是否继续? +``` + +3. 调用批量关闭逻辑。 +4. 展示结果弹窗。 + +结果弹窗字段: + +- 生产订单 +- SAP 单据号 +- 执行结果 +- 失败原因 +- 是否可重试 + +### 17.3 后端建议 + +由于当前前端很多 SAP 操作是直接调用 SAP/B1 接口或通过现有工具实现,批量关闭建议封装为前端逐单执行 + MES 记录结果,或后端新增 API。若 `.ashx` 仅支持 SQL,不适合在 SQL 里直接调 SAP。 + +建议流程: + +```text +前端选中订单 + -> 查询订单 SAP DocEntry + -> 逐单 PATCH SAP ProductionOrders + -> 每单结果写入 系统集成_SAP调用日志 + -> 更新 MES 订单状态或 SAP关闭状态扩展字段 +``` + +### 17.4 建议新增字段 + +表:`MES_接口_生产计划` + +```sql +ALTER TABLE dbo.MES_接口_生产计划 ADD + SAP关闭状态 nvarchar(20) NULL, + SAP关闭时间 datetime NULL, + SAP关闭失败原因 nvarchar(1000) NULL, + SAP关闭操作人 nvarchar(50) NULL; +``` + +如果不想改主表,新增扩展表: + +```sql +CREATE TABLE dbo.生产管理_订单关闭_SAP状态 ( + AID bigint IDENTITY(1,1) PRIMARY KEY, + 订单编号 int NOT NULL, + SAP单据号 nvarchar(100) NULL, + 关闭状态 nvarchar(20) NOT NULL, + 失败原因 nvarchar(1000) NULL, + 操作人 nvarchar(50) NULL, + 操作时间 datetime NOT NULL DEFAULT GETDATE(), + 是否可重试 bit NOT NULL DEFAULT 0 +); +``` + +### 17.5 存储过程 + +| 过程 | 用途 | +|---|---| +| `生产管理_订单关闭_SAP结果保存` | 保存每单关闭结果 | +| `生产管理_订单关闭_SAP结果查询` | 查询批量关闭结果 | +| `生产管理_订单关闭_可关闭校验` | 批量操作前校验订单是否可关 | + +## 18. 需求 15:及时检验报表 + +### 18.1 页面定位 + +新增页面: + +```text +src/views/QualityManagement/TimelyInspectionReport/index.vue +``` + +菜单: + +```text +质量管理 -> 质量报表 -> 及时检验报表 +``` + +### 18.2 查询口径 + +进入报表条件: + +1. `YL_加工中心_操作记录表` 中存在报工记录。 +2. `操作类别 = '报工'`。 +3. `操作数值 > 0`。 +4. `结束时间 < DATEADD(DAY, -2, GETDATE())`。 +5. 对应质检记录不存在,或检验数量不足。 + +### 18.3 页面字段 + +| 字段 | +|---| +| 生产订单 | +| TaskAID | +| 物料编码 | +| 物料名称 | +| 工序名称 | +| 指派对象 | +| 报工数量 | +| 已检数量 | +| 未检数量 | +| 报工结束时间 | +| 超期天数 | +| 操作人 | + +### 18.4 存储过程 + +过程名:`质量管理_及时检验报表_查询` + +参数: + +- 生产订单 +- 物料 +- 工序 +- 指派对象 +- 报工结束开始 +- 报工结束结束 +- 超期天数,默认 2 + +SQL 示例: + +```sql +CREATE PROCEDURE dbo.质量管理_及时检验报表_查询 + @生产订单 int = NULL, + @物料 nvarchar(100) = '', + @工序 nvarchar(100) = '', + @指派对象 nvarchar(100) = '', + @报工结束开始 date = NULL, + @报工结束结束 date = NULL, + @超期天数 int = 2 +AS +BEGIN + SET NOCOUNT ON; + + WITH rpt AS ( + SELECT + o.TaskAID, + SUM(ISNULL(o.操作数值,0)) AS 报工数量, + MAX(o.结束时间) AS 报工结束时间, + MAX(o.操作人) AS 操作人 + FROM dbo.YL_加工中心_操作记录表 o + WHERE o.操作类别 = N'报工' + AND ISNULL(o.操作数值,0) > 0 + AND o.结束时间 < DATEADD(DAY, -@超期天数, GETDATE()) + GROUP BY o.TaskAID + ), + qc AS ( + SELECT + TaskAID, + SUM(ISNULL(检验数量,0)) AS 已检数量 + FROM dbo.YL_质量检验_质检记录 + GROUP BY TaskAID + ) + SELECT + t.订单编号 AS 生产订单, + t.AID AS TaskAID, + t.物料编码, + t.物料名称, + t.工序名称, + t.指派对象, + rpt.报工数量, + ISNULL(qc.已检数量,0) AS 已检数量, + rpt.报工数量 - ISNULL(qc.已检数量,0) AS 未检数量, + rpt.报工结束时间, + DATEDIFF(DAY, rpt.报工结束时间, GETDATE()) AS 超期天数, + rpt.操作人 + FROM rpt + JOIN dbo.MES_接口_生产计划_生产任务 t ON rpt.TaskAID = t.AID + LEFT JOIN qc ON rpt.TaskAID = qc.TaskAID + WHERE rpt.报工数量 > ISNULL(qc.已检数量,0) + AND (@生产订单 IS NULL OR t.订单编号 = @生产订单) + AND (@物料 = '' OR t.物料编码 LIKE '%' + @物料 + '%' OR t.物料名称 LIKE '%' + @物料 + '%') + AND (@工序 = '' OR t.工序名称 = @工序) + AND (@指派对象 = '' OR t.指派对象 = @指派对象) + AND (@报工结束开始 IS NULL OR rpt.报工结束时间 >= @报工结束开始) + AND (@报工结束结束 IS NULL OR rpt.报工结束时间 < DATEADD(DAY, 1, @报工结束结束)) + ORDER BY 超期天数 DESC, rpt.报工结束时间; +END +``` + +### 18.5 不新增表 + +第一阶段不新增表。若要催办闭环,再新增催办记录表。 + +## 19. 需求 16:工序流转卡增加原料编码 + +### 19.1 需要查新分析 + +先定位工序流转卡打印页面和模板: + +- 搜索页面中 `流转卡`、`print`、`打印`。 +- 确认当前流转卡数据来源过程。 +- 确认原料编码来自 BOM、SAP 工艺路线,还是物料字段。 + +### 19.2 数据来源建议 + +优先顺序: + +1. `BOM数据` 中父件对应子件,取原料类子件编码。 +2. SAP BOM/物料清单同步表。 +3. 生产任务行文本备注或行物料字段。 + +### 19.3 存储过程 + +扩展流转卡查询过程,增加字段: + +| 字段 | 说明 | +|---|---| +| 原料编码 | BOM 子件编码 | +| 原料名称 | BOM 子件名称,可选 | +| 原料规格 | 可选 | + +SQL 示例: + +```sql +LEFT JOIN dbo.BOM数据 bom + ON bom.父件编码 = t.物料编码 +``` + +### 19.4 页面/打印 + +打印模板增加: + +```text +原料编码:XXXXXXXX +``` + +如果一个成品对应多个原料编码: + +- 用逗号合并。 +- 或打印明细区。 + +## 20. 需求 17-19:现场大屏 + +包括: + +- 一楼质检大屏幕 +- 机加现场大屏幕 +- 装配现场大屏幕 + +看板项目目录: + +| 大屏 | 项目目录 | +|---|---| +| 质检任务看板 | `质检任务看板` | +| 机加现场大屏 | `机加设备生产运营看板`、`机加设备生产运营看板二` | +| 装配现场大屏 | `装配任务看板` | + +### 20.1 通用大屏开发原则 + +1. 大屏只展示,不作为字段维护入口。 +2. 关键工序、缺勤、送检状态必须先有业务数据来源。 +3. 所有大屏过程必须支持 `@统计日期`,默认当天。 +4. 大屏刷新频率建议 30 秒以上,除设备状态外不建议 5 秒刷新复杂 SQL。 +5. 指标必须能下钻明细。 + +### 20.2 一楼质检大屏 + +#### 20.2.1 新增指标 + +| 指标 | 口径 | +|---|---| +| 质检及时率 | 及时检验任务数 / 应检任务数 | +| 超 2 天未检任务 | 最后生产完成时间超过 2 天且未检足 | +| 关键工序应检数 | 任务快照中 `是否关键工序=1` | +| 关键工序未检数 | 应检但未检足 | +| 关键工序已检数 | 已检足 | + +#### 20.2.2 需要新增字段 + +关键工序不要放在看板维护,应加在工艺和任务快照。 + +建议字段: + +```sql +ALTER TABLE dbo.车间生产管理工艺_零件工序_工艺库 ADD 是否关键工序 bit NULL DEFAULT 0; +ALTER TABLE dbo.车间生产管理工艺_零件生产工艺_工艺库 ADD 是否关键工序 bit NULL DEFAULT 0; +ALTER TABLE dbo.MES_接口_生产计划_生产任务 ADD 是否关键工序 bit NULL DEFAULT 0; +``` + +任务下发时把生产工艺中的 `是否关键工序` 快照到任务表。 + +#### 20.2.3 存储过程 + +扩展或新增: + +| 过程 | 用途 | +|---|---| +| `质量任务看板_未完成统计` | 增加超期天数、关键工序统计 | +| `质量任务看板_未完成明细查询` | 增加最后生产完成时间、是否关键工序 | +| `质量任务看板_及时率统计` | 新增及时率 | + +### 20.3 机加现场大屏 + +#### 20.3.1 新增指标 + +| 指标 | 口径 | +|---|---| +| 缺勤人员 | 应到人员 - 实到人员 | +| 关键工序任务汇总 | 已排产未完成且是否关键工序=1 | +| 关键工序任务明细 | 订单、物料、工序、设备、指派对象、计划开始、完成数 | + +#### 20.3.2 缺勤数据 + +不能从“没有报工”反推缺勤。 + +需要数据: + +| 数据 | 来源 | +|---|---| +| 应到人员 | 班次人员绑定表、排班表、岗位工位绑定 | +| 实到人员 | 考勤、上岗绑定、登录、报工记录 | + +建议新增排班表: + +```sql +CREATE TABLE dbo.人员排班表 ( + AID bigint IDENTITY(1,1) PRIMARY KEY, + 排班日期 date NOT NULL, + 班次编号 int NULL, + 班次名称 nvarchar(50) NULL, + 人员编号 int NOT NULL, + 人员姓名 nvarchar(50) NOT NULL, + 岗位 nvarchar(50) NULL, + 工位号 nvarchar(50) NULL, + 是否应到 bit NOT NULL DEFAULT 1, + 创建人 nvarchar(50) NULL, + 创建时间 datetime NOT NULL DEFAULT GETDATE() +); + +CREATE INDEX IX_人员排班表_日期班次 ON dbo.人员排班表(排班日期, 班次名称); +``` + +如果已有 `班次人员绑定表` 能满足,则不新建,只扩展字段。 + +#### 20.3.3 存储过程 + +| 过程 | 用途 | +|---|---| +| `机加现场大屏_缺勤人员查询` | 返回岗位、工位、姓名 | +| `机加现场大屏_关键工序统计` | 汇总关键工序任务 | +| `机加现场大屏_关键工序明细` | 明细下钻 | + +### 20.4 装配现场大屏 + +#### 20.4.1 新增指标 + +| 指标 | 口径 | +|---|---| +| 缺勤人员 | 同机加 | +| 及时送检任务 | 发料齐套后超过 2 天未送检 | +| 排序 | 加急优先,其次及时送检超期,再按计划开始或齐套时间 | + +#### 20.4.2 存储过程 + +| 过程 | 用途 | +|---|---| +| `装配现场大屏_缺勤人员查询` | 岗位、工位、姓名 | +| `装配现场大屏_及时送检任务查询` | 发料齐套后 2 天未送检 | +| `装配中心任务看板_装配任务查询` | 增加发料齐套时间、是否已送检、送检时间、超期天数 | + +#### 20.4.3 字段来源 + +| 字段 | 来源 | +|---|---| +| 发料齐套时间 | `MES_接口_生产计划.齐套时间` 或装配扩展表 | +| 是否已送检 | 送检记录/质检任务/质检记录 | +| 送检时间 | 送检记录 | +| 超期天数 | `DATEDIFF(DAY, 发料齐套时间, GETDATE())` | + +## 21. 需求 20:编程任务清单 / 编程报工 + +### 21.1 页面定位 + +新增页面: + +```text +src/views/ProductionManagement/ProgrammingTask/index.vue +``` + +菜单: + +```text +生产管理 -> 报工管理 -> 编程任务清单 +``` + +### 21.2 页面布局 + +```text +查询区: +设备 工位 程序员 状态 生产订单 物料 日期 +[查询] [重置] [新增编程任务] [导出] + +表格: +任务编号 生产订单 物料编码 物料名称 工序 设备/工位 程序号 +编程人员 状态 开始时间 结束时间 工时 操作 + +操作: +[开始编程] [结束编程] [编辑程序号] [工时记录] [报异常] +``` + +### 21.3 新增表 + +#### 21.3.1 编程任务表 + +```sql +CREATE TABLE dbo.生产管理_编程任务 ( + 编程任务ID bigint IDENTITY(1,1) PRIMARY KEY, + 编程任务编号 nvarchar(50) NOT NULL, + 生产订单 int NULL, + TaskAID bigint NULL, + 物料编码 nvarchar(100) NULL, + 物料名称 nvarchar(500) NULL, + 工序名称 nvarchar(100) NULL, + 设备编号 nvarchar(50) NULL, + 设备名称 nvarchar(100) NULL, + 工位编号 nvarchar(50) NULL, + 工位名称 nvarchar(100) NULL, + 程序号 nvarchar(100) NULL, + 任务来源 nvarchar(50) NULL, -- 人工创建/订单生成/设备任务派生 + 状态 nvarchar(20) NOT NULL DEFAULT N'未开始', + 任务说明 nvarchar(1000) NULL, + 创建人 nvarchar(50) NULL, + 创建时间 datetime NOT NULL DEFAULT GETDATE(), + 最后维护人 nvarchar(50) NULL, + 最后维护时间 datetime NULL +); +``` + +#### 21.3.2 编程工时记录表 + +```sql +CREATE TABLE dbo.生产管理_编程任务_工时记录 ( + 记录ID bigint IDENTITY(1,1) PRIMARY KEY, + 编程任务ID bigint NOT NULL, + 操作类别 nvarchar(20) NOT NULL, -- 开始/结束 + 操作人编号 int NULL, + 操作人 nvarchar(50) NOT NULL, + 开始时间 datetime NULL, + 结束时间 datetime NULL, + 工时分钟 int NULL, + 工作内容 nvarchar(1000) NULL, + 结束说明 nvarchar(1000) NULL, + 创建时间 datetime NOT NULL DEFAULT GETDATE() +); + +CREATE INDEX IX_生产管理_编程任务_工时记录_任务 +ON dbo.生产管理_编程任务_工时记录(编程任务ID); +``` + +### 21.4 存储过程 + +| 过程 | 用途 | +|---|---| +| `生产管理_编程任务_查询` | 列表查询 | +| `生产管理_编程任务_新增` | 新增任务 | +| `生产管理_编程任务_开始` | 开始编程 | +| `生产管理_编程任务_结束` | 结束编程并计算工时 | +| `生产管理_编程任务_工时明细` | 工时明细 | +| `生产管理_编程任务_程序号保存` | 维护程序号 | + +### 21.5 工时接入 + +`View_统一工时明细` 增加: + +```text +来源模块 = 编程 +工时类型 = 编程 +``` + +这样后续合同工时、工时报表可选择是否包含编程工时。 + +## 22. 需求 21-24:设备档案、设备数据采集、OEE、工时查询联动 + +### 22.1 设备档案管理 + +现有页面: + +```text +src/views/DeviceManagement/DeviceInformation/index.vue +``` + +现有表: + +```text +YL_设备管理_设备台账 +MES_资源主数据 +``` + +建议新增字段: + +```sql +ALTER TABLE dbo.YL_设备管理_设备台账 ADD + 是否主要设备 bit NULL DEFAULT 0, + 是否参与OEE bit NULL DEFAULT 0, + 设备标准工时 decimal(18,2) NULL, + 标准工时单位 nvarchar(20) NULL, + 采集设备编码 nvarchar(100) NULL, + 采集点位配置 nvarchar(max) NULL; +``` + +注意: + +- 设备标准工时不能替代工艺标准工时。 +- OEE 的标准单件工时优先来自工艺或设备+工序能力表。 + +建议新增设备工序能力表: + +```sql +CREATE TABLE dbo.设备管理_设备工序能力 ( + AID bigint IDENTITY(1,1) PRIMARY KEY, + 设备编号 nvarchar(50) NOT NULL, + 设备名称 nvarchar(100) NULL, + 工序名称 nvarchar(100) NOT NULL, + 物料编码 nvarchar(100) NULL, + 标准单件工时 decimal(18,4) NULL, + 单位 nvarchar(20) NULL DEFAULT N'分钟', + 是否启用 bit NOT NULL DEFAULT 1, + 创建人 nvarchar(50) NULL, + 创建时间 datetime NOT NULL DEFAULT GETDATE(), + 最后维护人 nvarchar(50) NULL, + 最后维护时间 datetime NULL +); +``` + +### 22.2 设备数据采集 + +现有表: + +- `CaChe_Var` +- `历史_设备数据_定时` +- `历史_工位设备状态每分钟记录` +- `YL_设备管理_工时记录` + +新增建议: + +#### 22.2.1 采集原始数据表 + +如果现有 `历史_设备数据_定时` 字段足够,可不新建。否则新增: + +```sql +CREATE TABLE dbo.设备采集_原始数据 ( + AID bigint IDENTITY(1,1) PRIMARY KEY, + 采集时间 datetime NOT NULL, + 设备编号 nvarchar(50) NULL, + 设备名称 nvarchar(100) NULL, + 工位号 nvarchar(50) NULL, + 变量名称 nvarchar(100) NULL, + 变量值 nvarchar(200) NULL, + 原始值 nvarchar(200) NULL, + 单位 nvarchar(20) NULL, + TagID nvarchar(100) NULL, + DeviceCode nvarchar(100) NULL, + 在线状态 nvarchar(20) NULL, + 采集质量 nvarchar(20) NULL, + 创建时间 datetime NOT NULL DEFAULT GETDATE() +); +``` + +#### 22.2.2 设备状态汇总表 + +```sql +CREATE TABLE dbo.设备采集_设备状态分钟汇总 ( + AID bigint IDENTITY(1,1) PRIMARY KEY, + 统计时间 datetime NOT NULL, + 统计日期 date NOT NULL, + 班次名称 nvarchar(50) NULL, + 设备编号 nvarchar(50) NULL, + 设备名称 nvarchar(100) NULL, + 工位号 nvarchar(50) NULL, + 状态代码 int NULL, + 状态名称 nvarchar(50) NULL, + 持续秒数 int NOT NULL DEFAULT 60, + 是否有效加工 bit NULL, + 创建时间 datetime NOT NULL DEFAULT GETDATE() +); +``` + +#### 22.2.3 设备任务绑定表 + +设备采集必须绑定 MES 任务,否则无法算任务级程序工时。 + +```sql +CREATE TABLE dbo.设备采集_任务绑定 ( + AID bigint IDENTITY(1,1) PRIMARY KEY, + 设备编号 nvarchar(50) NOT NULL, + 设备名称 nvarchar(100) NULL, + 工位号 nvarchar(50) NULL, + TaskAID bigint NOT NULL, + 生产订单 int NOT NULL, + 程序号 nvarchar(100) NULL, + 绑定开始时间 datetime NOT NULL, + 绑定结束时间 datetime NULL, + 绑定来源 nvarchar(50) NULL, -- 人工/条码/程序号/时间推断 + 绑定人 nvarchar(50) NULL, + 创建时间 datetime NOT NULL DEFAULT GETDATE() +); +``` + +### 22.3 OEE 指标 + +建议新增指标明细表: + +```sql +CREATE TABLE dbo.设备指标_班次明细 ( + AID bigint IDENTITY(1,1) PRIMARY KEY, + 统计日期 date NOT NULL, + 班次名称 nvarchar(50) NULL, + 设备编号 nvarchar(50) NOT NULL, + 设备名称 nvarchar(100) NULL, + 工位号 nvarchar(50) NULL, + TaskAID bigint NULL, + 生产订单 int NULL, + 物料编码 nvarchar(100) NULL, + 物料名称 nvarchar(500) NULL, + 工序名称 nvarchar(100) NULL, + 计划产量 decimal(18,2) NULL, + 实际产量 decimal(18,2) NULL, + 良品数 decimal(18,2) NULL, + 不良品数 decimal(18,2) NULL, + 标准单件工时 decimal(18,4) NULL, + 实际单件工时 decimal(18,4) NULL, + 设备运行工时分钟 decimal(18,2) NULL, + 标准可用工时分钟 decimal(18,2) NULL, + 产能利用率 decimal(18,4) NULL, + 设备利用率 decimal(18,4) NULL, + 性能开动率 decimal(18,4) NULL, + 产品合格率 decimal(18,4) NULL, + OEE decimal(18,4) NULL, + 计算时间 datetime NOT NULL DEFAULT GETDATE(), + 计算说明 nvarchar(1000) NULL +); +``` + +计算过程: + +| 过程 | 用途 | +|---|---| +| `设备指标_班次明细_生成` | 按日期班次生成指标 | +| `设备指标_OEE_查询` | 页面/看板查询 | +| `设备指标_OEE_明细` | 下钻查看三项组成 | + +### 22.4 工时查询联动 + +现有页面: + +```text +src/views/ProductionManagement/Workhours/index.vue +src/views/ProductionManagement/Timesheet/index.vue +src/views/ProductionManagement/WorkHoursCheck/index.vue +``` + +新增字段: + +- 程序工时 +- 设备运行工时 +- 实际单件工时 +- 标准单件工时 +- 设备采集状态 +- 采集质量 + +建议过程: + +```text +工时查询_设备采集工时_查询 +``` + +按 TaskAID、设备、时间段关联 `设备采集_任务绑定` 和设备状态汇总。 + +## 23. 需求 25:手续确认报表 + +### 23.1 页面定位 + +新增页面: + +```text +src/views/ProductionManagement/FormalityConfirmReport/index.vue +``` + +菜单: + +```text +报表中心 -> 装配报表 -> 手续确认报表 +``` + +### 23.2 页面布局 + +```text +查询区: +生产订单 合同号 物料 指派对象 发料齐套日期 手续确认状态 +[查询] [重置] [导出] [批量确认完成] + +表格: +选择 生产订单 合同号 物料编码 物料名称 指派对象 发料齐套时间 +装配完成时间 当前状态 手续确认 确认人 确认时间 操作 + +操作: +[确认完成] [查看装配明细] [查看异常] +``` + +### 23.3 新增表 + +表名:`生产管理_手续确认` + +```sql +CREATE TABLE dbo.生产管理_手续确认 ( + AID bigint IDENTITY(1,1) PRIMARY KEY, + 订单编号 int NOT NULL, + 确认状态 nvarchar(20) NOT NULL DEFAULT N'未完成', + 确认人 nvarchar(50) NULL, + 确认时间 datetime NULL, + 确认备注 nvarchar(500) NULL, + 创建时间 datetime NOT NULL DEFAULT GETDATE(), + 最后维护人 nvarchar(50) NULL, + 最后维护时间 datetime NULL +); + +CREATE UNIQUE INDEX UX_生产管理_手续确认_订单编号 +ON dbo.生产管理_手续确认(订单编号); +``` + +### 23.4 消失条件 + +报表只显示待确认数据: + +```sql +WHERE ISNULL(fc.确认状态, N'未完成') <> N'已完成' + AND ISNULL(p.订单状态, '') NOT IN (N'取消', N'关闭') + AND ISNULL(p.单据状态, '') NOT IN (N'取消', N'关闭') + AND ISNULL(p.入库数量, 0) < ISNULL(p.计划数量, 0) +``` + +### 23.5 存储过程 + +| 过程 | 用途 | +|---|---| +| `生产管理_手续确认报表_查询` | 待确认列表 | +| `生产管理_手续确认报表_确认完成` | 单条确认 | +| `生产管理_手续确认报表_批量确认完成` | 批量确认 | + +确认过程同时写 `系统管理_业务字段维护日志`。 + +## 24. 需求 26:产品合格率(工位) + +### 24.1 页面定位 + +新增或扩展质量报表页面: + +```text +src/views/QualityManagement/StationPassRate/index.vue +``` + +### 24.2 口径 + +公式: + +```text +产品合格率 = 良品数 / 总产量 +``` + +需要先确认: + +- 总产量取报工完成数量还是质检检验数量。 +- 良品数取质检合格数还是报工合格数。 +- 统计维度按工位、设备、指派对象还是实际操作工位。 + +建议第一版: + +- 总产量:质检记录 `检验数量` +- 良品数:质检记录 `合格数` +- 工位:关联任务表 `指派对象`,同时展示质检记录来源工位。 + +### 24.3 存储过程 + +过程名:`质量管理_产品合格率_工位查询` + +参数: + +- 开始日期 +- 结束日期 +- 工位 +- 工序 +- 物料 + +返回: + +- 工位 +- 检验数量 +- 合格数量 +- 不合格数量 +- 合格率 +- 明细数 + +### 24.4 不新增表 + +第一阶段不新增表。如果要日快照,写入 `质量管理_工位合格率_日快照`。 + +## 25. 需求 27:让步接收记录 + +### 25.1 页面定位 + +新增页面: + +```text +src/views/QualityManagement/ConcessionRecord/index.vue +``` + +菜单: + +```text +质量管理 -> 质量报表 -> 让步接收记录 +``` + +### 25.2 数据来源 + +现有字段: + +- `MES_接口_生产计划_生产任务.让步放行数量` +- `YL_质量检验_不合格品处理.申请让步放行` +- `YL_质量检验_不合格品处理_处理节点.让步放行数量` + +需求说“新增让步记录查询页面”,建议从不合格品处理和质检记录综合查询。 + +### 25.3 存储过程 + +过程名:`质量管理_让步接收记录_查询` + +参数: + +- 生产订单 +- 物料 +- 检验人 +- 检验开始 +- 检验结束 +- 让步状态 + +返回: + +- 生产订单 +- TaskAID +- 物料编码 +- 物料名称 +- 工序名称 +- 检验数量 +- 不合格数量 +- 让步放行数量 +- 申请让步放行 +- 检验人 +- 检验时间 +- 处理意见 + +### 25.4 不新增表 + +页面只查询,不维护。 + +## 26. 需求 28:设计任务报工模块 / 报工-技术-MES + +### 26.1 页面定位 + +新增页面: + +```text +src/views/ProductionManagement/DesignTaskWork/index.vue +``` + +菜单: + +```text +生产管理 -> 报工管理 -> 设计任务报工 +``` + +### 26.2 页面布局 + +```text +查询区: +任务名称 设计人员 状态 日期 +[查询] [重置] [新增设计任务] [导出] + +表格: +任务编号 任务名称 设计人员 状态 计划开始 计划完成 +开始时间 结束时间 工时 工作内容 结束说明 创建人 操作 + +操作: +[开始报工] [结束报工] [工时记录] [编辑] [取消] +``` + +### 26.3 新增表 + +#### 26.3.1 设计任务表 + +```sql +CREATE TABLE dbo.生产管理_设计任务 ( + 设计任务ID bigint IDENTITY(1,1) PRIMARY KEY, + 设计任务编号 nvarchar(50) NOT NULL, + 任务名称 nvarchar(200) NOT NULL, + 设计人员编号 int NULL, + 设计人员 nvarchar(50) NULL, + 状态 nvarchar(20) NOT NULL DEFAULT N'未开始', + 计划开始时间 datetime NULL, + 计划完成时间 datetime NULL, + 任务说明 nvarchar(1000) NULL, + 创建人 nvarchar(50) NULL, + 创建时间 datetime NOT NULL DEFAULT GETDATE(), + 最后维护人 nvarchar(50) NULL, + 最后维护时间 datetime NULL +); +``` + +#### 26.3.2 设计工时记录表 + +```sql +CREATE TABLE dbo.生产管理_设计任务_工时记录 ( + 记录ID bigint IDENTITY(1,1) PRIMARY KEY, + 设计任务ID bigint NOT NULL, + 操作人编号 int NULL, + 操作人 nvarchar(50) NOT NULL, + 开始时间 datetime NOT NULL, + 结束时间 datetime NULL, + 工时分钟 int NULL, + 工作内容 nvarchar(1000) NULL, + 结束说明 nvarchar(1000) NULL, + 创建时间 datetime NOT NULL DEFAULT GETDATE() +); +``` + +### 26.4 存储过程 + +| 过程 | 用途 | +|---|---| +| `生产管理_设计任务_查询` | 任务列表 | +| `生产管理_设计任务_新增` | 新建任务 | +| `生产管理_设计任务_编辑` | 编辑任务 | +| `生产管理_设计任务_取消` | 取消 | +| `生产管理_设计任务_开始` | 开始报工 | +| `生产管理_设计任务_结束` | 结束报工 | +| `生产管理_设计任务_工时明细` | 工时明细 | + +### 26.5 工时接入 + +`View_统一工时明细` 增加: + +```text +来源模块 = 设计 +工时类型 = 设计 +``` + +注意: + +- 设计任务当前不上传 SAP。 +- 设计任务不产生质量、装配、机加工时。 +- 后续装配已排产需求的合同工时汇总可选择纳入设计工时。 + +## 27. 需求 29:工时异常报表 + +### 27.1 页面定位 + +新增页面: + +```text +src/views/ProductionManagement/WorkTimeAbnormalReport/index.vue +``` + +### 27.2 异常口径 + +```text +实际单件工时 > 标准单件工时 +``` + +字段来源: + +| 字段 | 来源 | +|---|---| +| 实际单件工时 | 设备采集,或人工报工工时 / 完成数量 | +| 标准单件工时 | 生产工艺或设备工序能力表 | +| 设备/工位 | 任务指派对象、设备绑定 | +| 程序号 | 编程任务或设备采集 | + +### 27.3 建议新增表 + +如需要异常确认闭环: + +```sql +CREATE TABLE dbo.生产管理_工时异常确认 ( + AID bigint IDENTITY(1,1) PRIMARY KEY, + 统计日期 date NULL, + TaskAID bigint NULL, + 生产订单 int NULL, + 设备编号 nvarchar(50) NULL, + 设备名称 nvarchar(100) NULL, + 标准单件工时 decimal(18,4) NULL, + 实际单件工时 decimal(18,4) NULL, + 超出时长 decimal(18,4) NULL, + 超出比例 decimal(18,4) NULL, + 异常原因 nvarchar(500) NULL, + 责任部门 nvarchar(100) NULL, + 处理说明 nvarchar(1000) NULL, + 确认状态 nvarchar(20) NOT NULL DEFAULT N'未确认', + 确认人 nvarchar(50) NULL, + 确认时间 datetime NULL +); +``` + +### 27.4 存储过程 + +| 过程 | 用途 | +|---|---| +| `生产管理_工时异常报表_查询` | 查询异常 | +| `生产管理_工时异常报表_明细` | 查看来源明细 | +| `生产管理_工时异常报表_确认` | 异常确认 | + +### 27.5 页面字段 + +- 设备/工位 +- 生产订单 +- 物料编码 +- 物料名称 +- 工序名称 +- 指派对象 +- 操作人 +- 程序号 +- 标准单件工时 +- 实际单件工时 +- 超出时长 +- 超出比例 +- 开始时间 +- 结束时间 +- 班次 +- 异常原因 +- 确认状态 + +## 28. 需求 30:正在加工状态 + +### 28.1 目标 + +“正在加工状态:机加正在进行中”。 + +### 28.2 数据来源 + +优先复用: + +- `MES_ProductCenter_DoingTask` +- `v_CurrentProductionStatus` +- `YL_加工中心_操作记录表` 中开始未结束记录 + +### 28.3 页面/看板展示 + +可以在以下页面增加状态: + +- 加工中心任务列表 +- 生产计划跟踪 +- 机加现场大屏 + +展示规则: + +| 条件 | 状态 | +|---|---| +| 有开始记录且未报工结束 | 正在加工 | +| 任务状态已完成 | 已完成 | +| 有暂停记录未恢复 | 暂停中 | +| 无开始记录 | 未开工 | + +### 28.4 存储过程 + +过程名:`生产管理_正在加工状态_查询` + +返回: + +- TaskAID +- 生产订单 +- 工序名称 +- 指派对象 +- 操作人 +- 开始时间 +- 当前持续分钟 +- 状态 + +## 29. 暂不排期项的技术前置 + +### 29.1 及时拣配(机加/装配) + +必须先确认: + +1. 条码代表物料、箱号、批次、生产订单还是拣配单。 +2. SAP 库存和 MES 拣配状态谁是主口径。 +3. 扫码后是否写回 `拣配状态`、`齐套`、`发料状态`。 +4. 机加和装配是否共用拣配表。 + +建议表: + +```sql +CREATE TABLE dbo.生产管理_条码拣配记录 ( + AID bigint IDENTITY(1,1) PRIMARY KEY, + 拣配类型 nvarchar(20) NOT NULL, -- 机加/装配 + 条码 nvarchar(200) NOT NULL, + 生产订单 int NULL, + TaskAID bigint NULL, + 物料编码 nvarchar(100) NULL, + 物料名称 nvarchar(500) NULL, + 批次号 nvarchar(100) NULL, + 数量 decimal(18,2) NULL, + 拣配状态 nvarchar(20) NULL, + SAP校验状态 nvarchar(20) NULL, + 异常说明 nvarchar(500) NULL, + 拣配人 nvarchar(50) NULL, + 拣配时间 datetime NOT NULL DEFAULT GETDATE() +); +``` + +### 29.2 标牌打印操作 + +需求未定,不建表不开发。需确认: + +- 打印对象:物料、订单、设备、工位、产品? +- 条码内容。 +- 模板样式。 +- 是否需要打印记录。 + +### 29.3 首检、巡检 + +现有质检中心已有首检、巡检相关逻辑。空需求暂不开发。若后续提出,应先确认是新增报表、页面优化还是流程改造。 + +## 30. 菜单和权限 + +所有新增页面都需要写入 `登录基础数据_二级菜单`,并按角色分配。 + +建议新增菜单: + +| 页面 | 菜单 | +|---|---| +| 装配已排产需求 | 生产管理/装配管理 | +| 生产日报-送检 | 报表中心/生产日报 | +| 及时齐套跟踪结果报表 | 报表中心/齐套报表 | +| 机加班次产量表 | 报表中心/生产报表 | +| 发货通知列表 | 报表中心/交付报表 | +| 质检任务早知道 | 质量管理/质量报表 | +| 及时检验报表 | 质量管理/质量报表 | +| 手续确认报表 | 报表中心/装配报表 | +| 让步接收记录 | 质量管理/质量报表 | +| 设计任务报工 | 生产管理/报工管理 | +| 编程任务清单 | 生产管理/报工管理 | +| 工时异常报表 | 报表中心/工时报表 | + +菜单字段要参考现有 `登录基础数据_二级菜单`: + +- `path` +- `componet` +- `name` +- `title` +- `icon` +- `账号代码` + +## 31. 开发实施顺序 + +### 31.1 第一阶段:高优先级低风险 + +1. 及时开工报表正选/反选。 +2. 机加已排产日期筛选。 +3. 机加已排产历史工时弹窗。 +4. 生产工艺自动带出标准工艺。 +5. 工时报表指派对象。 +6. 小字段:备注、提示、流转卡原料编码。 + +交付标准: + +- 页面可查询。 +- 数据字段正确。 +- 导出同步。 +- 不影响现有流程。 + +### 31.2 第二阶段:装配已排产专项 + +1. 建装配扩展表。 +2. 做主查询页面。 +3. 加系统/非系统筛选。 +4. 接派工时间、合同交货期、发料齐套时间。 +5. 做装配完成时间和人工维护。 +6. 做当前人员、当前内容、历史说明。 +7. 接工时汇总和明细。 +8. 接异常明细。 +9. 做日计划导出打印。 +10. 派生质检任务早知道。 + +交付标准: + +- 主表字段完整。 +- 人工维护有日志。 +- 工时可钻取。 +- 日计划可导出/打印。 + +### 31.3 第三阶段:质量和齐套报表 + +1. 及时检验报表。 +2. 生产日报-送检。 +3. 及时齐套跟踪结果报表。 +4. 让步接收记录。 +5. 外协任务检验字段补充。 +6. 产品合格率。 + +交付标准: + +- 每个报表有明确口径。 +- 可导出。 +- 可钻明细。 +- SAP 来源显示同步时间。 + +### 31.4 第四阶段:流程增强 + +1. 异常管控统一入口。 +2. 生产订单批量关闭 SAP。 +3. 手续确认报表。 +4. 编程任务报工。 +5. 设计任务报工。 + +交付标准: + +- 写操作有确认。 +- 批量结果逐条返回。 +- 异常审批人多选可见,一人处理。 +- 工时进入统一工时视图。 + +### 31.5 第五阶段:设备采集和大屏 + +1. 设备档案字段。 +2. 设备采集原始数据和任务绑定。 +3. OEE 指标明细。 +4. 工时异常报表。 +5. 质检、机加、装配现场大屏。 + +交付标准: + +- 设备采集有原始数据和汇总数据。 +- OEE 可下钻。 +- 大屏指标无占位数据。 +- 缺勤有排班/实到来源。 + +## 32. 测试清单 + +### 32.1 页面测试 + +每个页面至少测试: + +- 查询为空。 +- 单条件查询。 +- 多条件组合查询。 +- 日期边界。 +- 分页。 +- 导出。 +- 弹窗打开关闭。 +- 保存成功。 +- 保存失败。 +- 无权限访问。 + +### 32.2 数据测试 + +重点验证: + +- 工时汇总和明细一致。 +- 日期筛选包含当天 00:00:00 到 23:59:59。 +- 已关闭/已入库/已完成任务是否正确排除。 +- SAP 字段为空时页面不报错。 +- 多人员当前任务合并显示正确。 +- 班次跨天统计正确。 + +### 32.3 性能测试 + +重点过程: + +- 装配已排产需求主查询。 +- 及时齐套跟踪主表。 +- 机加班次产量表。 +- 及时检验报表。 +- 大屏过程。 + +要求: + +- 普通报表分页查询 3 秒内返回。 +- 大屏过程 2 秒内返回。 +- 导出可慢,但必须有 loading。 + +### 32.4 回归测试 + +必须回归: + +- 机加排产。 +- 装配排产。 +- 加工中心报工。 +- 装配中心报工。 +- 质检收检。 +- 外协收检。 +- 工时统计。 +- 生产计划跟踪。 +- 看板刷新。 + +## 33. 风险和处理 + +| 风险 | 处理 | +|---|---| +| SAP 字段未到 | 页面字段先预留,显示空;存储过程字段从扩展表读取 | +| 发料齐套时间口径不稳 | 标记来源字段:SAP/MES/人工 | +| 设计工时依赖设计任务模块 | 装配已排产先显示装配/质量,设计为 0,模块完成后接入 | +| 设备采集不稳定 | OEE 和工时异常先用人工工时降级口径,并标记数据来源 | +| 缺勤无排班来源 | 不做缺勤正式统计,只做排班来源确认或新增排班表 | +| 动态 SQL 注入风险 | 新增过程尽量参数化 | +| 历史数据为空 | 字段允许 NULL,页面显示 `--`,不强行补假数据 | + +## 34. 交付物 + +每个需求完成时至少交付: + +1. 前端页面或页面改造。 +2. SQL 增量脚本。 +3. 新增/修改存储过程。 +4. 菜单和权限配置说明。 +5. 测试数据和测试结果。 +6. 字段口径说明。 +7. 如涉及 SAP,提供 SAP 调用日志或同步状态。 + diff --git a/analyze_mes_v20_views.js b/analyze_mes_v20_views.js new file mode 100644 index 0000000..d189402 --- /dev/null +++ b/analyze_mes_v20_views.js @@ -0,0 +1,731 @@ +const fs = require('fs'); +const path = require('path'); + +const root = path.resolve('MES_Manage_View_V20'); +const viewsRoot = path.join(root, 'src', 'views'); +const outFile = path.join(root, 'MES_Manage_View_V20_src_views_逐页面详细分析.md'); + +function existingSqlFiles() { + return fs.readdirSync(root) + .filter(x => x.toLowerCase().endsWith('.sql')) + .map(x => path.join(root, x)); +} + +function readText(file) { + const buf = fs.readFileSync(file); + if (buf.length >= 2 && buf[0] === 0xff && buf[1] === 0xfe) return buf.slice(2).toString('utf16le'); + if (buf.length >= 2 && buf[0] === 0xfe && buf[1] === 0xff) { + const swapped = Buffer.alloc(buf.length - 2); + for (let i = 2; i + 1 < buf.length; i += 2) { + swapped[i - 2] = buf[i + 1]; + swapped[i - 1] = buf[i]; + } + return swapped.toString('utf16le'); + } + if (buf.length >= 3 && buf[0] === 0xef && buf[1] === 0xbb && buf[2] === 0xbf) return buf.slice(3).toString('utf8'); + return buf.toString('utf8'); +} + +function walk(dir, exts, result = []) { + if (!fs.existsSync(dir)) return result; + for (const item of fs.readdirSync(dir, { withFileTypes: true })) { + const p = path.join(dir, item.name); + if (item.isDirectory()) walk(p, exts, result); + else if (exts.includes(path.extname(item.name).toLowerCase())) result.push(p); + } + return result; +} + +function rel(file) { + return path.relative(root, file).replace(/\\/g, '/'); +} + +function lineOf(text, index) { + return text.slice(0, index).split(/\r?\n/).length; +} + +function uniq(arr) { + return [...new Set((arr || []).filter(Boolean))]; +} + +function clean(s) { + return (s || '') + .replace(/<[^>]*>/g, '') + .replace(/\{\{.*?\}\}/g, '') + .replace(/\s+/g, ' ') + .trim(); +} + +function escapeReg(s) { + return s.replace(/[.*+?^${}()|[\]\\]/g, '\\$&'); +} + +function isInComment(text, index) { + const lineStart = text.lastIndexOf('\n', index) + 1; + const beforeOnLine = text.slice(lineStart, index); + if (/^\s*\/\//.test(beforeOnLine)) return true; + const blockStart = text.lastIndexOf('/*', index); + const blockEnd = text.lastIndexOf('*/', index); + return blockStart > blockEnd; +} + +function moduleNameFromPath(relPath) { + const parts = relPath.split('/'); + if (parts[0] !== 'src' || parts[1] !== 'views') return '其他'; + if (parts.length <= 3) return parts[2] || '根页面'; + return `${parts[2]} / ${parts.slice(3, -1).join(' / ') || path.basename(relPath)}`; +} + +function extractLabels(text) { + const labels = []; + const patterns = [ + /]*>([\s\S]*?)<\/el-button>/g, + /\blabel="([^"]+)"/g, + /\bplaceholder="([^"]+)"/g, + /\btitle="([^"]+)"/g + ]; + for (const re of patterns) { + let m; + while ((m = re.exec(text))) { + const value = clean(m[1]); + if (value && !/[{};]/.test(value) && value.length <= 48) labels.push(value); + } + } + return uniq(labels).slice(0, 30); +} + +function extractFrontendFields(text) { + const vModels = []; + const tableColumns = []; + const pushedParams = []; + + let m; + const vmRe = /\bv-model(?:\.[\w-]+)?="([^"]+)"/g; + while ((m = vmRe.exec(text))) vModels.push(clean(m[1])); + + const colRe = /]*)>/g; + while ((m = colRe.exec(text))) { + const attrs = m[1]; + const label = /label="([^"]+)"/.exec(attrs)?.[1] || ''; + const prop = /prop="([^"]+)"/.exec(attrs)?.[1] || ''; + if (label || prop) tableColumns.push({ label: clean(label), prop: clean(prop) }); + } + + const paramRe = /\.(?:push|unshift)\s*\(\s*\[\s*['"]([^'"]+)['"]\s*,\s*([^\]\n]+)\]/g; + while ((m = paramRe.exec(text))) pushedParams.push({ name: clean(m[1]), expr: clean(m[2]) }); + + return { + vModels: uniq(vModels).slice(0, 80), + tableColumns: uniq(tableColumns.map(x => `${x.label}|${x.prop}`)) + .map(x => { + const [label, prop] = x.split('|'); + return { label, prop }; + }) + .slice(0, 120), + pushedParams: uniq(pushedParams.map(x => `${x.name}|${x.expr}`)) + .map(x => { + const [name, expr] = x.split('|'); + return { name, expr }; + }) + .slice(0, 120) + }; +} + +function extractMethods(text) { + const methods = []; + const methodBlock = /methods\s*:\s*\{([\s\S]*?)\n\s*\}/m.exec(text); + const src = methodBlock ? methodBlock[1] : text; + const re = /^\s*([A-Za-z_$\u4e00-\u9fa5][\w$\u4e00-\u9fa5]*)\s*\([^)]*\)\s*\{/gm; + let m; + while ((m = re.exec(src))) methods.push(m[1]); + return uniq(methods).slice(0, 30); +} + +function extractCreateData(text) { + const calls = []; + const re = /CreateData\s*\(\s*['"]([^'"]+)['"]\s*,\s*['"]([^'"]+)['"]/g; + let m; + while ((m = re.exec(text))) { + if (isInComment(text, m.index)) continue; + calls.push({ type: m[1], name: m[2], line: lineOf(text, m.index) }); + } + return calls; +} + +function extractSapCalls(text) { + const calls = []; + const re = /(getB1|postB1|patchB1|posttm)\s*\(\s*([`'"])([\s\S]*?)\2/g; + let m; + while ((m = re.exec(text))) { + if (isInComment(text, m.index)) continue; + const snippet = text.slice(m.index, m.index + 1200); + const keys = []; + const keyRe = /["']?([\u4e00-\u9fa5A-Za-z_][\u4e00-\u9fa5A-Za-z0-9_$]*)["']?\s*:/g; + let km; + while ((km = keyRe.exec(snippet)) && keys.length < 24) { + if (!['if', 'for', 'while', 'switch', 'catch', 'function'].includes(km[1])) keys.push(km[1]); + } + calls.push({ fn: m[1], url: clean(m[3]), line: lineOf(text, m.index), payloadKeys: uniq(keys) }); + } + return calls; +} + +function extractApiImports(text) { + const imports = []; + const re = /from\s+['"](@\/api\/[^'"]+)['"]/g; + let m; + while ((m = re.exec(text))) imports.push(m[1]); + return uniq(imports); +} + +function stripSqlComments(sql) { + return sql.replace(/\/\*[\s\S]*?\*\//g, ' ').replace(/--.*$/gm, ' '); +} + +function compactSqlLine(s) { + return clean(s) + .replace(/\s*,\s*/g, ', ') + .replace(/\s*=\s*/g, ' = ') + .replace(/\s+/g, ' ') + .slice(0, 240); +} + +function extractSqlLines(body, regex, limit) { + return uniq(stripSqlComments(body) + .split(/\r?\n/) + .map(x => x.trim()) + .filter(x => regex.test(x)) + .map(compactSqlLine)) + .slice(0, limit); +} + +function extractSelectColumns(body, limit = 10) { + const noComments = stripSqlComments(body); + const m = /\bSELECT\b([\s\S]{0,2500}?)\bFROM\b/i.exec(noComments); + if (!m) return []; + return uniq(m[1].split(/\r?\n/) + .map(x => compactSqlLine(x.replace(/^\s*,/, ''))) + .filter(x => x && !/^(TOP|DISTINCT)$/i.test(x))) + .slice(0, limit); +} + +function objectRegex(name) { + return new RegExp(`(?:\\[dbo\\]\\.\\[${escapeReg(name)}\\]|dbo\\.\\[${escapeReg(name)}\\]|\\[${escapeReg(name)}\\]|\\b${escapeReg(name)}\\b)`, 'i'); +} + +function extractParams(body) { + const header = body.split(/\bAS\b/i)[0] || body.slice(0, 1000); + const params = []; + const re = /@([\u4e00-\u9fa5A-Za-z0-9_]+)\s+([A-Za-z0-9_\[\]\(\),]+)/g; + let m; + while ((m = re.exec(header))) params.push(`@${m[1]} ${m[2]}`); + return uniq(params).slice(0, 24); +} + +function summarizeProc(name, body) { + const verbs = []; + if (/\bSELECT\b/i.test(body)) verbs.push('查询'); + if (/\bINSERT\s+INTO\b/i.test(body)) verbs.push('新增'); + if (/\bUPDATE\b/i.test(body)) verbs.push('更新'); + if (/\bDELETE\s+FROM\b/i.test(body)) verbs.push('删除'); + if (/\bOPENJSON\b|JSON_VALUE|JSON_QUERY/i.test(body)) verbs.push('解析 JSON 批量数据'); + if (/ROW_NUMBER|OFFSET|@PageSize|@PageCurrent/i.test(body)) verbs.push('分页'); + if (/SAP\.SBO_YL/i.test(body)) verbs.push('读取 SAP B1 数据库对象'); + if (/报工|工时/.test(name + body)) verbs.push('处理报工/工时'); + if (/质检|检验|不合格/.test(name + body)) verbs.push('处理质检数据'); + if (/排产|派工|计划/.test(name + body)) verbs.push('处理计划/派工'); + if (/外协/.test(name + body)) verbs.push('处理外协业务'); + return uniq(verbs).join('、') || '执行数据库业务逻辑'; +} + +function extractSqlModel() { + const sql = existingSqlFiles().map(f => `\n-- FILE: ${path.basename(f)}\n${readText(f)}`).join('\n'); + const objects = []; + const objectRe = /CREATE\s+(TABLE|VIEW)\s+(?:\[dbo\]\.)?\[([^\]]+)\]/gi; + let m; + while ((m = objectRe.exec(sql))) objects.push({ type: m[1].toUpperCase(), name: m[2] }); + + const markers = []; + const procRe = /(?:CREATE|ALTER)\s+(?:\s*PROCEDURE|\s*PROC)\s+(?:\[dbo\]\.)?\[([^\]]+)\]/gi; + while ((m = procRe.exec(sql))) markers.push({ index: m.index, name: m[1] }); + + const procByName = {}; + for (let i = 0; i < markers.length; i++) { + const start = markers[i].index; + const nextGo = sql.slice(start).search(/\r?\nGO\r?\n/i); + const nextProc = i + 1 < markers.length ? markers[i + 1].index : sql.length; + const end = nextGo >= 0 ? Math.min(start + nextGo, nextProc) : nextProc; + const body = sql.slice(start, end); + const deps = []; + for (const obj of objects) { + if (objectRegex(obj.name).test(body)) deps.push(`${obj.type}:${obj.name}`); + } + const sapRefs = uniq(body.match(/SAP\.SBO_YL\.dbo\.[A-Za-z0-9_]+/g) || []); + for (const s of sapRefs) deps.push(`SAP:${s}`); + const writes = []; + for (const obj of objects) { + const n = escapeReg(obj.name); + const hit = new RegExp(`\\b(INSERT\\s+INTO|UPDATE|DELETE\\s+FROM|MERGE\\s+INTO)\\s+(?:\\[dbo\\]\\.\\[${n}\\]|dbo\\.\\[${n}\\]|\\[${n}\\]|${n})`, 'i').test(body); + if (hit) writes.push(obj.name); + } + const noComments = stripSqlComments(body); + procByName[markers[i].name] = { + name: markers[i].name, + body, + params: extractParams(body), + deps: uniq(deps), + writes: uniq(writes), + sapRefs, + summary: summarizeProc(markers[i].name, body), + features: { + selectColumns: extractSelectColumns(body), + filters: extractSqlLines(body, /\b(WHERE|AND|OR)\b/i, 10), + updates: extractSqlLines(body, /\b(UPDATE|SET|INSERT\s+INTO|DELETE\s+FROM|MERGE\s+INTO)\b/i, 12), + statusLines: extractSqlLines(body, /状态|排产|派工|加工|任务|质检|关闭|完成|已报工|DocEntry|SAP/i, 18), + grouping: extractSqlLines(body, /\b(GROUP\s+BY|HAVING|ORDER\s+BY|ROW_NUMBER|OFFSET|FETCH\s+NEXT)\b/i, 8), + tempTables: uniq(noComments.match(/#[\u4e00-\u9fa5A-Za-z0-9_]+/g) || []).slice(0, 10), + hasJson: /\bOPENJSON\b|JSON_VALUE|JSON_QUERY/i.test(noComments), + hasTransaction: /\bBEGIN\s+TRAN|COMMIT\s+TRAN|ROLLBACK\s+TRAN/i.test(noComments), + hasTryCatch: /\bTRY\b|\bCATCH\b/i.test(noComments), + hasPagination: /@PageCurrent|@PageSize|ROW_NUMBER|OFFSET\s+.*FETCH/i.test(noComments), + hasSap: /SAP\.SBO_YL/i.test(noComments) + } + }; + } + return { objects, procByName }; +} + +function operationByType(type) { + return { + '1': '旧版查询', + '2': '旧版增删改', + '7': '旧版批量/JSON', + '11': '当前通用存储过程查询/执行', + '12': '当前通用存储过程写入/业务动作', + '2001': '导出/报表类过程' + }[type] || `自定义类型 ${type}`; +} + +function procPurpose(name) { + const rules = [ + [/查询|Get|Load|Query|Search|读取|查看/, '查询/读取数据'], + [/新增|增加|Add|Insert/, '新增业务数据'], + [/修改|编辑|Edit|Update|更新|保存|Save/, '更新/保存业务数据'], + [/删除|Delete/, '删除业务数据'], + [/Finish|确认|关闭|Close/, '确认/关闭/完成业务动作'], + [/派工|Planned|排产|计划/, '计划排产或派工'], + [/报工|工时|WorkTime|ProdReport/, '报工或工时处理'], + [/质检|检验|Check|Quality/, '质量检验处理'], + [/外协/, '外协业务处理'], + [/登录|人员|角色|菜单|权限/, '基础权限/人员数据处理'], + [/设备|工位|资源|Station|Resource/, '设备/工位/资源数据处理'] + ]; + for (const [re, purpose] of rules) if (re.test(name)) return purpose; + return '业务存储过程调用'; +} + +function businessDomainFromName(name) { + const rules = [ + [/登录|人员|角色|菜单|权限|部门|工位管理/, '系统基础资料/权限'], + [/设备|报警|CaChe|StationStatus|工位设备/, '设备与实时数据'], + [/排产|派工|OrderPlanned|计划/, '计划排产'], + [/ProductCenter|ProductTask|加工中心|装配中心|报工|收料|开工|退库|发料|工时/, '生产执行/工时'], + [/外协/, '外协协同'], + [/图纸|工艺|Process|Drawing|Procedure|产品结构|标准/, '工艺与图纸'], + [/质检|检验|质量|不合格|Check/, '质量检验'], + [/销售/, '销售/订单状态'], + [/班次/, '班次与人员排班'], + [/加急/, '加急任务'] + ]; + for (const [re, domain] of rules) if (re.test(name)) return domain; + return '通用业务'; +} + +function pageBusinessNarrative(page) { + const p = page.relPath; + const labels = page.labels.slice(0, 10); + const procNames = uniq(page.procs.map(x => x.name)).slice(0, 6); + const common = []; + if (labels.length) common.push(`页面可见的操作/字段包括 ${labels.map(x => `“${x}”`).join('、')},这些是判断页面业务范围的主要线索。`); + if (procNames.length) common.push(`后端主要围绕 ${procNames.map(x => `\`${x}\``).join('、')}${page.procs.length > 6 ? ' 等过程' : ''} 取数或提交业务动作。`); + const rules = [ + [/PunctualWork/, '该页面用于发现“计划应开工但现场未及时开工”的任务。用户按任务状态、工位、工序、异常原因等条件筛选,页面展示生产订单、销售订单、物料、工序、指派对象、分配数量、上序合格数、加工/收料状态和加急数量,服务于生产异常提醒和催办。'], + [/CraftMaintain/, '该页面维护产品结构树。用户可以新增、编辑、删除产品结构节点,查询现有产品结构,并为后续工艺、物料、BOM 或生产任务提供层级基础数据。'], + [/DeviceDataHistory/, '该页面查询设备历史采集数据。用户按工位/设备、参数名称、起止时间分页查询历史记录,用于追溯设备运行参数。'], + [/DeviceInformation/, '该页面维护设备台账和设备相关基础资料。用户可以查询设备信息,新增、修改、删除设备,维护维修记录、工时记录或点检配置。'], + [/DeviceRealData/, '该页面展示设备实时或近实时数据。用户按工位和数据类型查询当前采集值、统计值或状态,通常用于设备运行监控。'], + [/Devicedata/, '该页面面向设备采集数据管理,查询缓存变量和设备数据,支持按设备、参数、时间等维度查看实时或历史采集结果。'], + [/InstallMakePlanDo|InstallMakePlan/, '该页面处理装配件排产。用户查询待排产/已排产装配任务,选择工位和人员,修改计划开工/完成时间、优先级、说明,执行单条派工、二次派工、批量确认排产,并在确认时同步 SAP 生产订单状态或创建相关请求。'], + [/SelfMakePlandone|SelfMakePlando|SelfMakePlan/, '该页面处理自制件/机加件排产。用户查询生产订单工序任务,筛选订单、合同、物料、工序、计划时间、排产状态和指派对象,完成工位派工、人员二次派工、外协分组、计划说明维护和排产确认。'], + [/PlannOrderClose/, '该页面用于生产订单关闭。用户筛选 SAP 未关闭或 MES 待确认订单,执行 SAP 生产订单关闭,并调用 MES 过程记录或确认订单关闭状态。'], + [/PlanShell/, '该页面是计划外壳/计划跟踪类页面,按缺料、发货通知、完成状态等条件查询计划或装配相关任务,用于计划人员集中查看订单齐套、发货和关闭情况。'], + [/priorityinstall/, '该页面用于装配优先级调整。用户查询装配计划任务,修改计划开工/完成时间、派工对象或优先级,用于插单和重点订单排序。'], + [/PartDrawing/, '该页面维护零件图纸。用户按物料查询图纸、查看文件、验证名称、删除图纸并保留删除记录。'], + [/PartDrawlook/, '该页面偏只读查看零件图纸,通常给生产或质检人员按物料快速打开图纸。'], + [/ProcurementDrawlook/, '该页面提供采购场景的图纸查看。用户按采购物料查询图纸,查看或删除图纸记录,支持采购、外协、来料检验时查阅技术文件。'], + [/ProcessDrawing/, '该页面维护工艺图纸。用户按物料/工艺条件查询工艺图,验证名称,查看或删除工艺图纸。'], + [/ProcedureManagement/, '该页面维护工序/路线阶段主数据。新增或修改工序时会同步 SAP B1 的 RouteStages,保证 MES 工序与 SAP 工艺阶段一致。'], + [/ProcessesDevelop/, '该页面用于工艺开发和生产工艺路线维护。用户围绕物料、工序、顺序、工艺参数、图纸等信息维护标准或生产用工艺路线。'], + [/ProcessInquiry/, '该页面用于工艺路线查询。用户按物料、产品、工序等条件查看标准工艺或生产工艺,服务于排产、生产和质检核对。'], + [/ProcessProduct/, '该页面维护产品与工艺/图纸的关系,使产品、物料、工序、图纸等基础数据形成可查询的工艺资料。'], + [/ProductionOrder/, '该页面处理生产订单资料。用户查询 ERP/MES 生产订单,并通过过程把 SAP 生产订单同步成 MES 生产计划和工序任务。'], + [/MachiningCenter/, '该页面是机加生产执行主界面。操作员按工位查看可执行任务和进行中任务,完成收料、开始加工、暂停/恢复、报工、辅助工序、首检/巡检/序检、生产发料查询、退库、图纸查看等动作,并写入加工中心操作记录和报工记录。'], + [/AssemblyCenter/, '该页面是装配生产执行主界面。装配人员按工位查询装配任务,处理开工、结束/报工、送检、缺料查询、收检记录、图纸查看和退库等动作,并会读取 SAP 生产订单信息辅助判断。'], + [/AssembleTaskManage/, '该页面管理装配任务。用户查询装配生产任务、查看工时汇总,进行派工、任务说明维护和外协/生产通知。'], + [/ProductionTaskManage/, '该页面管理生产任务。用户按工位、订单、工序查询任务,查看工时汇总,执行派工、修改计划字段、维护任务说明和通知状态。'], + [/ProductionTasksSum/, '该页面做生产任务汇总。用户按订单、工序、工位、时间等维度查询生产任务和工时汇总,并可编辑计划说明或派工信息。'], + [/ProductionPlanTrack/, '该页面跟踪生产计划执行。用户查看计划任务的开工、完工、进度、延期或异常情况,用于计划员追踪订单。'], + [/AssemblePlanTrack/, '该页面跟踪装配计划执行,展示装配任务进度、计划完成情况和异常。'], + [/AssembleTasksSum/, '该页面汇总装配任务,按订单、工位、人员或状态统计装配执行情况。'], + [/AssembleStatus/, '该页面查看装配现场状态,重点展示进行中任务和当前工位状态。'], + [/DeviceStatus/, '该页面查看设备/工位生产状态,通常用于判断设备是否在加工、待机、报警或空闲。'], + [/OutsourceMange/, '该页面管理外协任务。用户查询可外协工序,按供应商/订单/工序分组,执行外协派工并同步 SAP 采购请求或相关单据,维护外协发料、收料、质检记录、打印次数和备注。'], + [/SaleOutsourceMange/, '该页面管理销售相关外协任务。业务与外协管理类似,但面向销售订单或销售外协场景,包含派工同步 SAP、外协发料、历史记录和质检记录查询。'], + [/OutsourceSheet/, '该页面输出外协报表。用户按订单、合同、产品、计划号、供应商、状态分页查询外协报表,也可导出,用于外协进度、发料、收料、质检、开票等跟踪。'], + [/PickingTask/, '该页面处理拣配任务。用户查询生产订单相关拣配/领料任务,并可能联动 SAP 生产订单或库存出入库状态。'], + [/PersonnelBinding/, '该页面维护工位与人员绑定关系。用于限制或提示哪些人员可在指定工位报工、开工或执行任务。'], + [/ShiftManagement/, '该页面维护班次和班次人员绑定。用户新增、修改、删除班次,给班次绑定人员,为工时计算和报工归属提供基础数据。'], + [/Timesheet/, '该页面统计工时。用户按项目、作业者、设备、任务等维度查询工时数据,并可导出报表。'], + [/WorkHoursCheck/, '该页面用于工时校验。质检/管理人员查询待校验报工记录,系统计算标准/实际工时,保存单条或批量校验结果;通过校验后可把工序资源或工时/出库类单据上传到 SAP。'], + [/WorkhoursEdit/, '该页面用于编辑已产生的工时/报工记录,修正异常工时或补录说明。'], + [/Workhours/, '该页面用于工时查询,按工序、人员、设备、时间等条件查看工序工时。'], + [/Urgent/, '该页面维护加急任务。用户查询加急订单明细,并更新完成、转至等字段,用于生产/质检优先级管理。'], + [/AbnormalControl/, '该页面管理生产异常。用户查询异常记录,推进异常处理、关闭或记录处理结果。'], + [/login/, '该页面是登录入口,负责账号密码登录、角色选择、Token/Cookie 写入、路由权限初始化和密码修改入口。'], + [/dashboard/, '该页面是系统首页或欢迎页,用于承载看板入口或基础统计展示。'], + [/404/, '该页面是 404 错误页,用于路由不存在时展示错误信息。'], + [/purchaseIncoming/, '该页面处理采购/来料检验。质检人员查询待检任务,查看图纸、字典和检验人员,录入合格数、不合格数、检测数据,调用过程更新来料检验结果。'], + [/processReceive/, '该页面处理序检收检。质检人员接收工序检验任务,查询加急和字典信息,读取 SAP 工序状态,新增序检收检记录。'], + [/processSpecial/, '该页面处理过程/特殊检验。用户按工序任务录入特殊检验结果和检测明细。'], + [/firstSpecial/, '该页面处理首检/特殊首件检验。用户按工序和工位选择任务,录入首检数据。'], + [/final/, '该页面处理终检任务。质检人员查询终检任务,录入终检结果,并预留 SAP 生产订单状态回写。'], + [/materialReturn/, '该页面处理原材料退库检验。用户查询退库检验任务,读取 SAP 生产订单辅助信息,录入并更新检验结果。'], + [/salesReturn/, '该页面处理销售退货检验。用户查询销售退货待检任务,录入检验结果并更新质检记录。'], + [/OtherInbound/, '该页面处理其他入库检验。用户查询其他入库待检任务,录入检验结果并更新质检记录。'], + [/QualityCenter/, '该页面是质量综合处理中心。用户集中查询质检任务、收检记录、终检/入库任务和质检明细,录入检测数据、不合格处理,并读取 SAP 生产订单信息辅助校验。'], + [/QualityDetails/, '该页面查询质检明细。用户按订单、物料、检验类型、时间等条件查询和导出检测明细。'], + [/QualityStandardQuery/, '该页面维护/查询检验标准。用户按物料、工序、检测项目维护理论值、上下限、量具和启用状态。'], + [/Unqualified/, '该页面处理不合格品。用户查询不合格记录,查看处置流程和节点,推进让步放行、返工、报废等处理。'], + [/saleorderstatus/, '该页面查询销售订单状态。用户按销售订单、合同、物料等条件查看销售订单在 SAP/MES 中的履约、生产、发货或关闭状态。'], + [/MenuManagement/, '该页面维护菜单和权限。管理员查询、增加、修改、删除菜单/角色权限配置,用于动态路由和按钮权限。'], + [/OperationLog/, '该页面查询操作日志或报工操作记录,用于审计用户操作和追踪异常。'], + [/OrgManagement/, '该页面维护组织/角色类基础数据,支持新增、修改、删除和查询。'], + [/PersonnelManagement/, '该页面维护人员账号。管理员维护人员、部门、角色、启用状态等登录和权限基础数据。'], + [/SystemRrolemaintenance/, '该页面维护系统角色。管理员查询、新增、修改、删除角色数据。'], + [/WorkstationManagement/, '该页面维护工位资源。管理员在 MES 侧新增、修改、删除工位,同时调用 SAP B1 Resources 新增或更新资源主数据。'], + [/layout|Sidebar|Navbar|TagsView|AppMain|ResizeHandler/, '该文件属于系统布局组件,负责菜单、导航、标签页、内容承载或窗口自适应,不承载具体业务流程。'], + [/login/, '该页面是登录入口,负责账号密码登录、角色选择、Token/Cookie 写入、路由权限初始化和密码修改入口。'], + [/dashboard/, '该页面是系统首页或欢迎页,用于承载看板入口或基础统计展示。'], + [/404/, '该页面是 404 错误页,用于路由不存在时展示错误信息。'] + ]; + const found = rules.find(([re]) => re.test(p)); + return [found ? found[1] : '该页面为业务页面,具体功能由表单字段、按钮和存储过程调用共同决定。', ...common].join('\n\n'); +} + +function pageFlow(page) { + const p = page.relPath; + const flows = [ + [/SelfMakePlandone|SelfMakePlando|SelfMakePlan/, + '自制/机加排产流程:\n\n```mermaid\nflowchart LR\n A[输入订单/合同/物料/工序/时间条件] --> B[调用 MES_OrderPlanned_Query 查询待排产任务]\n B --> C[选择任务行]\n C --> D{派工方式}\n D --> E[MES_OrderPlanned_SingleTaskPlanned 单任务派工]\n D --> F[计划排产_二次派工 绑定人员]\n D --> G[计划排产_外协分组]\n E --> H[MES_OrderPlanned_EditTaskPlanned/DescriptionEdit 修改计划字段]\n F --> H\n G --> H\n H --> I[MES_OrderPlanned_Finish 确认排产]\n I --> J[PATCH /ProductionOrders(...) 回写 SAP 生产订单状态]\n J --> K[页面刷新任务状态]\n```\n'], + [/InstallMakePlanDo|InstallMakePlan/, + '装配排产流程:\n\n```mermaid\nflowchart LR\n A[输入订单/合同/物料/工序/时间条件] --> B[MES_OrderPlanned_Queryzp 查询装配任务]\n B --> C[选择任务]\n C --> D[Prog_MES_LoadStations 选择工位]\n D --> E[系统管理_人员管理_所有有效人员查询 选择人员]\n E --> F[计划排产_派工 或 MES_OrderPlanned_SingleTaskPlanned]\n F --> G[计划排产_二次派工]\n G --> H[MES_OrderPlanned_Finish 确认排产]\n H --> I[PATCH /ProductionOrders(...) 或 POST SAP 请求]\n I --> J[刷新排产结果]\n```\n'], + [/MachiningCenter/, + '机加中心执行流程:\n\n```mermaid\nflowchart LR\n A[选择工位/人员/任务条件] --> B[MES_ProductCenter_GetTask 查询可执行任务]\n B --> C[选择任务]\n C --> D[收料 MES_ProductTask_MaterialRecieved]\n D --> E[开始加工 MES_ProductTask_WorkingStart]\n E --> F{生产过程}\n F --> G[暂停/恢复 MES_ProductTask_Rest]\n F --> H[首检/巡检/序检]\n F --> I[报工 MES_ProductTask_ProdReport]\n I --> J[写入操作记录/报工记录]\n J --> K[必要时读取 SAP ProductionOrders]\n K --> L[刷新任务和进行中状态]\n```\n'], + [/AssemblyCenter/, + '装配中心执行流程:\n\n```mermaid\nflowchart LR\n A[选择工位/人员] --> B[MES_ProductCenter_GetTask_zp 查询装配任务]\n B --> C[查看缺料/图纸/工序]\n C --> D[MES_人员工时记录_开始 或生产任务开始]\n D --> E[执行装配]\n E --> F[MES_ProductTask_SendInspection 送检/报工]\n F --> G[收检记录/质检数据]\n G --> H[读取 SAP ProductionOrders 辅助判断]\n H --> I[刷新装配任务]\n```\n'], + [/WorkHoursCheck/, + '工时校验流程:\n\n```mermaid\nflowchart LR\n A[选择人员/订单/工序/日期] --> B[工时校验_获取昨日之前操作记录列表]\n B --> C[选择待校验记录]\n C --> D[usp_ValidateWorkTime 或 usp_BatchValidateWorkTime 计算工时]\n D --> E{校验结果}\n E --> F[工时校验_保存校验记录]\n E --> G[工时校验_批量保存校验记录]\n F --> H[更新校验状态]\n G --> H\n H --> I[GET/PATCH /ProductionOrders 补工序资源]\n I --> J[POST /InventoryGenExits 上传 SAP]\n J --> K[标记已上传/失败留痕]\n```\n'], + [/purchaseIncoming|processReceive|processSpecial|firstSpecial|final|materialReturn|salesReturn|OtherInbound|QualityCenter/, + '质检业务流程:\n\n```mermaid\nflowchart LR\n A[选择检验类型/订单/物料/工序] --> B[查询待检任务]\n B --> C[查看图纸/字典/检验人员]\n C --> D[录入检测数量、合格数、不合格数和检测明细]\n D --> E{检验类型}\n E --> F[来料/入库/退货检验更新]\n E --> G[序检收检新增或更新]\n E --> H[终检/首检/特殊检验保存]\n F --> I[写入 YL_质量检验_质检记录及明细]\n G --> I\n H --> I\n I --> J[必要时查询/回写 SAP 生产订单或单据]\n```\n'], + [/OutsourceMange|SaleOutsourceMange|OutsourceSheet/, + '外协业务流程:\n\n```mermaid\nflowchart LR\n A[输入订单/合同/供应商/工序条件] --> B[查询外协任务或外协报表]\n B --> C[选择外协工序/供应商]\n C --> D[计划排产_派工 或外协分组]\n D --> E[POST SAP 采购/外协相关请求]\n E --> F[外协发料查询/保存]\n F --> G[外协收料/质检记录]\n G --> H[更新打印次数/备注/报表状态]\n```\n'] + ]; + const found = flows.find(([re]) => re.test(p)); + if (found) return found[1]; + if (!page.procs.length) return '该页面未发现后端存储过程调用,通常不形成完整业务流程。'; + const procChain = uniq(page.procs.map(x => x.name)).slice(0, 8).map(x => `\`${x}\``).join(' -> '); + return `通用流程:用户输入查询/维护条件 -> 调用 ${procChain} -> 后端读写 SQL Server -> 页面刷新表格或弹窗结果。`; +} + +function fieldMappingTable(page) { + const rows = [ + '| 类型 | 前端字段/显示列 | 存储过程参数或表达式 | SQL返回字段/数据库字段线索 |', + '|---|---|---|---|' + ]; + const mappings = []; + for (const p of page.fields.pushedParams || []) { + const relatedProc = page.procs.find(proc => proc.sqlInfo?.params?.some(x => x.includes(`@${p.name}`))); + const sqlField = relatedProc?.sqlInfo?.features?.selectColumns?.find(x => x.includes(p.name)) || ''; + mappings.push(['参数', p.expr, `@${p.name}`, sqlField]); + } + for (const c of page.fields.tableColumns || []) { + if (!c.label && !c.prop) continue; + const sqlField = page.procs + .flatMap(proc => proc.sqlInfo?.features?.selectColumns || []) + .find(x => (c.prop && x.includes(c.prop)) || (c.label && x.includes(c.label))) || ''; + mappings.push(['显示列', c.label || c.prop, '', sqlField || c.prop || c.label]); + } + for (const v of page.fields.vModels || []) { + const name = v.split('.').pop(); + const param = page.fields.pushedParams.find(x => x.expr.includes(v) || x.expr.includes(name)); + mappings.push(['输入字段', v, param ? `@${param.name}` : '', '']); + } + const uniqRows = uniq(mappings.map(x => x.join('|'))).slice(0, 40); + if (!uniqRows.length) return '未从页面模板中抽取到明确的 `v-model`、表格列或 `param.push` 字段映射。'; + for (const item of uniqRows) { + const [type, front, param, sql] = item.split('|'); + rows.push(`| ${type} | \`${front || '-'}\` | ${param ? `\`${param}\`` : '-'} | ${sql ? `\`${sql}\`` : '-'} |`); + } + return rows.join('\n'); +} + +function statusFlow(page) { + const lines = []; + for (const proc of page.procs) { + const info = proc.sqlInfo; + if (!info) continue; + const status = info.features.statusLines || []; + const useful = status.filter(x => /状态|排产|派工|加工|任务|质检|关闭|完成|已报工|DocEntry|SAP/i.test(x)); + if (useful.length) lines.push(`- \`${proc.name}\`:${useful.slice(0, 8).map(x => `\`${x}\``).join(';')}`); + } + if (!lines.length) return '未从当前 SQL 静态解析到明确的状态字段变更。'; + return lines.join('\n'); +} + +function sapInterfaceList(page) { + if (!page.sapCalls.length) return '页面无直接 SAP Service Layer 调用。'; + const lines = ['| 行号 | 方法 | 接口 | 调用时机/影响判断 | 提交字段线索 |', '|---:|---|---|---|---|']; + for (const c of page.sapCalls) { + const timing = c.url.includes('ProductionOrders') + ? '读取或更新 SAP 生产订单。失败会导致 MES 与 SAP 订单状态/工序资源不同步。' + : c.url.includes('InventoryGenExits') + ? '上传库存发出/工时相关单据。失败会导致 SAP 未生成对应业务单据。' + : c.url.includes('Resources') + ? '新增或更新 SAP 资源主数据。失败会导致 MES 工位与 SAP 资源不一致。' + : c.url.includes('RouteStages') + ? '新增或更新 SAP 工序阶段。失败会导致 MES 工序与 SAP RouteStages 不一致。' + : '调用外部接口,失败会影响对应外部系统同步。'; + lines.push(`| ${c.line} | \`${c.fn}\` | \`${c.url}\` | ${timing} | ${mdList(c.payloadKeys.slice(0, 12))} |`); + } + return lines.join('\n'); +} + +function dbCallChain(page) { + if (!page.procs.length) return '无数据库调用链。'; + const lines = []; + for (const proc of page.procs) { + const deps = proc.sqlInfo ? depsMd(proc.sqlInfo.deps) : '过程体未解析'; + const result = proc.purpose; + lines.push(`- \`${page.relPath}\` -> \`${proc.name}\` -> ${deps} -> ${result}`); + } + return lines.join('\n'); +} + +function mdList(items, empty = '无') { + if (!items || !items.length) return empty; + return items.map(x => `\`${x}\``).join('、'); +} + +function depsMd(deps) { + if (!deps || !deps.length) return '未在 SQL 中解析到明确依赖'; + const tables = deps.filter(x => x.startsWith('TABLE:')).map(x => x.slice(6)); + const views = deps.filter(x => x.startsWith('VIEW:')).map(x => x.slice(5)); + const sap = deps.filter(x => x.startsWith('SAP:')).map(x => x.slice(4)); + const parts = []; + if (tables.length) parts.push(`表:${mdList(tables)}`); + if (views.length) parts.push(`视图:${mdList(views)}`); + if (sap.length) parts.push(`SAP/链接库:${mdList(sap)}`); + return parts.join(';') || '未在 SQL 中解析到明确依赖'; +} + +function explainProc(proc) { + const info = proc.sqlInfo; + const lines = []; + lines.push(`\`${proc.name}\` 属于 ${businessDomainFromName(proc.name)},前端以 type=${proc.type}(${proc.op})调用,页面用途是 ${proc.purpose}。`); + if (!info) { + lines.push('当前工作区 SQL 中没有解析到该过程体,因此只能确认前端调用关系,不能准确说明内部读写表、过滤条件和状态变更。'); + return lines.join(' '); + } + const f = info.features; + lines.push(`数据库处理摘要:${info.summary}。`); + lines.push(`读取/关联对象:${depsMd(info.deps)}。`); + if (info.writes.length) lines.push(`写入或更新对象:${mdList(info.writes)}。`); + if (info.params.length) lines.push(`入参/分页参数:${mdList(info.params)}。`); + if (f.selectColumns.length) lines.push(`主要返回字段线索:${mdList(f.selectColumns)}。`); + if (f.filters.length) lines.push(`关键过滤/匹配条件:${f.filters.map(x => `\`${x}\``).join(';')}。`); + if (f.updates.length) lines.push(`关键写入/状态处理语句线索:${f.updates.map(x => `\`${x}\``).join(';')}。`); + if (f.grouping.length) lines.push(`排序/分组/分页线索:${f.grouping.map(x => `\`${x}\``).join(';')}。`); + const flags = []; + if (f.hasPagination) flags.push('分页'); + if (f.hasJson) flags.push('JSON 批量解析'); + if (f.hasTransaction) flags.push('事务控制'); + if (f.hasTryCatch) flags.push('异常捕获'); + if (f.hasSap) flags.push('读取 SAP 数据库对象'); + if (f.tempTables.length) flags.push(`临时表 ${mdList(f.tempTables)}`); + if (flags.length) lines.push(`实现特征:${flags.join('、')}。`); + return lines.join(' '); +} + +function procTable(procs) { + if (!procs.length) return '未发现 `CreateData(...)` 存储过程调用。'; + const rows = [ + '| 行号 | type | 存储过程 | 前端用途 | SQL摘要 | 依赖对象 |', + '|---:|---|---|---|---|---|' + ]; + for (const p of procs) { + const info = p.sqlInfo; + rows.push(`| ${p.line} | ${p.type}(${p.op}) | \`${p.name}\` | ${p.purpose} | ${info ? info.summary : '未找到过程体'} | ${info ? depsMd(info.deps) : '未知'} |`); + } + return rows.join('\n'); +} + +function sapTable(calls, procs) { + const procSap = []; + for (const p of procs) { + if (p.sqlInfo && p.sqlInfo.sapRefs.length) procSap.push(`${p.name}: ${p.sqlInfo.sapRefs.join(', ')}`); + } + if (!calls.length && !procSap.length) return '未发现页面直接调用 SAP B1 Service Layer;相关存储过程也未解析到 `SAP.SBO_YL` 链接库引用。'; + const lines = []; + if (calls.length) { + lines.push('页面直接 SAP/接口调用:'); + for (const c of calls) lines.push(`- 第 ${c.line} 行:\`${c.fn}("${c.url}")\``); + } + if (procSap.length) { + lines.push('存储过程内读取 SAP B1 数据库对象:'); + for (const s of procSap) lines.push(`- ${s}`); + } + return lines.join('\n'); +} + +function techFlags(page) { + const flags = ['Vue 2 Options API', 'Element UI']; + if (page.procs.length) flags.push('`CreateData` + `ExecDatabase` 调用后端过程'); + else flags.push('未发现页面级后端存储过程调用'); + if (page.sapCalls.length) flags.push('SAP B1 Service Layer(`src/api/b1s.js`)'); + if (page.imports.includes('@/api/tm') || page.sapCalls.some(x => x.fn === 'posttm')) flags.push('TM/OpenAPI 接口(`src/api/tm.js`)'); + if (page.hasEcharts) flags.push('ECharts'); + if (page.hasFullCalendar) flags.push('FullCalendar'); + if (page.hasMqtt) flags.push('MQTT'); + if (page.hasPdf) flags.push('PDF/图纸预览或导出'); + if (page.hasExcel) flags.push('Excel/报表导出'); + return flags; +} + +function moduleSummary(pages) { + const groups = {}; + for (const p of pages) { + const top = p.relPath.split('/')[2] || '其他'; + groups[top] ||= []; + groups[top].push(p); + } + const lines = ['| 模块 | 页面数 | 主要能力 |', '|---|---:|---|']; + for (const [mod, ps] of Object.entries(groups)) { + const allProcs = uniq(ps.flatMap(p => p.procs.map(x => x.name))); + const allSap = ps.reduce((n, p) => n + p.sapCalls.length, 0); + const ability = []; + if (allProcs.length) ability.push(`过程 ${allProcs.length} 个`); + if (allSap) ability.push(`直接 SAP 调用 ${allSap} 处`); + if (ps.some(p => p.hasEcharts)) ability.push('图表'); + if (ps.some(p => p.hasMqtt)) ability.push('设备实时通信'); + lines.push(`| ${mod} | ${ps.length} | ${ability.join('、') || '布局/静态页面'} |`); + } + return lines.join('\n'); +} + +const sqlModel = extractSqlModel(); +const pages = walk(viewsRoot, ['.vue', '.js']).sort().map(file => { + const text = readText(file); + const relPath = rel(file); + const procs = extractCreateData(text).map(p => ({ + ...p, + op: operationByType(p.type), + purpose: procPurpose(p.name), + sqlInfo: sqlModel.procByName[p.name] + })); + const page = { + file, + relPath, + module: moduleNameFromPath(relPath), + lines: text.split(/\r?\n/).length, + labels: extractLabels(text), + methods: extractMethods(text), + fields: extractFrontendFields(text), + procs, + sapCalls: extractSapCalls(text), + imports: extractApiImports(text), + hasMqtt: /mqtt|MQTT/.test(text), + hasEcharts: /echarts|ECharts|\$echarts/.test(text), + hasFullCalendar: /FullCalendar|@fullcalendar/.test(text), + hasPdf: /pdfjs|jspdf|html2canvas|pdf/i.test(text), + hasExcel: /xlsx|exportExcel|Excel|导出/.test(text) + }; + page.functionDesc = pageBusinessNarrative(page); + return page; +}); + +const now = new Date().toISOString().slice(0, 10); +let md = ''; +md += `# MES_Manage_View_V20 src/views 逐页面详细分析\n\n`; +md += `生成日期:${now}\n\n`; +md += `分析范围:\`MES_Manage_View_V20/src/views\` 下 ${pages.length} 个 .vue/.js 文件;辅助读取 \`src/api\`、\`config/index.js\`、\`static/config.js\` 和 SQL 脚本。\n\n`; +md += `## 重要说明\n\n`; +md += `- 页面功能不是只按文件名猜测,报告同时参考页面路径、按钮/字段文案、方法名、存储过程名和 SQL 过程体。\n`; +md += `- 存储过程处理说明来自 SQL 静态解析:读写对象、参数、返回字段、过滤条件、更新语句、分组分页、JSON、事务、SAP 链接库等。\n`; +md += `- 如果某个过程没有解析到过程体,报告会明确说明不能准确判断内部表/视图和处理逻辑。\n\n`; + +md += `## 技术路线总览\n\n`; +md += `- 前端:Vue 2.7、Vue Router、Vuex、Element UI,页面以 Options API 为主。\n`; +md += `- 数据访问:页面调用 \`this.CreateData(type, procedureName, params[, pageSize, pageCurrent])\` 组包,再调用 \`this.ExecDatabase(data)\` 访问后端。\n`; +md += `- 后端:统一接口接收 type/name/param,执行 SQL Server 存储过程,返回 \`response.data\` 和分页信息。\n`; +md += `- 数据库:\`YL_MESDB\`,核心对象包括生产计划/生产任务、加工中心操作记录、质检记录、设备数据、权限菜单等表和视图。\n`; +md += `- SAP:\`src/api/b1s.js\` 通过 \`window.dt_Config.baseURLB1\` 访问 B1 Service Layer;部分过程也跨库读取 \`SAP.SBO_YL.dbo.*\`。\n\n`; + +md += `## 模块汇总\n\n${moduleSummary(pages)}\n\n`; + +const allSapCalls = []; +for (const p of pages) { + for (const c of p.sapCalls) allSapCalls.push({ page: p.relPath, ...c }); +} +if (allSapCalls.length) { + md += `## SAP 交互总清单\n\n`; + md += `| 页面 | 行号 | 方法 | 接口 | 提交字段线索 |\n|---|---:|---|---|---|\n`; + for (const c of allSapCalls) { + md += `| \`${c.page}\` | ${c.line} | \`${c.fn}\` | \`${c.url}\` | ${mdList(c.payloadKeys.slice(0, 10))} |\n`; + } + md += `\n`; +} + +for (let i = 0; i < pages.length; i++) { + const p = pages[i]; + md += `## ${i + 1}. ${p.relPath}\n\n`; + md += `**页面位置**:\`${p.relPath}\` \n`; + md += `**所属模块**:${p.module} \n`; + md += `**源码行数**:${p.lines}\n\n`; + md += `### 页面功能\n\n${p.functionDesc}\n\n`; + md += `### 页面流程图\n\n${pageFlow(p)}\n\n`; + md += `### 用户操作与页面线索\n\n`; + md += `可见按钮/字段线索:${mdList(p.labels.slice(0, 18))}\n\n`; + md += `主要方法线索:${mdList(p.methods.slice(0, 18))}\n\n`; + md += `### 字段映射表\n\n${fieldMappingTable(p)}\n\n`; + md += `### 技术路线\n\n${techFlags(p).map(x => `- ${x}`).join('\n')}\n\n`; + md += `### 调用的存储过程总览\n\n${procTable(p.procs)}\n\n`; + md += `### 与 SAP 的交互\n\n${sapTable(p.sapCalls, p.procs)}\n\n`; + md += `### SAP 接口级说明\n\n${sapInterfaceList(p)}\n\n`; + md += `### 状态流转说明\n\n${statusFlow(p)}\n\n`; + md += `### 数据库调用链\n\n${dbCallChain(p)}\n\n`; + md += `### 存储过程处理逻辑明细\n\n`; + if (!p.procs.length) { + md += `无页面级存储过程调用。\n\n`; + } else { + for (const proc of p.procs) md += `- ${explainProc(proc)}\n`; + md += `\n`; + } +} + +md += `## SQL 对象总览\n\n`; +md += `脚本中解析到表/视图 ${sqlModel.objects.length} 个、存储过程 ${Object.keys(sqlModel.procByName).length} 个。\n\n`; +md += `### 表/视图清单\n\n`; +for (const obj of sqlModel.objects) md += `- ${obj.type === 'TABLE' ? '表' : '视图'}:\`${obj.name}\`\n`; + +fs.writeFileSync(outFile, md, 'utf8'); +console.log(outFile); diff --git a/tools/create_dev_plan_docx.ps1 b/tools/create_dev_plan_docx.ps1 new file mode 100644 index 0000000..e715de4 --- /dev/null +++ b/tools/create_dev_plan_docx.ps1 @@ -0,0 +1,206 @@ +param( + [Parameter(Mandatory = $true)] + [string]$PlanMarkdown, + + [Parameter(Mandatory = $true)] + [string]$SourceMarkdown, + + [Parameter(Mandatory = $true)] + [string]$OutputDocx +) + +$ErrorActionPreference = 'Stop' + +function Escape-XmlText { + param([AllowNull()][string]$Text) + if ($null -eq $Text) { return '' } + return [System.Security.SecurityElement]::Escape($Text) +} + +function Add-Paragraph { + param( + [System.Collections.Generic.List[string]]$Parts, + [string]$Text, + [string]$Style = $null + ) + $styleXml = '' + if ($Style) { + $styleXml = "" + } + $Parts.Add("$styleXml$(Escape-XmlText $Text)") +} + +function Add-Table { + param( + [System.Collections.Generic.List[string]]$Parts, + [string[]]$Headers, + [object[]]$Rows + ) + $tbl = New-Object System.Text.StringBuilder + [void]$tbl.Append('') + [void]$tbl.Append('') + [void]$tbl.Append('') + foreach ($h in $Headers) { + [void]$tbl.Append('') + [void]$tbl.Append((Escape-XmlText $h)) + [void]$tbl.Append('') + } + [void]$tbl.Append('') + foreach ($row in $Rows) { + [void]$tbl.Append('') + foreach ($cell in $row) { + [void]$tbl.Append('') + [void]$tbl.Append((Escape-XmlText ([string]$cell))) + [void]$tbl.Append('') + } + [void]$tbl.Append('') + } + [void]$tbl.Append('') + $Parts.Add($tbl.ToString()) +} + +function Flush-TableBuffer { + param( + [System.Collections.Generic.List[string]]$Parts, + [System.Collections.Generic.List[string]]$Buffer + ) + if ($Buffer.Count -lt 2) { + foreach ($line in $Buffer) { + Add-Paragraph -Parts $Parts -Text $line + } + $Buffer.Clear() + return + } + $header = $Buffer[0].Trim('|').Split('|') | ForEach-Object { $_.Trim() } + $rows = @() + for ($i = 2; $i -lt $Buffer.Count; $i++) { + $rows += ,($Buffer[$i].Trim('|').Split('|') | ForEach-Object { $_.Trim() }) + } + Add-Table -Parts $Parts -Headers $header -Rows $rows + $Buffer.Clear() +} + +function Add-MarkdownContent { + param( + [System.Collections.Generic.List[string]]$Parts, + [string]$MarkdownPath + ) + $lines = [System.IO.File]::ReadAllLines($MarkdownPath, [System.Text.Encoding]::UTF8) + $tableBuffer = New-Object System.Collections.Generic.List[string] + $inCode = $false + + foreach ($line in $lines) { + if ($line.TrimStart().StartsWith('```')) { + if ($tableBuffer.Count -gt 0) { Flush-TableBuffer -Parts $Parts -Buffer $tableBuffer } + $inCode = -not $inCode + Add-Paragraph -Parts $Parts -Text $line -Style 'Code' + continue + } + if ($inCode) { + Add-Paragraph -Parts $Parts -Text $line -Style 'Code' + continue + } + if ($line.TrimStart().StartsWith('|') -and $line.TrimEnd().EndsWith('|')) { + $tableBuffer.Add($line) + continue + } + if ($tableBuffer.Count -gt 0) { Flush-TableBuffer -Parts $Parts -Buffer $tableBuffer } + + if ($line.StartsWith('### ')) { + Add-Paragraph -Parts $Parts -Text $line.Substring(4) -Style 'Heading3' + } elseif ($line.StartsWith('## ')) { + Add-Paragraph -Parts $Parts -Text $line.Substring(3) -Style 'Heading2' + } elseif ($line.StartsWith('# ')) { + Add-Paragraph -Parts $Parts -Text $line.Substring(2) -Style 'Heading1' + } elseif ($line.Trim().StartsWith('- ')) { + Add-Paragraph -Parts $Parts -Text ('· ' + $line.Trim().Substring(2)) + } elseif ([string]::IsNullOrWhiteSpace($line)) { + Add-Paragraph -Parts $Parts -Text '' + } else { + Add-Paragraph -Parts $Parts -Text $line + } + } + if ($tableBuffer.Count -gt 0) { Flush-TableBuffer -Parts $Parts -Buffer $tableBuffer } +} + +if (-not (Test-Path -LiteralPath $PlanMarkdown)) { throw "Plan markdown not found: $PlanMarkdown" } +if (-not (Test-Path -LiteralPath $SourceMarkdown)) { throw "Source markdown not found: $SourceMarkdown" } + +$outputDir = Split-Path -Path $OutputDocx -Parent +if (-not (Test-Path -LiteralPath $outputDir)) { + New-Item -ItemType Directory -Path $outputDir | Out-Null +} + +$tempRoot = Join-Path $env:TEMP ("docx_" + [Guid]::NewGuid().ToString('N')) +$wordDir = Join-Path $tempRoot 'word' +$relsDir = Join-Path $tempRoot '_rels' +$wordRelsDir = Join-Path $wordDir '_rels' +New-Item -ItemType Directory -Path $wordDir, $relsDir, $wordRelsDir | Out-Null + +$parts = New-Object System.Collections.Generic.List[string] +Add-MarkdownContent -Parts $parts -MarkdownPath $PlanMarkdown +Add-MarkdownContent -Parts $parts -MarkdownPath $SourceMarkdown + +$documentXml = @" + + + + $($parts -join "`n") + + + + + + +"@ + +$stylesXml = @' + + + + + + + + + +'@ + +$contentTypesXml = @' + + + + + + + +'@ + +$relsXml = @' + + + + +'@ + +$docRelsXml = @' + + + + +'@ + +[System.IO.File]::WriteAllText((Join-Path $tempRoot '[Content_Types].xml'), $contentTypesXml, [System.Text.Encoding]::UTF8) +[System.IO.File]::WriteAllText((Join-Path $relsDir '.rels'), $relsXml, [System.Text.Encoding]::UTF8) +[System.IO.File]::WriteAllText((Join-Path $wordDir 'document.xml'), $documentXml, [System.Text.Encoding]::UTF8) +[System.IO.File]::WriteAllText((Join-Path $wordDir 'styles.xml'), $stylesXml, [System.Text.Encoding]::UTF8) +[System.IO.File]::WriteAllText((Join-Path $wordRelsDir 'document.xml.rels'), $docRelsXml, [System.Text.Encoding]::UTF8) + +if (Test-Path -LiteralPath $OutputDocx) { + Remove-Item -LiteralPath $OutputDocx -Force +} + +Add-Type -AssemblyName System.IO.Compression.FileSystem +[System.IO.Compression.ZipFile]::CreateFromDirectory($tempRoot, $OutputDocx) +Remove-Item -LiteralPath $tempRoot -Recurse -Force +Write-Output $OutputDocx