更新装配、精工车间、技术中心、仓储模块,新增工序工价、生产审核、三楼仓库可视化等功能及文档SQL

This commit is contained in:
Developer
2026-07-06 11:21:59 +08:00
parent be0ff91e24
commit 9c1f52078d
43 changed files with 8566 additions and 233 deletions

View File

@@ -44,6 +44,10 @@ API 文件按业务模块组织在 `src/api/` 目录下,子目录与业务模
环境配置集中在 `static/config.js` 中,通过导出常量供 `src/utils/request.js` 引用。包含主服务地址、立库接口地址、文件上传下载路径、WebSocket 地址等。环境切换通过注释切换 IP 地址实现,不使用 `.env` 文件。修改配置时需同时关注 `request.js` 中的引用。 环境配置集中在 `static/config.js` 中,通过导出常量供 `src/utils/request.js` 引用。包含主服务地址、立库接口地址、文件上传下载路径、WebSocket 地址等。环境切换通过注释切换 IP 地址实现,不使用 `.env` 文件。修改配置时需同时关注 `request.js` 中的引用。
## 后端数据库
后端使用 SQL Server 数据库连接信息如下IP 地址 `192.168.1.27`,数据库名 `ERPTOOL_JY_20250826Back`,账号 `sa`,密码 `126.com`
## 文件上传下载 ## 文件上传下载
文件上传使用多个专用处理器:`uploadFile.ashx`(通用上传)、`MESUploadFile.ashx`MES 系统上传)、`uploadOP.ashx`(工序上传)、`uploadPerson.ashx`(人员上传)等。文件下载使用 `downloadFile.ashx``MESDownloadFile.ashx`。Excel 导出使用 `ExcelDownLoad` 配置指向 `MESCommonBase.ashx`,前端通过 `this.exportExcel_NPOI(param)` 触发下载。图片查看使用 `v-viewer` 插件。 文件上传使用多个专用处理器:`uploadFile.ashx`(通用上传)、`MESUploadFile.ashx`MES 系统上传)、`uploadOP.ashx`(工序上传)、`uploadPerson.ashx`(人员上传)等。文件下载使用 `downloadFile.ashx``MESDownloadFile.ashx`。Excel 导出使用 `ExcelDownLoad` 配置指向 `MESCommonBase.ashx`,前端通过 `this.exportExcel_NPOI(param)` 触发下载。图片查看使用 `v-viewer` 插件。
@@ -75,3 +79,6 @@ SVG 图标位于 `src/icons/svg/` 目录,通过 `svg-sprite-loader` 自动注
## GPT/Codex 执行日志 ## GPT/Codex 执行日志
每次 GPT/Codex 执行完成后,将完整的执行过程使用日志追加到 `/gptlog-process/gpdlog.md`,日志使用中文。 每次 GPT/Codex 执行完成后,将完整的执行过程使用日志追加到 `/gptlog-process/gpdlog.md`,日志使用中文。
日志包含提问和结论以及完整的执行过程,写入该文件的日志内容必须使用中文记录。

View File

@@ -15,20 +15,21 @@
5. 优化现有看板数据展示,并新增仓库、采购等业务看板。 5. 优化现有看板数据展示,并新增仓库、采购等业务看板。
6. 增加新订单语音播报能力,提升部门电视机、现场广播等场景下的消息触达效率。 6. 增加新订单语音播报能力,提升部门电视机、现场广播等场景下的消息触达效率。
7. 完善质检 PDA 应急方案,在 PDA 设备故障时使用手机扫码保障生产不中断。 7. 完善质检 PDA 应急方案,在 PDA 设备故障时使用手机扫码保障生产不中断。
8. 三楼仓库可视化界面,直观展示各库位状态及整体仓储情况
## 03-需求一:默认库位设置功能调整 ## 需求一:优化仓储相关业务流程,减少物料维护页面职责过重的问题
### 3.1 需求背景 ### 1 需求背景
当前“设置默认库位”功能位于物料标准维护或物料标准相关页面中,导致物料基础维护页面承载了仓储业务配置职责。为降低页面复杂度,并使库位规则更贴近入库业务,需要将默认库位设置从物料标准维护中移出。 由仓库主管提出.当前“设置默认库位”功能位于物料标准维护或物料标准相关页面中,导致物料基础维护页面承载了仓储业务配置职责。为降低页面复杂度,并使库位规则更贴近入库业务,需要将默认库位设置从物料标准维护中移出,该功能转到由仓库人员决定库位
### 3.2 功能目标 ### 2 功能目标
1. 去除物料标准维护中的“设置默认库位”入口和相关操作。 1. 去除物料标准维护中的“设置默认库位”入口和相关操作。
2. 将默认库位设置功能迁移到其他更合适的仓储组件,或新建“默认库位设置”组件。 2. 将默认库位设置功能迁移到其他更合适的仓储组件,或新建“默认库位设置”组件。
3. 物料入库选择库位时,根据该物料是否存在默认库存或库位库存显示不同的库位范围。 3. 物料入库选择库位时,根据该物料是否存在默认库存或库位库存显示不同的库位范围。
### 3.3 业务规则 ### 3 业务规则
1. 如果物料没有默认库存或没有可识别的默认库位库存,入库时显示全库位选择。 1. 如果物料没有默认库存或没有可识别的默认库位库存,入库时显示全库位选择。
2. 如果物料已有库存库位,入库时优先显示该物料已有库存的库位选择。 2. 如果物料已有库存库位,入库时优先显示该物料已有库存的库位选择。
@@ -36,7 +37,7 @@
4. 新组件需要支持按物料编码、物料名称、图号、规格型号等条件查询物料。 4. 新组件需要支持按物料编码、物料名称、图号、规格型号等条件查询物料。
5. 默认库位设置后,应能被物料入库、库存盘点、库存查询等仓储业务读取。 5. 默认库位设置后,应能被物料入库、库存盘点、库存查询等仓储业务读取。
### 3.4 前端范围 ### 4 前端范围
1. 移除物料标准维护页面中的默认库位设置按钮、弹窗和相关方法。 1. 移除物料标准维护页面中的默认库位设置按钮、弹窗和相关方法。
2. 新增或迁移默认库位设置组件,建议放入仓储管理模块。 2. 新增或迁移默认库位设置组件,建议放入仓储管理模块。
@@ -45,13 +46,31 @@
- 有库存时显示该物料已有库存库位。 - 有库存时显示该物料已有库存库位。
4. 保持 Vue 2 Options API 和 Element UI 原有开发风格。 4. 保持 Vue 2 Options API 和 Element UI 原有开发风格。
### 3.5 后端范围 ### 5 后端范围
1. 梳理现有默认库位相关存储过程、表字段和调用页面。 1. 梳理现有默认库位相关存储过程、表字段和调用页面。
2. 根据新组件补充查询、保存、删除默认库位的接口。 2. 根据新组件补充查询、保存、删除默认库位的接口。
3. 入库库位查询过程需支持按物料返回全库位或已有库存库位。 3. 入库库位查询过程需支持按物料返回全库位或已有库存库位。
### 3.6 验收标准 ### 6 功能实现流程图
```mermaid
flowchart TD
A["开始:调整默认库位设置功能"] --> B["前端移除物料标准维护中的默认库位入口"]
B --> C["新建或迁移默认库位设置组件"]
C --> D["组件提供物料查询和默认库位维护"]
D --> E["调用后端默认库位查询/保存/删除过程"]
E --> F["数据库保存物料与默认库位关系"]
F --> G["物料入库页面选择物料"]
G --> H{"该物料是否已有库存库位"}
H -- "是" --> I["查询并显示该物料已有库存库位"]
H -- "否" --> J["查询并显示全库位或默认库位候选"]
I --> K["用户选择库位并提交入库"]
J --> K
K --> L["刷新入库、库存盘点、库存查询相关数据"]
```
### 7 验收标准
1. 物料标准维护页面不再出现默认库位设置入口。 1. 物料标准维护页面不再出现默认库位设置入口。
2. 新默认库位设置组件可完成查询、设置、修改、删除。 2. 新默认库位设置组件可完成查询、设置、修改、删除。
@@ -59,19 +78,19 @@
4. 物料已有库存库位时,入库页面只显示符合规则的库位。 4. 物料已有库存库位时,入库页面只显示符合规则的库位。
5. 默认库位变更后,相关仓储页面读取结果一致。 5. 默认库位变更后,相关仓储页面读取结果一致。
## 04-需求二:现有查询功能增加物料编码查询 ## 需求二:提升物料查询效率,在现有查询功能中统一补充物料编码查询能力
### 4.1 需求背景 ### 1 需求背景
系统中已有多个物料查询入口,但部分页面只能按物料名称、图号、规格型号等条件查询,无法直接按物料编码定位,影响仓储、销售、技术、装配等场景的查询效率。 由罗伟提出.系统中已有多个物料查询入口,但部分页面只能按物料名称、图号、规格型号等条件查询,无法直接按物料编码定位,影响仓储、销售、技术、装配等场景的查询效率,以及查询准确性
### 4.2 功能目标 ### 2 功能目标
1. 在现有涉及物料查询的组件中新增“物料编码”查询条件。 1. 在现有涉及物料查询的组件中新增“物料编码”查询条件。
2. 物料编码查询需要与原有条件组合查询。 2. 物料编码查询需要与原有条件组合查询。
3. 查询结果、导出结果、选择弹窗结果保持一致。 3. 查询结果、导出结果、选择弹窗结果保持一致。
### 4.3 覆盖范围 ### 3 覆盖范围
优先覆盖以下类型页面: 优先覆盖以下类型页面:
@@ -83,7 +102,7 @@
| 销售管理 | 订单管理、订单审核、订单查询 | 物料选择弹窗 | | 销售管理 | 订单管理、订单审核、订单查询 | 物料选择弹窗 |
| 装配管理 | 接收装配任务、接收滑台装配任务 | 物料选择弹窗 | | 装配管理 | 接收装配任务、接收滑台装配任务 | 物料选择弹窗 |
### 4.4 前端规则 ### 4 前端规则
1. 搜索栏新增 `物料编码` 输入框。 1. 搜索栏新增 `物料编码` 输入框。
2. 输入框 placeholder 可使用“物料编码”或“物料编号”,但传参建议统一使用 `物料编码` 2. 输入框 placeholder 可使用“物料编码”或“物料编号”,但传参建议统一使用 `物料编码`
@@ -91,7 +110,7 @@
4. 导出功能应同步携带物料编码条件。 4. 导出功能应同步携带物料编码条件。
5. 不新增第三方库,不改变现有 `CreateData``ExecDatabase``getTable` 调用模式。 5. 不新增第三方库,不改变现有 `CreateData``ExecDatabase``getTable` 调用模式。
### 4.5 后端规则 ### 5 后端规则
1. 相关查询存储过程增加可选参数: 1. 相关查询存储过程增加可选参数:
- `物料编码_check` - `物料编码_check`
@@ -100,26 +119,44 @@
3. 传入物料编码时,应支持模糊查询或按现场确认规则查询。 3. 传入物料编码时,应支持模糊查询或按现场确认规则查询。
4. 导出过程与页面查询过程保持条件一致。 4. 导出过程与页面查询过程保持条件一致。
### 4.6 验收标准 ### 6 功能实现流程图
```mermaid
flowchart TD
A["开始:现有查询补充物料编码"] --> B["梳理涉及物料查询的页面和弹窗"]
B --> C["搜索栏或弹窗新增物料编码输入框"]
C --> D["查询方法拼接物料编码_check和物料编码参数"]
D --> E["调用原有CreateData/ExecDatabase/getTable流程"]
E --> F["后端查询过程接收物料编码可选参数"]
F --> G{"是否传入物料编码"}
G -- "是" --> H["按物料编码追加过滤条件"]
G -- "否" --> I["沿用原有查询条件"]
H --> J["返回查询结果"]
I --> J
J --> K["表格或物料选择弹窗刷新"]
K --> L["导出流程同步携带相同物料编码条件"]
```
### 7 验收标准
1. 用户可通过物料编码直接查询目标物料。 1. 用户可通过物料编码直接查询目标物料。
2. 物料编码可与物料名称、图号、规格型号等条件组合查询。 2. 物料编码可与物料名称、图号、规格型号等条件组合查询。
3. 查询和导出数据一致。 3. 查询和导出数据一致。
4. 所有改造页面无模板解析错误、无明显布局错位。 4. 所有改造页面无模板解析错误、无明显布局错位。
## 05-需求三:车间派工组件移动端自适应 ## 需求三:改善移动端使用体验,支持车间派工在手机或移动终端上自适应展示和操作
### 5.1 需求背景 ### 1 需求背景
车间派工业务需要在移动设备上查看和操作,当前桌面端布局在手机或窄屏设备上可能存在表格过宽、按钮拥挤、筛选条件不易操作等问题。 由车间主管提出.车间派工业务需要在移动设备上查看和操作,当前桌面端布局在手机或窄屏设备上可能存在表格过宽、按钮拥挤、筛选条件不易操作等问题。
### 5.2 功能目标 ### 2 功能目标
1. 开发车间派工组件的移动端自适应布局。 1. 开发车间派工组件的移动端自适应布局。
2. 保持桌面端原有操作习惯不受影响。 2. 保持桌面端原有操作习惯不受影响。
3. 移动端重点保证查询、查看、派工、确认等高频操作可用。 3. 移动端重点保证查询、查看、派工、确认等高频操作可用。
### 5.3 前端要求 ### 3 前端要求
1. 使用响应式样式适配手机、平板、窄屏电脑。 1. 使用响应式样式适配手机、平板、窄屏电脑。
2. 搜索条件在移动端可折叠或纵向排列。 2. 搜索条件在移动端可折叠或纵向排列。
@@ -128,27 +165,44 @@
5. 弹窗在移动端宽度应适配屏幕,不应超出视口。 5. 弹窗在移动端宽度应适配屏幕,不应超出视口。
6. 不引入 Vue 3、Composition API 或新的 UI 库。 6. 不引入 Vue 3、Composition API 或新的 UI 库。
### 5.4 重点场景 ### 4 重点场景
1. 手机查看待派工任务。 1. 手机查看待派工任务。
2. 手机按订单、物料、工序、人员等条件筛选。 2. 手机按订单、物料、工序、人员等条件筛选。
3. 手机进入派工明细并提交。 3. 手机进入派工明细并提交。
4. 手机查看派工状态、数量、人员、设备等关键字段。 4. 手机查看派工状态、数量、人员、设备等关键字段。
### 5.5 验收标准 ### 5 功能实现流程图
```mermaid
flowchart TD
A["开始:车间派工移动端适配"] --> B["梳理车间派工桌面端页面结构和核心操作"]
B --> C["识别搜索区、列表区、明细区、操作按钮"]
C --> D["增加响应式样式和移动端布局规则"]
D --> E{"当前屏幕宽度是否为移动端"}
E -- "是" --> F["搜索条件纵向排列或折叠展示"]
F --> G["表格转为横向滚动或核心字段卡片列表"]
G --> H["弹窗宽度和按钮点击区域适配手机"]
E -- "否" --> I["保留桌面端原有布局"]
H --> J["调用原有查询、派工、提交接口"]
I --> J
J --> K["按移动端和桌面端分别验证页面与业务操作"]
```
### 6 验收标准
1. 375px、414px、768px、1366px 宽度下页面可正常展示。 1. 375px、414px、768px、1366px 宽度下页面可正常展示。
2. 移动端无关键按钮遮挡、重叠、不可点击问题。 2. 移动端无关键按钮遮挡、重叠、不可点击问题。
3. 桌面端布局保持稳定。 3. 桌面端布局保持稳定。
4. 派工提交、查询、刷新等原有功能正常。 4. 派工提交、查询、刷新等原有功能正常。
## 06-需求四:库存盘点物料系列、库位编辑优化 ## 需求四:完善库存盘点物料系列、库位编辑、入库库位选择等库存基础能力
### 6.1 需求背景 ### 1 需求背景
库存盘点需要更细粒度筛选物料,并支持对盘点库位进行维护。当前盘点和入库库位选择逻辑需要与物料库存库位更紧密关联。 由罗伟提出.库存盘点需要更细粒度筛选物料,并支持对盘点库位进行维护。当前盘点和入库库位选择逻辑需要与物料库存库位更紧密关联。
### 6.2 功能目标 ### 2 功能目标
1. 新增“系列”字段,用于物料筛选和盘点筛选。 1. 新增“系列”字段,用于物料筛选和盘点筛选。
2. 在物料维护组件中支持编辑物料系列。 2. 在物料维护组件中支持编辑物料系列。
@@ -156,14 +210,14 @@
4. 库存盘点组件添加编辑库位功能。 4. 库存盘点组件添加编辑库位功能。
5. 物料入库组件的库位选择只显示有该物料的库位。 5. 物料入库组件的库位选择只显示有该物料的库位。
### 6.3 物料维护要求 ### 3 物料维护要求
1. 物料维护列表展示“系列”字段。 1. 物料维护列表展示“系列”字段。
2. 新增、编辑物料时可维护“系列”。 2. 新增、编辑物料时可维护“系列”。
3. 系列字段建议使用中文字段名 `系列` 3. 系列字段建议使用中文字段名 `系列`
4. 系列可根据现场数据情况使用输入框或下拉框。 4. 系列可根据现场数据情况使用输入框或下拉框。
### 6.4 库存盘点要求 ### 4 库存盘点要求
1. 搜索栏增加“系列”筛选条件。 1. 搜索栏增加“系列”筛选条件。
2. 支持按系列查询物料盘点数据。 2. 支持按系列查询物料盘点数据。
@@ -171,13 +225,13 @@
4. 表格展示需要包含系列字段,便于盘点人员核对。 4. 表格展示需要包含系列字段,便于盘点人员核对。
5. 增加编辑库位功能,可调整物料对应盘点库位。 5. 增加编辑库位功能,可调整物料对应盘点库位。
### 6.5 物料入库要求 ### 5 物料入库要求
1. 入库时选择库位只显示有该物料的库位。 1. 入库时选择库位只显示有该物料的库位。
2. 如果该物料没有任何库存库位,需要结合需求一规则显示全库位或默认库位候选。 2. 如果该物料没有任何库存库位,需要结合需求一规则显示全库位或默认库位候选。
3. 库位下拉数据需要避免显示与该物料无关且容易误选的库位。 3. 库位下拉数据需要避免显示与该物料无关且容易误选的库位。
### 6.6 后端要求 ### 6 后端要求
1. 物料基础表或相关视图增加 `系列` 字段。 1. 物料基础表或相关视图增加 `系列` 字段。
2. 物料维护查询、新增、编辑过程支持系列字段。 2. 物料维护查询、新增、编辑过程支持系列字段。
@@ -185,7 +239,27 @@
4. 库位编辑过程需要记录修改人、修改时间。 4. 库位编辑过程需要记录修改人、修改时间。
5. 入库库位查询过程按物料库存库位过滤。 5. 入库库位查询过程按物料库存库位过滤。
### 6.7 验收标准 ### 7 功能实现流程图
```mermaid
flowchart TD
A["开始:库存盘点和物料系列优化"] --> B["数据库物料基础数据增加系列字段"]
B --> C["物料维护组件新增系列展示和编辑"]
C --> D["保存物料系列到后端"]
D --> E["库存盘点组件搜索栏增加系列筛选"]
E --> F["调用盘点查询过程并传入系列参数"]
F --> G["盘点表格展示物料、库存、系列、库位等信息"]
G --> H["用户编辑盘点库位"]
H --> I["调用库位编辑过程并记录修改人和修改时间"]
I --> J["刷新库存盘点列表"]
J --> K["物料入库选择物料"]
K --> L["按物料查询已有库存库位"]
L --> M{"是否存在该物料库位"}
M -- "是" --> N["入库库位下拉只显示该物料库位"]
M -- "否" --> O["按默认库位规则显示候选库位"]
```
### 8 验收标准
1. 物料维护可新增和编辑系列字段。 1. 物料维护可新增和编辑系列字段。
2. 库存盘点可按系列筛选数据。 2. 库存盘点可按系列筛选数据。
@@ -193,13 +267,13 @@
4. 物料入库库位选择符合“只显示该物料相关库位”的规则。 4. 物料入库库位选择符合“只显示该物料相关库位”的规则。
5. 相关查询、保存后刷新数据一致。 5. 相关查询、保存后刷新数据一致。
## 07-需求五:看板优化 ## 需求五:优化现有看板数据展示,并新增仓库、采购等业务看板
### 7.1 需求背景 ### 1 需求背景
现场看板需要更清晰地展示仓库、采购、订单、库存等业务状态。现有看板需要数据口径优化,同时新增部分业务看板。 由罗总提出,开会讨论得出.现场看板需要更清晰地展示仓库、采购、订单、库存等业务状态。现有看板需要数据口径优化,同时新增部分业务看板。
### 7.2 功能目标 ### 2 功能目标
1. 新增仓库看板组件。 1. 新增仓库看板组件。
2. 新增或优化采购看板组件。 2. 新增或优化采购看板组件。
@@ -207,7 +281,7 @@
4. 仓库看板展示入库单滚动信息。 4. 仓库看板展示入库单滚动信息。
5. 采购看板展示仍在采购中的合同。 5. 采购看板展示仍在采购中的合同。
### 7.3 仓库看板要求 ### 3 仓库看板要求
1. 展示入库单滚动列表。 1. 展示入库单滚动列表。
2. 滚动内容建议包括入库单号、供应商、物料名称、物料编码、数量、入库日期、状态。 2. 滚动内容建议包括入库单号、供应商、物料名称、物料编码、数量、入库日期、状态。
@@ -215,21 +289,40 @@
4. 大屏展示时文字清晰,不出现字段重叠。 4. 大屏展示时文字清晰,不出现字段重叠。
5. 支持异常状态突出显示,例如待处理、待上架、未完成。 5. 支持异常状态突出显示,例如待处理、待上架、未完成。
### 7.4 采购看板要求 ### 4 采购看板要求
1. 展示仍在采购中的合同。 1. 展示仍在采购中的合同。
2. 合同状态口径需要明确,例如未完成、采购中、部分到货、逾期未到。 2. 合同状态口径需要明确,例如未完成、采购中、部分到货、逾期未到。
3. 建议展示合同号、供应商、物料、数量、已到数量、未到数量、交期、状态。 3. 建议展示合同号、供应商、物料、数量、已到数量、未到数量、交期、状态。
4. 对逾期或临近交期的数据进行醒目提示。 4. 对逾期或临近交期的数据进行醒目提示。
### 7.5 现有看板优化要求 ### 5 现有看板优化要求
1. 梳理现有看板数据来源和字段含义。 1. 梳理现有看板数据来源和字段含义。
2. 对不准确、不及时或口径不一致的数据进行调整。 2. 对不准确、不及时或口径不一致的数据进行调整。
3. 保持大屏自适应显示效果。 3. 保持大屏自适应显示效果。
4. 对滚动、刷新、排序、状态颜色做统一规范。 4. 对滚动、刷新、排序、状态颜色做统一规范。
### 7.6 验收标准 ### 6 功能实现流程图
```mermaid
flowchart TD
A["开始:看板新增与优化"] --> B["梳理现有看板组件和数据接口"]
B --> C["确认仓库看板、采购看板、现有看板数据口径"]
C --> D["新增仓库看板组件"]
C --> E["新增或优化采购看板组件"]
C --> F["调整现有看板数据查询逻辑"]
D --> G["查询入库单数据并生成滚动列表"]
E --> H["查询采购中的合同和交期状态"]
F --> I["统一字段、排序、状态颜色、刷新频率"]
G --> J["大屏页面自动滚动展示"]
H --> J
I --> J
J --> K["按刷新频率重新拉取数据"]
K --> L["验证大屏分辨率、滚动、刷新和数据准确性"]
```
### 7 验收标准
1. 仓库看板可滚动展示入库单数据。 1. 仓库看板可滚动展示入库单数据。
2. 采购看板可展示采购中的合同。 2. 采购看板可展示采购中的合同。
@@ -237,27 +330,27 @@
4. 大屏展示无明显错位、遮挡、空白异常。 4. 大屏展示无明显错位、遮挡、空白异常。
5. 自动刷新不影响页面稳定性。 5. 自动刷新不影响页面稳定性。
## 08-需求六:语音播报 ## 需求六:增加新订单语音播报能力,提升部门电视机、现场广播等场景下的消息触达效率
### 8.1 需求背景 ### 1 需求背景
当系统产生新的订单或重要业务消息时,需要在部门电视机或全场广播中自动播报,类似商家外卖新订单语音提醒,减少人工盯屏和漏看消息。 由罗总提出,开会讨论的出.当系统产生新的订单或重要业务消息时,需要在部门电视机或全场广播中自动播报,类似商家外卖新订单语音提醒,减少人工盯屏和漏看消息。
### 8.2 功能目标 ### 2 功能目标
1. 新订单产生时触发语音播报。 1. 新订单产生时触发语音播报。
2. 支持部门电视机播报或全场广播播报。 2. 支持部门电视机播报或全场广播播报。
3. 播报内容简洁明确,便于现场人员快速理解。 3. 播报内容简洁明确,便于现场人员快速理解。
4. 后续可扩展到采购到货、异常提醒、质检任务等事件。 4. 后续可扩展到采购到货、异常提醒、质检任务等事件。
### 8.3 播报场景 ### 3 播报场景
1. 新订单生成。 1. 新订单生成。
2. 新订单分配到指定部门。 2. 新订单分配到指定部门。
3. 订单状态发生关键变化。 3. 订单状态发生关键变化。
4. 后续可扩展为库存预警、采购逾期、质检待处理等。 4. 后续可扩展为库存预警、采购逾期、质检待处理等。
### 8.4 播报内容建议 ### 4 播报内容建议
新订单播报示例: 新订单播报示例:
@@ -271,7 +364,7 @@
技术中心有新的图纸确认任务,请及时处理。 技术中心有新的图纸确认任务,请及时处理。
``` ```
### 8.5 技术要求 ### 5 技术要求
1. 前端可使用浏览器语音能力或播放预生成音频。 1. 前端可使用浏览器语音能力或播放预生成音频。
2. 如果用于电视机浏览器,需要确认浏览器是否允许自动播放声音。 2. 如果用于电视机浏览器,需要确认浏览器是否允许自动播放声音。
@@ -279,14 +372,33 @@
4. 新消息检测可采用轮询、WebSocket 或已有消息接口。 4. 新消息检测可采用轮询、WebSocket 或已有消息接口。
5. 需要增加播报开关、播报范围、播报频率、防重复播报规则。 5. 需要增加播报开关、播报范围、播报频率、防重复播报规则。
### 8.6 权限和配置 ### 6 权限和配置
1. 管理员可配置是否启用语音播报。 1. 管理员可配置是否启用语音播报。
2. 可按部门配置播报内容和播报设备。 2. 可按部门配置播报内容和播报设备。
3. 同一订单不应重复无限播报。 3. 同一订单不应重复无限播报。
4. 需要记录已播报状态或播报日志,便于追查。 4. 需要记录已播报状态或播报日志,便于追查。
### 8.7 验收标准 ### 7 功能实现流程图
```mermaid
flowchart TD
A["开始:语音播报功能"] --> B["配置播报开关、部门范围、播报终端"]
B --> C["前端看板或播报终端启动消息监听"]
C --> D["通过轮询、WebSocket或消息接口检测新订单"]
D --> E{"是否存在未播报的新订单"}
E -- "否" --> C
E -- "是" --> F["生成播报文本"]
F --> G{"当前终端是否允许播放声音"}
G -- "是" --> H["调用浏览器语音或播放音频"]
G -- "否" --> I["提示用户激活播放权限或使用客户端方案"]
H --> J["回写已播报状态或记录播报日志"]
I --> J
J --> K["防止同一订单重复播报"]
K --> C
```
### 8 验收标准
1. 新订单出现后,指定终端可听到语音播报。 1. 新订单出现后,指定终端可听到语音播报。
2. 同一订单不会被重复播报造成干扰。 2. 同一订单不会被重复播报造成干扰。
@@ -294,19 +406,19 @@
4. 部门播报和全场播报范围符合配置。 4. 部门播报和全场播报范围符合配置。
5. 电视机或广播设备在生产环境中可稳定使用。 5. 电视机或广播设备在生产环境中可稳定使用。
## 09-需求七:质检 PDA 手机扫码应急功能 ## 需求七:完善质检 PDA 应急方案,在 PDA 设备故障时使用手机扫码保障生产不中断
### 9.1 需求背景 ### 1 需求背景
质检 PDA 已有扫码作业能力,但在 PDA 设备故障时,需要使用手机应急完成扫码和质检相关工作。当前功能已开发完成,但生产环境下由于扫码组件安全限制无法使用。 由质检部门提出,梁宁超核实后上报需求.质检 PDA 已有扫码作业能力,但在 PDA 设备故障时,需要使用手机应急完成扫码和质检相关工作。当前功能已开发完成,但生产环境下由于扫码组件安全限制无法使用。
### 9.2 功能目标 ### 2 功能目标
1. 确保手机扫码功能在生产环境可正常使用。 1. 确保手机扫码功能在生产环境可正常使用。
2. 在 PDA 故障时,手机可以临时替代 PDA 进行扫码质检作业。 2. 在 PDA 故障时,手机可以临时替代 PDA 进行扫码质检作业。
3. 解决扫码组件在生产环境下的安全限制问题。 3. 解决扫码组件在生产环境下的安全限制问题。
### 9.3 问题说明 ### 3 问题说明
扫码组件通常依赖浏览器摄像头权限。生产环境可能存在以下限制: 扫码组件通常依赖浏览器摄像头权限。生产环境可能存在以下限制:
@@ -316,7 +428,7 @@
4. 扫码组件要求安全上下文HTTP 环境不可用。 4. 扫码组件要求安全上下文HTTP 环境不可用。
5. 内嵌浏览器或企业微信、钉钉 WebView 权限策略不同。 5. 内嵌浏览器或企业微信、钉钉 WebView 权限策略不同。
### 9.4 解决方向 ### 4 解决方向
1. 将生产环境扫码页面部署到 HTTPS。 1. 将生产环境扫码页面部署到 HTTPS。
2. 配置可信域名和证书,避免直接使用不安全 HTTP 地址调用摄像头。 2. 配置可信域名和证书,避免直接使用不安全 HTTP 地址调用摄像头。
@@ -324,7 +436,7 @@
4. 针对手机浏览器、企业微信、钉钉等访问方式分别验证摄像头权限。 4. 针对手机浏览器、企业微信、钉钉等访问方式分别验证摄像头权限。
5. 保留手工输入条码的兜底方案,避免扫码不可用时业务中断。 5. 保留手工输入条码的兜底方案,避免扫码不可用时业务中断。
### 9.5 功能要求 ### 5 功能要求
1. 手机页面可打开摄像头并扫码。 1. 手机页面可打开摄像头并扫码。
2. 扫码结果可回填到质检业务流程。 2. 扫码结果可回填到质检业务流程。
@@ -332,7 +444,27 @@
4. 页面需要适配手机端显示。 4. 页面需要适配手机端显示。
5. 扫码权限异常时给出明确提示,例如“请使用 HTTPS 地址访问”或“请允许摄像头权限”。 5. 扫码权限异常时给出明确提示,例如“请使用 HTTPS 地址访问”或“请允许摄像头权限”。
### 9.6 验收标准 ### 6 功能实现流程图
```mermaid
flowchart TD
A["开始质检PDA手机扫码应急"] --> B["用户使用手机打开质检扫码页面"]
B --> C{"访问环境是否为HTTPS或安全上下文"}
C -- "否" --> D["提示使用HTTPS地址或可信访问方式"]
C -- "是" --> E["请求摄像头权限"]
E --> F{"用户是否授权摄像头"}
F -- "否" --> G["提示开启摄像头权限并提供手动输入"]
F -- "是" --> H["启动扫码组件识别条码"]
H --> I{"是否扫码成功"}
I -- "否" --> G
I -- "是" --> J["扫码结果回填质检业务单据"]
G --> K["手动输入条码"]
J --> L["调用原有质检业务查询或提交接口"]
K --> L
L --> M["完成质检应急作业并保留PDA原有流程"]
```
### 7 验收标准
1. 生产环境手机扫码可正常调用摄像头。 1. 生产环境手机扫码可正常调用摄像头。
2. 扫码后可完成质检业务操作。 2. 扫码后可完成质检业务操作。
@@ -340,19 +472,103 @@
4. 摄像头权限失败时有明确提示和手动输入兜底。 4. 摄像头权限失败时有明确提示和手动输入兜底。
5. 不影响 PDA 原有扫码功能。 5. 不影响 PDA 原有扫码功能。
## 10-优先级建议 ## 需求八:三楼仓库可视化界面,直观展示各库位状态及整体仓储情况
### 1 需求背景
由仓库管理提出.三楼仓库目前缺少直观的库位可视化展示能力,仓库人员无法快速了解各库位使用状态、物料分布和整体仓储情况。现有立库查询界面已具备 2D 网格矩阵可视化能力(巷道筛选、状态颜色标识、库位点击查看物料详情、统计面板),可参考该方案为三楼仓库开发类似的可视化界面。
### 2 功能目标
1. 新增三楼仓库可视化组件,直观展示三楼仓库各库位的实时状态。
2. 展示三楼仓库整体统计信息,包括总库位数、已占用库位数、空闲库位数、使用率等。
3. 支持按区域、库位类型、物料等条件筛选库位。
4. 支持点击库位查看物料详情,包括物料编号、物料名称、图号、规格型号、库存数量等。
5. 参考立库可视化界面的颜色标识方案,用不同颜色区分库位状态。
### 3 界面参考
参考现有立库可视化界面(`WarehouseVisualization` 组件)的设计模式:
1. **统计面板**:顶部展示总库位数、已占用数、空闲数、使用率等关键指标,参考立库的 `el-row` + `el-col` 卡片布局。
2. **颜色图例**:用不同颜色标识库位状态,参考立库的颜色方案:
- 绿色:有库存(对应立库"有物料有托盘"
- 橙色/黄色:预占或待处理
- 灰色:空闲库位
- 红色:异常或禁用
3. **库位矩阵**:以网格或表格形式展示库位分布,行列对应仓库物理位置。
4. **库位详情弹窗**:点击库位后弹窗展示物料明细,参考立库的 `el-dialog` 详情弹窗。
5. **筛选条件**:支持按区域、库位编号、物料编码等条件筛选。
### 4 前端要求
1. 新增三楼仓库可视化页面,建议放在仓储管理模块下,路径如 `src/views/WarehouseManagement/ThirdFloorWarehouse/`
2. 参考立库可视化组件的页面结构:统计卡片 + 图例 + 库位网格矩阵 + 详情弹窗。
3. 使用 Vue 2 Options API + Element UI保持与现有代码风格一致。
4. 库位网格支持点击交互,点击后弹出物料详情。
5. 支持区域切换或筛选,适配三楼仓库的物理布局(如多个区域或排)。
6. 统计数据实时计算,支持手动刷新和自动刷新(刷新频率可配置)。
7. 适配大屏展示,文字清晰、布局不拥挤。
8. 不引入新的第三方库,不使用 Vue 3 或 Composition API。
### 5 后端要求
1. 新增三楼仓库库位数据查询接口,返回库位编号、库位状态、所在区域等信息。
2. 新增三楼仓库库位物料详情查询接口,根据库位编号返回物料信息(物料编号、物料名称、图号、规格型号、库存数量、批次等)。
3. 接口命名遵循现有规范(如 `仓储管理_三楼仓库库位_查询数据`)。
4. 如果三楼仓库库位数据已有现成的查询过程,优先复用,必要时补充字段。
5. 统计数据可由前端根据库位列表计算,也可由后端单独提供汇总接口。
### 6 功能实现流程图
```mermaid
flowchart TD
A["开始:三楼仓库可视化界面"] --> B["梳理三楼仓库库位数据和物理布局"]
B --> C["后端新增或复用库位查询和物料详情接口"]
C --> D["前端新增三楼仓库可视化页面组件"]
D --> E["页面加载时调用库位查询接口获取全部库位数据"]
E --> F["根据库位数据生成网格矩阵并按状态着色"]
F --> G["顶部展示统计面板:总库位、已占用、空闲、使用率"]
G --> H["用户点击某个库位"]
H --> I{"库位是否有物料"}
I -- "是" --> J["弹出物料详情弹窗:物料编号、名称、图号、型号、数量等"]
I -- "否" --> K["弹出库位信息弹窗:库位编号、状态、区域"]
J --> L["用户关闭弹窗或继续操作"]
K --> L
L --> M{"是否切换区域或筛选条件"}
M -- "是" --> N["按筛选条件重新查询库位数据"]
N --> F
M -- "否" --> O{"是否手动刷新或自动刷新触发"}
O -- "是" --> E
O -- "否" --> L
```
### 7 验收标准
1. 三楼仓库可视化页面可正常加载并展示所有库位。
2. 不同状态的库位用不同颜色区分,图例说明清晰。
3. 统计面板数据与实际库位状态一致。
4. 点击有物料的库位可查看物料详情。
5. 点击空闲库位可查看库位基本信息。
6. 区域筛选和条件筛选功能正常。
7. 刷新数据后页面状态更新正确。
8. 大屏展示布局合理,文字清晰可读。
9. 不影响现有立库可视化功能。
## 03-优先级建议
| 优先级 | 需求 | 原因 | | 优先级 | 需求 | 原因 |
| --- | --------------- | ------------------ | | --- | --------------- | ----------------------------------------- |
| P2 | 质检 PDA 手机扫码应急功能 | 已开发但生产不可用,影响故障应急能力 | | P2 | 质检 PDA 手机扫码应急功能 | 已开发但生产不可用,影响故障应急能力,即使PDA设备故障也可手动输入不影响现场生产 |
| P0 | 库存盘点及入库库位选择优化 | 直接影响库存准确性和入库操作 | | P0 | 库存盘点及入库库位选择优化 | 直接影响库存准确性和入库操作,现场急要 |
| P0 | 默认库位设置功能调整 | 影响仓储配置职责和入库库位逻辑 | | P0 | 默认库位设置功能调整 | 影响仓储配置职责和入库库位逻辑,现场急要 |
| P0 | 物料编码查询 | 涉及页面多,但收益明确 | | P0 | 物料编码查询 | 涉及页面多,但收益明确,现场急要 |
| P1 | 车间派工移动端适配 | 改善现场移动操作效率 | | P1 | 三楼仓库可视化界面 | 参考立库已有方案,可快速实现,提升仓库管理直观性 |
| P2 | 看板优化 | 影响现场展示和管理效率 | | P1 | 车间派工移动端适配 | 改善现场移动操作效率,现场提出,未经过确认需要 |
| P2 | 语音播报 | 需要确认硬件、浏览器和广播接入方案 | | P2 | 看板优化 | 影响现场展示和管理效率,需求还不明确 |
| P2 | 语音播报 | 需要确认硬件、浏览器和广播接入方案,需求还不明确 |
## 11-实施拆分建议 ## 04-实施拆分建议
### 第一阶段:库存与查询基础能力 ### 第一阶段:库存与查询基础能力
@@ -360,6 +576,7 @@
2. 物料编码查询补充。 2. 物料编码查询补充。
3. 物料系列字段和库存盘点筛选。 3. 物料系列字段和库存盘点筛选。
4. 物料入库库位过滤。 4. 物料入库库位过滤。
5. 三楼仓库可视化界面(参考立库可视化组件)。
### 第二阶段:移动端与应急能力 ### 第二阶段:移动端与应急能力
@@ -373,7 +590,7 @@
3. 现有看板数据口径调整。 3. 现有看板数据口径调整。
4. 新订单语音播报试点。 4. 新订单语音播报试点。
## 12-待确认事项 ## 05-待确认事项
1. 默认库位设置新组件归属菜单:仓储管理、基础数据,或单独配置模块。 1. 默认库位设置新组件归属菜单:仓储管理、基础数据,或单独配置模块。
2. “没有默认库存”与“没有库存库位”的业务定义是否一致。 2. “没有默认库存”与“没有库存库位”的业务定义是否一致。
@@ -384,8 +601,11 @@
7. 语音播报使用电视机网页播放,还是接入全场广播硬件。 7. 语音播报使用电视机网页播放,还是接入全场广播硬件。
8. 手机扫码生产环境访问方式HTTPS 域名、内网 IP、企业微信、钉钉或普通浏览器。 8. 手机扫码生产环境访问方式HTTPS 域名、内网 IP、企业微信、钉钉或普通浏览器。
9. 语音播报和扫码功能是否需要新增系统配置表。 9. 语音播报和扫码功能是否需要新增系统配置表。
10. 三楼仓库的物理布局和库位编码规则(区域划分、行列定义)。
11. 三楼仓库库位状态分类是否与立库一致,还是需要单独定义(如是否有"预占"、"异常"等状态)。
12. 三楼仓库可视化是否需要自动刷新,刷新频率多少。
## 13-风险说明 ## 06-风险说明
1. 默认库位、库存库位、入库库位逻辑如果口径不统一,可能导致入库误选库位。 1. 默认库位、库存库位、入库库位逻辑如果口径不统一,可能导致入库误选库位。
2. 物料编码查询涉及页面多,需要避免漏改导出和弹窗查询。 2. 物料编码查询涉及页面多,需要避免漏改导出和弹窗查询。
@@ -393,9 +613,18 @@
4. 看板数据口径需与业务部门确认,否则容易出现“页面正确但业务理解不一致”的问题。 4. 看板数据口径需与业务部门确认,否则容易出现“页面正确但业务理解不一致”的问题。
5. 浏览器语音自动播放和摄像头扫码都受 HTTPS、安全策略、设备权限影响必须在生产环境实测。 5. 浏览器语音自动播放和摄像头扫码都受 HTTPS、安全策略、设备权限影响必须在生产环境实测。
6. 全场广播接入可能涉及硬件、网络、音频设备,不应只按前端功能估算工作量。 6. 全场广播接入可能涉及硬件、网络、音频设备,不应只按前端功能估算工作量。
7. 三楼仓库库位数据如果与立库数据结构差异较大,可能需要单独设计接口和前端组件,复用程度需评估。
## 14-文档备注 ## 07-文档备注
本次变更为新增需求文档,未修改业务代码。 本次变更为新增需求文档,未修改业务代码。
修改人:Ld 修改时间:2026-06-29 10:29:16 修改人:Ld 修改时间:2026-06-29 10:29:16
补充内容:为 7 项需求分别增加功能实现流程图。
修改人:Ld 修改时间:2026-06-29 14:24:36
补充内容:新增需求八"三楼仓库可视化界面",参考立库查询界面设计,优先级 P1纳入第一阶段实施。同步更新优先级建议、实施拆分、待确认事项和风险说明。
修改人:Ld 修改时间:2026-06-30

View File

@@ -0,0 +1,919 @@
# 三楼仓库可视化界面设计方案
## 一、背景
由仓库管理提出,三楼仓库目前缺少直观的库位可视化展示能力,仓库人员无法快速了解各库位使用状态、物料分布和整体仓储情况。现有立库查询界面已具备 2D 网格矩阵可视化能力(巷道筛选、状态颜色标识、库位点击查看物料详情、统计面板),可参考该方案为三楼仓库开发类似的可视化界面。
当前仓库人员判断库位使用情况主要依赖库位管理页面(`LocationManagement`)逐条查询和物料库位页面(`MaterialLocation`)按物料查阅,缺少全局视角的库位状态总览。在盘点、出入库规划、空间利用率评估等场景下,仓库人员需要一屏总览仓库所有库位状态和物料分布,便于快速定位目标库位和发现异常。
本次需求优先级为 P1纳入第一阶段实施。
<br/>
## 二、现状核对
### 2.1 已有立库可视化组件
主组件文件:
- `src/views/WarehouseManagement/WarehouseVisualization/index.vue`
- 组件名:`WarehouseVisualizationSystem`
已实现功能:
- 按 4 个巷道加载立库数据,接口名为 `GetPositionView`
- 库位矩阵用原生 HTML `<table>` 绘制
- 4 种库位状态0=空库位、1=有托盘无物料、2=有物料有托盘、9=锁库
- 统计信息卡片:总库位数、有物料有托盘数、有托盘无物料数、空闲库位数、使用率、数据行数
- 支持按行-层筛选、分页显示
- 点击状态为 2 的库位调用 `StockDetail(rowLayer, column)` 查询 `StockDetailView` 获取物料明细
- 点击非 2 状态库位弹出库位详情弹窗
- 支持文字/图标两种显示模式切换
- 使用独立的立库数据库服务入口(`ExecDatabase1`,走 `config.js` 中的 `url1`
辅助组件文件:
- `src/views/WarehouseVisualization/index.vue`
- 组件名:`WarehouseVisualization`
- 纯展示组件,通过 `props` 接收 `warehouseData`
### 2.2 已有仓储数据页面
| 页面 | 路径 | 功能 |
| --- | --- | --- |
| 库位管理 | `WarehouseManagement/LocationManagement/index.vue` | 库位增删改查,接口 `仓储管理_库位_查询` |
| 物料库位 | `WarehouseManagement/MaterialLocation/index.vue` | 按物料查库位,接口 `仓储管理_物料库位_查询数据` |
| 库存查询 | `WarehouseManagement/InventoryQuery/index.vue` | 库存汇总查询,接口 `仓储管理_库存查询_查询` |
| 库存盘点 | `WarehouseManagement/InventoryCheck/index.vue` | 盘点数据查询 |
| 仓储汇总 | `WarehouseManagement/WarehouseSummary/index.vue` | 看板式统计汇总 |
### 2.3 接口调用模式
仓储管理模块所有页面的 API 调用均内联在 `.vue` 组件中,通过 `this.CreateData()` + `this.ExecDatabase()` 构造请求参数并调用后端,无独立 API 文件。接口命名遵循 `模块_子模块_操作` 格式。
立库可视化走独立的 `ExecDatabase1`(连接立库数据库 `url1`),三楼仓库数据走主业务数据库(`ExecDatabase`),两者数据源不同。
### 2.4 数据差异
| 对比项 | 立库 | 三楼仓库 |
| --- | --- | --- |
| 数据服务 | 独立志库数据库(`url1:10006` | 主业务数据库(`url:8030` |
| 库位编码 | 行-列-层 三段式(如 `03-12-01` | 待确认(需求文档待确认事项第 10 条) |
| 调用方法 | `ExecDatabase1` | `ExecDatabase` |
| 库位状态 | 0=空、1=有盘无物、2=有物有盘、9=锁 | 待确认(需求文档待确认事项第 11 条) |
| 物理布局 | 巷道-行-列-层 四维结构 | 待确认(需求文档待确认事项第 10 条) |
## 三、设计原则
1. 参考立库可视化组件的页面结构和交互模式(统计卡片 + 图例 + 库位网格矩阵 + 详情弹窗),复用成熟的交互设计,降低用户学习成本。
2. 三楼仓库数据走主业务数据库(`ExecDatabase`),不走立库独立服务(`ExecDatabase1`),与库位管理、物料库位、库存盘点等仓储页面使用同一数据源。
3. 接口命名遵循项目现有规范(如 `仓储管理_三楼仓库库位_查询数据`)。
4. 使用 Vue 2 Options API + Element UI保持与现有代码风格一致。
5. 不引入新的第三方库,不使用 Vue 3 或 Composition API。
6. 样式与立库可视化保持一致的设计语言(颜色方案、卡片风格、单元格交互),但库位布局和状态分类根据三楼仓库实际业务定义。
7. 库位数据查询和物料详情查询走标准后端接口名,前端不直接拼 SQL与立库组件中 `StockDetail` 直接构造 SQL 的做法不同,降低前后端耦合。
<br/>
## 四、前端页面结构设计
### 4.1 页面总览
新增三楼仓库可视化页面,路径:`src/views/WarehouseManagement/ThirdFloorWarehouse/index.vue`
页面整体采用标准的 `div.app-container > el-card` 布局,主体包含以下区域:
1. 顶部筛选与操作区
2. 统计信息卡片区
3. 状态图例区
4. 三楼仓库库位网格矩阵区
5. 分页区
6. 库位详情弹窗
7. 物料信息弹窗
### 4.2 顶部筛选与操作区
参考立库可视化的筛选区布局,但筛选维度调整为三楼仓库的实际布局维度。
#### 4.2.1 区域筛选
控件类型:`el-select`
用途:三楼仓库按物理区域划分(如 A 区、B 区、C 区等,具体区域名称需现场确认)。
数据来源:页面初始化时从库位数据中自动提取去重,或后端返回区域字典。
选项生成规则:
- 从库位查询结果中提取 `区域` 字段
- 自动去重
- 按区域编码或名称排序
#### 4.2.2 库位类型筛选
控件类型:`el-select`
可选项(具体需现场确认):
- 全部
- 有库存
- 空闲
- 预占/待处理
- 异常/禁用
用途:按库位状态快速筛选关注类别的库位。
#### 4.2.3 库位编号搜索
控件类型:`el-input`
用途:直接输入库位编号定位到对应库位。
交互:
- 输入库位编号后,点击搜索,矩阵中匹配的库位高亮显示
- 支持模糊匹配
#### 4.2.4 操作按钮
| 按钮 | 类型 | 作用 |
| --- | --- | --- |
| 搜索 | `el-button type="primary"` | 按筛选条件重新查询库位数据 |
| 重置 | `el-button type="default"` | 清空所有筛选条件,恢复全局视图 |
| 刷新数据 | `el-button type="success"` | 重新调用后端接口获取最新数据 |
| 自动刷新开关 | `el-switch` | 控制定时自动刷新(默认关闭) |
#### 4.2.5 显示模式切换
控件类型:`el-switch`
两种模式:
- 显示文字:每个库位格显示状态简称(如 `存``空``预``异`
- 显示图标:每个库位格显示对应 Element UI 图标
### 4.3 统计信息卡片区
参考立库可视化的 `el-row + el-col` 卡片布局,展示以下 6 项指标:
| 序号 | 统计项 | 计算方式 | 颜色 |
| --- | --- | --- | --- |
| 1 | 总库位数 | 当前加载的库位总数 | `#303133` |
| 2 | 有库存 | 状态为"有库存"的库位数 | `#4caf50`(绿色) |
| 3 | 预占/待处理 | 状态为"预占"的库位数 | `#ff9800`(橙色) |
| 4 | 空闲库位 | 状态为"空闲"的库位数 | `#e0e0e0`(灰色) |
| 5 | 异常/禁用 | 状态为"异常"的库位数 | `#f56c6c`(红色) |
| 6 | 使用率 | `(有库存 + 预占) / 总库位数 * 100%` | `#2196f3`(蓝色) |
布局:`el-row :gutter="10"`,每项占 `el-col :span="4"`
统计计算方式:
- 前端根据库位列表数据实时计算
- 支持筛选后重新统计(筛选后统计数字反映当前筛选结果)
### 4.4 状态图例区
参考立库可视化图例,居中展示库位状态颜色含义:
| 颜色 | 含义 | 文字简称 | 图标 |
| --- | --- | --- | --- |
| 绿色 `#4caf50` | 有库存 | 存 | `el-icon-box` |
| 橙色 `#ff9800` | 预占或待处理 | 预 | `el-icon-time` |
| 灰色 `#e0e0e0` | 空闲库位 | 空 | `el-icon-minus` |
| 红色 `#f56c6c` | 异常或禁用 | 异 | `el-icon-warning` |
| 蓝色边框 `#2196f3` | 当前选中库位 | — | — |
说明:
- 具体状态分类需与仓库现场确认(待确认事项第 11 条)
- 如果三楼仓库不需要"预占"和"异常"状态,可简化为三种状态(有库存、空闲、选中)
- 如果三楼仓库与立库状态分类一致,可直接复用立库的 4 状态方案0=空、1=盘无物、2=物有盘、9=锁),但建议重新命名以贴合三楼仓库业务
### 4.5 库位网格矩阵区
参考立库可视化组件使用原生 `<table>` 绘制矩阵的方案。
#### 4.5.1 矩阵布局
三楼仓库的物理布局需现场确认(待确认事项第 10 条),本设计按以下原则适配:
- 如果三楼仓库按"排-列"二维布局:每行对应一排,每列对应一个列号
- 如果三楼仓库按"区域-排-列"三维布局:区域通过顶部筛选切换,每个区域内按"排-列"二维展示
- 如果三楼仓库按不规则布局:可按库位编号分组展示,或按物理位置映射到网格
矩阵结构:
```html
<table class="warehouse-table">
<thead>
<tr>
<th class="row-header">排/行号</th>
<th v-for="col in columnCount" :key="col" class="column-header">{{ col }}</th>
</tr>
</thead>
<tbody>
<tr v-for="(row, rowIndex) in displayedLocationData" :key="rowIndex">
<td class="row-label-cell">{{ row['行标识'] }}</td>
<td v-for="col in columnKeys" :key="col"
:class="['status-' + row[col].状态, { 'selected-cell': isSelected(row['行标识'], col) }]"
class="location-cell"
@click="selectLocation(row['行标识'], col, row[col])"
@mouseenter="onCellHover(row['行标识'], col, row[col])"
@mouseleave="onCellLeave">
<div class="cell-content">
<span v-if="showCellText === 'text'" class="cell-text">{{ getStatusText(row[col].状态) }}</span>
<span v-else class="cell-icon"><i :class="getStatusIcon(row[col].状态)"></i></span>
<div v-if="isHoveredCell(row['行标识'], col)" class="cell-tooltip">
{{ getStatusDescription(row[col].状态) }}
</div>
</div>
</td>
</tr>
</tbody>
</table>
```
#### 4.5.2 单元格数据结构
每个库位单元格的数据结构建议如下:
```javascript
{
'行标识': 'A-01', // 行/排标识
1: { // 列号对应的库位信息
库位编号: 'A-01-01',
库位名称: 'A-01-01',
状态: 0, // 0=空闲, 1=预占, 2=有库存, 3=异常
区域: 'A区'
},
2: {
库位编号: 'A-01-02',
库位名称: 'A-01-02',
状态: 2,
区域: 'A区'
}
// ...
}
```
说明:
- 矩阵数据结构参考立库 `warehouseData` 的组织方式(行标识 + 列号映射),但每个单元格从简单状态值扩展为包含 `库位编号``库位名称``状态``区域` 的对象
- 与立库组件中单元格仅存储状态数字值(`0/1/2/9`)相比,三楼仓库单元格存储更丰富的信息,便于点击时直接获取库位编号查询物料明细
#### 4.5.3 单元格交互效果
参考立库可视化组件的交互设计:
- 鼠标悬停:单元格放大(`transform: scale(1.1)`)并显示状态说明浮层
- 点击选中:蓝色边框高亮选中库位
- 选中后高亮当前行和列
### 4.6 分页区
参考立库分页方案,当库位行数较多时支持分页显示:
- 分页针对"行数据",不是单元格
- 每页可选条数:`5``8``10``15`
- 布局:`total, sizes, prev, pager, next, jumper`
### 4.7 库位详情弹窗
点击非"有库存"状态的库位时弹出,参考立库的库位详情弹窗但信息更丰富。
弹窗标题:`库位详情 - {库位编号}`
弹窗内容(使用 `el-descriptions` 组件):
| 字段 | 数据来源 | 说明 |
| --- | --- | --- |
| 库位编号 | 行数据 | 当前点击的库位编号 |
| 库位名称 | 行数据 | 库位显示名称 |
| 区域 | 行数据 | 所属区域 |
| 当前状态 | 行数据 | 状态中文说明 |
| 状态描述 | 前端映射 | 状态对应的业务说明 |
| 最后更新时间 | 后端接口 | 该库位最近一次库存变动时间(需后端支持) |
弹窗底部操作按钮:
| 按钮 | 作用 |
| --- | --- |
| 关闭 | 关闭弹窗 |
### 4.8 物料信息弹窗
点击"有库存"状态的库位时弹出,参考立库的物料信息弹窗。
弹窗标题:`库位物料信息 - {库位编号}`
弹窗内容(使用 `el-table` 组件):
| 列名 | 字段 | 宽度 | 说明 |
| --- | --- | --- | --- |
| 物料编号 | `物料编号` | 150 | 显示溢出省略 |
| 物料名称 | `物料名称` | 120 | 显示溢出省略 |
| 图号 | `图号` | 150 | 显示溢出省略 |
| 规格型号 | `规格型号` | 150 | 显示溢出省略 |
| 库存数量 | `库存数量` | 100 | 右对齐,大于 0 绿色、等于 0 红色,保留 3 位小数,下方显示单位 |
| 批次 | `批次` | 120 | 显示溢出省略 |
弹窗底部操作按钮:
| 按钮 | 作用 |
| --- | --- |
| 关闭 | 关闭弹窗 |
数据来源:调用后端接口 `仓储管理_三楼仓库库位物料_查询数据`,传入库位编号。
### 4.9 自动刷新
仓储汇总看板(`WarehouseSummary`)已有 1 分钟定时刷新的先例。三楼仓库可视化支持可选的自动刷新:
- 默认关闭,通过顶部 `el-switch` 开启
- 刷新频率可选30 秒、1 分钟、5 分钟
- 刷新时调用与初始加载相同的后端接口重新查询
- 刷新期间显示 `v-loading` 加载动画
- 刷新期间不阻断用户操作
<br/>
## 五、后端接口设计
### 5.1 库位数据查询接口
接口名:`仓储管理_三楼仓库库位_查询数据`
请求类型:`type = '1'`(查询)
请求参数:
| 参数名 | 参数类型 | 是否必填 | 说明 |
| --- | --- | --- | --- |
| `区域_check` | int | 否 | 是否传入区域筛选0=不筛选1=筛选 |
| `区域` | string | 否 | 区域名称,如 `A区` |
| `库位编号_check` | int | 否 | 是否传入库位编号筛选 |
| `库位编号` | string | 否 | 库位编号,支持模糊匹配 |
| `库位状态_check` | int | 否 | 是否传入状态筛选 |
| `库位状态` | int | 否 | 库位状态值 |
返回数据结构:
```javascript
[
{
'行标识': 'A-01', // 矩阵行标识
1: { // 列号
库位编号: 'A-01-01',
库位名称: 'A-01-01',
状态: 0, // 0=空闲, 1=预占, 2=有库存, 3=异常
区域: 'A区'
},
2: {
库位编号: 'A-01-02',
库位名称: 'A-01-02',
状态: 2,
区域: 'A区'
}
// ...
},
// ...
]
```
说明:
- 返回数据结构与立库 `GetPositionView` 类似,但单元格从简单数字扩展为含库位信息的对象
- 如果后端返回扁平的库位列表更便于实现,前端也可以在接收到扁平数据后自行转换为矩阵结构(见 5.3 节数据转换说明)
- 后端也可以按立库的方式返回矩阵格式,前端直接渲染
备选方案(后端返回扁平列表):
```javascript
[
{ 库位编号: 'A-01-01', 库位名称: 'A-01-01', 状态: 0, 区域: 'A区', : 'A-01', : 1 },
{ 库位编号: 'A-01-02', 库位名称: 'A-01-02', 状态: 2, 区域: 'A区', : 'A-01', : 2 },
// ...
]
```
前端接收到扁平数据后自动生成矩阵(见 5.3 节)。
### 5.2 库位物料详情查询接口
接口名:`仓储管理_三楼仓库库位物料_查询数据`
请求类型:`type = '1'`(查询)
请求参数:
| 参数名 | 参数类型 | 是否必填 | 说明 |
| --- | --- | --- | --- |
| `库位编号_check` | int | 是 | 固定传 1 |
| `库位编号` | string | 是 | 当前点击的库位编号 |
| `UserID` | string | 是 | 从 Cookie 获取 |
| `ModularID` | string | 是 | 当前路由路径 |
返回数据结构:
```javascript
[
{
物料编号: '02.009.001.0001',
物料名称: '齿轮',
图号: 'LRS3056-001',
规格型号: 'LRS3056-001-A',
库存数量: 12.000,
单位: '台',
批次: 'BATCH20260601001'
}
]
```
说明:
- 返回字段与立库 `StockDetailView` 对齐(物料编号 mno、物料名称 mname、图号 spec、型号 thao、库存数量 qty、单位 munit、批次 batch但使用中文字段名以保持与项目命名规范一致
- 如果后端已在仓储管理相关视图中维护了三楼仓库的物料库存与库位关系,优先复用现有视图或过程
### 5.3 数据转换(前端侧)
如果后端返回扁平的库位列表,前端需要将扁平数据转换为矩阵结构。转换逻辑如下:
```javascript
// 将扁平库位列表转换为矩阵结构
transformToMatrix(locationList) {
// 按"排/行标识"分组
var rowMap = {}
locationList.forEach(function(item) {
var rowKey = item. || item.行标识
if (!rowMap[rowKey]) {
rowMap[rowKey] = { '行标识': rowKey }
}
var colKey = item.
rowMap[rowKey][colKey] = {
库位编号: item.库位编号,
库位名称: item.库位名称,
状态: item.状态,
区域: item.区域
}
})
// 转为数组并按行标识排序
var matrixData = Object.values(rowMap)
matrixData.sort(function(a, b) {
return a['行标识'].localeCompare(b['行标识'])
})
return matrixData
}
```
### 5.4 后端接口复用评估
| 已有接口 | 可否复用 | 说明 |
| --- | --- | --- |
| `仓储管理_库位_查询` | 部分复用 | 现有库位管理页查询全部库位,但缺少"状态"字段和矩阵布局信息,需补充或新增三楼仓库专用接口 |
| `仓储管理_物料库位_查询数据` | 作为物料详情备选 | 按物料查库位,可反向使用按库位查物料,但参数和返回字段可能需要调整 |
| `仓储管理_库存查询_查询` | 不直接复用 | 库存查询按物料聚合,与按库位聚合的需求方向不同 |
| `仓储管理_库存盘点_查询` | 参考数据来源 | 库存盘点数据包含物料与库位的对应关系和库存数量,可作为三楼仓库库位状态和物料明细的数据来源 |
| `GetPositionView`(立库) | 不复用 | 立库走独立数据库,数据结构不同 |
<br/>
## 六、data 数据结构设计
```javascript
data() {
return {
// ========== 筛选条件 ==========
areaFilter: '', // 区域筛选值
statusFilter: '', // 状态筛选值
locationCodeSearch: '', // 库位编号搜索
areaOptions: [], // 区域下拉选项,从数据动态生成
statusOptions: [ // 状态下拉选项
{ label: '全部', value: '' },
{ label: '有库存', value: 2 },
{ label: '预占/待处理', value: 1 },
{ label: '空闲', value: 0 },
{ label: '异常/禁用', value: 3 }
],
// ========== 自动刷新 ==========
autoRefresh: false, // 自动刷新开关
refreshInterval: 60, // 刷新间隔(秒)
refreshTimer: null, // 定时器引用
refreshOptions: [ // 刷新间隔选项
{ label: '30秒', value: 30 },
{ label: '1分钟', value: 60 },
{ label: '5分钟', value: 300 }
],
// ========== 分页 ==========
pageCurrent: 1,
pageSize: 8,
// ========== 矩阵数据 ==========
locationRawData: [], // 后端返回的原始数据(扁平列表)
locationMatrixData: [], // 转换后的矩阵数据
filteredData: [], // 筛选后的矩阵数据
displayedData: [], // 当前页显示的矩阵数据
// ========== 选中与交互状态 ==========
selectedCell: null, // { 行标识, 列号, 库位信息 }
highlightedRow: null, // 当前高亮行
hoveredCell: null, // 当前悬停单元格
// ========== 统计信息 ==========
statistics: {
total: 0,
withStock: 0,
preOccupied: 0,
empty: 0,
abnormal: 0,
usageRate: 0
},
// ========== 弹窗 ==========
detailDialogVisible: false, // 库位详情弹窗
detailInfo: {}, // 当前弹窗展示的库位信息
materialDialogVisible: false, // 物料信息弹窗
materialLoading: false,
materialList: [], // 当前库位的物料列表
materialLocationCode: '', // 当前查询的库位编号
// ========== 显示设置 ==========
showCellText: 'text', // 'text' 或 'icon'
loading: false,
lastUpdateTime: ''
}
}
```
<br/>
## 七、methods 核心方法设计
### 7.1 数据加载与转换
```javascript
// 加载三楼仓库库位数据
loadLocationData() {
this.loading = true
var param = []
param[0] = ['区域_check', this.areaFilter ? 1 : 0]
param[1] = ['区域', this.areaFilter]
param[2] = ['库位编号_check', this.locationCodeSearch ? 1 : 0]
param[3] = ['库位编号', this.locationCodeSearch]
param[4] = ['库位状态_check', this.statusFilter !== '' ? 1 : 0]
param[5] = ['库位状态', this.statusFilter]
var Data = this.CreateData('1', '仓储管理_三楼仓库库位_查询数据', param)
this.getTable(Data).then(response => {
this.locationRawData = response.data || []
this.locationMatrixData = this.transformToMatrix(this.locationRawData)
this.filteredData = this.locationMatrixData
this.updateStatistics()
this.updateDisplayedData()
this.updateAreaOptions()
this.updateLastUpdateTime()
this.loading = false
}).catch(() => {
this.loading = false
})
}
// 将扁平库位列表转换为矩阵结构
transformToMatrix(list) {
// 按"排/行标识"分组(同 5.3 节)
}
```
### 7.2 统计计算
```javascript
updateStatistics() {
var withStock = 0
var preOccupied = 0
var empty = 0
var abnormal = 0
this.filteredData.forEach(function(row) {
Object.keys(row).forEach(function(key) {
if (key !== '行标识') {
var status = row[key].状态
if (status === 2) withStock++
else if (status === 1) preOccupied++
else if (status === 0) empty++
else if (status === 3) abnormal++
}
})
})
var total = withStock + preOccupied + empty + abnormal
var usageRate = total > 0 ? (((withStock + preOccupied) / total) * 100).toFixed(1) : 0
this.statistics = { total, withStock, preOccupied, empty, abnormal, usageRate }
}
```
### 7.3 单元格点击交互
```javascript
selectLocation(rowKey, colKey, locationInfo) {
this.selectedCell = { 行标识: rowKey, 列号: colKey, 信息: locationInfo }
this.highlightedRow = rowKey
if (locationInfo.状态 === 2) {
// 有库存,查询物料明细
this.loadMaterialDetail(locationInfo.库位编号)
} else {
// 非有库存状态,显示库位详情
this.showLocationDetail(locationInfo)
}
}
// 查询库位物料明细
loadMaterialDetail(locationCode) {
this.materialLoading = true
this.materialLocationCode = locationCode
var param = []
param[0] = ['库位编号_check', 1]
param[1] = ['库位编号', locationCode]
var Data = this.CreateData('1', '仓储管理_三楼仓库库位物料_查询数据', param)
this.getTable(Data).then(response => {
this.materialList = response.data || []
this.materialDialogVisible = true
this.materialLoading = false
}).catch(() => {
this.materialLoading = false
})
}
// 显示库位详情
showLocationDetail(locationInfo) {
this.detailInfo = {
库位编号: locationInfo.库位编号,
库位名称: locationInfo.库位名称,
区域: locationInfo.区域,
状态: this.getStatusLabel(locationInfo.状态),
状态描述: this.getStatusDescription(locationInfo.状态)
}
this.detailDialogVisible = true
}
```
### 7.4 状态映射方法
```javascript
// 获取状态显示文字
getStatusLabel(status) {
var map = { 0: '空', 1: '预', 2: '存', 3: '异' }
return map[status] || '未知'
}
// 获取状态完整描述
getStatusDescription(status) {
var map = {
0: '空闲库位,可存放物料',
1: '预占或待处理,库位已被预留',
2: '有库存,库位上存放有物料',
3: '异常或禁用,库位不可使用'
}
return map[status] || '未知状态'
}
// 获取状态图标类名
getStatusIcon(status) {
var map = {
0: 'el-icon-minus',
1: 'el-icon-time',
2: 'el-icon-box',
3: 'el-icon-warning'
}
return map[status] || 'el-icon-question'
}
```
### 7.5 自动刷新
```javascript
// 切换自动刷新
handleAutoRefreshChange(val) {
if (val) {
this.startAutoRefresh()
} else {
this.stopAutoRefresh()
}
}
startAutoRefresh() {
this.stopAutoRefresh()
var self = this
this.refreshTimer = setInterval(function() {
self.loadLocationData()
}, this.refreshInterval * 1000)
}
stopAutoRefresh() {
if (this.refreshTimer) {
clearInterval(this.refreshTimer)
this.refreshTimer = null
}
}
```
<br/>
## 八、页面样式设计
参考立库可视化组件的样式方案,保持一致的设计语言。
### 8.1 核心样式类
| 类名 | 用途 | 参考来源 |
| --- | --- | --- |
| `.warehouse-table` | 矩阵表格 | 立库 `.warehouse-table` 复用 |
| `.location-cell` | 库位单元格 | 立库 `.warehouse-cell` 调整命名 |
| `.status-0` | 空闲库位灰色 | 立库 `.status-0` 复用 |
| `.status-1` | 预占橙色 | 立库 `.status-1`(橙色),新增 |
| `.status-2` | 有库存绿色 | 立库 `.status-2` 复用 |
| `.status-3` | 异常红色 | 新增,区别于立库锁库蓝色 |
| `.selected-cell` | 选中蓝色边框 | 立库 `.selected-cell` 复用 |
| `.highlighted-row` | 行高亮 | 立库 `.highlighted-row` 复用 |
| `.cell-tooltip` | 悬浮提示 | 立库 `.cell-tooltip` 复用 |
| `.legend-color` | 图例色块 | 立库 `.legend-color` 复用 |
### 8.2 大屏适配
参考立库可视化组件的响应式断点:
```scss
// 全屏大屏:默认 1920px
.warehouse-table {
min-width: 1200px;
.location-cell { min-width: 40px; height: 40px; }
}
// 中等屏幕1400px 以下
@media (max-width: 1400px) {
.warehouse-table {
min-width: 900px;
.location-cell { min-width: 35px; height: 35px; }
}
}
// 小屏幕992px 以下
@media (max-width: 992px) {
.warehouse-table {
min-width: 700px;
.location-cell { min-width: 30px; height: 30px; }
}
}
```
### 8.3 与立库样式的差异
| 差异项 | 立库 | 三楼仓库 |
| --- | --- | --- |
| 异常状态颜色 | 锁库=天蓝色 `skyblue` | 异常=红色 `#f56c6c` |
| 状态数量 | 4 种 | 3-4 种(取决于现场确认) |
| 单元格内容 | 纯状态值 | 含库位信息的对象 |
<br/>
## 九、功能实现流程
```mermaid
flowchart TD
A["开始:三楼仓库可视化"] --> B["页面 created 调用 loadLocationData"]
B --> C["构造请求参数:区域、库位编号、状态"]
C --> D["调用 仓储管理_三楼仓库库位_查询数据"]
D --> E{"后端返回数据格式"}
E -- "矩阵格式" --> F["直接渲染矩阵"]
E -- "扁平列表" --> G["前端调用 transformToMatrix 转换为矩阵"]
F --> H["更新统计卡片、图例、矩阵"]
G --> H
H --> I["用户操作"]
I --> J{"操作类型"}
J -- "切换区域" --> K["更新 areaFilter 并重新 loadLocationData"]
J -- "切换状态筛选" --> L["前端筛选 filteredData 并重新统计"]
J -- "输入库位编号搜索" --> M["高亮匹配库位"]
J -- "切换显示模式" --> N["切换文字/图标"]
J -- "点击库位" --> O{"库位状态"}
O -- "有库存" --> P["调用 仓储管理_三楼仓库库位物料_查询数据"]
P --> Q["弹出物料信息表格弹窗"]
O -- "非有库存" --> R["弹出库位详情描述弹窗"]
J -- "开启自动刷新" --> S["启动定时器,按间隔重新 loadLocationData"]
S --> I
K --> H
L --> H
```
<br/>
## 十、待确认事项
| 序号 | 事项 | 影响 | 建议 |
| --- | --- | --- | --- |
| 1 | 三楼仓库的物理布局和库位编码规则 | 决定矩阵行列定义和编码规则 | 需仓库现场确认区域划分、排/列号规则 |
| 2 | 库位状态分类是否与立库一致 | 决定状态数量、颜色和业务含义 | 建议与仓库确认是否需要"预占"和"异常"状态 |
| 3 | 自动刷新频率 | 刷新频率影响服务器压力 | 建议默认 1 分钟,大屏场景可配置 |
| 4 | 后端是否可返回矩阵格式数据 | 影响前端转换复杂度 | 建议后端返回扁平列表,前端转换为矩阵,职责更清晰 |
| 5 | 库位数据是否与立库共用表还是独立表 | 影响后端接口是否复用 | 需后端确认三楼仓库库位数据所在表 |
| 6 | 是否需要导出功能 | 需求文档未提及,但立库已预留 | 建议本期暂不实现,预留后续扩展 |
| 7 | 三楼仓库库位数量规模 | 影响是否需要分页和性能优化 | 需现场确认库位总数,若少于 100 个可一屏展示不分页 |
<br/>
## 十一、影响范围
### 11.1 新增文件
| 文件 | 说明 |
| --- | --- |
| `src/views/WarehouseManagement/ThirdFloorWarehouse/index.vue` | 三楼仓库可视化页面组件 |
### 11.2 新增后端接口
| 接口名 | 说明 |
| --- | --- |
| `仓储管理_三楼仓库库位_查询数据` | 查询三楼仓库库位列表及状态 |
| `仓储管理_三楼仓库库位物料_查询数据` | 按库位编号查询物料明细 |
### 11.3 不受影响
- 立库可视化组件 `WarehouseVisualization` 不受影响
- 库位管理 `LocationManagement` 不受影响
- 物料库位 `MaterialLocation` 不受影响
- 其他仓储业务页面不受影响
<br/>
## 十二、验收清单
| 序号 | 验收项 | 验收方式 |
| --- | --- | --- |
| 1 | 三楼仓库可视化页面可正常加载并展示所有库位 | 打开页面,确认矩阵展示正常 |
| 2 | 不同状态的库位用不同颜色区分,图例说明清晰 | 检查图例与矩阵颜色对应 |
| 3 | 统计面板数据与实际库位状态一致 | 手工统计库位数量与面板数据对比 |
| 4 | 点击有库存的库位可查看物料详情 | 点击绿色库位,弹窗显示物料编号、名称、图号、库存数量等 |
| 5 | 点击空闲库位可查看库位基本信息 | 点击灰色库位,弹窗显示库位编号、状态说明等 |
| 6 | 区域筛选和状态筛选功能正常 | 切换筛选条件,矩阵刷新并统计更新 |
| 7 | 库位编号搜索可定位到对应库位 | 输入库位编号,点击搜索,目标库位高亮 |
| 8 | 刷新数据后页面状态更新正确 | 点击刷新按钮,矩阵重新加载 |
| 9 | 自动刷新开启后定时更新 | 开启自动刷新,等待自动刷新触发,确认数据更新 |
| 10 | 文字/图标两种显示模式切换正常 | 切换显示模式,确认单元格内容变化 |
| 11 | 大屏展示布局合理,文字清晰可读 | 在 1920px 宽度下检查布局和字体 |
| 12 | 不影响现有立库可视化功能 | 切换到立库可视化页面,确认功能正常 |
| 13 | 分页功能正常(如库位行数较多) | 切换分页,确认分页数据正确 |
<br/>
## 十三、风险与回退
### 13.1 风险
| 风险 | 影响 | 缓解措施 |
| --- | --- | --- |
| 三楼仓库库位数据与立库数据结构差异较大 | 可能需要单独设计接口和前端组件 | 复用立库可视化交互设计模式,仅数据层调整 |
| 库位编码规则未确认 | 矩阵行列定义无法确定 | 先与仓库确认编码规则再开发,避免返工 |
| 库位状态分类未确认 | 状态值和颜色方案无法确定 | 先与仓库确认状态需求再定义映射 |
| 库位数量规模未知 | 影响性能和分页设计 | 预留分页方案,小规模时可一屏展示 |
| 后端接口未就绪 | 前端无法联调 | 前端先用模拟数据开发,接口就绪后对接 |
### 13.2 回退方式
- 该功能为新增页面,不修改现有任何组件
- 如有问题,直接移除 `ThirdFloorWarehouse` 目录和对应菜单配置即可回退
- 不影响其他任何仓储页面功能
<br/>
## 十四、发布步骤
1. 后端部署库位查询和物料详情查询接口
2. 后端配置三楼仓库可视化的菜单数据(路由、菜单名称、图标等)
3. 发布前端代码(`ThirdFloorWarehouse/index.vue`
4. 清浏览器缓存后进入系统
5. 在仓储管理菜单下打开三楼仓库可视化页面
6. 验证库位矩阵展示与仓库实际布局一致
7. 验证统计卡片数据准确
8. 验证点击库位可查看物料详情或库位详情
9. 验证筛选、搜索、刷新、自动刷新等功能正常
10. 由仓库人员在现场环境实际使用并确认数据正确性
<br/>
## 十五、实施拆分
### 开发步骤
| 步骤 | 内容 | 前置依赖 |
| --- | --- | --- |
| 1 | 与仓库确认物理布局、库位编码规则、状态分类 | 无 |
| 2 | 后端新增库位查询和物料详情查询接口 | 步骤 1 |
| 3 | 前端创建 `ThirdFloorWarehouse/index.vue` 页面框架 | 步骤 1 |
| 4 | 实现矩阵数据加载和转换逻辑 | 步骤 2、3 |
| 5 | 实现统计卡片、图例、矩阵渲染 | 步骤 4 |
| 6 | 实现单元格点击交互和弹窗 | 步骤 5 |
| 7 | 实现筛选、搜索、分页功能 | 步骤 5 |
| 8 | 实现自动刷新功能 | 步骤 4 |
| 9 | 大屏适配和样式调优 | 步骤 7 |
| 10 | 联调测试 | 步骤 9 |
<br/>
修改人:Ld 修改时间:2026-06-30

Binary file not shown.

View File

@@ -0,0 +1,235 @@
# MES 提交审批到质检入库全链路测试报告
## 一、测试结论
本次测试通过数据库事务方式模拟完整业务链路,链路可以跑通。
验证通过的流程为:
1. MES 工作站工作机端提交生产完成审批。
2. JY 主系统生产审核组件审核通过。
3. 原 MES 完工链路继续执行,工序和工艺计划完成数据更新。
4. PDA 仓库自制件质检入口可查询到待质检数据,并可提交质检。
5. JY 主系统仓储模块自制件入库确认可查询并完成入库。
6. 测试全程在事务内执行并最终回滚,未污染正式业务数据。
需要注意:自制件最终入库确认入口当前在 JY 主系统仓储模块,不在 PDA 项目的采购件入库页面中PDA 项目本次验证的是自制件质检入口。
## 二、测试环境
| 项目 | 内容 |
| --- | --- |
| 测试时间 | 2026-07-06 |
| 数据库服务器 | 192.168.1.27 |
| 数据库 | ERPTOOL_JY_20250826Back |
| MES 工作站项目 | D:\景耀\MES工作站 |
| JY 主系统项目 | D:\景耀\JY1.0 |
| PDA 仓库项目 | D:\景耀\PDA_仓库 6.30 |
| 测试方式 | SQL Server 事务内模拟,最终 ROLLBACK |
## 三、涉及入口和过程
| 环节 | 前端入口 | 后端过程 |
| --- | --- | --- |
| MES 提交审批 | `D:\景耀\MES工作站\src\components\login.vue` | `MES_机加工MES_加工完成整修审核_提交` |
| 系统内审核 | `D:\景耀\JY1.0\src\views\SeikoWorkshop\ProductionCompletionAudit\index.vue` | `机加工MES_加工完成整修审核_审核数据` |
| 原完工链路 | 审核过程内部继续调用 | `设备管理_零件工序_工序完成过程情况_增加数据` |
| PDA 自制件质检查询 | `D:\景耀\PDA_仓库 6.30\src\components\purchasedWareHouse.vue` | `质检管理_订单查询_查询数据``质检管理_工序任务_查询数据``质检管理_工序信息_查询数据``质检管理_分配任务_查询数据` |
| PDA 自制件质检提交 | `D:\景耀\PDA_仓库 6.30\src\components\purchasedWareHouse.vue` | `车间生产管理_质检管理_不合格处理` |
| 自制件入库确认 | `D:\景耀\JY1.0\src\views\WarehouseManagement\PurchasePartsStorage\index.vue` | `仓储管理_自制件入库_查询``仓储管理_自制件入库_循环执行` |
## 四、测试数据
| 字段 | 值 |
| --- | --- |
| 工序流水号 | 124831 |
| 工艺计划流水号 | 6584 |
| 工艺任务流水号 | 38671 |
| 订单流水号 | 19278 |
| 订单号 | BHGZ202606250004 |
| 产品名称 | XT40-2-BT40-AMB |
| 零件名称 | 打刀缸 |
| 零件图号 | XT40-2-BT40-BC-G |
| 物料流水号 | 496 |
| 工序 | 改制 |
| 操作者 | 王建荣 |
| 工位号 | C080 |
| 设备 | 半自动双面铣床 |
| 测试完成数量 | 1 |
| 测试货位流水号 | 1 |
选用该数据的原因:该任务为末道工序,未完成数量为 1 件,具备从完工审核推进到自制件质检和入库确认的完整条件。
## 五、测试步骤与结果
### 1. MES 工作站提交审批
执行过程:`MES_机加工MES_加工完成整修审核_提交`
关键参数:
| 参数 | 值 |
| --- | --- |
| 工序流水号 | 124831 |
| 工作者考勤编号 | 6027 |
| 完成数量 | 1 |
| 完成类型 | 1 |
| 录工票人员编号 | 209 |
| 工位号 | C080 |
| 开始时间 | 2026-07-06 08:30:00 |
| 结束时间 | 2026-07-06 08:40:00 |
结果:
| 字段 | 值 |
| --- | --- |
| result | 1 |
| 审核流水号 | 10 |
结论MES 工作站提交审批成功,审核记录可以生成。
### 2. JY 主系统审核通过
执行过程:`机加工MES_加工完成整修审核_审核数据`
审核结果:
| 字段 | 值 |
| --- | --- |
| result | 1 |
| 审核状态 | 审核通过 |
| 审核表开始时间 | 2026-07-06 08:30:00 |
| 审核表结束时间 | 2026-07-06 08:40:00 |
| 工序完成数量 | 1 |
| 工序状态 | 4 |
| 工艺计划完成数量 | 1 |
| 工艺计划考核状态 | 3 |
结论:审核通过后已继续调用原 MES 完工链路,工序完成和工艺计划完成数据已推进。
### 3. PDA 自制件质检查询
在审核通过后的事务内,模拟 PDA 页面查询:
| 查询过程 | 验证结果 |
| --- | --- |
| `质检管理_订单查询_查询数据` | 可查到订单 `19278 / BHGZ202606250004` |
| `质检管理_工序任务_查询数据` | 可查到 `改制-王建荣`,任务流水号 `38671` |
| `质检管理_工序信息_查询数据` | 可查到零件、工序、设备和数量 |
| `质检管理_分配任务_查询数据` | 可查到该工序分配记录 |
结论审核通过后PDA 自制件质检页面的数据查询链路可用。
### 4. PDA 自制件质检提交
执行过程:`车间生产管理_质检管理_不合格处理`
关键参数:
| 参数 | 值 |
| --- | --- |
| 零部件流水号 | 38671 |
| 质检类型代码 | 3 |
| 数量 | 1 |
| 是否合格 | 1 |
| 人员编号 | 5 |
| 不合格数量 | 0 |
| 订单流水号 | 19278 |
| 订单号 | BHGZ202606250004 |
| 质检数量 | 1 |
结果:
| 字段 | 值 |
| --- | --- |
| 质检流水号 | 15915 |
| 质检主表记录数 | 1 |
| 待入库单数 | 1 |
结论PDA 自制件质检提交成功,并生成自制待入库单。
### 5. 自制件入库查询
执行过程:`仓储管理_自制件入库_查询`
查询条件:
| 参数 | 值 |
| --- | --- |
| 订单号_check | 1 |
| 订单号 | 19278 |
| 零件图号_check | 1 |
| 零件图号 | XT40-2-BT40-BC-G |
结果:
| 字段 | 值 |
| --- | --- |
| 工艺计划流水号 | 6584 |
| 物料流水号 | 496 |
| 零件名称 | 打刀缸 |
| 零件图号 | XT40-2-BT40-BC-G |
| 完成数量 | 1 |
| 入库数量 | 0 |
| 本次入库 | 1 |
| 类型 | 自制件 |
结论:质检后,自制件入库确认列表可以查询到该待入库记录。
### 6. 自制件入库确认
执行过程:`仓储管理_自制件入库_循环执行`
关键参数:
| 参数 | 值 |
| --- | --- |
| 物料流水号组 | 496 |
| 实际到货数量组 | 1 |
| 工艺计划流水号组 | 6584 |
| 入库人员流水号 | 5 |
| 货位流水号组 | 1 |
| 类型组 | 自制件 |
| 批号组 | 0 |
事务内结果:
| 字段 | 值 |
| --- | --- |
| 工艺计划入库数量 | 1 |
| 工艺计划考核状态 | 4 |
| 自制件入库记录数 | 1 |
| 货位存量 | 1 |
结论:自制件入库确认成功,库存与工艺计划入库状态能够更新。
### 7. 回滚验证
执行 `ROLLBACK TRAN` 后复查:
| 字段 | 回滚后结果 |
| --- | --- |
| 工序完成数量 | NULL |
| 工序状态 | NULL |
| 工艺计划完成数量 | 0 |
| 工艺计划入库数量 | 0 |
| 工艺计划考核状态 | 2 |
| 审核记录是否存在 | 0 |
| 质检记录是否存在 | 0 |
结论:测试数据已全部回滚,未污染正式数据。
## 六、风险和注意事项
1. 本次为数据库事务内模拟测试,验证的是后端过程和页面查询入口对应的业务链路,不等同于人工在浏览器逐按钮点击的 UI 测试。
2. 自制件最终入库确认入口在 JY 主系统仓储模块 `PurchasePartsStorage`PDA 项目当前未发现自制件最终入库确认页面。
3. PDA 项目的 `inbound.vue` 主要覆盖采购件、离线件、车间采购件等入库,不是本次自制件完工质检后的最终入库确认入口。
4. 若后续要求“全程都在 PDA 完成入库确认”,需要新增或调整 PDA 自制件入库确认页面,并对接 `仓储管理_自制件入库_查询``仓储管理_自制件入库_循环执行`
## 七、最终结论
从 MES 工作站提交生产完成审批,到 JY 主系统审核通过,再到 PDA 自制件质检,最后到 JY 主系统自制件入库确认,数据库业务链路验证通过。
本次测试未发现阻断性问题。
修改人:Ld 修改时间:2026-07-06 09:14:24;

View File

@@ -0,0 +1,423 @@
# 工序工价与生产任务审核开发说明
## 一、需求来源
本文档根据桌面需求文件 `工序工价需求文档.docx``生产任务审核.docx` 整理,用于指导 JY1.0 前端、接口和数据库开发。
## 二、需求范围
本次需求分为两组功能:
1. 工序工价与工时金额:新增工序定价录入、工时统计金额显示、整修记录补助金额。
2. 生产任务审核:车间工况机完成数量提报或异常报备后,先生成计划员审核单,审核通过后进入原系统后续流程。
## 三、现状入口
| 功能点 | 现有入口 | 现有接口/过程 |
| --- | --- | --- |
| 工时统计 | `src/views/SeikoWorkshop/WorkingHoursStatistics/index.vue` | `车间生产管理_工人工时统计_查询数据``精工车间_员工工时统计_详情_查询数据``车间生产管理_设备工时统计_查询数据``精工车间_设备工时统计_详情_查询数据` |
| 工艺/工序基础维护 | `src/views/BasicData/WorkshopProcessMaintenance/index.vue` | `工艺名称_查询``车间生产管理工艺_基础表_工艺名称_增加数据``车间生产管理工艺_基础表_工艺名称_修改名称及简称` |
| 生产任务查询 | `src/views/SeikoWorkshop/ProductionTaskQuery/index.vue` | `精工车间_生成任务_查询数据``车间生产管理工艺_追溯加工_查询工序` |
| 整修记录 | `src/views/DeviceManagement/RepairRecord/index.vue` | `设备管理_整修记录_查询` |
## 四、工序工价功能设计
### 4.1 新增独立工序工价维护页面
需求中提到现场希望把 9 个工价字段放入已有车间查看工艺组件。考虑现有查看工艺组件偏生产现场查看,字段较多且属于工价管理,建议新增独立页面。
建议新增页面:
```text
src/views/SeikoWorkshop/ProcessPrice/index.vue
```
建议新增接口文件:
```text
src/api/ManufacturingCenter/ProcessPrice.js
```
页面结构:
1. 搜索栏:工序名称、工艺名称、零件名称、图号、启用状态。
2. 左侧表格:工序列表。
3. 右侧表格或弹窗:工序工价字段维护。
4. 操作:查询、新增、编辑、删除、查看历史定价。
建议字段:
| 字段名 | 类型 | 说明 |
| --- | --- | --- |
| 工价流水号 | int | 主键 |
| 工序流水号 | int | 关联 `车间生产管理工艺_零件工序` |
| 工艺计划流水号 | int | 关联生产任务工艺计划 |
| 工序名称 | nvarchar | 页面显示 |
| 计价方式 | nvarchar | 按件、按时、固定金额 |
| 单件工价 | decimal | 按件计价 |
| 单时工价 | decimal | 按工时计价 |
| 准结工价 | decimal | 准结补偿 |
| 难度系数 | decimal | 价格修正 |
| 质量系数 | decimal | 质量修正 |
| 设备系数 | decimal | 设备修正 |
| 生效日期 | datetime | 价格生效时间 |
| 失效日期 | datetime | 价格失效时间 |
| 是否启用 | int | 1 启用0 停用 |
| 备注 | nvarchar | 说明 |
| 创建人 | nvarchar | 操作者 |
| 创建时间 | datetime | 写入时间 |
| 修改人 | nvarchar | 最后修改人 |
| 修改时间 | datetime | 最后修改时间 |
> 需求原文提到“9 个字段数据”,实际字段名称需要现场确认。上表先按定价业务补全为可落库方案,开发前应与业务确认 9 个必填字段。
### 4.2 工序历史定价
新增历史查询能力,用于查看工序价格变更轨迹。
建议数据表:
```text
车间生产管理工艺_工序工价历史记录
```
记录内容:
| 字段名 | 说明 |
| --- | --- |
| 历史流水号 | 主键 |
| 工价流水号 | 对应当前工价记录 |
| 工序流水号 | 对应工序 |
| 修改前数据 | 可按字段拆列或保存摘要 |
| 修改后数据 | 可按字段拆列或保存摘要 |
| 操作类型 | 新增、编辑、停用 |
| 操作者 | 当前用户 |
| 操作时间 | 当前时间 |
### 4.3 接口设计
新增过程建议:
| 接口名称 | type | 用途 |
| --- | --- | --- |
| `车间生产管理工艺_工序工价_查询数据` | `11` | 查询工序工价列表 |
| `车间生产管理工艺_工序工价_增加数据` | `12` | 新增工序工价 |
| `车间生产管理工艺_工序工价_编辑数据` | `12` | 编辑工序工价 |
| `车间生产管理工艺_工序工价_删除数据` | `12` | 停用或删除工价 |
| `车间生产管理工艺_工序工价_历史_查询数据` | `11` | 查询历史定价 |
前端请求继续使用项目统一方式:
```js
var Data = this.CreateData('11', '车间生产管理工艺_工序工价_查询数据', param, this.pageSize, this.pageCurrent)
this.ExecDatabase(Data).then(response => {
this.tableData = response.data.rows
this.total = response.data.total
})
```
## 五、工时统计金额功能设计
### 5.1 页面改造
修改页面:
```text
src/views/SeikoWorkshop/WorkingHoursStatistics/index.vue
```
员工工时统计左侧汇总表增加:
| 新增列 | 说明 |
| --- | --- |
| 工价 | 按所选人员统计周期内匹配工序工价后的平均或汇总工价 |
| 总金额 | 汇总加工金额 |
员工工时明细表增加:
| 新增列 | 说明 |
| --- | --- |
| 工价 | 当前工序匹配的有效工价 |
| 金额 | 按 `完成数``加工时长` 和计价方式计算 |
设备工时统计如业务需要同步增加金额列,字段逻辑与员工工时一致,但汇总维度为设备。
### 5.2 汇总规则
建议后端统一计算金额,前端只展示和汇总,避免不同页面计算规则不一致。
计价规则:
| 计价方式 | 金额计算 |
| --- | --- |
| 按件 | `完成数 * 单件工价 * 难度系数 * 质量系数 * 设备系数` |
| 按时 | `加工时长 / 60 * 单时工价 * 难度系数 * 质量系数 * 设备系数` |
| 固定金额 | `固定工价` |
表格最后一栏金额汇总可使用 Element UI `show-summary`,也可由后端返回汇总行。为保证分页情况下金额准确,建议后端返回总金额字段,前端展示分页明细和总计。
### 5.3 工时修正
需求中提到“工时记录与现实不同时可以修改”。建议新增明细行编辑入口,仅允许有权限人员调整。
新增字段:
| 字段名 | 说明 |
| --- | --- |
| 原加工时长 | 系统扫码产生的原始工时 |
| 调整后工时 | 审核后用于结算的工时 |
| 工时调整原因 | 必填 |
| 工时调整人 | 当前用户 |
| 工时调整时间 | 当前时间 |
新增接口:
| 接口名称 | type | 用途 |
| --- | --- | --- |
| `车间生产管理工艺_工时统计_工时修正_编辑数据` | `12` | 修改工时并记录原因 |
| `车间生产管理工艺_工时统计_工时修正记录_查询数据` | `11` | 查看修正历史 |
## 六、整修记录补助金额功能设计
### 6.1 页面改造
修改页面:
```text
src/views/DeviceManagement/RepairRecord/index.vue
```
搜索栏新增:
| 控件 | 字段 |
| --- | --- |
| `el-input``el-select` | 报备人 |
表格新增:
| 新增列 | 说明 |
| --- | --- |
| 单时补助 | 可编辑,记录每小时补助金额 |
| 总金额 | 自动计算,`工时 * 单时补助` |
页面新增汇总:
1. 当前查询条件下的整修工时合计。
2. 当前查询条件下的补助金额合计。
### 6.2 编辑规则
1. `单时补助` 必须大于等于 0。
2. `总金额` 不允许手工编辑,由后端或前端按工时自动计算。
3. 修改单时补助后写入操作日志。
4. 导出 Excel 时同步输出 `单时补助``总金额`
### 6.3 接口设计
调整现有查询过程:
```text
设备管理_整修记录_查询
```
新增入参:
```text
报备人
```
新增返回字段:
```text
单时补助
总金额
```
新增编辑过程:
| 接口名称 | type | 用途 |
| --- | --- | --- |
| `设备管理_整修记录_单时补助_编辑数据` | `12` | 更新单时补助 |
| `设备管理_整修记录_补助修改记录_查询数据` | `11` | 查询补助修改历史 |
## 七、生产任务审核功能设计
### 7.1 业务流程
车间工况机端提报加工完成或异常报备时,先生成审核单。计划员审核通过后,再进入原有后续流程。
经现场讨论,取消“不通过打回”功能。如数据不准确,由审核员在审核页面直接修改完成数量、完成时间、异常信息等数据后审核通过。
```mermaid
flowchart TD
A["工况机提报完成数量或异常报备"] --> B["生成生产任务审核单"]
B --> C["计划员进入审核页面"]
C --> D{"数据是否准确"}
D -- "准确" --> E["审核通过"]
D -- "不准确" --> F["审核员修改完成数量/完成时间/异常信息"]
F --> E
E --> G["写入原生产任务后续流程"]
G --> H["刷新生产任务/工时/追溯数据"]
```
### 7.2 新增审核页面
建议新增页面:
```text
src/views/SeikoWorkshop/ProductionTaskAudit/index.vue
```
页面结构:
1. 搜索栏:提交时间、订单号、零件名称、图号、操作者、审核状态。
2. 表格:待审核/已审核任务。
3. 操作:查看、编辑、审核通过。
表格字段:
| 字段名 | 说明 |
| --- | --- |
| 审核流水号 | 主键 |
| 来源类型 | 完工提报、异常报备 |
| 工艺计划流水号 | 关联生产任务 |
| 工序流水号 | 关联工序 |
| 订单号 | 显示 |
| 零件名称 | 显示 |
| 图号 | 显示 |
| 工序 | 显示 |
| 提报完成数量 | 工况机提报数量 |
| 审核完成数量 | 审核员可修改 |
| 提报完成时间 | 工况机提报时间 |
| 审核完成时间 | 审核员可修改 |
| 异常类型 | 异常报备使用 |
| 异常说明 | 异常报备使用 |
| 提报人 | 工况机操作者 |
| 提报时间 | 创建审核单时间 |
| 审核状态 | 待审核、已审核 |
| 审核人 | 当前用户 |
| 审核时间 | 审核通过时间 |
| 审核备注 | 说明 |
### 7.3 数据表设计
建议新增:
```text
车间生产管理_生产任务审核单
```
关键字段:
| 字段名 | 类型 | 说明 |
| --- | --- | --- |
| 审核流水号 | int identity | 主键 |
| 来源类型 | nvarchar(20) | 完工提报/异常报备 |
| 业务流水号 | int | 原工况机记录或异常记录 |
| 工艺计划流水号 | int | 生产任务 |
| 工序流水号 | int | 工序 |
| 提报完成数量 | decimal(18, 4) | 原始数量 |
| 审核完成数量 | decimal(18, 4) | 审核后数量 |
| 提报完成时间 | datetime | 原始时间 |
| 审核完成时间 | datetime | 审核后时间 |
| 异常类型 | nvarchar(100) | 异常报备 |
| 异常说明 | nvarchar(500) | 异常报备 |
| 提报人 | nvarchar(50) | 工况机人员 |
| 提报时间 | datetime | 创建时间 |
| 审核状态 | int | 0 待审核1 已审核 |
| 审核人 | nvarchar(50) | 计划员 |
| 审核时间 | datetime | 审核时间 |
| 审核备注 | nvarchar(500) | 备注 |
| 是否删除 | int | 软删除 |
### 7.4 接口设计
新增过程:
| 接口名称 | type | 用途 |
| --- | --- | --- |
| `精工车间_生产任务审核_查询数据` | `11` | 审核单分页查询 |
| `精工车间_生产任务审核_编辑数据` | `12` | 审核前修改提报数据 |
| `精工车间_生产任务审核_通过` | `12` | 审核通过并推进原流程 |
| `精工车间_生产任务审核_详情_查询数据` | `11` | 查看单据详情 |
审核通过过程必须使用事务:
```text
BEGIN TRAN
锁定审核单
校验审核状态 = 待审核
更新审核单审核数量、审核时间、审核人
按来源类型调用或复刻原完工/异常报备后续逻辑
更新生产任务、工序、工时、异常记录
COMMIT TRAN
```
失败时:
```text
ROLLBACK TRAN
返回 result = 0 和 msg
```
## 八、权限与菜单
建议新增菜单:
| 菜单名称 | 路由 |
| --- | --- |
| 工序工价维护 | `/SeikoWorkshop/ProcessPrice` |
| 生产任务审核 | `/SeikoWorkshop/ProductionTaskAudit` |
建议权限:
1. 工序工价维护:仅工艺、财务、车间管理人员可编辑。
2. 工时修正:仅车间主管或授权计划员可编辑。
3. 生产任务审核:计划员可审核,车间操作员不可审核自己的提报。
4. 整修补助编辑:设备管理或车间主管可编辑。
## 九、开发步骤
1. 与现场确认工序工价 9 个字段的准确名称、类型和必填规则。
2. 创建工序工价主表、历史表、生产任务审核单表。
3. 新增工序工价查询、新增、编辑、删除、历史查询存储过程。
4. 改造工时统计查询过程,返回工价、金额、总金额。
5. 改造整修记录查询过程,支持报备人筛选,返回单时补助和总金额。
6. 新增整修记录单时补助编辑过程。
7. 改造工况机完成提报、异常报备后端逻辑,改为先生成审核单。
8. 新增生产任务审核查询、编辑、通过过程。
9. 新增 `ProcessPrice` 页面。
10. 新增 `ProductionTaskAudit` 页面。
11. 修改 `WorkingHoursStatistics` 页面,增加工价、金额展示和汇总。
12. 修改 `RepairRecord` 页面,增加报备人筛选、补助编辑、金额汇总。
13. 配置菜单和角色权限。
14. 联调工况机提报、审核通过、生产任务流转、工时统计、整修补助导出。
## 十、验收清单
| 验收项 | 预期结果 |
| --- | --- |
| 工序工价新增 | 保存成功,列表可查询 |
| 工序工价编辑 | 修改后历史记录可追溯 |
| 历史定价查询 | 能查看同一工序多次价格变更 |
| 工时统计金额 | 明细金额和汇总金额正确 |
| 工时修正 | 调整后工时参与金额计算,并保留原始工时 |
| 整修记录按报备人查询 | 能按报备人过滤数据 |
| 整修补助编辑 | 单时补助保存成功,总金额自动变化 |
| 整修记录导出 | 导出包含单时补助和总金额 |
| 完工提报审核单 | 工况机提交后生成待审核单 |
| 异常报备审核单 | 异常报备后生成待审核单 |
| 审核数据修改 | 审核员可修改完成数量、完成时间 |
| 审核通过 | 通过后进入原生产任务后续流程 |
| 重复审核控制 | 已审核单据不能再次审核 |
| 权限控制 | 未授权用户不能编辑工价、补助或审核 |
## 十一、风险与待确认项
1. 工序工价“9 个字段”的具体字段名未在需求文档中列明,需要业务补充。
2. 工时金额计算需要确认按件、按时还是混合计价,以及是否区分准结工时。
3. 工况机端完工和异常报备的现有后续逻辑需要在数据库中定位后再改造,避免绕过原有工时、质检、追溯更新。
4. 审核员修改完成数量后,是否需要同步影响质检数、不良数、入库可用数,需要业务确认。
5. 已有历史工时是否需要补算金额,需要确认补算范围。
修改人:Ld 修改时间:2026-07-02 13:01:57;

View File

@@ -0,0 +1,248 @@
# 工序工价开发说明
## 一、需求来源
本文档根据桌面需求文件 `工序工价需求文档.docx` 整理,用于指导 JY1.0 工序工价、工时金额和整修补助相关开发。
## 二、需求范围
本需求包含三个目标:
1. 给工序增加 9 个工价相关字段,并支持录入、维护和历史定价查看。
2. 工时统计组件增加工价、金额字段,并在汇总栏展示金额合计。
3. 整修记录模块增加按报备人查询,并增加单时补助、总金额和汇总。
## 三、现有入口
| 功能点 | 现有入口 | 现有接口/过程 |
| --- | --- | --- |
| 工时统计 | `src/views/SeikoWorkshop/WorkingHoursStatistics/index.vue` | `车间生产管理_工人工时统计_查询数据``精工车间_员工工时统计_详情_查询数据``车间生产管理_设备工时统计_查询数据``精工车间_设备工时统计_详情_查询数据` |
| 工艺/工序基础维护 | `src/views/BasicData/WorkshopProcessMaintenance/index.vue` | `工艺名称_查询``车间生产管理工艺_基础表_工艺名称_增加数据``车间生产管理工艺_基础表_工艺名称_修改名称及简称` |
| 整修记录 | `src/views/DeviceManagement/RepairRecord/index.vue` | `设备管理_整修记录_查询` |
## 四、工序工价维护设计
### 4.1 页面方案
需求原文提到现场希望把 9 个字段加入已有车间查看工艺组件。考虑现有查看工艺组件偏现场查看,字段多且属于价格管理,建议新增独立页面。
建议新增页面:
```text
src/views/SeikoWorkshop/ProcessPrice/index.vue
```
建议新增接口文件:
```text
src/api/ManufacturingCenter/ProcessPrice.js
```
页面结构:
1. 搜索栏:工艺名称、工序名称、零件名称、图号、启用状态。
2. 数据表格:展示工序工价记录。
3. 操作列:新增、编辑、停用、历史定价。
4. 弹窗:维护 9 个工价字段和备注。
### 4.2 字段设计
需求文档未列出 9 个字段的准确名称,开发前需现场补充确认。建议先按以下字段作为设计草案:
| 字段名 | 类型 | 说明 |
| --- | --- | --- |
| 工价流水号 | int | 主键 |
| 工序流水号 | int | 关联工序 |
| 工艺计划流水号 | int | 可选,关联生产任务工艺计划 |
| 工序名称 | nvarchar | 页面显示 |
| 计价方式 | nvarchar | 按件、按时、固定金额 |
| 单件工价 | decimal | 按件计价 |
| 单时工价 | decimal | 按工时计价 |
| 准结工价 | decimal | 准结补偿 |
| 难度系数 | decimal | 价格修正 |
| 质量系数 | decimal | 质量修正 |
| 设备系数 | decimal | 设备修正 |
| 生效日期 | datetime | 价格生效时间 |
| 失效日期 | datetime | 价格失效时间 |
| 是否启用 | int | 1 启用0 停用 |
| 备注 | nvarchar | 说明 |
| 创建人 | nvarchar | 当前用户 |
| 创建时间 | datetime | 写入时间 |
| 修改人 | nvarchar | 最后修改人 |
| 修改时间 | datetime | 最后修改时间 |
### 4.3 历史定价
新增历史记录表:
```text
车间生产管理工艺_工序工价历史记录
```
历史表记录工价新增、编辑、停用前后的关键数据,支持按工序查看历次定价变化。
## 五、接口设计
新增过程:
| 接口名称 | type | 用途 |
| --- | --- | --- |
| `车间生产管理工艺_工序工价_查询数据` | `11` | 分页查询工序工价 |
| `车间生产管理工艺_工序工价_增加数据` | `12` | 新增工价 |
| `车间生产管理工艺_工序工价_编辑数据` | `12` | 编辑工价 |
| `车间生产管理工艺_工序工价_删除数据` | `12` | 停用或删除 |
| `车间生产管理工艺_工序工价_历史_查询数据` | `11` | 查询历史定价 |
前端继续使用项目统一请求方式:
```js
var Data = this.CreateData('11', '车间生产管理工艺_工序工价_查询数据', param, this.pageSize, this.pageCurrent)
this.ExecDatabase(Data).then(response => {
this.tableData = response.data.rows
this.total = response.data.total
})
```
## 六、工时统计金额设计
修改页面:
```text
src/views/SeikoWorkshop/WorkingHoursStatistics/index.vue
```
员工工时统计汇总表新增:
| 字段 | 说明 |
| --- | --- |
| 工价 | 当前统计周期匹配的工价信息 |
| 总金额 | 查询条件下人员金额合计 |
员工工时明细表新增:
| 字段 | 说明 |
| --- | --- |
| 工价 | 当前工序有效工价 |
| 金额 | 按工价规则计算 |
建议后端返回金额,前端只展示和汇总,避免分页和多页面计算规则不一致。
金额规则建议:
| 计价方式 | 金额计算 |
| --- | --- |
| 按件 | `完成数 * 单件工价 * 难度系数 * 质量系数 * 设备系数` |
| 按时 | `加工时长 / 60 * 单时工价 * 难度系数 * 质量系数 * 设备系数` |
| 固定金额 | `固定工价` |
## 七、工时修正设计
需求补充提到工时记录与实际不符时可修改。建议在员工工时明细行增加“修正工时”入口。
新增字段:
| 字段名 | 说明 |
| --- | --- |
| 原加工时长 | 系统扫码原始工时 |
| 调整后工时 | 用于金额结算的工时 |
| 工时调整原因 | 必填 |
| 工时调整人 | 当前用户 |
| 工时调整时间 | 当前时间 |
新增接口:
| 接口名称 | type | 用途 |
| --- | --- | --- |
| `车间生产管理工艺_工时统计_工时修正_编辑数据` | `12` | 修改工时 |
| `车间生产管理工艺_工时统计_工时修正记录_查询数据` | `11` | 查询修正历史 |
## 八、整修记录补助设计
修改页面:
```text
src/views/DeviceManagement/RepairRecord/index.vue
```
搜索栏新增:
| 控件 | 字段 |
| --- | --- |
| `el-input``el-select` | 报备人 |
表格新增:
| 字段 | 说明 |
| --- | --- |
| 单时补助 | 可编辑,记录每小时补助金额 |
| 总金额 | 自动计算,`工时 * 单时补助` |
规则:
1. 单时补助必须大于等于 0。
2. 总金额不允许手工编辑。
3. 修改单时补助时写入修改记录。
4. 导出 Excel 同步包含单时补助和总金额。
调整现有查询过程:
```text
设备管理_整修记录_查询
```
新增入参:
```text
报备人
```
新增返回字段:
```text
单时补助
总金额
```
新增接口:
| 接口名称 | type | 用途 |
| --- | --- | --- |
| `设备管理_整修记录_单时补助_编辑数据` | `12` | 更新单时补助 |
| `设备管理_整修记录_补助修改记录_查询数据` | `11` | 查询补助修改历史 |
## 九、开发步骤
1. 与现场确认工序工价 9 个字段的准确名称、类型、必填规则。
2. 创建工序工价主表和历史表。
3. 新增工序工价查询、新增、编辑、删除、历史查询过程。
4. 新增 `ProcessPrice` 页面并配置菜单。
5. 改造工时统计查询过程,返回工价、金额、总金额。
6. 修改 `WorkingHoursStatistics` 页面,增加工价、金额展示和汇总。
7. 新增工时修正过程和修正记录查询。
8. 改造整修记录查询过程,支持报备人筛选,返回单时补助和总金额。
9. 修改 `RepairRecord` 页面,增加报备人筛选、补助编辑、金额汇总。
10. 联调导出、分页、汇总和权限控制。
## 十、验收清单
| 验收项 | 预期结果 |
| --- | --- |
| 工序工价新增 | 保存成功,列表可查询 |
| 工序工价编辑 | 修改后历史记录可追溯 |
| 历史定价查询 | 能查看同一工序多次价格变更 |
| 工时统计金额 | 明细金额和汇总金额正确 |
| 工时修正 | 调整后工时参与金额计算,并保留原始工时 |
| 整修记录按报备人查询 | 能按报备人过滤数据 |
| 整修补助编辑 | 单时补助保存成功,总金额自动变化 |
| 整修记录导出 | 导出包含单时补助和总金额 |
| 权限控制 | 未授权用户不能编辑工价、工时和补助 |
## 十一、风险与待确认项
1. 工序工价 9 个字段的具体名称未在需求文档中列明。
2. 工时金额计算需要确认按件、按时还是混合计价。
3. 准结工时是否参与金额计算需要确认。
4. 已有历史工时是否需要补算金额需要确认。
5. 整修补助是否按所有工时计算,还是按有效整修时间计算,需要确认。
修改人:Ld 修改时间:2026-07-02 13:05:56;

View File

@@ -0,0 +1,214 @@
# 生产任务审核开发说明
## 一、需求来源
本文档根据桌面需求文件 `生产任务审核.docx` 整理,用于指导 JY1.0 生产任务审核功能开发。
## 二、需求范围
本需求目标:
车间工况机端填报完成数量,或进行异常报备时,需要先提交计划员审核。审核通过后,系统才进入原有后续流程。
现场讨论结果:
1. 取消“不通过打回”功能。
2. 如果提报数据不准确,由审核员直接修改完成数量、完成时间等数据。
3. 审核员修正后审核通过,再进入系统后续流程。
## 三、现有入口
| 功能点 | 现有入口 | 现有接口/过程 |
| --- | --- | --- |
| 生产任务查询 | `src/views/SeikoWorkshop/ProductionTaskQuery/index.vue` | `精工车间_生成任务_查询数据` |
| 零件追溯 | `src/views/SeikoWorkshop/ProductionTaskQuery/index.vue` | `车间生产管理工艺_追溯加工_查询工序` |
| 车间派工 | `src/views/SeikoWorkshop/WorkshopAssignment/index.vue` | 派工、取消派工、已派工查询相关过程 |
| 工时统计 | `src/views/SeikoWorkshop/WorkingHoursStatistics/index.vue` | 工人工时、设备工时统计过程 |
## 四、业务流程
```mermaid
flowchart TD
A["工况机提报完成数量或异常报备"] --> B["生成生产任务审核单"]
B --> C["计划员进入审核页面"]
C --> D{"提报数据是否准确"}
D -- "准确" --> E["审核通过"]
D -- "不准确" --> F["审核员修改完成数量/完成时间/异常信息"]
F --> E
E --> G["写入原生产任务后续流程"]
G --> H["刷新生产任务、工时、追溯数据"]
```
## 五、新增审核页面
建议新增页面:
```text
src/views/SeikoWorkshop/ProductionTaskAudit/index.vue
```
页面结构:
1. 搜索栏:提交时间、订单号、零件名称、图号、操作者、审核状态。
2. 数据表格:待审核和已审核任务。
3. 操作列:查看、编辑、审核通过。
4. 编辑弹窗:允许审核员修正完成数量、完成时间、异常信息和审核备注。
## 六、页面字段
| 字段名 | 说明 |
| --- | --- |
| 审核流水号 | 主键 |
| 来源类型 | 完工提报、异常报备 |
| 工艺计划流水号 | 关联生产任务 |
| 工序流水号 | 关联工序 |
| 订单号 | 页面显示 |
| 零件名称 | 页面显示 |
| 图号 | 页面显示 |
| 工序 | 页面显示 |
| 提报完成数量 | 工况机原始提报数量 |
| 审核完成数量 | 审核员可修改 |
| 提报完成时间 | 工况机原始提报时间 |
| 审核完成时间 | 审核员可修改 |
| 异常类型 | 异常报备使用 |
| 异常说明 | 异常报备使用 |
| 提报人 | 工况机操作者 |
| 提报时间 | 创建审核单时间 |
| 审核状态 | 待审核、已审核 |
| 审核人 | 当前审核用户 |
| 审核时间 | 审核通过时间 |
| 审核备注 | 说明 |
## 七、数据表设计
建议新增表:
```text
车间生产管理_生产任务审核单
```
字段设计:
| 字段名 | 类型 | 说明 |
| --- | --- | --- |
| 审核流水号 | int identity | 主键 |
| 来源类型 | nvarchar(20) | 完工提报/异常报备 |
| 业务流水号 | int | 原工况机记录或异常记录 |
| 工艺计划流水号 | int | 生产任务 |
| 工序流水号 | int | 工序 |
| 提报完成数量 | decimal(18, 4) | 原始数量 |
| 审核完成数量 | decimal(18, 4) | 审核后数量 |
| 提报完成时间 | datetime | 原始时间 |
| 审核完成时间 | datetime | 审核后时间 |
| 异常类型 | nvarchar(100) | 异常报备 |
| 异常说明 | nvarchar(500) | 异常报备 |
| 提报人 | nvarchar(50) | 工况机人员 |
| 提报时间 | datetime | 创建时间 |
| 审核状态 | int | 0 待审核1 已审核 |
| 审核人 | nvarchar(50) | 计划员 |
| 审核时间 | datetime | 审核时间 |
| 审核备注 | nvarchar(500) | 备注 |
| 是否删除 | int | 软删除 |
## 八、接口设计
新增过程:
| 接口名称 | type | 用途 |
| --- | --- | --- |
| `精工车间_生产任务审核_查询数据` | `11` | 审核单分页查询 |
| `精工车间_生产任务审核_编辑数据` | `12` | 审核前修改提报数据 |
| `精工车间_生产任务审核_通过` | `12` | 审核通过并推进原流程 |
| `精工车间_生产任务审核_详情_查询数据` | `11` | 查看单据详情 |
前端请求示例:
```js
var Data = this.CreateData('11', '精工车间_生产任务审核_查询数据', param, this.pageSize, this.pageCurrent)
this.ExecDatabase(Data).then(response => {
this.tableData = response.data.rows
this.total = response.data.total
})
```
## 九、审核通过事务
审核通过过程必须使用事务,确保审核单和原生产任务流程一致。
```text
BEGIN TRAN
锁定审核单
校验审核状态 = 待审核
更新审核完成数量、审核完成时间、审核人、审核时间
按来源类型执行原完工提报或异常报备后续逻辑
更新生产任务、工序、工时、异常记录
COMMIT TRAN
```
失败时:
```text
ROLLBACK TRAN
返回 result = 0 和 msg
```
## 十、前端交互规则
1. 待审核状态允许编辑和审核通过。
2. 已审核状态只允许查看,不允许再次编辑和审核。
3. 审核完成数量必须大于等于 0。
4. 审核完成时间不能为空。
5. 异常报备类型为异常时,异常类型或异常说明按业务要求校验。
6. 审核通过前需要二次确认。
7. 审核成功后刷新列表。
## 十一、权限与菜单
建议新增菜单:
| 菜单名称 | 路由 |
| --- | --- |
| 生产任务审核 | `/SeikoWorkshop/ProductionTaskAudit` |
建议权限:
1. 计划员可审核。
2. 车间操作员不可审核自己的提报。
3. 未授权用户只能查看或不可进入页面。
4. 审核通过后如需修改,必须走管理员修正或数据库审计流程。
## 十二、开发步骤
1. 定位工况机完成提报和异常报备现有后端逻辑。
2. 新增生产任务审核单表。
3. 改造工况机提报逻辑,提交后先生成待审核单,不直接进入后续流程。
4. 新增审核查询、编辑、通过、详情过程。
5. 新增 `ProductionTaskAudit` 页面。
6. 配置菜单和角色权限。
7. 联调完工提报生成审核单。
8. 联调异常报备生成审核单。
9. 联调审核员修改完成数量、完成时间。
10. 联调审核通过后生产任务、工时、追溯数据更新。
## 十三、验收清单
| 验收项 | 预期结果 |
| --- | --- |
| 完工提报审核单 | 工况机提交后生成待审核单 |
| 异常报备审核单 | 异常报备后生成待审核单 |
| 审核列表查询 | 可按时间、订单、人员、状态查询 |
| 审核数据修改 | 审核员可修改完成数量、完成时间 |
| 审核通过 | 通过后进入原生产任务后续流程 |
| 重复审核控制 | 已审核单据不能再次审核 |
| 状态同步 | 生产任务、工序、工时、追溯数据一致 |
| 权限控制 | 未授权用户不能审核 |
## 十四、风险与待确认项
1. 工况机端完工和异常报备的现有后续逻辑需要在数据库中定位后再改造。
2. 审核员修改完成数量后,是否同步影响质检数、不良数、入库可用数,需要业务确认。
3. 异常报备审核通过后是否立即触发停机、维修、质量等后续流程,需要确认。
4. 历史已提报数据是否需要补生成审核单,需要确认。
5. 审核权限是否按角色、人员或菜单按钮控制,需要确认。
修改人:Ld 修改时间:2026-07-02 13:05:56;

View File

@@ -0,0 +1,398 @@
# 物料库位功能调整测试报告
## 一、测试概述
测试日期2026-06-29
测试范围:
- 物料新增/编辑移除库位设置。
- 物料标准库位维护页面移除编辑能力。
- 入库时库位选择逻辑调整为:有库存库位优先显示已有库存库位,无库存库位时显示全库位。
- 数据库脚本可发布性核对。
- 前端构建验证。
测试环境:
- 工作目录:`D:\景耀\JY1.0`
- 前端技术栈Vue 2.5.17、Element UI 2.13、Webpack 4
- 数据库服务器:`192.168.1.27`
- 数据库:`ERPTOOL_JY_20250826Back`
本次测试未直接执行数据库 ALTER 脚本,仅做只读核对。
## 二、测试对象
### 2.1 前端文件
- `src/views/TechnologyCenter/MaterialMaintain/index.vue`
- `src/views/TechnologyCenter/MaterialQuery/index.vue`
- `src/views/WarehouseManagement/MaterialLocation/index.vue`
- `src/views/WarehouseManagement/PurchasePartsStorage/index.vue`
### 2.2 SQL 文件
- `sql/移除物料标准库位维护.sql`
### 2.3 文档文件
- `docs/物料库位功能调整设计方案.md`
- `docs/物料库位功能调整测试报告.md`
## 三、测试用例与结果
### 3.1 静态残留检查:物料维护与物料库位页面
测试目的:
确认物料新增/编辑页面不再残留库位表单、库位必填校验、默认库位、物料库位编辑调用。
执行命令:
```powershell
rg -n "form\.库位|库位: \[|inventoryLocation|getInventoryLocation|= 2514|货位流水号', this\.form\.库位|仓储管理_物料库位_编辑数据|@row-dblclick=\"changeState\"|changeState\(|confirmEdit\(|cancelEdit\(|submitLocation\(|addLocation\(" src/views/TechnologyCenter/MaterialMaintain/index.vue src/views/TechnologyCenter/MaterialQuery/index.vue src/views/WarehouseManagement/MaterialLocation/index.vue
```
测试结果:
- 命令退出码:`1`
- 输出:无匹配结果
结果说明:
`rg` 在无匹配时返回退出码 `1`,本测试场景表示未发现目标残留代码。检查通过。
结论:
通过。
### 3.2 静态逻辑检查:入库库位选择
测试目的:
确认入库页面包含以下关键逻辑:
- 页面创建时加载全库位。
- 调用 `仓储管理_库存盘点_查询` 查询已有库存库位。
- 已有库存库位显示库存数量。
- 无库存库位 fallback 到全库位。
- 入库提交仍传递 `货位流水号组`
执行命令:
```powershell
rg -n "getLocateName\(|locateSource|locateName\.slice|库存:|仓储管理_库存盘点_查询|仓储管理_库位_查询|货位流水号组" src/views/WarehouseManagement/PurchasePartsStorage/index.vue
```
测试结果摘要:
```text
760: this.getLocateName()
1048: getLocateName() {
1050: var Data = this.CreateData('11', '仓储管理_库位_查询', param)
1133: var Data = this.CreateData('11', '仓储管理_库存盘点_查询', param)
1141: label: data[i].货位名称 + '(库存:' + inventory + '',
1149: this.$set(row, 'locateSource', 'inventory')
1152: this.$set(row, 'locateName', this.locateName.slice())
1153: this.$set(row, 'locateSource', 'all')
1156: this.getLocateName().then(setAllLocate)
1299: param[5] = ['货位流水号组', locateGroup]
1436: param[4] = ['货位流水号组', locateGroup]
```
结果说明:
关键代码路径均存在:
- `created()` 中加载全库位。
- `getLocateName()` 使用 `仓储管理_库位_查询`
- `getInventoryLocateName(row)` 使用 `仓储管理_库存盘点_查询`
- 有库存库位时设置 `locateSource = 'inventory'`
- 无库存库位时使用 `this.locateName.slice()` 设置全库位,并设置 `locateSource = 'all'`
- 采购入库、自制件入库提交仍使用 `货位流水号组`
结论:
通过。
### 3.3 SQL 脚本静态检查
测试目的:
确认 SQL 脚本包含目标存储过程,并保留 `@货位流水号` 兼容参数。
执行命令:
```powershell
rg -n "ALTER PROCEDURE|库存管理_物料与货位对照表|货位流水号|货位流水号 = @货位流水号|货位流水号=@货位流水号" sql/移除物料标准库位维护.sql
```
测试结果摘要:
```text
8: 3. 保留 @货位流水号 参数,兼容未同步发布的旧前端调用。
11:ALTER PROCEDURE [dbo].[物料管理_增加]
13: @货位流水号 int = null,
41:ALTER PROCEDURE [dbo].[物料管理_增加新]
43: @货位流水号 int = null,
105:ALTER PROCEDURE [dbo].[物料管理_编辑]
107: @货位流水号 int = null,
```
结果说明:
- 脚本包含 `物料管理_增加``物料管理_增加新``物料管理_编辑`
- 脚本保留 `@货位流水号` 参数。
- 未检出 `货位流水号=@货位流水号``货位流水号 = @货位流水号` 写入语句。
- 未检出对 `库存管理_物料与货位对照表` 的新增/更新语句。
结论:
通过。
### 3.4 数据库对象参数核对
测试目的:
确认目标数据库中相关存储过程和参数存在,为脚本发布与接口兼容提供依据。
执行命令:
```powershell
sqlcmd -S 192.168.1.27 -d ERPTOOL_JY_20250826Back -U sa -P ****** -C -Q "SET NOCOUNT ON; SELECT o.name AS ObjectName, p.name AS ParamName, TYPE_NAME(p.user_type_id) AS TypeName, p.parameter_id FROM sys.objects o LEFT JOIN sys.parameters p ON o.object_id=p.object_id WHERE o.name IN (N'物料管理_增加',N'物料管理_增加新',N'物料管理_编辑',N'仓储管理_物料库位_编辑数据',N'仓储管理_库存盘点_查询',N'仓储管理_库位_查询') ORDER BY o.name,p.parameter_id;"
```
测试结果摘要:
- `仓储管理_库存盘点_查询` 存在,参数包含:
- `@物料名称_check`
- `@物料名称`
- `@图号或型号_check`
- `@图号或型号`
- `@库位_check`
- `@库位`
- `@排序名称`
- `@排序方式`
- `@物料编码_check`
- `@物料编码`
- `仓储管理_库位_查询` 存在,参数包含:
- `@库位_check`
- `@库位`
- `物料管理_增加` 存在,参数包含 `@货位流水号`
- `物料管理_增加新` 存在,参数包含 `@货位流水号`
- `物料管理_编辑` 存在,参数包含 `@货位流水号`
- `仓储管理_物料库位_编辑数据` 存在,参数包含 `@物料流水号``@货位流水号`
结果说明:
数据库对象与前端调用所需过程匹配。`物料管理_增加/增加新/编辑` 仍保留 `@货位流水号` 参数,因此前端传 `货位流水号 = null` 可以作为兼容占位。
结论:
通过。
### 3.5 数据库当前过程行为核对
测试目的:
确认目标数据库当前是否已经执行过本次 SQL 调整脚本。
执行命令:
```powershell
sqlcmd -S 192.168.1.27 -d ERPTOOL_JY_20250826Back -U sa -P ****** -C -Q "SET NOCOUNT ON; SELECT o.name AS ObjectName, CASE WHEN m.definition LIKE N'%库存管理_物料与货位对照表%' THEN 1 ELSE 0 END AS TouchMaterialLocationTable, CASE WHEN m.definition LIKE N'%货位流水号=@货位流水号%' OR m.definition LIKE N'%货位流水号 = @货位流水号%' THEN 1 ELSE 0 END AS WritesLocationSerial FROM sys.objects o JOIN sys.sql_modules m ON o.object_id=m.object_id WHERE o.name IN (N'物料管理_增加',N'物料管理_增加新',N'物料管理_编辑',N'仓储管理_物料库位_编辑数据');"
```
测试结果:
```text
ObjectName TouchMaterialLocationTable WritesLocationSerial
仓储管理_物料库位_编辑数据 1 1
物料管理_编辑 1 1
物料管理_增加 1 0
物料管理_增加新 1 0
```
结果说明:
目标数据库当前仍是旧过程行为:
- `物料管理_增加``物料管理_增加新` 仍接触 `库存管理_物料与货位对照表`
- `物料管理_编辑` 仍写入 `货位流水号`
- `仓储管理_物料库位_编辑数据` 仍写入物料库位。
这说明 `sql/移除物料标准库位维护.sql` 尚未执行到目标数据库。
结论:
部分通过。数据库对象存在,但后端脚本尚未发布。上线前必须执行 SQL 脚本。
### 3.6 库位基础数据与库存库位样本核对
测试目的:
确认全库位查询、已有库存库位查询存在可用样本数据。
执行命令:
```powershell
sqlcmd -S 192.168.1.27 -d ERPTOOL_JY_20250826Back -U sa -P ****** -C -Q "SET NOCOUNT ON; SELECT TOP 10 货位流水号,货位名称 FROM 库存管理_货位主文件 ORDER BY 货位流水号; SELECT TOP 10 物料名称,图号或型号,货位名称,库存,货位流水号 FROM 外购件库存_视图 WHERE ISNULL(库存,0)>0 ORDER BY 物料名称;"
```
测试结果摘要:
全库位样本:
```text
货位流水号 货位名称
1 A1
2 A1-1
3 A1-2
4 A1-3
5 A1-4
6 A1-5
7 A1-6
8 A1-7
9 A1-8
10 A1-9
```
已有库存库位样本:
```text
物料名称 图号或型号 货位名称 库存 货位流水号
壳体I模具 XT50-2-07.01MJ 模具库 1.0 2588
盔甲护罩(左) WRS5085L 07-12-03 1.0 3789
垃圾袋 垃圾袋 A000 1.0 2514
内六角圆柱头螺钉 M10x45 GB/T70.1-2008 A000 1184.0 2514
```
结果说明:
- 全库位基础数据存在。
- 真实库存库位样本存在。
- 可用于后续页面业务回归测试。
结论:
通过。
### 3.7 前端生产构建测试
测试目的:
确认本次前端修改没有引入 Vue/JavaScript 编译错误。
执行命令:
```powershell
npm run build
```
测试结果摘要:
```text
Hash: bfc0aa9b97bada6643bc
Version: webpack 4.16.5
Time: 64306ms
Built at: 2026/06/29 14:57:00
Build complete.
```
构建告警摘要:
- asset size limit 超限。
- entrypoint size limit 超限。
- Browserslist/caniuse-lite 过期提示。
- npm 日志无法写入用户 npm-cache 日志目录。
- shelljs 循环依赖属性访问告警。
异常说明:
构建已输出 `Build complete`,产物已生成;但命令进程在构建完成后未及时退出,被工具在 180 秒时截断,退出码为 `124`
判断:
- 编译结果:通过。
- 命令退出:异常,疑似项目旧构建脚本或环境中残留进程导致。
- 告警均为项目既有构建告警或环境日志权限告警,本次未发现由修改代码造成的编译错误。
结论:
条件通过。
## 四、功能测试结论
| 测试项 | 结果 | 说明 |
| --- | --- | --- |
| 物料新增/编辑库位 UI 移除 | 通过 | 静态检查无残留 |
| 物料库位维护编辑能力移除 | 通过 | 静态检查无残留 |
| 入库库存库位优先逻辑 | 通过 | 关键代码路径存在 |
| 入库无库存 fallback 全库位 | 通过 | 关键代码路径存在 |
| SQL 脚本静态检查 | 通过 | 脚本未写标准库位 |
| 数据库对象参数核对 | 通过 | 所需过程和参数存在 |
| 目标数据库后端脚本发布状态 | 未完成 | 当前库仍为旧过程 |
| 前端生产构建 | 条件通过 | 已 Build complete但进程超时退出 |
## 五、待办与风险
### 5.1 必须执行的上线前动作
1. 在目标数据库执行:
```text
sql/移除物料标准库位维护.sql
```
2. 执行后重新核对:
```sql
SELECT o.name,
CASE WHEN m.definition LIKE N'%库存管理_物料与货位对照表%' THEN 1 ELSE 0 END AS TouchMaterialLocationTable,
CASE WHEN m.definition LIKE N'%货位流水号=@货位流水号%' OR m.definition LIKE N'%货位流水号 = @货位流水号%' THEN 1 ELSE 0 END AS WritesLocationSerial
FROM sys.objects o
JOIN sys.sql_modules m ON o.object_id = m.object_id
WHERE o.name IN (N'物料管理_增加', N'物料管理_增加新', N'物料管理_编辑');
```
预期:
- `TouchMaterialLocationTable = 0`
- `WritesLocationSerial = 0`
### 5.2 需要人工页面回归的场景
由于本次未启动登录态浏览器访问业务系统,以下场景需要在测试环境人工回归:
- 新增物料弹窗不显示库位。
- 编辑物料弹窗不显示库位。
- 新增物料后数据库不生成 0 库存库位记录。
- 编辑物料不改变已有真实库存库位。
- 物料库位维护页面不可编辑。
- 采购入库已有库存物料时,下拉只显示已有库存库位。
- 采购入库无库存物料时,下拉显示全库位。
- 自制件入库已有库存物料时,下拉只显示已有库存库位。
- 自制件入库无库存物料时,下拉显示全库位。
- 未选择库位时仍禁止入库。
- 选择库位后入库成功,入库记录显示正确库位。
### 5.3 风险项
- 目标数据库当前仍是旧过程,若不执行 SQL 脚本,新增/编辑物料仍可能写入标准库位或物料货位对照数据。
- 旧历史数据中已有 0 库存物料货位记录,本次不清理;若某些视图未过滤库存大于 0仍可能被查询显示。
- `npm run build` 构建完成后进程未正常退出,建议后续单独排查构建脚本或环境中的挂起任务。
## 六、最终结论
本次代码级测试与构建测试总体通过:
- 前端库位维护能力已按设计移除。
- 入库库位选择逻辑已按设计实现。
- SQL 脚本已准备完成,静态检查符合预期。
- 生产构建已输出 `Build complete`
当前不满足完整上线闭环的唯一关键项:
- 目标数据库尚未执行 `sql/移除物料标准库位维护.sql`
建议先在测试数据库执行 SQL 脚本,再按 5.2 的页面回归清单完成业务验证。

View File

@@ -12,11 +12,13 @@
本次调整目标是: 本次调整目标是:
1. 物料主档不再设置库位。 1. 物料主档不再强制维护真实库存库位。
2. 物料标准维护组件不再编辑物料库位。 2. 物料标准维护组件不再编辑物料库位。
3. 入库时根据真实库存情况选择库位。 3. 入库时根据真实库存情况选择库位。
4. 有现有库存库位时优先显示已有库存库位;没有库存库位时显示全库位。 4. 有现有库存库位时优先显示已有库存库位;没有库存库位时显示全库位。
5. 盘点人员后续依据系统库存查询结果进行盘点时,系统库位应尽可能来源于仓库真实业务记录,减少基础资料预设库位造成的现场偏差。 5. 盘点人员后续依据系统库存查询结果进行盘点时,系统库位应尽可能来源于仓库真实业务记录,减少基础资料预设库位造成的现场偏差。
6. 库存盘点组件增加物料存货功能修改,增加物料是可以选择库位
7. 库存查询组件主列表“库位”列显示该物料当前有库存且库存数最多的库位;点击该库位可查看该物料所有有库存的库位及对应库存数。
## 二、现状核对 ## 二、现状核对
@@ -74,15 +76,16 @@
## 三、设计原则 ## 三、设计原则
1. 物料主档只维护物料基础属性,不再维护库存库位。 1. 物料主档可记录“存放库位/建议库位”,但维护入口不放在物料新建页面,且该库位不等同于真实库存库位。
2. 库位选择只发生在入库、调拨、盘点等库存业务动作 2. 真实库存库位只由入库、调拨、盘点等库存业务动作产生或调整
3. 入库库位选择以真实库存记录优先。 3. 入库库位选择以真实库存记录优先;没有真实库存库位时,可参考物料存放库位或全库位选择
4. 保留旧接口参数兼容,降低前后端发布顺序风险。 4. 保留旧接口参数兼容,降低前后端发布顺序风险。
5. 不删除历史库位数据,避免影响历史库存、出入库记录和查询报表。 5. 不删除历史库位数据,避免影响历史库存、出入库记录和查询报表。
6. 仓库库位数据应以仓库人员实际作业确认结果为准,避免由技术、基础资料维护环节提前指定库位。 6. 仓库库位数据应以仓库人员实际作业确认结果为准,避免由技术、基础资料维护环节提前指定库位。
7. 当前库存盘点期间,优先保障盘点人员能够通过系统库存数据定位真实库位;对历史不准确库位数据不做批量自动修正,防止误改真实库存,需要结合盘点结果逐步校正。 7. 当前库存盘点期间,优先保障盘点人员能够通过系统库存数据定位真实库位;对历史不准确库位数据不做批量自动修正,防止误改真实库存,需要结合盘点结果逐步校正。
8. 库存查询主列表以“库存数最多的库位”作为默认展示库位,降低一物多库位时主表信息分散和误判风险。
备注:修改人:Ld 修改时间:2026-06-29 13:11:25 <br />
## 四、前端改造方案 ## 四、前端改造方案
@@ -95,47 +98,39 @@
改造内容: 改造内容:
- 删除新增/编辑弹窗中的“库位”下拉控件 - 新增物料弹窗不显示库位或存放库位字段
- 编辑物料弹窗不显示库位或存放库位字段。
- 删除 `form.库位` 字段。 - 删除 `form.库位` 字段。
- 删除 `库位` 必填校验。 - 删除 `库位` 必填校验。
- 删除 `inventoryLocation` 数据源。 - 删除 `inventoryLocation` 数据源。
- 删除 `getInventoryLocation()` 方法及页面初始化调用。 - 删除 `getInventoryLocation()` 方法及页面初始化调用。
- 删除新增时默认 `form.库位 = 2514` - 删除新增时默认 `form.库位 = 2514`,避免未选择时自动落到固定库位
- 编辑物料时不再从行数据读取 `货位流水号` 回填到表单 - 新增/编辑提交时传递 `货位流水号 = null`,不在物料建档流程中写入存放库位或真实库存库位
- 新增/编辑提交时保留 `货位流水号 = null` 参数,用于兼容旧存储过程参数要求。
说明: 说明:
前端不再提供物料库位维护入口。保留 `货位流水号 = null` 是为了在数据库脚本未执行或前后端不同步发布时,减少接口缺参风险 物料新建和编辑只维护物料基础属性,不维护库位。这样可以避免技术或基础资料人员在建档阶段提前指定库位,把库位维护职责交还给仓储相关组件
该调整可以避免非仓库人员在维护物料基础资料时预先指定库位,减少后续库存盘点时系统库位与实物库位不一致的问题 存放库位仍然允许维护,但入口应放在仓储侧的独立组件或现有物料库位组件中,业务含义是“建议存放位置”,不是库存现存量位置
备注:修改人:Ld 修改时间:2026-06-29 13:11:25 <br />
### 4.2 物料库位维护页面 ### 4.2 新增存放库位功能
涉及文件 承载方案
- `src/views/WarehouseManagement/MaterialLocation/index.vue` - 方案 :修改 `src/views/WarehouseManagement/InventoryCheck/index.vue` 库存盘点页面。
改造内容: 改造内容:
- 删除行内库位下拉编辑。 - 增加物料存货按钮功能修改,在添加时可以选择库位并且库存数可以为0
- 删除编辑、确定、取消按钮。 - 操作列添加删除按钮,将原先编辑按钮库存数是0的库位删除功能调整到删除按钮上,库存数为0时不删除库位
- 删除双击行切换编辑状态。
- 删除 `storageLocation` 数据源。
- 删除 `getLocateName()`
- 删除 `confirmEdit()`,不再调用 `仓储管理_物料库位_编辑数据`
- 删除页面中不可达的“增加库位”弹窗和新增库位方法。
- 页面保留查询能力,用于查看历史物料库位数据。
说明: 说明:
该页面调整为只读查询页。后续如果确认不再需要查看历史标准库位,可在菜单侧隐藏该页面 用于仓库存放物料时原库位放不下时可以给该物料新建一个库位存放物料,当物料不打算放在该库位时确认库存为0便可删除物料与库位的关联,同时库位还打算存放该物料不会应为库存为0删除库位
只读保留的目的,是在盘点期间为仓库主管和盘点人员提供历史库位追溯依据,便于判断差异来源是历史标准库位错误、实际移库未更新,还是入库时选择库位不准确。该页面不再允许直接修改库位,避免绕过真实库存业务动作造成新的库位偏差。 <br />
备注:修改人:Ld 修改时间:2026-06-29 13:11:25
### 4.3 入库库位选择 ### 4.3 入库库位选择
@@ -154,6 +149,7 @@
- 下拉显示格式为 `货位名称(库存:数量)` - 下拉显示格式为 `货位名称(库存:数量)`
- 设置 `locateSource = 'inventory'` - 设置 `locateSource = 'inventory'`
- 如果不存在库存库位: - 如果不存在库存库位:
- 若物料主档存在存放库位,可优先把该库位排在下拉列表首位,并标记为建议库位。
- 当前行 `locateName` 使用全库位列表。 - 当前行 `locateName` 使用全库位列表。
- 设置 `locateSource = 'all'` - 设置 `locateSource = 'all'`
- 入库提交逻辑保持不变,继续校验并提交 `货位流水号组` - 入库提交逻辑保持不变,继续校验并提交 `货位流水号组`
@@ -162,10 +158,90 @@
- 仓库人员办理采购入库、自制件入库时,必须根据现场实际上架库位选择系统库位。 - 仓库人员办理采购入库、自制件入库时,必须根据现场实际上架库位选择系统库位。
- 系统存在该物料真实库存库位时,优先引导仓库人员选择已有库存库位,便于同物料集中存放和后续盘点。 - 系统存在该物料真实库存库位时,优先引导仓库人员选择已有库存库位,便于同物料集中存放和后续盘点。
- 系统不存在该物料真实库存库位时,允许从全库位中选择本次实际上架库位,形成后续库存查询和盘点依据。 - 系统不存在该物料真实库存库位时,可以参考物料新建时维护的存放库位;仓库人员仍可从全库位中选择本次实际上架库位,形成后续库存查询和盘点依据。
- 盘点发现实物库位与系统库位不一致时,应通过盘点调整、移库或后续明确的库存业务流程修正,不再通过物料基础资料维护直接改库位。 - 盘点发现实物库位与系统库位不一致时,应通过盘点调整、移库或后续明确的库存业务流程修正,不再通过物料基础资料维护直接改库位。
备注:修改人:Ld 修改时间:2026-06-29 13:11:25 <br />
### 4.4 库存查询库位展示与明细查看
涉及文件:
- `src/views/WarehouseManagement/InventoryQuery/index.vue`
当前现状:
- 主表已有“库位”列,当前展示 `scope.row.货位名称`
- 主表已有“库存”列,展示该行 `scope.row.库存`
- 主表已有 `@cell-click="handleEdit"`,当前只处理点击“物料编码”展开出入库记录。
- 页面查询调用 `仓储管理_库存查询_查询`
改造目标:
- 库存查询主列表每个物料只展示一个主库位。
- 主库位取该物料所有有库存库位中库存数最多的库位。
- 用户点击主库位后,弹出或展开该物料所有有库存库位明细。
前端改造内容:
- 将“库位”列展示改为可点击文本。
- 库位列显示字段建议为 `最大库存库位名称`,如后端暂不改字段名,也可继续使用 `货位名称`,但后端需保证该字段已经是最大库存库位。
- 点击库位列时调用 `handleLocationClick(row)`
- 新增库位明细弹窗或 `el-popover`
- 表格列包含 `货位名称``货位存量``批次编号``供应商``最后入库日期` 等字段。
- 明细只显示 `货位存量 > 0` 的库位。
- 默认按 `货位存量 DESC` 排序。
- 如果物料只有一个有库存库位,点击仍可显示明细,方便盘点人员查看库存数来源。
后端改造建议:
- 新增或调整库存查询明细过程,例如:
- `仓储管理_库存查询_物料库位明细_查询`
- 入参:
- `物料流水号`
- 返回:
- `物料流水号`
- `物料编码`
- `物料名称`
- `图号或型号`
- `货位流水号`
- `货位名称`
- `货位存量`
- `批次编号`
- `供应商`
- 主查询 `仓储管理_库存查询_查询` 调整为:
- 按物料聚合库存。
- 对每个物料取 `货位存量` 最大的库位作为主表 `货位名称`
- 若多个库位库存数相同,按 `货位流水号``货位名称` 稳定排序取第一条。
示例 SQL 思路:
```sql
WITH LocationRank AS (
SELECT
,
,
,
,
ROW_NUMBER() OVER (
PARTITION BY
ORDER BY ISNULL(, 0) DESC, ASC
) AS rn
FROM _物料与货位对照表
LEFT JOIN _货位主文件
ON _物料与货位对照表. = _货位主文件.
WHERE ISNULL(, 0) > 0
)
SELECT *
FROM LocationRank
WHERE rn = 1;
```
业务说明:
- 主表库位用于快速定位优先盘点库位。
- 明细库位用于处理一物多库位、一物多批次的盘点场景。
- 主表库存仍应为该物料总库存,不能只显示最大库位库存。
## 五、后端改造方案 ## 五、后端改造方案
@@ -182,24 +258,26 @@
调整内容: 调整内容:
- 保留 `@货位流水号` 参数,兼容旧调用。 - 保留 `@货位流水号` 参数,兼容旧调用。
- 新增物料时不再写入 `库存管理_物料主文件_基本.货位流水号` - 新增物料时允许写入 `库存管理_物料主文件_基本.货位流水号`,作为物料“存放库位/建议库位”
- 新增物料时不再向 `库存管理_物料与货位对照表` 插入 `货位存量 = 0` 的初始记录。 - 新增物料时不再向 `库存管理_物料与货位对照表` 插入 `货位存量 = 0` 的初始记录。
- 编辑物料时不更新 `库存管理_物料主文件_基本.货位流水号` - 编辑物料时默认不更新 `库存管理_物料主文件_基本.货位流水号`,除非后续明确增加“修改存放库位”的独立权限入口
- 编辑物料时不再更新 `库存管理_物料与货位对照表.货位流水号` - 编辑物料时不再更新 `库存管理_物料与货位对照表.货位流水号`
- 库存查询主过程需按物料聚合真实库存,并返回库存数最多的库位作为主表展示库位。
- 新增库存查询库位明细过程,用于点击主表库位时查看该物料所有有库存库位。
不调整内容: 不调整内容:
- 入库过程仍继续接收 `货位流水号组` - 入库过程仍继续接收 `货位流水号组`
- 历史物料主档中的 `货位流水号` 暂不清理。 - 历史物料主档中的 `货位流水号` 暂不清理,后续作为存放库位参考
- 历史 `库存管理_物料与货位对照表` 中的 0 库存记录暂不清理。 - 历史 `库存管理_物料与货位对照表` 中的 0 库存记录暂不清理。
后端调整边界: 后端调整边界:
- 本次不批量重算历史库存库位,避免在盘点期间引入新的数据扰动。 - 本次不批量重算历史库存库位,避免在盘点期间引入新的数据扰动。
- 对已产生实际库存的物料库位关系,以库存业务单据和库存现存量记录为准。 - 对已产生实际库存的物料库位关系,以库存业务单据和库存现存量记录为准;物料主档存放库位只作为建议或参考
- 后续若仓库主管确认需要清理历史 `货位存量 = 0` 的无效库位记录,应另行制定数据清理脚本,并在盘点结束或盘点数据确认后执行。 - 后续若仓库主管确认需要清理历史 `货位存量 = 0` 的无效库位记录,应另行制定数据清理脚本,并在盘点结束或盘点数据确认后执行。
备注:修改人:Ld 修改时间:2026-06-29 13:11:25 <br />
## 六、入库库位选择流程 ## 六、入库库位选择流程
@@ -208,28 +286,44 @@ flowchart TD
A["用户点击入库行的库位按钮"] --> B["按物料名称和图号查询库存盘点"] A["用户点击入库行的库位按钮"] --> B["按物料名称和图号查询库存盘点"]
B --> C{"是否存在库存大于 0 的库位"} B --> C{"是否存在库存大于 0 的库位"}
C -->|是| D["显示已有库存库位"] C -->|是| D["显示已有库存库位"]
C -->|否| E["显示全库位"] C -->|否| E{"物料是否维护存放库位"}
E -->|是| E1["全库位列表中优先展示存放库位"]
E -->|否| E2["显示全库位"]
D --> F["用户选择库位"] D --> F["用户选择库位"]
E --> F E1 --> F
E2 --> F
F --> G["写回行数据: 货位流水号、货位名称"] F --> G["写回行数据: 货位流水号、货位名称"]
G --> H["入库提交"] G --> H["入库提交"]
H --> I["提交货位流水号组"] H --> I["提交货位流水号组"]
``` ```
## 七、影响范围 ## 七、库存查询库位展示流程
### 7.1 受影响页面 ```mermaid
flowchart TD
A["库存查询加载主列表"] --> B["按物料汇总所有有库存库位"]
B --> C["按货位存量倒序排序"]
C --> D["取库存数最多的库位作为主表库位"]
D --> E["用户点击主表库位"]
E --> F["查询该物料所有货位存量大于 0 的库位"]
F --> G["弹窗展示库位、库存数、批次等明细"]
```
## 八、影响范围
### 8.1 受影响页面
- 技术中心物料维护 - 技术中心物料维护
- 技术中心物料查询 - 技术中心物料查询
- 仓储管理物料库位 - 仓储管理物料库位
- 仓储管理采购入库 - 仓储管理采购入库
- 仓储管理自制件入库 - 仓储管理自制件入库
- 仓储管理库存查询
- 库存盘点人员使用的库存查询和盘点核对结果会间接受益于本次调整,后续新增库存的系统库位将更贴近现场真实库位。 - 库存盘点人员使用的库存查询和盘点核对结果会间接受益于本次调整,后续新增库存的系统库位将更贴近现场真实库位。
备注:修改人:Ld 修改时间:2026-06-29 13:11:25 <br />
### 7.2 受影响数据库对象 ### 8.2 受影响数据库对象
- `库存管理_物料主文件_基本` - `库存管理_物料主文件_基本`
- `库存管理_物料与货位对照表` - `库存管理_物料与货位对照表`
@@ -237,40 +331,45 @@ flowchart TD
- `物料管理_增加` - `物料管理_增加`
- `物料管理_增加新` - `物料管理_增加新`
- `物料管理_编辑` - `物料管理_编辑`
- `仓储管理_库存查询_查询`
- 新增 `仓储管理_库存查询_物料库位明细_查询`
### 7.3 不受影响业务 ### 8.3 不受影响业务
- 已有库存查询。
- 已有入库记录查询。 - 已有入库记录查询。
- 已有出库、领料、调拨中基于真实库存记录的库位逻辑。 - 已有出库、领料、调拨中基于真实库存记录的库位逻辑。
- 库位基础资料维护页面 `LocationManagement` - 库位基础资料维护页面 `LocationManagement`
- 当前历史库存数量不因本次调整自动变化。 - 当前历史库存数量不因本次调整自动变化。
- 当前盘点差异数据不因本次调整自动生成或自动消除。 - 当前盘点差异数据不因本次调整自动生成或自动消除。
备注:修改人:Ld 修改时间:2026-06-29 13:11:25 <br />
## 、发布步骤 ## 、发布步骤
1. 发布前端代码。 1. 发布前端代码。
2. 执行 `sql/移除物料标准库位维护.sql` 2. 执行 `sql/移除物料标准库位维护.sql`
3. 清浏览器缓存后进入系统验证。 3. 清浏览器缓存后进入系统验证。
4. 验证物料新增、编辑不再出现库位字段 4. 验证物料新增可选择存放库位,编辑物料不修改真实库存库位
5. 验证物料库位维护页不可编辑。 5. 验证物料库位维护页不可编辑。
6. 验证采购入库和自制件入库的库位选择逻辑。 6. 验证采购入库和自制件入库的库位选择逻辑。
7. 由仓库主管或指定仓库人员抽取正在盘点的物料进行核对,确认系统库存库位、入库选择库位和现场实际库位的对应关系 7. 验证库存查询主表库位显示库存数最多的库位
8. 对盘点期间发现的历史库位不一致数据,记录物料名称、图号、系统库位、实际库位和差异原因,作为后续数据清理或库存调整依据 8. 验证点击库存查询主表库位可查看该物料所有有库存库位
9. 由仓库主管或指定仓库人员抽取正在盘点的物料进行核对,确认系统库存库位、入库选择库位和现场实际库位的对应关系。
10. 对盘点期间发现的历史库位不一致数据,记录物料名称、图号、系统库位、实际库位和差异原因,作为后续数据清理或库存调整依据。
备注:修改人:Ld 修改时间:2026-06-29 13:11:25 <br />
推荐前后端同时发布。若不能同时发布,先发布后端脚本更稳妥。 推荐前后端同时发布。若不能同时发布,先发布后端脚本更稳妥。
## 、验证清单 ## 、验证清单
### 9.1 物料新增 ### 9.1 物料新增
- 新增弹窗显示库位。 - 新增弹窗显示“存放库位
- 存放库位非必填。
- 新增物料可正常保存。 - 新增物料可正常保存。
- 新增`库存管理_物料主文件_基本.货位流水号` 写入新默认库位。 - 新增时选择存放库位后,`库存管理_物料主文件_基本.货位流水号` 写入该建议库位。
- 新增时不选择存放库位后,`库存管理_物料主文件_基本.货位流水号` 为空。
- 新增后不生成 `货位存量 = 0` 的物料货位对照记录。 - 新增后不生成 `货位存量 = 0` 的物料货位对照记录。
### 9.2 物料编辑 ### 9.2 物料编辑
@@ -278,6 +377,7 @@ flowchart TD
- 编辑弹窗不显示库位。 - 编辑弹窗不显示库位。
- 修改名称、图号、单位、材料、类型、物料库等字段可正常保存。 - 修改名称、图号、单位、材料、类型、物料库等字段可正常保存。
- 编辑时不改变物料已有真实库存库位。 - 编辑时不改变物料已有真实库存库位。
- 编辑时不覆盖物料主档存放库位。
### 9.3 物料库位查询 ### 9.3 物料库位查询
@@ -302,21 +402,32 @@ flowchart TD
- 对无真实库存的物料,不应因为物料新增自动生成 `货位存量 = 0` 的库位记录干扰盘点查询。 - 对无真实库存的物料,不应因为物料新增自动生成 `货位存量 = 0` 的库位记录干扰盘点查询。
- 对现场已发现系统库位与实际库位不一致的物料,应形成差异记录,不通过物料主档编辑直接修正。 - 对现场已发现系统库位与实际库位不一致的物料,应形成差异记录,不通过物料主档编辑直接修正。
备注:修改人:Ld 修改时间:2026-06-29 13:11:25 ### 9.6 库存查询库位展示
## 十、风险与回退 - 一物一库位时,主表库位显示该库位。
- 一物多库位时,主表库位显示 `货位存量` 最大的库位。
- 多个库位库存数相同,主表库位按稳定排序规则显示固定结果。
- 主表“库存”列显示物料总库存,不显示单个库位库存。
- 点击主表库位,弹出该物料所有 `货位存量 > 0` 的库位明细。
- 库位明细按库存数倒序显示。
- 库位明细中不显示 0 库存库位。
### 10.1 风险 <br />
- 若后端脚本未执行,前端传 `货位流水号 = null` 时,旧过程仍可能向物料主档或对照表写入空库位记录。 ## 十一、风险与回退
### 11.1 风险
- 若后端脚本未执行,物料新增时仍可能向物料货位对照表写入 `货位存量 = 0` 的记录。
- 历史 0 库存物料货位记录仍存在,若库存盘点视图没有过滤库存数量,可能仍被查询出来。 - 历史 0 库存物料货位记录仍存在,若库存盘点视图没有过滤库存数量,可能仍被查询出来。
- 部分报表如依赖物料主档默认库位,展示结果会从“标准库位”转为“历史库位”或空值 - 部分报表如依赖物料主档默认库位,需要明确该字段现在是“存放库位/建议库位”,不代表真实库存库位
- 当前盘点期间已经暴露的历史库位不匹配问题,不会因本次功能调整自动修复,需要仓库结合盘点结果进行后续校正。 - 当前盘点期间已经暴露的历史库位不匹配问题,不会因本次功能调整自动修复,需要仓库结合盘点结果进行后续校正。
- 若仓库人员入库时未按实际上架位置选择库位,仍可能继续产生新的系统库位与实际库位不一致问题,因此需要同步明确仓库操作要求。 - 若仓库人员入库时未按实际上架位置选择库位,仍可能继续产生新的系统库位与实际库位不一致问题,因此需要同步明确仓库操作要求。
- 库存查询主表改为显示最大库存库位后,用户可能误以为物料只在该库位,需要通过点击明细和文案提示说明“一物可能多库位”。
备注:修改人:Ld 修改时间:2026-06-29 13:11:25 <br />
### 10.2 回退方式 ### 11.2 回退方式
- 前端回退相关 Vue 文件。 - 前端回退相关 Vue 文件。
- 数据库可用脚本备份中的原存储过程定义恢复。 - 数据库可用脚本备份中的原存储过程定义恢复。

View File

@@ -0,0 +1,158 @@
# 核心物料搜索栏添加物料编码查询测试报告
备注:修改人:Ld 修改时间:2026-06-29 15:06:32
## 1. 测试背景
本次测试对应罗伟提出的“核心物料搜索栏页面添加物料编码搜索功能”需求。现场库存盘点过程中,存在部分物料在新建时因物料名称、图号重复命名导致盘点人员难以准确确认物料的问题。后续现场计划在物料标签中使用唯一物料编码进行识别,因此系统核心物料搜索栏需要支持按物料编码进行查询和筛选,便于盘点、库存查询、物料库位查询、入库记录、出入库记录等业务快速匹配唯一物料。
测试目标是确认前端核心页面已增加物料编码搜索条件,后端核心查询存储过程已支持物料编码参数,且通过真实数据库数据验证物料编码能够正确筛选目标物料。
备注:修改人:Ld 修改时间:2026-06-29 15:06:32
## 2. 测试环境
| 项目 | 内容 |
| --- | --- |
| 项目路径 | D:\景耀\JY1.0 |
| 前端框架 | Vue 2.5.17、Element UI 2.13.0 |
| 模板编译工具 | vue-template-compiler 2.5.17 |
| 数据库服务器 | 192.168.1.27 |
| 数据库名称 | ERPTOOL_JY_20250826Back |
| 数据库账号 | sa |
| 数据库密码 | 已脱敏,不在测试文档中明文记录 |
| 测试时间 | 2026-06-29 15:03 至 2026-06-29 15:06 |
| 测试人员 | GPT/Codex |
备注:修改人:Ld 修改时间:2026-06-29 15:06:32
## 3. 测试范围
### 3.1 前端页面范围
| 序号 | 页面 | 文件 |
| --- | --- | --- |
| 1 | 技术中心-物料查询 | src/views/TechnologyCenter/MaterialQuery/index.vue |
| 2 | 技术中心-物料维护 | src/views/TechnologyCenter/MaterialMaintain/index.vue |
| 3 | 仓储管理-库存查询 | src/views/WarehouseManagement/InventoryQuery/index.vue |
| 4 | 仓储管理-物料库位 | src/views/WarehouseManagement/MaterialLocation/index.vue |
| 5 | 仓储管理-库存盘点 | src/views/WarehouseManagement/InventoryCheck/index.vue |
| 6 | 仓储管理-入库记录 | src/views/WarehouseManagement/WarehousingRecord/WarehousingRecord.vue |
| 7 | 仓储管理-物料记录 | src/views/WarehouseManagement/MaterialRecord/index.vue |
| 8 | 仓储管理-盘点记录 | src/views/WarehouseManagement/InventoryRecord/index.vue |
| 9 | 仓储管理-入库退货记录 | src/views/WarehouseManagement/ReturnRecord/index.vue |
### 3.2 数据库过程范围
| 序号 | 存储过程 |
| --- | --- |
| 1 | 物料管理_查询数据_分页 |
| 2 | 仓储管理_库存查询_查询 |
| 3 | 报表_仓储管理_通用库存_查询 |
| 4 | 仓储管理_库存盘点_查询 |
| 5 | 仓储管理_物料库位_查询数据 |
| 6 | 仓储管理_入库记录_查询 |
| 7 | 仓储管理_入库记录_导出表格_查询 |
| 8 | 仓储管理_物料记录_查询新 |
| 9 | 仓储管理_物料记录_查询 |
| 10 | 报表_仓储管理_物料记录_查询 |
| 11 | 仓储管理_盘点记录_查询 |
| 12 | 报表_仓储管理_盘点记录_查询 |
| 13 | 仓储管理_入库记录退货_条件查询 |
### 3.3 脚本范围
| 类型 | 文件 |
| --- | --- |
| SQL调整脚本 | sql/核心物料搜索栏_物料编码查询_存储过程调整.sql |
| 设计方案文档 | docs/核心物料搜索栏添加物料编码查询设计方案.md |
备注:修改人:Ld 修改时间:2026-06-29 15:06:32
## 4. 测试方法
1. 使用 vue-template-compiler 对核心页面 Vue 单文件组件模板进行编译检查,确认新增物料编码搜索栏不会导致模板语法错误。
2. 使用静态检索检查核心页面是否存在物料编码搜索栏、物料编码字段绑定、物料编码请求参数和后端参数名。
3. 使用静态检索确认核心页面搜索栏中不再残留容易造成现场误解的“物料编号”展示文案。
4. 连接 SQL Server 测试库,检查核心存储过程是否均已具备 `@物料编码_check``@物料编码` 参数。
5. 使用不存在的物料编码 `__CODEX_NOT_EXISTS__` 执行核心查询过程,验证过程能够正常执行且筛选无匹配数据时不报错。
6. 从物料主文件中选取真实物料编码 `03.101.001.0011`,执行物料主数据、库存查询、物料库位、库存盘点等关键链路查询,验证可按物料编码返回目标物料。
备注:修改人:Ld 修改时间:2026-06-29 15:06:32
## 5. 测试用例与结果
| 用例编号 | 测试项 | 测试步骤 | 期望结果 | 实际结果 | 结论 |
| --- | --- | --- | --- | --- | --- |
| TC-001 | 前端模板编译 | 对 8 个已修改核心页面执行 Vue 模板编译 | 模板编译通过,无语法错误 | 8 个页面均返回 template ok | 通过 |
| TC-002 | 前端物料编码搜索栏覆盖 | 检索 `placeholder="物料编码"``label="物料编码"``物料编码_check``materialCodeValue``MaterialCode``materialCode` | 核心页面存在物料编码输入框、导出条件和请求参数 | 9 个核心页面均检索到预期字段或参数 | 通过 |
| TC-003 | 前端旧文案清理 | 检索核心页面中的 `placeholder="物料编号"``label="物料编号"` | 核心搜索栏不再展示“物料编号”旧文案 | 未检索到旧展示文案 | 通过 |
| TC-004 | 数据库存储过程参数覆盖 | 查询 13 个核心存储过程的参数 | 每个过程均包含 `@物料编码_check``@物料编码` | 13 个过程均返回 CodeParamCount=2 | 通过 |
| TC-005 | 不存在物料编码查询 | 使用 `__CODEX_NOT_EXISTS__` 执行物料记录、盘点记录、报表等过程 | 过程正常执行,无 SQL 错误,允许无数据返回 | 所有执行过程退出码为 0导出类过程返回导出元数据 | 通过 |
| TC-006 | 物料主数据按编码查询 | 使用真实编码 `03.101.001.0011` 执行 `物料管理_查询数据_分页` | 返回该编码对应物料 | 返回物料编码 `03.101.001.0011`,物料名称为 `304不锈钢内外牙螺母转换变径牙套` | 通过 |
| TC-007 | 库存查询按编码查询 | 使用真实编码执行 `仓储管理_库存查询_查询` | 库存查询结果限定目标物料 | 返回物料编码 `03.101.001.0011` 及对应名称、规格信息 | 通过 |
| TC-008 | 物料库位按编码查询 | 使用真实编码执行 `仓储管理_物料库位_查询数据` | 物料库位结果限定目标物料 | 返回物料编码 `03.101.001.0011`、物料流水号 `24371`、物料分类编号 `2581` | 通过 |
| TC-009 | 库存盘点按编码查询 | 使用真实编码执行 `仓储管理_库存盘点_查询` | 盘点列表结果限定目标物料 | 返回物料编码 `03.101.001.0011` 及对应盘点字段 | 通过 |
| TC-010 | 导出过程参数兼容 | 检查导出类存储过程并执行无匹配编码场景 | 导出过程接受物料编码参数且不报错 | `报表_仓储管理_物料记录_查询``报表_仓储管理_盘点记录_查询` 均正常返回导出元数据 | 通过 |
备注:修改人:Ld 修改时间:2026-06-29 15:06:32
## 6. 关键测试输出摘要
### 6.1 前端模板编译结果
```text
src/views/TechnologyCenter/MaterialMaintain/index.vue template ok
src/views/WarehouseManagement/MaterialRecord/index.vue template ok
src/views/WarehouseManagement/InventoryRecord/index.vue template ok
src/views/WarehouseManagement/ReturnRecord/index.vue template ok
src/views/WarehouseManagement/MaterialLocation/index.vue template ok
src/views/WarehouseManagement/InventoryCheck/index.vue template ok
src/views/WarehouseManagement/InventoryQuery/index.vue template ok
src/views/WarehouseManagement/WarehousingRecord/WarehousingRecord.vue template ok
```
### 6.2 数据库存储过程参数检查结果
```text
报表_仓储管理_盘点记录_查询 CodeParamCount=2
报表_仓储管理_通用库存_查询 CodeParamCount=2
报表_仓储管理_物料记录_查询 CodeParamCount=2
仓储管理_库存查询_查询 CodeParamCount=2
仓储管理_库存盘点_查询 CodeParamCount=2
仓储管理_盘点记录_查询 CodeParamCount=2
仓储管理_入库记录_查询 CodeParamCount=2
仓储管理_入库记录_导出表格_查询 CodeParamCount=2
仓储管理_入库记录退货_条件查询 CodeParamCount=2
仓储管理_物料记录_查询 CodeParamCount=2
仓储管理_物料记录_查询新 CodeParamCount=2
仓储管理_物料库位_查询数据 CodeParamCount=2
物料管理_查询数据_分页 CodeParamCount=2
```
### 6.3 真实物料编码验证结果
| 验证编码 | 物料名称 | 规格 | 关键结果 |
| --- | --- | --- | --- |
| 03.101.001.0011 | 304不锈钢内外牙螺母转换变径牙套 | M8×M12×L20 | 物料主数据、库存查询、物料库位、库存盘点均可按编码返回目标物料 |
备注:修改人:Ld 修改时间:2026-06-29 15:06:32
## 7. 风险与限制
1. 本次未执行浏览器登录后的端到端点击测试,原因是当前测试环境未启动已认证的前端业务系统;已通过 Vue 模板编译、静态字段覆盖和数据库真实过程调用验证核心链路。
2. 本次未执行完整 `npm run build`,避免对当前工作区已有构建产物和无关脏文件产生额外影响;如后续上线前需要,可单独执行完整构建验证。
3. SQL 正向测试依赖当前测试库真实数据,若后续物料编码 `03.101.001.0011` 被删除、停用或调整,复测时需要重新选取存在的物料编码。
4. `仓储管理_库存查询_查询` 执行时会输出动态 SQL 文本,该输出为过程现有行为,不属于本次物料编码查询改造错误。
备注:修改人:Ld 修改时间:2026-06-29 15:06:32
## 8. 测试结论
本次测试结论为通过。
核心物料搜索栏已覆盖物料编码查询条件,相关前端页面模板编译通过,核心页面未残留容易混淆的“物料编号”搜索栏展示文案。数据库侧 13 个核心查询及导出存储过程均已包含物料编码筛选参数,使用不存在编码和真实编码分别验证后,过程执行正常,真实物料编码能够正确匹配物料主数据、库存查询、物料库位和库存盘点结果。
该功能满足现场库存盘点通过唯一物料编码快速确认物料的需求,可进入后续人工业务验收和上线前回归验证阶段。
备注:修改人:Ld 修改时间:2026-06-29 15:06:32

View File

@@ -19,11 +19,15 @@
| 15 | 2026-06-27 | 执行不污染数据的测试并生成测试报告 | `零件改制功能测试报告.md` | eslint 通过;显示不一致数为 0重复关联数为 0 | 补历史数据或做真实流程验收 | | 15 | 2026-06-27 | 执行不污染数据的测试并生成测试报告 | `零件改制功能测试报告.md` | eslint 通过;显示不一致数为 0重复关联数为 0 | 补历史数据或做真实流程验收 |
| 16 | 2026-06-29 | 修复生产任务查询动态 SQL 别名绑定问题 | `精工车间_生成任务_查询数据` | 将动态条件统一改为 `P.字段名` | 执行数据库过程更新并页面验证 | | 16 | 2026-06-29 | 修复生产任务查询动态 SQL 别名绑定问题 | `精工车间_生成任务_查询数据` | 将动态条件统一改为 `P.字段名` | 执行数据库过程更新并页面验证 |
| 17 | 2026-06-29 | 拆分标准化推进文档 | `docs/零件改制/README.md``01-06` 文档 | 文档结构完成 | 后续按任务矩阵继续推进 | | 17 | 2026-06-29 | 拆分标准化推进文档 | `docs/零件改制/README.md``01-06` 文档 | 文档结构完成 | 后续按任务矩阵继续推进 |
| 18 | 2026-07-01 | 按推荐方案落地改制物料替换显示 | `技术中心_改制订单_发起改制``车间生产管理_零件工艺计划_视图``PartModificationOrder/index.vue` | 数据库结构验证通过,前端 eslint 通过 | 使用已维护新物料的测试订单做真实发起和入库验证 |
| 19 | 2026-07-01 | 修复发起改制后零件列表未按改制目标替换显示 | `技术中心_改制订单_零件_查询``技术中心_改制订单_发起改制``src/views/TechnologyCenter/PartModificationOrder/index.vue``sql/零件改制_发起改制_精确基本件.sql` | SQL 抽样验证:组件 4283 已显示 `XT40-205MF-01.02-G`,组件 2652 不再被串件覆盖;前端 eslint 通过 | 页面刷新后由接口回显最新改制目标,继续做真实发起与生产入库闭环验收 |
## 当前下一步 ## 当前下一步
1. `精工车间_生成任务_查询数据` 最新完整 SQL 应用到数据库 1. 使用页面真实发起一条带 `原基本件流水号` 的改制订单
2. 使用图号 `XT40-07.01` 再次执行查询,确认不再出现 4104 错误 2. 验证改制发起页面刷新后只替换被点击的零件行
3. 使用一条业务允许的测试订单发起真实改制 3. 验证生产任务查询、车间派工、MES 待加工显示
4. 验证生产任务查询、车间派工、MES 待加工显示 4. 验证自制件入库是否使用改制物料流水号
5. 补齐 3 条历史未回写 `工艺计划流水号` 的改制记录,或确认无需处理。 5. 补齐历史改制记录的 `改制物料流水号` 或确认无需处理。
修改人:Ld 修改时间:2026-07-01 14:46:30;

View File

@@ -22,6 +22,8 @@
| GZ-018 | 改制记录查询页面 | 待开发 | 可按改制订单号、原订单、零件图号查询记录 | 后续新增 | | GZ-018 | 改制记录查询页面 | 待开发 | 可按改制订单号、原订单、零件图号查询记录 | 后续新增 |
| GZ-019 | 历史记录回写处理 | 待确认 | 未回写工艺计划流水号的历史记录明确处理方式 | 当前有 3 条未回写 | | GZ-019 | 历史记录回写处理 | 待确认 | 未回写工艺计划流水号的历史记录明确处理方式 | 当前有 3 条未回写 |
| GZ-020 | 完整业务流验收 | 待验收 | 使用测试订单完成发起、生产任务、派工、MES、入库验证 | 需业务允许测试数据 | | GZ-020 | 完整业务流验收 | 待验收 | 使用测试订单完成发起、生产任务、派工、MES、入库验证 | 需业务允许测试数据 |
| GZ-021 | 改制任务入库链路验证 | 部分通过 | 完成生产后能进入自制件入库查询,且库存入到正确改制物料 | 当前仅验证可进入入库查询,库存物料流水号仍有风险 |
| GZ-022 | 改制物料流水号支持 | 已完成 | 改制记录保存目标物料流水号,入库使用改制目标物料 | 已加字段、改发起过程、改生产任务视图;历史数据未匹配到新物料 |
## 状态说明 ## 状态说明
@@ -41,4 +43,5 @@
2. `GZ-020`:选择测试订单跑完整流程。 2. `GZ-020`:选择测试订单跑完整流程。
3. `GZ-016``GZ-017`:验证 MES 和车间派工显示。 3. `GZ-016``GZ-017`:验证 MES 和车间派工显示。
4. `GZ-019`:确认历史未回写记录是否需要补数据。 4. `GZ-019`:确认历史未回写记录是否需要补数据。
5. `GZ-018`:开发改制记录查询页面。 5. 处理历史改制记录未维护改制物料流水号的问题。
6. `GZ-018`:开发改制记录查询页面。

View File

@@ -147,3 +147,170 @@ AND P.操作日期 <= @结束时间
| MES 待加工页面截图 | 待补充 | 需现场终端或模拟终端截图 | | MES 待加工页面截图 | 待补充 | 需现场终端或模拟终端截图 |
| 真实发起改制 job_id/report_id | 暂无 | 当前未通过自动化任务创建真实业务数据 | | 真实发起改制 job_id/report_id | 暂无 | 当前未通过自动化任务创建真实业务数据 |
| 完整流程测试报告 | 待补充 | 需业务允许测试数据后生成 | | 完整流程测试报告 | 待补充 | 需业务允许测试数据后生成 |
## 8. 入库链路测试证据
测试报告:
```text
docs/零件改制/零件改制入库链路测试报告.md
```
测试方式:
- 使用事务临时将一条改制任务完成数量设置为批次数量。
- 调用 `仓储管理_自制件入库_查询`
- 查询结束后立即 `ROLLBACK TRAN`,未保留业务数据改动。
测试结果:
| 工艺计划流水号 | 订单号 | 零件名称 | 零件图号 | 物料流水号 | 批次数量 | 完成数量 | 入库数量 | 本次入库 | 类型 |
| --- | --- | --- | --- | --- | --- | --- | --- | --- | --- |
| 6591 | BHGZ-202607010011 | 300封油板 | URS3042Z-07-01 | 741 | 1 | 1 | 0 | 1 | 自制件 |
结论:
- 改制任务完成生产后可以进入现有自制件入库查询。
- 但当前库存入库仍使用原基本件物料流水号,存在入到原物料而非改制目标物料的风险。
后续验收要求:
- 增加并维护 `改制物料流水号` 后,再验证库存是否入到正确改制物料。
## 9. 改制物料流水号修改证据
### 9.1 已完成修改
新增字段:
```sql
ALTER TABLE dbo._改制订单记录
ADD int NULL;
```
已修改过程:
```text
dbo.技术中心_改制订单_发起改制
```
发起改制时新增逻辑:
```sql
SELECT TOP 1
@ =
FROM dbo._物料主文件_基本
WHERE LTRIM(RTRIM()) = LTRIM(RTRIM(@))
AND LTRIM(RTRIM()) = LTRIM(RTRIM(@))
AND ISNULL(, 0) = 0
ORDER BY DESC;
IF @ IS NULL
BEGIN
SELECT '0' AS result, '未找到改制零件对应的新物料,请先维护物料信息' AS msg;
RETURN;
END;
```
已修改视图:
```text
dbo.车间生产管理_零件工艺计划_视图
```
视图已关联:
```sql
LEFT OUTER JOIN dbo._物料主文件_基本 AS
ON dbo._改制订单记录. = .
```
并让以下字段优先使用改制物料:
```text
零件名称
零件图号
物料流水号
物料编码
代号
货位流水号
单位
```
### 9.2 结构验证
执行结果:
| 检查项 | 结果 |
| --- | --- |
| 改制物料字段存在 | 1 |
| 发起过程已包含改制物料 | 1 |
| 生产任务视图已关联改制物料 | 1 |
| 发起过程会写入改制物料 | 1 |
### 9.2.1 前端验证
修改文件:
```text
src/views/TechnologyCenter/PartModificationOrder/index.vue
```
调整内容:
- 发起改制弹窗打开后,改制零件名称和改制零件图号不再默认填原零件信息。
- 提交前要求填写已维护的新物料名称和图号。
- 保留原零件图号和改制零件图号不能相同的校验。
执行命令:
```bash
npx eslint --ext .vue D:\景耀\JY1.0\src\views\TechnologyCenter\PartModificationOrder\index.vue
```
结果:
```text
通过
```
### 9.3 历史数据验证
执行结果:
| 未删除改制记录数 | 未维护改制物料数 | 已维护改制物料数 |
| --- | --- | --- |
| 11 | 11 | 0 |
结论:
- 当前历史改制记录没有回填到 `改制物料流水号`
- 原因是现有物料主文件中没有与历史改制记录的“改制零件名称 + 改制零件图号”完全匹配的可用物料。
- 新流程已经阻止继续产生这类数据:后续发起改制时,如果没有先维护物料信息,会返回失败提示。
## 10. 改制发起页面零件列表替换显示验证
执行命令:
```powershell
sqlcmd -S 192.168.1.27 -d ERPTOOL_JY_20250826Back -U sa -P ****** -b -W -s "|" -Q "EXEC dbo.技术中心_改制订单_零件_查询 @组件流水号=4283; EXEC dbo.技术中心_改制订单_零件_查询 @组件流水号=2652;"
sqlcmd -S 192.168.1.27 -d ERPTOOL_JY_20250826Back -U sa -P ****** -b -f 65001 -i "sql\零件改制_发起改制_精确基本件.sql"
sqlcmd -S 192.168.1.27 -d ERPTOOL_JY_20250826Back -U sa -P ****** -b -W -s "|" -Q "SELECT PARAMETER_NAME, DATA_TYPE FROM INFORMATION_SCHEMA.PARAMETERS WHERE SPECIFIC_NAME=N'技术中心_改制订单_发起改制' ORDER BY ORDINAL_POSITION;"
npx eslint "src/views/TechnologyCenter/PartModificationOrder/index.vue"
```
验证结果:
| 验证项 | 结果 |
| --- | --- |
| 组件 4283 改制行 | `205伺服电机挂板 / XT40-205MF-01.02-G``是否改制=1` |
| 组件 2652 同流水号历史行 | 保持 `打刀缸 / NPM35T63x13BL-TZ1179C``是否改制=0` |
| 发起过程参数 | 已包含 `@原基本件流水号 int` |
| 前端 lint | 通过 |
结论:
- `技术中心_改制订单_零件_查询` 已按订单、组件、基本件三条件关联改制记录,避免只按基本件流水号导致串件。
- 发起弹窗保留 `原零件名称``原零件图号`,列表展示可按最新改制目标替换。
修改人:Ld 修改时间:2026-07-01 14:46:30;

View File

@@ -79,3 +79,73 @@ FROM 车间生产管理_零件工艺计划_视图 AS P
## DR-012为什么保留历史设计方案和测试报告 ## DR-012为什么保留历史设计方案和测试报告
本次拆分出的 `01-06` 文档用于后续推进和任务管理,原设计方案、开发说明、测试报告保留作为上下文证据,避免历史决策丢失。 本次拆分出的 `01-06` 文档用于后续推进和任务管理,原设计方案、开发说明、测试报告保留作为上下文证据,避免历史决策丢失。
## DR-013为什么发起改制前必须先维护新物料
入库流程最终按 `物料流水号` 写入库存。如果只修改显示用的零件名称和图号,而不切换物料流水号,库存会入到原物料,造成库存台账错误。
因此最终规则调整为:
```text
发起改制前,必须先在物料主文件维护改制后的新物料。
发起改制时,系统使用改制零件名称 + 改制零件图号查询新物料流水号。
查不到新物料时,禁止发起改制。
```
对应查询条件:
```sql
_物料主文件_基本. = @
_物料主文件_基本. = @
= 0
```
## DR-014为什么视图中的物料字段也要优先使用改制物料
现有入库查询、生产任务、派工和 MES 多处依赖 `车间生产管理_零件工艺计划_视图`。如果只在改制记录里保存改制物料流水号,但视图仍返回原物料流水号,入库仍会写错库存。
因此视图中以下字段统一优先取改制物料:
```text
零件名称
零件图号
物料流水号
物料编码
代号
货位流水号
单位
```
这样后续 `仓储管理_自制件入库_查询``仓储管理_自制件入库_循环执行` 不需要大改,就能按新物料入库。
## DR-015为什么发起弹窗不再默认填入原零件名称和图号
如果弹窗默认把原零件名称、原零件图号带入改制目标,用户容易直接提交,虽然有“图号不能相同”的校验,但体验上仍然容易误解为可以在原零件基础上简单修改。
最终决定:
```text
原零件信息只读展示。
改制零件名称和改制零件图号默认置空。
用户必须填写已经在物料信息中维护好的新物料名称和图号。
后端根据名称 + 图号查找改制物料流水号。
```
这样可以强化业务规则:改制目标必须先存在于物料主文件,后续入库才能入到正确物料。
## DR-016为什么零件列表替换显示不直接修改原 BOM
发起改制后,技术中心页面需要让用户看到“这条零件已经改制到哪个目标”,但原 BOM 仍然是订单原始技术数据,直接修改原 BOM 会影响历史追溯和未改制流程。
最终决定:
```text
不修改原 BOM。
零件列表查询时按最新未删除改制记录覆盖显示零件名称和图号。
接口额外返回原零件名称、原零件图号,弹窗继续用于原件校验。
关联条件必须包含原订单流水号、原组件流水号、原基本件流水号,避免同流水号跨组件串件。
```
这样既满足页面可见性,也保证改制记录、生产任务、入库物料各自有清晰依据。
修改人:Ld 修改时间:2026-07-01 14:46:30;

View File

@@ -0,0 +1,299 @@
# 零件改制入库链路测试报告
## 1. 测试目的
验证零件改制任务在完成生产后,是否能够进入现有“自制件入库”流程,并判断是否存在入库数据风险。
## 2. 测试方式
本次采用只读查询和事务内回滚模拟方式测试。
- 未保留任何业务数据改动。
- 未真实新增库存。
- 未真实执行入库提交。
- 使用事务临时修改完成数量,调用现有自制件入库查询过程后立即回滚。
## 3. 涉及对象
### 3.1 前端页面
```text
src/views/WarehouseManagement/PurchasePartsStorage/index.vue
```
自制件入库页签使用接口:
```text
仓储管理_自制件入库_查询
仓储管理_自制件入库_循环执行
物料入库_自制件入库_零件图号_查询数据
```
### 3.2 数据库对象
```text
技术中心_改制订单记录
车间生产管理_零件工艺计划_视图
车间生产管理工艺_零件工艺计划
仓储管理_自制件入库_查询
仓储管理_自制件入库_循环执行
库存管理_物料与货位对照表
库存管理_外购件累计库存
库存管理_自制件_入库记录
```
## 4. 当前改制任务状态检查
执行 SQL
```sql
SELECT
COUNT(*) AS ,
SUM(CASE WHEN ISNULL(V.,0) > ISNULL(V.,0) THEN 1 ELSE 0 END) AS ,
SUM(CASE WHEN ISNULL(V.,0) >= ISNULL(V.,0) AND ISNULL(V.,0) > 0 THEN 1 ELSE 0 END) AS ,
SUM(CASE WHEN V. IS NULL THEN 1 ELSE 0 END) AS
FROM dbo._改制订单记录 GZ
LEFT JOIN dbo._零件工艺计划_视图 V
ON GZ. = V.
WHERE ISNULL(GZ.,0)=0;
```
结果:
| 改制任务数 | 当前可入库数 | 已完成生产数 | 未关联生产任务数 |
| --- | --- | --- | --- |
| 11 | 0 | 0 | 3 |
结论:
- 当前没有已经完成生产并可入库的改制任务。
- 有 3 条历史改制记录未关联到生产任务,原因是未回写 `工艺计划流水号`
## 5. 入库查询模拟测试
### 5.1 测试 SQL
以下 SQL 在事务中临时将一条改制任务的 `完成数量` 设置为 `批次数量`,调用现有自制件入库查询后立即回滚。
```sql
BEGIN TRAN;
DECLARE @ int;
DECLARE @ int;
DECLARE @ int;
DECLARE @ nvarchar(50);
SELECT TOP 1
@ = V.,
@ = V.,
@ = V.,
@ = V.
FROM dbo._改制订单记录 GZ
INNER JOIN dbo._零件工艺计划_视图 V
ON GZ. = V.
WHERE ISNULL(GZ.,0)=0
AND V. IS NOT NULL
ORDER BY GZ. DESC;
UPDATE dbo._零件工艺计划
SET = @
WHERE = @;
EXEC dbo._自制件入库_查询
@ = 0,
@ = 0,
@_check = 1,
@ = @,
@_check = 1,
@ = @;
ROLLBACK TRAN;
```
### 5.2 查询结果
| 工艺计划流水号 | 订单号 | 零件名称 | 零件图号 | 物料流水号 | 批次数量 | 完成数量 | 入库数量 | 本次入库 | 类型 |
| --- | --- | --- | --- | --- | --- | --- | --- | --- | --- |
| 6591 | BHGZ-202607010011 | 300封油板 | URS3042Z-07-01 | 741 | 1 | 1 | 0 | 1 | 自制件 |
结论:
- 改制任务在完成生产后,可以进入现有 `仓储管理_自制件入库_查询` 查询结果。
- 页面层面具备被选择并执行自制件入库的条件。
## 6. 入库执行逻辑分析
现有自制件入库提交过程:
```text
仓储管理_自制件入库_循环执行
```
关键逻辑:
```sql
INSERT INTO _物料与货位对照表
(
,
,
,
,
)
VALUES
(
@,
@,
@,
GETDATE(),
@
);
INSERT INTO _自制件_入库记录
(
,
,
,
,
)
VALUES
(
@,
@,
@,
GETDATE(),
@
);
UPDATE _零件工艺计划
SET = ISNULL(,0) + @
WHERE = @;
```
该过程会:
- 增加货位库存。
- 增加累计库存。
- 写入自制件入库记录。
- 回写工艺计划入库数量。
- 入库数量达到生产数量减报废数量时,将工艺计划状态更新为入库完成。
## 7. 风险发现
### 7.1 入库可执行,但可能入到原物料流水号
当前改制任务查询结果中,虽然视图显示了改制后的零件名称和零件图号,但 `物料流水号` 仍来自原基本件关联的物料。
抽样结果:
| 改制订单编号 | 改制零件图号 | 工艺计划流水号 | 物料流水号 | 当前物料代号 | 结论 |
| --- | --- | --- | --- | --- | --- |
| BHGZ-202607010011 | URS3042Z-07-01 | 6591 | 741 | URS2267Z-04 | 不一致 |
| BHGZ-202606270010 | XT40-2-BT40-14.09-G | 6590 | 1716 | XT40-MF-05.08 | 不一致 |
| BHGZ-202606260009 | XT20-02-G | 6589 | 1251 | XT20-09 | 不一致 |
影响:
- 如果直接使用现有入库流程,库存可能增加到原基本件物料,而不是改制后的目标零件物料。
- 页面显示看起来是改制零件,但库存台账实际使用的是原 `物料流水号`
## 8. 测试结论
### 8.1 能否正常进入入库流程
可以。
完成生产后,只要满足:
```sql
>
```
改制任务可以被 `仓储管理_自制件入库_查询` 查出,并进入现有自制件入库页面。
### 8.2 能否直接认为入库完全正确
不能。
当前链路存在关键风险:
```text
显示字段使用改制零件信息
库存入库仍使用原物料流水号
```
因此只能说“流程可进入入库”,但不能确认“库存入到正确改制物料”。
## 9. 修复方案执行情况
### 9.1 已执行方案
已在 `技术中心_改制订单记录` 中增加改制目标物料流水号:
```sql
ALTER TABLE dbo._改制订单记录
ADD int NULL;
```
已修改 `技术中心_改制订单_发起改制`
```sql
SELECT TOP 1
@ =
FROM dbo._物料主文件_基本
WHERE LTRIM(RTRIM()) = LTRIM(RTRIM(@))
AND LTRIM(RTRIM()) = LTRIM(RTRIM(@))
AND ISNULL(, 0) = 0;
```
查不到新物料时禁止发起:
```sql
SELECT '0' AS result, '未找到改制零件对应的新物料,请先维护物料信息' AS msg;
```
已修改 `车间生产管理_零件工艺计划_视图`,让以下字段优先使用改制物料:
```text
物料流水号
物料编码
代号
货位流水号
货位名称
单位
```
同时保留改制订单编号、改制零件名称、改制零件图号的优先显示。
### 9.2 当前验证结果
结构验证:
| 检查项 | 结果 |
| --- | --- |
| 改制物料字段存在 | 1 |
| 发起过程已包含改制物料 | 1 |
| 生产任务视图已关联改制物料 | 1 |
历史数据:
| 未删除改制记录数 | 未维护改制物料数 | 已维护改制物料数 |
| --- | --- | --- |
| 11 | 11 | 0 |
说明:
- 历史改制记录没有匹配到新物料流水号。
- 原因是物料主文件中没有与历史记录的“改制零件名称 + 改制零件图号”完全匹配的可用物料。
- 新流程已阻止继续产生该问题。
## 10. 后续验收项
| 验收项 | 状态 | 标准 |
| --- | --- | --- |
| 改制任务完成后可进入自制件入库查询 | 通过 | 事务回滚模拟已验证 |
| 改制任务入库后库存写入正确物料 | 待新数据验证 | 新流程已支持改制物料流水号,需用新发起改制订单验证 |
| 入库后工艺计划入库数量增加 | 待真实流程验证 | 入库数量应增加 |
| 入库完成后考核状态变为 4 | 待真实流程验证 | 完成数量全部入库后状态为入库 |
| 入库记录显示改制订单编号 | 待联调 | 入库记录查询需关联改制记录 |

View File

@@ -57,6 +57,8 @@
"chalk": "2.4.1", "chalk": "2.4.1",
"copy-webpack-plugin": "4.5.2", "copy-webpack-plugin": "4.5.2",
"css-loader": "1.0.0", "css-loader": "1.0.0",
"docx-to-pdf": "^1.1.0",
"docx2pdf-converter": "^2.1.1",
"eslint": "4.19.1", "eslint": "4.19.1",
"eslint-friendly-formatter": "4.0.1", "eslint-friendly-formatter": "4.0.1",
"eslint-loader": "2.0.0", "eslint-loader": "2.0.0",

View File

@@ -0,0 +1,94 @@
-- 三楼仓库可视化 - 库位查询存储过程
-- 创建时间: 2026-06-30
-- 说明: 查询三楼仓库库位列表及状态(三段式库位编码: 排号-列号-层号)
-- 状态: 0=空闲, 1=有物料无库存, 2=有库存
-- 矩阵布局: 竖向排号,横向列号
IF EXISTS (SELECT name FROM sys.procedures WHERE name = '仓储管理_三楼仓库库位_查询数据')
DROP PROCEDURE _三楼仓库库位_查询数据
GO
CREATE PROCEDURE [dbo].[_三楼仓库库位_查询数据]
@_check bit = 0,
@ nvarchar(50) = NULL,
@_check bit = 0,
@ nvarchar(50) = NULL,
@_check bit = 0,
@ int = NULL
AS
BEGIN
SET NOCOUNT ON;
SELECT
h. AS ,
h. AS ,
CASE
WHEN EXISTS (SELECT 1 FROM _物料与货位对照表 ml WHERE ml. = h. AND ml. > 0) THEN 2
WHEN EXISTS (SELECT 1 FROM _物料主文件_基本 m WHERE m. = h.) THEN 1
ELSE 0
END AS ,
PARSENAME(REPLACE(h., '-', '.'), 3) AS ,
CAST(PARSENAME(REPLACE(h., '-', '.'), 2) AS int) AS ,
PARSENAME(REPLACE(h., '-', '.'), 1) AS ,
h.
INTO #TempLocations
FROM _货位主文件 h
WHERE LEN(h.) - LEN(REPLACE(h., '-', '')) = 2
AND ISNUMERIC(PARSENAME(REPLACE(h., '-', '.'), 3)) = 1
DECLARE @sql nvarchar(4000)
SET @sql = 'SELECT 库位编号, 库位名称, 状态, 排号, 列号, 层号, 货位流水号 FROM #TempLocations WHERE 1=1'
IF @_check = 1 AND @ IS NOT NULL
SET @sql = @sql + ' AND 排号 = @p_row'
IF @_check = 1 AND @ IS NOT NULL
SET @sql = @sql + ' AND 库位编号 LIKE ''%'' + @p_code + ''%'''
IF @_check = 1 AND @ IS NOT NULL
SET @sql = @sql + ' AND 状态 = @p_status'
SET @sql = @sql + ' ORDER BY 排号, 列号, 层号'
EXEC sp_executesql @sql,
N'@p_row nvarchar(50), @p_code nvarchar(50), @p_status int',
@p_row = @, @p_code = @, @p_status = @
DROP TABLE #TempLocations
END
GO
-- 三楼仓库可视化 - 库位物料查询存储过程
-- 创建时间: 2026-06-30
-- 说明: 按库位编号查询三楼仓库库位上的物料明细
IF EXISTS (SELECT name FROM sys.procedures WHERE name = '仓储管理_三楼仓库库位物料_查询数据')
DROP PROCEDURE _三楼仓库库位物料_查询数据
GO
CREATE PROCEDURE [dbo].[_三楼仓库库位物料_查询数据]
@_check bit = 0,
@ nvarchar(50) = NULL
AS
BEGIN
SET NOCOUNT ON;
IF @_check = 1 AND @ IS NOT NULL
BEGIN
SELECT
m. AS ,
m. AS ,
m. AS ,
m. AS ,
ISNULL(ml., 0) AS ,
ISNULL(m., '') AS ,
ISNULL(ml., '') AS
FROM _货位主文件 h
INNER JOIN _物料主文件_基本 m ON h. = m.
LEFT JOIN _物料与货位对照表 ml ON m. = ml. AND ml. = h.
WHERE h. = @
ORDER BY m.
END
END
GO

View File

@@ -0,0 +1,238 @@
-- 入库记录查询关联入库单去重修正
-- 修改人:Ld 修改时间:2026-07-02 16:50:22;
ALTER PROCEDURE [dbo].[_入库记录_查询]
@_check bit = null,
@ nvarchar(50)=null,
@_check bit = null,
@ nvarchar(50) = null,
@_check bit = null,
@ nvarchar(50) = null,
@_check bit = null,
@ nvarchar(50) = null,
@_check bit = null,
@ datetime = null,
@ datetime = null,
@_check bit = null,
@ int = null,
@_check bit = null,
@ nvarchar(50) = null,
@ int =null,
@ int =null,
@_check bit = null,
@ varchar(50) = null
AS
declare @selectStr nvarchar(4000)
declare @selectStrWhere nvarchar(4000)
set @selectStr =
-- 修改人:Ld 修改时间:2026-07-02 16:50:22; 入库单先按采购合同流水号聚合,避免一合同多入库单行导致入库记录重复。
' select A.*,1 as 打印条码数,库存管理_物料主文件_基本.物料编码,采购管理_供应商.供应商编号,货位名称,isnull(累计库存,0) as 库存,入库单去重.入库单号 from (SELECT *
FROM 仓储管理_采购入库记录_视图
UNION ALL
SELECT *
FROM 仓储管理_自制入库记录_视图
UNION ALL
SELECT *
FROM 仓储管理_退料入库记录_视图
UNION ALL
SELECT *
FROM 仓储管理_通用入库记录_视图
UNION ALL
SELECT *
FROM 仓储管理_耗材采购入库记录_视图
UNION ALL
SELECT *
FROM 仓储管理_备货入库记录_视图) AS A LEFT JOIN
库存管理_物料主文件_基本 ON A.物料流水号 = 库存管理_物料主文件_基本.物料流水号 LEFT JOIN
采购管理_供应商 ON A.供应商流水号 = 采购管理_供应商.供应商流水号 LEFT JOIN
库存管理_货位主文件 ON 库存管理_物料主文件_基本.货位流水号 = 库存管理_货位主文件.货位流水号 LEFT JOIN
库存管理_外购件累计库存 ON 库存管理_物料主文件_基本.物料流水号 = 库存管理_外购件累计库存.物料流水号 LEFT JOIN
(SELECT 采购合同流水号, MAX(入库单号) AS 入库单号 FROM 仓储管理_入库单 GROUP BY 采购合同流水号) AS 入库单去重 ON A.采购合同流水号 = 入库单去重.采购合同流水号 '
set @selectStrWhere = 'where 1 = 1 '
if(@_check = 1)
set @selectStrWhere = @selectStrWhere+' and replace(isnull(物料名称,''''),'' '','''') + replace(isnull(图号或型号,''''),'' '','''') + 批次编号 like + ''%'' + replace(@物料名称,'' '','''') + ''%'' '
if(@_check = 1)
set @selectStrWhere = @selectStrWhere+' and replace(isnull(库存管理_物料主文件_基本.物料编码,''''),'' '','''') like + ''%'' + replace(@物料编码,'' '','''') + ''%'' '
if(@_check = 1)
set @selectStrWhere = @selectStrWhere+' and 入库日期 >=@开始时间 and 入库日期 <=@结束时间 '
if(@_check = 1)
set @selectStrWhere = @selectStrWhere+' and 订单号 like + ''%'' + @订单号 + ''%'' '
if(@_check = 1)
set @selectStrWhere = @selectStrWhere+' and A.类型 = @类型 '
if(@_check = 1)
set @selectStrWhere = @selectStrWhere+' and A.采购合同流水号 = @采购合同流水号 '
if(@_check = 1)
set @selectStrWhere = @selectStrWhere+' and 供应商 = @供应商名称 '
if(@_check = 1)
set @selectStrWhere = @selectStrWhere+' and 入库单号 like + ''%'' + @入库单号 + ''%'' '
if @ = 1
begin
if @ = 1
begin
set @selectStr = @selectStr+@selectStrWhere+'order by 物料编码 DESC'
end
else
begin
set @selectStr = @selectStr+@selectStrWhere+'order by 物料编码 ASC'
end
end
else if @ = 2
begin
if @ = 1
begin
set @selectStr = @selectStr+@selectStrWhere+'order by 物料名称 DESC'
end
else
begin
set @selectStr = @selectStr+@selectStrWhere+'order by 物料名称 ASC'
end
end
else if @ = 3
begin
if @ = 1
begin
set @selectStr = @selectStr+@selectStrWhere+'order by 图号或型号 DESC'
end
else
begin
set @selectStr = @selectStr+@selectStrWhere+'order by 图号或型号 ASC'
end
end
else if @ = 4
begin
if @ = 1
begin
set @selectStr = @selectStr+@selectStrWhere+'order by 货位名称 DESC'
end
else
begin
set @selectStr = @selectStr+@selectStrWhere+'order by 货位名称 ASC'
end
end
else if @ = 5
begin
if @ = 1
begin
set @selectStr = @selectStr+@selectStrWhere+'order by 批次编号 DESC'
end
else
begin
set @selectStr = @selectStr+@selectStrWhere+'order by 批次编号 ASC'
end
end
else if @ = 6
begin
if @ = 1
begin
set @selectStr = @selectStr+@selectStrWhere+'order by 供应商编号 DESC'
end
else
begin
set @selectStr = @selectStr+@selectStrWhere+'order by 供应商编号 ASC'
end
end
else if @ = 7
begin
if @ = 1
begin
set @selectStr = @selectStr+@selectStrWhere+'order by 采购合同编号 DESC'
end
else
begin
set @selectStr = @selectStr+@selectStrWhere+'order by 采购合同编号 ASC'
end
end
else
begin
set @selectStr = @selectStr+@selectStrWhere + ' order by 入库日期 desc '
end
EXEC sp_executesql @selectStr,N'@物料名称 nvarchar(50),@物料编码 nvarchar(50),@开始时间 datetime,@结束时间 datetime,@订单号 nvarchar(50),@类型 nvarchar(50),@采购合同流水号 int,@供应商名称 nvarchar(50),@入库单号 nvarchar(50) ',
@,@,@,@,@,@,@,@,@
GO
ALTER PROCEDURE [dbo].[_入库记录_导出表格_查询]
@_check bit = null,
@ nvarchar(50) = null,
@_check bit = null,
@ nvarchar(50)=null,
@_check bit = null,
@ nvarchar(50) = null,
@_check bit = null,
@ nvarchar(50) = null,
@_check bit = null,
@ nvarchar(50) = null,
@_check bit = null,
@ datetime = null,
@ datetime = null,
@_check bit = null,
@ int = null,
@_check bit = null,
@ nvarchar(50) = null
AS
select '入库记录_'+replace(replace(replace(CONVERT(nvarchar(19),GETDATE(),21),':',''),'-',''),' ','-') as tablename,'15' as tabletype
select 256*15 as ,256*30 as ,256*30 as ,256*20 as [/],256*15 as ,256*15 as ,256*15 as ,246*20 as ,256*30 as ,
256*30 as ,256*15 as ,256*30 as ,256*20 as ,256*30 as ,256*20 as [/],256*20 as
select 0 as ,0 as ,0 as ,0 as [/],0 as ,1 as ,0 as ,0 as ,0 as
,0 as ,0 as ,0 as ,0 as ,0 as ,0 as [/],0 as
declare @selectStr nvarchar(4000)
declare @selectStrWhere nvarchar(4000)
set @selectStr =
-- 修改人:Ld 修改时间:2026-07-02 16:50:22; 入库单先按采购合同流水号聚合,保持导出与页面查询去重口径一致。
' select A.类型,库存管理_物料主文件_基本.物料编码 AS 物料编号,A.物料名称,A.图号或型号 AS [图号/型号],A.单位,A.入库数,货位名称,A.入库日期,
A.批次编号,采购管理_供应商.供应商编号,A.供应商,A.采购合同编号 AS 采购合同,A.订单号,A.产品名称 AS [产品/组件名称],A.备注,入库单去重.入库单号 from (SELECT *
FROM 仓储管理_采购入库记录_视图
UNION ALL
SELECT *
FROM 仓储管理_自制入库记录_视图
UNION ALL
SELECT *
FROM 仓储管理_退料入库记录_视图
UNION ALL
SELECT *
FROM 仓储管理_通用入库记录_视图
UNION ALL
SELECT *
FROM 仓储管理_耗材采购入库记录_视图
UNION ALL
SELECT *
FROM 仓储管理_备货入库记录_视图) AS A LEFT JOIN
库存管理_物料主文件_基本 ON A.物料流水号 = 库存管理_物料主文件_基本.物料流水号 LEFT JOIN
采购管理_供应商 ON A.供应商流水号 = 采购管理_供应商.供应商流水号 LEFT JOIN
库存管理_货位主文件 ON 库存管理_物料主文件_基本.货位流水号 = 库存管理_货位主文件.货位流水号 LEFT JOIN
(SELECT 采购合同流水号, MAX(入库单号) AS 入库单号 FROM 仓储管理_入库单 GROUP BY 采购合同流水号) AS 入库单去重 ON A.采购合同流水号 = 入库单去重.采购合同流水号 '
set @selectStrWhere = 'where 1 = 1 '
if(@_check = 1)
set @selectStrWhere = @selectStrWhere+' and replace(isnull(物料名称,''''),'' '','''') + replace(isnull(图号或型号,''''),'' '','''') like + ''%'' + replace(@物料名称,'' '','''') + ''%'' '
if(@_check = 1)
set @selectStrWhere = @selectStrWhere+' and replace(isnull(库存管理_物料主文件_基本.物料编码,''''),'' '','''') like + ''%'' + replace(@物料编码,'' '','''') + ''%'' '
if(@_check = 1)
set @selectStrWhere = @selectStrWhere+' and 入库日期 >=@开始时间 and 入库日期 <=@结束时间 '
if(@_check = 1)
set @selectStrWhere = @selectStrWhere+' and 订单号 like + ''%'' + @订单号 + ''%'' '
if(@_check = 1)
set @selectStrWhere = @selectStrWhere+' and A.类型 = @类型 '
if(@_check = 1)
set @selectStrWhere = @selectStrWhere+' and 采购合同流水号 = @采购合同流水号 '
if(@_check = 1)
set @selectStrWhere = @selectStrWhere+' and 供应商 = @供应商名称 '
if(@_check = 1)
set @selectStrWhere = @selectStrWhere+' and 入库单号 like + ''%'' + @入库单号 + ''%'' '
set @selectStr = @selectStr+@selectStrWhere+'order by 入库日期 DESC'
EXEC sp_executesql @selectStr,N'@物料名称 nvarchar(50),@物料编码 nvarchar(50),@开始时间 datetime,@结束时间 datetime,@订单号 nvarchar(50),@类型 nvarchar(50),@采购合同流水号 int,@供应商名称 nvarchar(50),@入库单号 nvarchar(50) ',
@,@,@,@,@,@,@,@,@
GO

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,236 @@
USE [ERPTOOL_JY_20250826Back]
GO
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
-- 员工工时汇总增加工价总价,工价取工序工价当前启用最终单价,总价=完成数量*工价;修改人:Ld 修改时间:2026-07-06 09:12:38;
ALTER PROCEDURE [dbo].[_工人工时统计_查询数据]
@ DATETIME = NULL,
@ DATETIME = NULL
AS
BEGIN
SET NOCOUNT ON;
SELECT
SUM(a.) AS ,
SUM(a.) AS ,
SUM(a.) AS ,
a. AS ,
a.
FROM (
SELECT
ISNULL(f., 0) AS ,
p.,
f.,
f.,
f.,
ISNULL(f., 0) * ISNULL(price., 0) AS
FROM dbo._零件工序_工序完成过程情况 f
INNER JOIN dbo._人员名单 p ON f. = p.
OUTER APPLY (
SELECT TOP 1 ISNULL(pp.[(/)], 0) AS
FROM dbo._工序工价 pp
WHERE pp. = f.
AND ISNULL(pp., 1) = 1
ORDER BY ISNULL(pp., CONVERT(DATE, '1900-01-01')) DESC, pp. DESC, pp. DESC
) price
WHERE f. >= @
AND f. <= @
) a
GROUP BY a., a.;
END
GO
-- 员工工时明细增加工价总价,明细按零件名称+图号+工序匹配工序工价;修改人:Ld 修改时间:2026-07-06 09:12:38;
ALTER PROCEDURE [dbo].[_员工工时统计_详情_查询数据]
@ INT = 62,
@ DATETIME = NULL,
@ DATETIME = NULL,
@ INT = NULL,
@ INT = NULL
AS
BEGIN
SET NOCOUNT ON;
SELECT
data.*,
data. / NULLIF(data., 0) AS ,
ISNULL(price., 0) AS ,
ISNULL(data., 0) * ISNULL(price., 0) AS
FROM dbo._零件工序加工时长_视图 data
OUTER APPLY (
SELECT TOP 1 ISNULL(pp.[(/)], 0) AS
FROM dbo._工序工价 pp
WHERE pp. = data.
AND pp. = data.
AND pp. = data.
AND ISNULL(pp., 1) = 1
ORDER BY ISNULL(pp., CONVERT(DATE, '1900-01-01')) DESC, pp. DESC, pp. DESC
) price
WHERE data. = @
AND data. >= @
AND data. < DATEADD(DAY, 1, @)
ORDER BY
CASE WHEN @ = 1 AND @ = 1 THEN data. END DESC,
CASE WHEN @ = 1 AND @ <> 1 THEN data. END ASC,
CASE WHEN ISNULL(@, 0) <> 1 THEN data. END DESC;
END
GO
-- 设备工时汇总增加工价总价,工价取工序工价当前启用最终单价,总价=完成数量*工价;修改人:Ld 修改时间:2026-07-06 09:12:38;
ALTER PROCEDURE [dbo].[_设备工时统计_查询数据]
@ DATETIME = NULL,
@ DATETIME = NULL
AS
BEGIN
SET NOCOUNT ON;
SELECT
SUM(a.) AS ,
a. AS ,
SUM(a.) AS ,
SUM(a.) AS
FROM (
SELECT
ISNULL(f., 0) AS ,
e. + N'-' + f. AS ,
f.,
ISNULL(f., 0) * ISNULL(price., 0) AS
FROM dbo._零件工序_工序完成过程情况 f
INNER JOIN dbo._设备工位点检表 e ON f. = e.
OUTER APPLY (
SELECT TOP 1 ISNULL(pp.[(/)], 0) AS
FROM dbo._工序工价 pp
WHERE pp. = f.
AND ISNULL(pp., 1) = 1
ORDER BY ISNULL(pp., CONVERT(DATE, '1900-01-01')) DESC, pp. DESC, pp. DESC
) price
WHERE f. >= @
AND f. <= @
) a
GROUP BY a.;
END
GO
-- 设备工时明细增加工价总价,明细按零件名称+图号+工序匹配工序工价;修改人:Ld 修改时间:2026-07-06 09:12:38;
ALTER PROCEDURE [dbo].[_设备工时统计_详情_查询数据]
@ NVARCHAR(50) = NULL,
@ DATETIME = NULL,
@ DATETIME = NULL,
@ INT = NULL,
@ INT = NULL
AS
BEGIN
SET NOCOUNT ON;
SELECT
data.*,
ISNULL(price., 0) AS ,
ISNULL(data., 0) * ISNULL(price., 0) AS
FROM dbo._零件工序加工时长_视图 data
OUTER APPLY (
SELECT TOP 1 ISNULL(pp.[(/)], 0) AS
FROM dbo._工序工价 pp
WHERE pp. = data.
AND pp. = data.
AND pp. = data.
AND ISNULL(pp., 1) = 1
ORDER BY ISNULL(pp., CONVERT(DATE, '1900-01-01')) DESC, pp. DESC, pp. DESC
) price
WHERE data. = @
AND data. >= @
AND data. <= @
ORDER BY
CASE WHEN @ = 1 AND @ = 1 THEN data. END DESC,
CASE WHEN @ = 1 AND @ <> 1 THEN data. END ASC,
CASE WHEN ISNULL(@, 0) <> 1 THEN data. END DESC;
END
GO
-- 员工工时导出增加工价总价列,保持与页面明细一致;修改人:Ld 修改时间:2026-07-06 09:12:38;
ALTER PROCEDURE [dbo].[_精工车间_员工工时统计_查询数据]
@ DATETIME = NULL,
@ DATETIME = NULL,
@ INT = NULL,
@ INT = NULL
AS
BEGIN
SET NOCOUNT ON;
SELECT N'库存_' + REPLACE(REPLACE(REPLACE(CONVERT(NVARCHAR(19), GETDATE(), 21), ':', ''), '-', ''), ' ', '-') AS tablename, '17' AS tabletype;
SELECT
256 * 15 AS ,
256 * 10 AS ,
256 * 30 AS ,
256 * 30 AS ,
256 * 20 AS ,
256 * 10 AS ,
256 * 15 AS M,
256 * 10 AS ,
256 * 10 AS ,
256 * 12 AS ,
256 * 30 AS ,
256 * 30 AS ,
256 * 10 AS ,
256 * 25 AS ,
246 * 25 AS ,
246 * 25 AS ;
SELECT
0 AS ,
1 AS ,
0 AS ,
0 AS ,
0 AS ,
1 AS ,
1 AS M,
1 AS ,
1 AS ,
1 AS ,
0 AS ,
0 AS ,
0 AS ,
0 AS ,
0 AS ,
0 AS ;
SELECT
data.,
data.,
data.,
data. AS ,
data.,
data. AS ,
data. AS M,
data. AS ,
ISNULL(price., 0) AS ,
ISNULL(data., 0) * ISNULL(price., 0) AS ,
data. AS ,
data. AS ,
data.,
data. AS ,
data.,
data.
FROM dbo._零件工序加工时长_视图 data
OUTER APPLY (
SELECT TOP 1 ISNULL(pp.[(/)], 0) AS
FROM dbo._工序工价 pp
WHERE pp. = data.
AND pp. = data.
AND pp. = data.
AND ISNULL(pp., 1) = 1
ORDER BY ISNULL(pp., CONVERT(DATE, '1900-01-01')) DESC, pp. DESC, pp. DESC
) price
WHERE data. >= @
AND data. <= @
ORDER BY
CASE WHEN @ = 1 AND @ = 1 THEN data. END DESC,
CASE WHEN @ = 1 AND @ <> 1 THEN data. END ASC,
CASE WHEN ISNULL(@, 0) <> 1 THEN data. END DESC;
END
GO

View File

@@ -0,0 +1,381 @@
-- 生产完成审核查询与审核处理 修改人:Ld 修改时间:2026-07-02 13:57:18;
IF OBJECT_ID(N'[dbo].[机加工MES_加工完成整修审核_查询数据]', N'P') IS NOT NULL
DROP PROCEDURE [dbo].[MES_加工完成整修审核_查询数据];
GO
CREATE PROCEDURE [dbo].[MES_加工完成整修审核_查询数据]
@_check INT = 0,
@ NVARCHAR(20) = N'',
@_check INT = 0,
@ NVARCHAR(50) = N'',
@_check INT = 0,
@ NVARCHAR(100) = N'',
@_check INT = 0,
@ NVARCHAR(20) = N'',
@ NVARCHAR(20) = N'',
@PageCurrent INT = 1,
@PageSize INT = 100
AS
BEGIN
SET NOCOUNT ON;
IF @PageCurrent IS NULL OR @PageCurrent < 1 SET @PageCurrent = 1;
IF @PageSize IS NULL OR @PageSize < 1 SET @PageSize = 100;
;WITH AuditData AS (
SELECT
ROW_NUMBER() OVER (
ORDER BY
CASE WHEN A. = N'待审核' THEN 0 ELSE 1 END,
A. DESC,
A.id DESC
) AS RowNum,
A.id,
A.,
A.,
V.,
V.,
V.,
V.,
V.,
V.,
V. AS ,
V.,
V.,
V.,
V.,
A.,
A.,
. AS ,
A.,
A.,
A.,
. AS ,
A.,
ISNULL(SB., A.) AS ,
A.,
A.,
A.,
A.,
A.,
A.,
ISNULL(., A.) AS ,
A.,
A.id,
A.,
CONVERT(VARCHAR(19), A., 120) AS ,
CONVERT(VARCHAR(19), A., 120) AS ,
CONVERT(VARCHAR(19), A., 120) AS ,
A.,
. AS ,
CONVERT(VARCHAR(19), A., 120) AS ,
A.,
A.,
CONVERT(VARCHAR(19), A., 120) AS
FROM [dbo].[MES_机加工MES_加工完成整修审核表] AS A
LEFT JOIN [dbo].[_零件工序_视图] AS V
ON A. = V.
LEFT JOIN [dbo].[_人员名单] AS
ON A. = .
LEFT JOIN [dbo].[_人员名单] AS
ON A. = .
OR A. = .
LEFT JOIN [dbo].[_人员名单] AS
ON A. = CONVERT(NVARCHAR(100), .)
OR A. = CONVERT(NVARCHAR(100), .)
OR A. = .
LEFT JOIN [dbo].[_人员名单] AS
ON A. = CONVERT(NVARCHAR(100), .)
OR A. = CONVERT(NVARCHAR(100), .)
OR A. = .
LEFT JOIN [dbo].[_设备工位点检表] AS SB
ON A. = SB.
WHERE (@_check = 0 OR A. = @)
AND (@_check = 0 OR A. = @)
AND (@_check = 0 OR ISNULL(., ISNULL(A., N'')) LIKE N'%' + @ + N'%')
AND (@_check = 0 OR CONVERT(DATE, A.) BETWEEN CONVERT(DATE, @) AND CONVERT(DATE, @))
)
SELECT
id,
,
,
,
,
,
,
,
,
,
,
,
,
,
,
,
,
,
,
,
,
,
,
,
,
,
,
,
,
,
,
id,
,
,
,
,
,
,
,
,
,
FROM AuditData
WHERE RowNum BETWEEN ((@PageCurrent - 1) * @PageSize + 1) AND (@PageCurrent * @PageSize)
ORDER BY RowNum;
SELECT COUNT(1) AS total
FROM [dbo].[MES_机加工MES_加工完成整修审核表] AS A
LEFT JOIN [dbo].[_人员名单] AS
ON A. = CONVERT(NVARCHAR(100), .)
OR A. = CONVERT(NVARCHAR(100), .)
OR A. = .
WHERE (@_check = 0 OR A. = @)
AND (@_check = 0 OR A. = @)
AND (@_check = 0 OR ISNULL(., ISNULL(A., N'')) LIKE N'%' + @ + N'%')
AND (@_check = 0 OR CONVERT(DATE, A.) BETWEEN CONVERT(DATE, @) AND CONVERT(DATE, @));
END;
GO
-- 生产完成审核状态更新,审核通过时接入原 MES 完工链路 修改人:Ld 修改时间:2026-07-02 14:55:23;
IF OBJECT_ID(N'[dbo].[机加工MES_加工完成整修审核_审核数据]', N'P') IS NOT NULL
DROP PROCEDURE [dbo].[MES_加工完成整修审核_审核数据];
GO
CREATE PROCEDURE [dbo].[MES_加工完成整修审核_审核数据]
@ INT,
@ NVARCHAR(20),
@ NVARCHAR(100) = NULL,
@ NVARCHAR(1000) = NULL,
@ FLOAT = NULL,
@ DATETIME = NULL,
@ DATETIME = NULL,
@ DATETIME = NULL,
@ DATETIME = NULL,
@ NVARCHAR(1000) = NULL
AS
BEGIN
SET NOCOUNT ON;
DECLARE @ NVARCHAR(50);
DECLARE @ INT;
DECLARE @ NVARCHAR(50);
DECLARE @ FLOAT;
DECLARE @ INT;
DECLARE @ INT;
DECLARE @ NVARCHAR(100);
DECLARE @ NVARCHAR(500);
DECLARE @ NVARCHAR(100);
DECLARE @id INT;
DECLARE @ NVARCHAR(1000);
DECLARE @ FLOAT;
DECLARE @ INT;
DECLARE @ NVARCHAR(100);
DECLARE @ INT;
DECLARE @ BIT;
DECLARE @ TABLE (result NVARCHAR(100));
IF NOT EXISTS (
SELECT 1
FROM [dbo].[MES_机加工MES_加工完成整修审核表]
WHERE id = @
AND = N'待审核'
)
BEGIN
SELECT N'0' AS result, N'该审核记录不存在或已审核' AS message;
RETURN;
END;
IF @ NOT IN (N'审核通过', N'审核不通过')
BEGIN
SELECT N'0' AS result, N'审核状态不正确' AS message;
RETURN;
END;
SELECT
@ = ,
@ = ,
@ = ,
@ = ISNULL(@, ),
@ = ,
@ = ,
@ = ,
@ = ,
@ = ,
@id = id,
@ = ISNULL(@, )
FROM [dbo].[MES_机加工MES_加工完成整修审核表]
WHERE id = @
AND = N'待审核';
BEGIN TRY
SET @ = CASE WHEN @@TRANCOUNT = 0 THEN 1 ELSE 0 END;
IF @ = 1
BEGIN
BEGIN TRAN;
END
ELSE
BEGIN
SAVE TRAN ;
END;
IF @ = N'审核通过' AND @ = N'加工完成'
BEGIN
IF @ IS NULL OR @ IS NULL OR @ IS NULL OR @ IS NULL OR @ IS NULL
BEGIN
IF @ = 1 ROLLBACK TRAN ELSE ROLLBACK TRAN ;
SELECT N'0' AS result, N'审核记录缺少原 MES 完工必需参数' AS message;
RETURN;
END;
IF @ <= 0 OR @ <> FLOOR(@)
BEGIN
IF @ = 1 ROLLBACK TRAN ELSE ROLLBACK TRAN ;
SELECT N'0' AS result, N'完成数量必须为大于 0 的整数' AS message;
RETURN;
END;
INSERT INTO @(result)
EXEC [dbo].[_零件工序_工序完成过程情况_增加数据]
@ = @,
@ = @,
@ = @,
@ = @,
@ = @,
@ = @,
@ = @,
@ = @ OUTPUT,
@ = @ OUTPUT;
SELECT TOP 1 @ = result FROM @;
IF ISNULL(@, N'') <> N'成功'
BEGIN
IF @ = 1 ROLLBACK TRAN ELSE ROLLBACK TRAN ;
SELECT N'0' AS result, ISNULL(@, N'原 MES 完工流程执行失败') AS message;
RETURN;
END;
IF @ IS NOT NULL
BEGIN
SELECT @ = MAX()
FROM [dbo].[_零件工序_工序完成过程情况]
WHERE = @
AND = @
AND = @;
UPDATE [dbo].[_零件工序_工序完成过程情况]
SET = ISNULL(@, ),
= @,
= CONVERT(DATE, @),
= @,
= CASE WHEN ISNUMERIC(@) = 1 THEN CAST(@ AS INT) ELSE END,
= GETDATE()
WHERE = @;
UPDATE [dbo].[_零件工序]
SET = CASE WHEN IS NULL OR >= ISNULL(, 0) THEN @ ELSE END
WHERE = @;
END;
IF @ IS NOT NULL AND @ IS NULL
BEGIN
SELECT @ = MAX()
FROM [dbo].[_零件工序_工序完成过程情况]
WHERE = @
AND = @
AND = @;
UPDATE [dbo].[_零件工序_工序完成过程情况]
SET = @,
= CASE WHEN ISNUMERIC(@) = 1 THEN CAST(@ AS INT) ELSE END,
= GETDATE()
WHERE = @;
END;
END;
IF @ = N'审核通过' AND @ = N'结束整修'
BEGIN
IF @id IS NULL OR @ IS NULL
BEGIN
IF @ = 1 ROLLBACK TRAN ELSE ROLLBACK TRAN ;
SELECT N'0' AS result, N'审核记录缺少整修结束必需参数' AS message;
RETURN;
END;
UPDATE [dbo].[_整修]
SET = CASE WHEN @ IS NULL THEN ELSE CONVERT(VARCHAR(20), @, 120) END,
= CONVERT(VARCHAR(20), ISNULL(@, GETDATE()), 120),
= N'1',
= @
WHERE id = @id
AND = @;
END;
UPDATE [dbo].[MES_机加工MES_加工完成整修审核表]
SET = @,
= @,
= GETDATE(),
= ISNULL(@, N''),
= CASE WHEN @ = N'审核通过' AND @ = N'加工完成' THEN @ ELSE END,
= CASE
WHEN @ = N'审核通过' AND @ = N'加工完成' AND @ IS NOT NULL THEN @
WHEN @ = N'审核通过' AND @ = N'结束整修' AND @ IS NOT NULL THEN @
ELSE
END,
= CASE
WHEN @ = N'审核通过' AND @ = N'加工完成' AND @ IS NOT NULL THEN @
WHEN @ = N'审核通过' AND @ = N'结束整修' THEN ISNULL(@, GETDATE())
ELSE
END,
= CASE WHEN @ = N'审核通过' AND @ = N'结束整修' THEN @ ELSE END,
= CASE WHEN @ = N'审核通过' AND @ = N'加工完成' THEN @ ELSE END,
= CASE WHEN @ = N'审核通过' AND @ = N'加工完成' THEN @ ELSE END,
= N'Ld',
= GETDATE()
WHERE id = @
AND = N'待审核';
IF @ = 1
BEGIN
COMMIT TRAN;
END;
END TRY
BEGIN CATCH
IF @@TRANCOUNT > 0
BEGIN
IF ISNULL(@, 1) = 1
BEGIN
ROLLBACK TRAN;
END
ELSE
BEGIN
ROLLBACK TRAN ;
END;
END;
SELECT N'0' AS result, ERROR_MESSAGE() AS message;
RETURN;
END CATCH;
SELECT N'1' AS result;
END;
GO

View File

@@ -0,0 +1,259 @@
USE [ERPTOOL_JY_20250826Back]
GO
-- 核心物料搜索栏增加物料编码查询条件
-- 需求提出人:罗伟
-- 说明:以下过程补充 @物料编码_check、@物料编码 可选参数。未传入物料编码时保持原查询逻辑不变。
-- 备注:修改人:Ld 修改时间:2026-06-29 14:30:00
ALTER PROCEDURE [dbo].[_物料记录_查询新]
@_check bit = null,
@ nvarchar(50) = null,
@_check bit = null,
@ nvarchar(50) = null,
@_check bit = null,
@ datetime = null,
@ datetime = null
AS
BEGIN
declare @selectStr nvarchar(4000)
declare @selectStrWhere nvarchar(4000)
set @selectStr =
'SELECT row_number() OVER (ORDER BY b.记录时间) AS id, d.*, CONVERT(int, isnull(出库数, 0)) AS 出库数, isnull(入库数, 0) AS 入库数, 库存管理_货位主文件.货位名称, 单位名称_基础表.单位, isnull(库存数, 0) AS 库存数, 记录时间
FROM (SELECT 物料流水号, 库存数, CONVERT(varchar(10), 操作日期, 23) AS 记录时间 FROM 库存管理_每日库存结余表) AS b
LEFT JOIN (SELECT sum(领料数) AS 出库数, 物料流水号, 领料日期 FROM 仓储管理_出库记录_视图 GROUP BY 物料流水号, 领料日期) AS c ON b.物料流水号 = c.物料流水号 AND c.领料日期 = b.记录时间
LEFT JOIN (SELECT sum(入库数) AS 入库数, 物料流水号, 入库日期 FROM 仓储管理_入库记录_视图 GROUP BY 物料流水号, 入库日期) AS a ON b.物料流水号 = a.物料流水号 AND a.入库日期 = b.记录时间
INNER JOIN (SELECT 物料编码, 名称, 代号, 物料流水号, 货位流水号, 单位流水号 FROM 库存管理_物料主文件_基本) AS d ON b.物料流水号 = d.物料流水号
LEFT JOIN 单位名称_基础表 ON d.单位流水号 = 单位名称_基础表.单位流水号
LEFT JOIN 库存管理_货位主文件 ON d.货位流水号 = 库存管理_货位主文件.货位流水号 '
set @selectStrWhere = ' where 1 = 1 '
if(@_check = 1)
set @selectStrWhere = @selectStrWhere + ' and replace(isnull(名称,''''),'' '','''') + replace(isnull(代号,''''),'' '','''') + replace(isnull(物料编码,''''),'' '','''') like ''%'' + replace(@物料名称,'' '','''') + ''%'' '
if(@_check = 1)
set @selectStrWhere = @selectStrWhere + ' and replace(isnull(物料编码,''''),'' '','''') like ''%'' + replace(@物料编码,'' '','''') + ''%'' '
if(@_check = 1)
set @selectStrWhere = @selectStrWhere + ' and 记录时间 >= convert(varchar(10),@开始时间,23) and 记录时间 <= convert(varchar(10),@结束时间,23) '
set @selectStr = @selectStr + @selectStrWhere + ' order by 记录时间 desc'
EXEC sp_executesql @selectStr,
N'@物料名称 nvarchar(50),@物料编码 nvarchar(50),@开始时间 datetime,@结束时间 datetime',
@,@,@,@
END
GO
ALTER PROCEDURE [dbo].[_物料记录_查询]
@_check bit = null,
@ nvarchar(50) = null,
@_check bit = null,
@ nvarchar(50) = null,
@_check bit = null,
@ datetime = null,
@ datetime = null
AS
BEGIN
declare @selectStr nvarchar(4000)
set @selectStr =
' select sum(convert(int,isnull(出库数,0))) as 出库数,sum(isnull(入库数,0)) as 入库数,sum(isnull(库存数,0)) as 库存数 from (select 物料流水号,库存数,convert(varchar(10),操作日期,23) as 记录时间 from 库存管理_每日库存结余表 where 1 = 1 '
if(@_check = 1)
set @selectStr = @selectStr + ' and convert(varchar(10),操作日期,23) >= @开始时间 and convert(varchar(10),操作日期,23) <= @结束时间 '
set @selectStr = @selectStr +
' ) as b left join (select sum(领料数) as 出库数,物料流水号,领料日期 from 仓储管理_出库记录_视图 where 1=1 '
if(@_check = 1)
set @selectStr = @selectStr + ' and 领料日期 >= @开始时间 and 领料日期 <= @结束时间 '
set @selectStr = @selectStr +
' group by 物料流水号,领料日期 ) as c on b.物料流水号 = c.物料流水号 and c.领料日期 = b.记录时间 left join (select sum(入库数) as 入库数,物料流水号,入库日期 from 仓储管理_入库记录_视图 where 1=1 '
if(@_check = 1)
set @selectStr = @selectStr + ' and 入库日期 >= @开始时间 and 入库日期 <= @结束时间 '
set @selectStr = @selectStr +
' group by 物料流水号,入库日期 ) as a on b.物料流水号 = a.物料流水号 and a.入库日期 = b.记录时间
inner join (select 物料编码,名称,代号,物料流水号,货位流水号,单位流水号 from 库存管理_物料主文件_基本 where 1 = 1 '
if(@_check = 1)
set @selectStr = @selectStr + ' and replace(isnull(名称,''''),'' '','''') + replace(isnull(代号,''''),'' '','''') + replace(isnull(物料编码,''''),'' '','''') like ''%'' + replace(@物料名称,'' '','''') + ''%'' '
if(@_check = 1)
set @selectStr = @selectStr + ' and replace(isnull(物料编码,''''),'' '','''') like ''%'' + replace(@物料编码,'' '','''') + ''%'' '
set @selectStr = @selectStr +
' ) as d on b.物料流水号 = d.物料流水号 left join 单位名称_基础表 on d.单位流水号 = 单位名称_基础表.单位流水号
left join 库存管理_货位主文件 on d.货位流水号 = 库存管理_货位主文件.货位流水号 '
EXEC sp_executesql @selectStr,
N'@物料名称 nvarchar(50),@物料编码 nvarchar(50),@开始时间 datetime,@结束时间 datetime',
@,@,@,@
END
GO
ALTER PROCEDURE [dbo].[_仓储管理_物料记录_查询]
@_check bit = null,
@ nvarchar(50) = null,
@_check bit = null,
@ nvarchar(50) = null,
@_check bit = null,
@ datetime = null,
@ datetime = null
AS
BEGIN
select '物料记录_' + replace(replace(replace(CONVERT(nvarchar(19),GETDATE(),21),':',''),'-',''),' ','-') as tablename,'15' as tabletype
select 256*15 as ,256*30 as ,256*30 as ,256*10 as ,256*15 as ,256*15 as ,256*15 as ,256*15 as ,256*15 as
select 0 as ,0 as ,0 as ,0 as ,1 as ,1 as ,1 as ,0 as ,0 as
declare @selectStr nvarchar(4000)
set @selectStr =
' select d.物料编码,名称,代号,单位名称_基础表.单位,isnull(出库数,0) as 出库数,isnull(入库数,0) as 入库数,isnull(库存数,0) as 库存数,库存管理_货位主文件.货位名称 as 库位,记录时间 from (select 物料流水号,库存数,convert(varchar(10),操作日期,23) as 记录时间 from 库存管理_每日库存结余表 where 1 = 1 '
if(@_check = 1)
set @selectStr = @selectStr + ' and convert(varchar(10),操作日期,23) >= @开始时间 and convert(varchar(10),操作日期,23) <= @结束时间 '
set @selectStr = @selectStr +
' ) as b left join (select sum(领料数) as 出库数,物料流水号,领料日期 from 仓储管理_出库记录_视图 where 1=1 '
if(@_check = 1)
set @selectStr = @selectStr + ' and 领料日期 >= @开始时间 and 领料日期 <= @结束时间 '
set @selectStr = @selectStr +
' group by 物料流水号,领料日期 ) as c on b.物料流水号 = c.物料流水号 and c.领料日期 = b.记录时间 left join (select sum(入库数) as 入库数,物料流水号,入库日期 from 仓储管理_入库记录_视图 where 1=1 '
if(@_check = 1)
set @selectStr = @selectStr + ' and 入库日期 >= @开始时间 and 入库日期 <= @结束时间 '
set @selectStr = @selectStr +
' group by 物料流水号,入库日期 ) as a on b.物料流水号 = a.物料流水号 and a.入库日期 = b.记录时间
inner join (select 物料编码,名称,代号,物料流水号,货位流水号,单位流水号 from 库存管理_物料主文件_基本 where 1 = 1 '
if(@_check = 1)
set @selectStr = @selectStr + ' and replace(isnull(名称,''''),'' '','''') + replace(isnull(代号,''''),'' '','''') + replace(isnull(物料编码,''''),'' '','''') like ''%'' + replace(@物料名称,'' '','''') + ''%'' '
if(@_check = 1)
set @selectStr = @selectStr + ' and replace(isnull(物料编码,''''),'' '','''') like ''%'' + replace(@物料编码,'' '','''') + ''%'' '
set @selectStr = @selectStr +
' ) as d on b.物料流水号 = d.物料流水号 left join 单位名称_基础表 on d.单位流水号 = 单位名称_基础表.单位流水号
left join 库存管理_货位主文件 on d.货位流水号 = 库存管理_货位主文件.货位流水号 '
EXEC sp_executesql @selectStr,
N'@物料名称 nvarchar(50),@物料编码 nvarchar(50),@开始时间 datetime,@结束时间 datetime',
@,@,@,@
END
GO
ALTER PROCEDURE [dbo].[_盘点记录_查询]
@_check bit = null,
@ nvarchar(50) = null,
@_check bit = null,
@ nvarchar(50) = null,
@_check bit = null,
@ datetime = null,
@ datetime = null
AS
BEGIN
declare @selectStr nvarchar(4000)
set @selectStr = ' select * from 库存管理_盘点记录_视图 where 1 = 1 '
if(@_check = 1)
set @selectStr = @selectStr + ' and replace(isnull(名称,''''),'' '','''') + replace(isnull(代号,''''),'' '','''') + replace(isnull(物料编码,''''),'' '','''') like ''%'' + replace(@物料名称,'' '','''') + ''%'' '
if(@_check = 1)
set @selectStr = @selectStr + ' and replace(isnull(物料编码,''''),'' '','''') like ''%'' + replace(@物料编码,'' '','''') + ''%'' '
if(@_check = 1)
set @selectStr = @selectStr + ' and convert(varchar(10),修改时间,23) >= @开始时间 and convert(varchar(10),修改时间,23) <= @结束时间 '
set @selectStr = @selectStr + ' order by 修改时间 desc '
EXEC sp_executesql @selectStr,
N'@物料名称 nvarchar(50),@物料编码 nvarchar(50),@开始时间 datetime,@结束时间 datetime',
@,@,@,@
END
GO
ALTER PROCEDURE [dbo].[_仓储管理_盘点记录_查询]
@_check bit = null,
@ nvarchar(50) = null,
@_check bit = null,
@ nvarchar(50) = null,
@_check bit = null,
@ datetime = null,
@ datetime = null
AS
BEGIN
select '盘点记录_' + replace(replace(replace(CONVERT(nvarchar(19),GETDATE(),21),':',''),'-',''),' ','-') as tablename,'15' as tabletype
select 256*15 as ,256*30 as ,256*30 as ,256*10 as ,256*15 as ,256*15 as ,256*15 as ,256*25 as
select 0 as ,0 as ,0 as ,0 as ,1 as ,1 as ,0 as ,0 as
declare @selectStr nvarchar(4000)
set @selectStr = ' select * from 库存管理_盘点记录_视图 where 1 = 1 '
if(@_check = 1)
set @selectStr = @selectStr + ' and replace(isnull(名称,''''),'' '','''') + replace(isnull(代号,''''),'' '','''') + replace(isnull(物料编码,''''),'' '','''') like ''%'' + replace(@物料名称,'' '','''') + ''%'' '
if(@_check = 1)
set @selectStr = @selectStr + ' and replace(isnull(物料编码,''''),'' '','''') like ''%'' + replace(@物料编码,'' '','''') + ''%'' '
if(@_check = 1)
set @selectStr = @selectStr + ' and convert(varchar(10),修改时间,23) >= @开始时间 and convert(varchar(10),修改时间,23) <= @结束时间 '
EXEC sp_executesql @selectStr,
N'@物料名称 nvarchar(50),@物料编码 nvarchar(50),@开始时间 datetime,@结束时间 datetime',
@,@,@,@
END
GO
ALTER PROCEDURE [dbo].[_入库记录退货_条件查询]
@_check bit = null,
@ nvarchar(50) = null,
@_check bit = null,
@ nvarchar(50) = null,
@_check bit = null,
@ nvarchar(50) = null,
@_check bit = null,
@ nvarchar(50) = null,
@_check bit = null,
@ nvarchar(50) = null,
@ nvarchar(50) = null
AS
BEGIN
declare @selectStr nvarchar(4000)
declare @selectStrWhere nvarchar(4000)
set @selectStr = ' select * from [dbo].[仓储管理_入库记录退货_视图] '
set @selectStrWhere = ' where 1 = 1 '
if(@_check = 1)
set @selectStrWhere = @selectStrWhere + ' and 物料名称 + 图号或型号 like ''%'' + @物料名称 + ''%'' '
if(@_check = 1)
set @selectStrWhere = @selectStrWhere + ' and 采购合同 like ''%'' + @采购合同 + ''%'' '
if(@_check = 1)
set @selectStrWhere = @selectStrWhere + ' and 供应商 like ''%'' + @供应商 + ''%'' '
if(@_check = 1)
set @selectStrWhere = @selectStrWhere + ' and replace(isnull(物料编码,''''),'' '','''') like ''%'' + replace(@物料编码,'' '','''') + ''%'' '
if(@_check = 1)
set @selectStrWhere = @selectStrWhere + ' and convert(varchar(10),退货时间,23) >= @开始时间 and convert(varchar(10),退货时间,23) <= @结束时间 '
set @selectStr = @selectStr + @selectStrWhere + ' order by 退货时间 desc '
EXEC sp_executesql @selectStr,
N'@物料名称 nvarchar(50),@采购合同 nvarchar(50),@供应商 nvarchar(50),@物料编码 nvarchar(50),@开始时间 nvarchar(50),@结束时间 nvarchar(50)',
@,@,@,@,@,@
END
GO

View File

@@ -0,0 +1,11 @@
-- 修正生产审核菜单组件路径,避免动态路由加载不存在的 ProductionCompletionAudi 目录 修改人:Ld 修改时间:2026-07-02 14:12:00;
UPDATE dbo._模块信息
SET path = N'SeikoWorkshop/ProductionCompletionAudit',
component = N'/SeikoWorkshop/ProductionCompletionAudit',
name = N'ProductionCompletionAudit'
WHERE id = 152
AND title = N'生产审核';
SELECT id, path, component, name, title
FROM dbo._模块信息
WHERE id = 152;

View File

@@ -0,0 +1,50 @@
-- 采购入库合同明细关联未入库最新到货记录
-- 修改人:Ld 修改时间:2026-07-02 17:11:48;
ALTER VIEW dbo._采购合同明细_视图
AS
SELECT dbo._采购合同明细., dbo._物料主文件_基本. AS ,
dbo._物料主文件_基本. AS , dbo._采购合同明细., CASE WHEN isnull(,
0) = 1 THEN _采购批次. ELSE _采购合同明细. END AS , CASE WHEN isnull(,
0) = 1 THEN _采购批次. ELSE END AS ,
dbo._订单信息_基础表. AS , dbo._订单信息_基础表.,
dbo._采购合同明细., dbo._采购合同明细.,
dbo.PDM_零件明细表_标准件和外购件., dbo._采购合同.,
dbo.PDM_零件明细表_标准件和外购件., dbo._合同审批.,
ISNULL(dbo._物料主文件_基本., 0) AS , dbo._货位主文件.,
dbo._采购批次., dbo._采购批次., dbo._采购合同明细.,
dbo.PDM_零件明细表_标准件和外购件.使, dbo._物料主文件_基本.,
dbo._手动完成记录.id AS id, . AS ,
dbo._采购合同. AS , dbo._供应商., .,
.
FROM dbo._采购合同明细 INNER JOIN
dbo.PDM_零件明细表_标准件和外购件 ON
dbo._采购合同明细. = dbo.PDM_零件明细表_标准件和外购件. INNER
JOIN
dbo._物料主文件_基本 ON
dbo.PDM_零件明细表_标准件和外购件. = dbo._物料主文件_基本. INNER JOIN
dbo.PDM_组件名称 ON
dbo.PDM_零件明细表_标准件和外购件. = dbo.PDM_组件名称. INNER JOIN
dbo.PDM_机床名称 ON dbo.PDM_组件名称. = dbo.PDM_机床名称. INNER JOIN
dbo.PDM_项目名称 ON dbo.PDM_机床名称. = dbo.PDM_项目名称. INNER JOIN
dbo._订单信息_基础表 ON
dbo.PDM_项目名称. = dbo._订单信息_基础表. INNER JOIN
dbo._采购合同 ON
dbo._采购合同明细. = dbo._采购合同. INNER JOIN
dbo._采购批次 ON
dbo._采购合同明细. = dbo._采购批次. INNER JOIN
dbo._供应商 ON
dbo._采购合同. = dbo._供应商. OUTER APPLY
(SELECT TOP 1 *
FROM dbo._采购到货
WHERE = dbo._采购合同明细.
AND = dbo._物料主文件_基本.
AND ISNULL(, '') <> N'已入库'
ORDER BY ISNULL(id, 0) DESC) AS LEFT OUTER JOIN
dbo._货位主文件 ON
dbo._物料主文件_基本. = dbo._货位主文件. LEFT OUTER JOIN
dbo._合同审批 ON
dbo._采购合同. = dbo._合同审批. LEFT OUTER JOIN
dbo._手动完成记录 ON
dbo._采购合同明细. = dbo._手动完成记录.
GO

View File

@@ -0,0 +1,315 @@
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
ALTER PROCEDURE [dbo].[_改制订单_发起改制]
@ int = null,
@ int = null,
@ nvarchar(50) = null,
@ nvarchar(50) = null,
@ int = null,
@ date = null,
@ int = null,
@ nvarchar(50) = null,
@ nvarchar(50) = null,
@ int = null
AS
BEGIN
SET NOCOUNT ON;
DECLARE @ int;
DECLARE @ int;
DECLARE @ varchar(100);
DECLARE @ int;
DECLARE @ int;
DECLARE @ int;
DECLARE @ varchar(100);
DECLARE @ varchar(100);
DECLARE @n int;
IF ISNULL(LTRIM(RTRIM(@)), '') <> ''
AND ISNULL(LTRIM(RTRIM(@)), '') <> ''
AND LTRIM(RTRIM(@)) = LTRIM(RTRIM(@))
BEGIN
SELECT '0' AS result, '改制零件图号不能与原零件图号相同' AS msg;
RETURN;
END;
IF @ IS NULL OR @ IS NULL
BEGIN
SELECT '0' AS result, '原订单流水号或原组件流水号不能为空' AS msg;
RETURN;
END;
IF ISNULL(@, '') = '' OR ISNULL(@, '') = ''
BEGIN
SELECT '0' AS result, '改制零件名称或改制零件图号不能为空' AS msg;
RETURN;
END;
IF ISNULL(@, 0) <= 0
BEGIN
SELECT '0' AS result, '改制数量必须大于0' AS msg;
RETURN;
END;
-- 修改人:Ld 修改时间:2026-07-01 14:45:00; 优先使用前端点击行传入的原基本件流水号,避免同组件内重复零件或历史流水号导致改制记录回显错位。
IF @ IS NULL
BEGIN
SELECT TOP 1
@ = B.
FROM dbo.PDM_零件明细表_所有视图 AS B
WHERE B. = @
AND B. = @
AND (ISNULL(@, '') = '' OR B. = @)
AND (ISNULL(@, '') = '' OR B.[] = @)
ORDER BY B. DESC;
END;
IF @ IS NULL
BEGIN
SELECT TOP 1
@ =
FROM dbo.PDM_零件明细表_基本件
WHERE = @
ORDER BY DESC;
END;
IF @ IS NULL
BEGIN
SELECT '0' AS result, '未找到原零件基本件流水号' AS msg;
RETURN;
END;
SELECT TOP 1
@ =
FROM dbo._物料主文件_基本
WHERE LTRIM(RTRIM()) = LTRIM(RTRIM(@))
AND LTRIM(RTRIM()) = LTRIM(RTRIM(@))
AND ISNULL(, 0) = 0
ORDER BY DESC;
IF @ IS NULL
BEGIN
SELECT '0' AS result, '未找到改制零件对应的新物料,请先维护物料信息' AS msg;
RETURN;
END;
IF @ IS NULL
SET @ = CONVERT(date, GETDATE());
BEGIN TRY
BEGIN TRAN;
SELECT @n = COUNT(*)
FROM dbo._改制订单排序
WHERE = CONVERT(varchar(4), GETDATE(), 23);
IF @n = 0
BEGIN
SET @ = CONVERT(varchar(4), GETDATE(), 23);
INSERT INTO dbo._改制订单排序(, )
VALUES(@, 1);
SET @ = 1;
END
ELSE
BEGIN
UPDATE dbo._改制订单排序
SET = + 1
WHERE = CONVERT(varchar(4), GETDATE(), 23);
SELECT @ =
FROM dbo._改制订单排序
WHERE = CONVERT(varchar(4), GETDATE(), 23);
END;
SET @ = RIGHT(10000 + CONVERT(varchar(100), @), 4);
SET @ =
'BHGZ' + '-'
+ DATENAME(year, GETDATE())
+ DATENAME(month, GETDATE())
+ RIGHT(100 + DAY(GETDATE()), 2)
+ CONVERT(varchar, @);
INSERT INTO dbo._改制订单记录
(
,
,
,
,
,
,
,
,
,
,
,
,
,
,
)
VALUES
(
@,
@,
@,
@,
@,
@,
@,
@,
@,
@,
@,
N'待生成任务',
@,
GETDATE(),
0
);
SET @ = SCOPE_IDENTITY();
INSERT INTO dbo._零件工艺计划
(
,
,
,
,
,
,
,
)
VALUES
(
@,
@,
@,
GETDATE(),
2,
GETDATE(),
@,
@
);
SET @ = SCOPE_IDENTITY();
UPDATE dbo._改制订单记录
SET = @,
= N'工艺完成'
WHERE = @;
SELECT TOP 1
@ =
FROM dbo._基础表_工艺名称
WHERE = N'改制'
AND ISNULL(, 1) = 1;
IF @ IS NULL
BEGIN
INSERT INTO dbo._基础表_工艺名称(, )
VALUES(N'改制', 1);
SET @ = SCOPE_IDENTITY();
END;
SELECT TOP 1
@ =
FROM dbo._零件工序
WHERE = @
ORDER BY ;
IF @ IS NOT NULL
BEGIN
UPDATE dbo._零件工序
SET = @,
= 1,
= N'改制',
= 0,
= 0,
= 1,
= 0,
= 0,
= 0,
= 0,
= 1
WHERE = @;
END
ELSE
BEGIN
INSERT INTO dbo._零件工序
(
,
,
,
,
,
,
,
,
,
,
,
)
VALUES
(
@,
@,
1,
N'改制',
0,
0,
1,
0,
0,
0,
0,
1
);
END;
EXEC dbo._工艺保存_派工
@ = @,
@ = @;
UPDATE dbo.PDM_组件名称
SET = 1,
= 1
WHERE = @;
UPDATE dbo._订单信息_基础表
SET = 1,
= 1,
= 0,
= @,
= GETDATE(),
= @
WHERE = @;
COMMIT TRAN;
SELECT
'1' AS result,
'改制订单已生成' AS msg,
@ AS ,
@ AS ,
@ AS ,
@ AS ;
END TRY
BEGIN CATCH
IF @@TRANCOUNT > 0
ROLLBACK TRAN;
SELECT
'0' AS result,
ERROR_MESSAGE() AS msg;
END CATCH;
END;
GO

View File

@@ -63,7 +63,7 @@
<el-button type="text" icon="el-icon-picture-outline" size="mini" @click="ContractPhoto(scope.row)"/> <el-button type="text" icon="el-icon-picture-outline" size="mini" @click="ContractPhoto(scope.row)"/>
</el-tooltip> </el-tooltip>
<el-button type="text" icon="el-icon-download" size="mini" @click="assembly(scope.row)">接收任务</el-button> <el-button type="text" icon="el-icon-download" size="mini" @click="assembly(scope.row)">接收任务</el-button>
<el-button :disabled="Number(scope.row.订单类型) !== 1" type="text" icon="el-icon-right" size="mini" @click="goBack(scope.row)">打回</el-button> <el-button type="text" icon="el-icon-right" size="mini" @click="goBack(scope.row)">打回</el-button>
<el-button type="text" icon="el-icon-search" size="mini" @click="historicalOrders(scope.row)">历史订单</el-button> <el-button type="text" icon="el-icon-search" size="mini" @click="historicalOrders(scope.row)">历史订单</el-button>
<el-button type="text" size="mini" @click="viewOrder(scope.row)">查看订单</el-button> <el-button type="text" size="mini" @click="viewOrder(scope.row)">查看订单</el-button>
</template> </template>

View File

@@ -0,0 +1,774 @@
<template>
<div class="app-container">
<el-card style="height: 850px;padding: 0">
<!-- 修改人:Ld 修改时间:2026-07-06 08:36:02 -->
<!-- 参考制定工艺组件的订单产品零件查询入口 -->
<div class="toolbar">
<el-select v-model="queryForm.订单流水号" clearable filterable size="small" style="width: 170px" placeholder="订单号" @change="handleOrderChange">
<el-option v-for="item in orderNumberType" :key="item.value" :label="item.label" :value="item.value" />
</el-select>
<el-select v-model="queryForm.组件流水号" clearable filterable size="small" style="width: 190px" placeholder="产品名称" @change="handleProductChange">
<el-option v-for="item in productName" :key="item.value" :label="item.label" :value="item.value" />
</el-select>
<el-select v-model="queryForm.工艺计划流水号" clearable filterable size="small" style="width: 220px" placeholder="零件名称" @change="pageCurrent = 1;searchTable()">
<el-option v-for="item in partName" :key="item.value" :label="item.label" :value="item.value">
<span style="float: left">{{ item.label }}</span>
<span style="float: right; color: #8492a6; font-size: 13px">{{ item.name }}</span>
</el-option>
</el-select>
<el-select v-model="queryForm.是否启用" clearable filterable size="small" style="width: 120px" placeholder="启用状态" @change="pageCurrent = 1;searchTable()">
<el-option v-for="item in statusOptions" :key="item.value" :label="item.label" :value="item.value" />
</el-select>
<el-input v-model="queryForm.工序名称" clearable size="small" style="width: 150px" placeholder="工序名称" @keyup.enter.native="pageCurrent = 1;searchTable()" />
<el-button icon="el-icon-search" type="primary" plain size="small" style="margin-left: 10px" @click="pageCurrent = 1;searchTable()">查询</el-button>
<el-button :disabled="!queryForm.工艺计划流水号" icon="el-icon-document-copy" type="warning" plain size="small" @click="openCopyDialog()">拷贝</el-button>
</div>
<!-- 修改人:Ld 修改时间:2026-07-02 15:33:23 -->
<!-- 工序工价列表 -->
<el-table
v-loading="loading"
:data="tableData"
border
highlight-current-row
stripe
size="mini"
height="720"
style="width: 100%;">
<el-table-column type="index" label="序号" align="center" width="60" />
<el-table-column label="订单号" align="center" show-overflow-tooltip width="140">
<template slot-scope="scope">
{{ scope.row.订单号 }}
</template>
</el-table-column>
<el-table-column label="产品名称" align="center" show-overflow-tooltip width="140">
<template slot-scope="scope">
{{ scope.row.产品名称 }}
</template>
</el-table-column>
<el-table-column label="工序名称" align="center" show-overflow-tooltip width="150">
<template slot-scope="scope">
{{ scope.row.工序名称 }}
</template>
</el-table-column>
<el-table-column label="零件名称" align="center" show-overflow-tooltip width="150">
<template slot-scope="scope">
{{ scope.row.零件名称 }}
</template>
</el-table-column>
<el-table-column label="图号" align="center" show-overflow-tooltip width="120">
<template slot-scope="scope">
{{ scope.row.图号 }}
</template>
</el-table-column>
<el-table-column label="工序顺序" align="center" width="80">
<template slot-scope="scope">
{{ scope.row.工序顺序 }}
</template>
</el-table-column>
<el-table-column label="定额工时" align="center" width="90">
<template slot-scope="scope">
{{ scope.row.定额工时 }}
</template>
</el-table-column>
<el-table-column label="准结工时" align="center" width="90">
<template slot-scope="scope">
{{ scope.row.准结工时 }}
</template>
</el-table-column>
<el-table-column label="机动时间s" align="center" width="90">
<template slot-scope="scope">
{{ scope.row.机动时间s }}
</template>
</el-table-column>
<el-table-column label="辅助时间s" align="center" width="90">
<template slot-scope="scope">
{{ scope.row.辅助时间s }}
</template>
</el-table-column>
<el-table-column label="总时间s" align="center" width="90">
<template slot-scope="scope">
{{ scope.row.总时间s }}
</template>
</el-table-column>
<el-table-column label="单装数量(件)" align="center" width="110">
<template slot-scope="scope">
{{ scope.row['单装数量(件)'] }}
</template>
</el-table-column>
<el-table-column label="操作台数" align="center" width="90">
<template slot-scope="scope">
{{ scope.row.操作台数 }}
</template>
</el-table-column>
<el-table-column label="日产能(件)" align="center" width="100">
<template slot-scope="scope">
{{ scope.row['日产能(件)'] }}
</template>
</el-table-column>
<el-table-column label="最终单价(元/件)" align="center" width="130">
<template slot-scope="scope">
{{ scope.row['最终单价(元/件)'] }}
</template>
</el-table-column>
<el-table-column label="生效日期" align="center" width="110">
<template slot-scope="scope">
{{ scope.row.生效日期 }}
</template>
</el-table-column>
<el-table-column label="变更次数" align="center" width="90">
<template slot-scope="scope">
{{ scope.row.变更次数 }}
</template>
</el-table-column>
<el-table-column label="启用状态" align="center" width="90">
<template slot-scope="scope">
<el-tag :type="Number(scope.row.是否启用) === 1 ? 'success' : 'info'" size="mini">
{{ Number(scope.row.是否启用) === 1 ? '启用' : '停用' }}
</el-tag>
</template>
</el-table-column>
<el-table-column label="备注" align="center" show-overflow-tooltip min-width="140">
<template slot-scope="scope">
{{ scope.row.备注 }}
</template>
</el-table-column>
<el-table-column label="操作" align="center" width="170" fixed="right">
<template slot-scope="scope">
<el-button type="text" size="mini" icon="el-icon-edit-outline" @click="openEditDialog(scope.row)">设置</el-button>
<el-button :disabled="!scope.row.工价流水号" type="text" size="mini" icon="el-icon-document" @click="openHistoryDialog(scope.row)">历史</el-button>
<el-button :disabled="!scope.row.工价流水号" type="text" size="mini" icon="el-icon-turn-off" style="color:#f56c6c" @click="handleDisable(scope.row)">停用</el-button>
</template>
</el-table-column>
</el-table>
<!-- 修改人:Ld 修改时间:2026-07-02 15:33:23 -->
<!-- 分页 -->
<div class="block" style="margin-top: 10px;">
<!-- 修改人:Ld 修改时间:2026-07-06 08:52:37 -->
<!-- 工序工价数据量超过 100 放开分页条数选择 -->
<el-pagination
:current-page="pageCurrent"
:page-sizes="[20, 50, 100, 200, 500, 1000]"
:page-size="pageSize"
:total="total"
layout="total, sizes, prev, pager, next, jumper"
@size-change="handleSizeChange"
@current-change="handleCurrentChange" />
</div>
</el-card>
<!-- 修改人:Ld 修改时间:2026-07-02 15:33:23 -->
<!-- 工价设置弹窗 -->
<el-dialog v-el-drag-dialog :visible.sync="dialogFormVisible" :title="dialogTitle" center width="960px">
<el-form ref="form" :model="form" :rules="rules" label-position="left" label-width="100px">
<el-row :gutter="16">
<el-col :span="12">
<el-form-item label="工艺名称" prop="工艺名称">
<el-input v-model="form.工艺名称" disabled size="small" />
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="工序名称" prop="工序名称">
<el-input v-model="form.工序名称" disabled size="small" />
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="16">
<el-col :span="12">
<el-form-item label="零件名称" prop="零件名称">
<el-input v-model="form.零件名称" disabled size="small" />
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="图号" prop="图号">
<el-input v-model="form.图号" disabled size="small" />
</el-form-item>
</el-col>
</el-row>
<!-- 修改人:Ld 修改时间:2026-07-03 08:02:29 -->
<!-- 按现场确认的 9 个工价字段维护 -->
<el-row :gutter="16">
<el-col :span="8">
<el-form-item label="机动时间s" prop="机动时间s">
<el-input-number v-model="form.机动时间s" :min="0" :precision="2" :step="1" controls-position="right" style="width: 100%;" />
</el-form-item>
</el-col>
<el-col :span="8">
<el-form-item label="辅助时间s" prop="辅助时间s">
<el-input-number v-model="form.辅助时间s" :min="0" :precision="2" :step="1" controls-position="right" style="width: 100%;" />
</el-form-item>
</el-col>
<el-col :span="8">
<el-form-item label="总时间s" prop="总时间s">
<el-input-number v-model="form.总时间s" :min="0" :precision="2" :step="1" controls-position="right" style="width: 100%;" />
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="16">
<el-col :span="8">
<el-form-item label="单装数量(件)" prop="单装数量(件)">
<el-input-number v-model="form['单装数量(件)']" :min="0" :precision="2" :step="1" controls-position="right" style="width: 100%;" />
</el-form-item>
</el-col>
<el-col :span="8">
<el-form-item label="操作台数" prop="操作台数">
<el-input-number v-model="form.操作台数" :min="0" :precision="2" :step="1" controls-position="right" style="width: 100%;" />
</el-form-item>
</el-col>
<el-col :span="8">
<el-form-item label="日产能(件)" prop="日产能(件)">
<el-input-number v-model="form['日产能(件)']" :min="0" :precision="2" :step="1" controls-position="right" style="width: 100%;" />
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="16">
<el-col :span="12">
<el-form-item label="最终单价" prop="最终单价(元/件)">
<!-- 修改人:Ld 修改时间:2026-07-06 09:23:45; 最终单价输入框仅保留两位小数显示 -->
<el-input-number v-model="form['最终单价(元/件)']" :min="0" :precision="2" :step="0.1" controls-position="right" style="width: 100%;" />
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="生效日期" prop="生效日期">
<el-date-picker v-model="form.生效日期" type="date" value-format="yyyy-MM-dd" format="yyyy-MM-dd" clearable size="small" placeholder="选择生效日期" style="width: 100%;" />
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="16">
<el-col :span="12">
<el-form-item label="变更次数" prop="变更次数">
<el-input-number v-model="form.变更次数" :min="0" :precision="0" :step="1" controls-position="right" style="width: 100%;" />
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="启用状态" prop="是否启用">
<el-select v-model="form.是否启用" clearable filterable size="small" style="width: 100%;" placeholder="请选择启用状态">
<el-option v-for="item in statusOptions" :key="item.value" :label="item.label" :value="item.value" />
</el-select>
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="16">
<el-col :span="24">
<el-form-item label="备注" prop="备注">
<el-input v-model="form.备注" :rows="3" type="textarea" clearable maxlength="200" show-word-limit />
</el-form-item>
</el-col>
</el-row>
</el-form>
<div slot="footer" class="dialog-footer">
<el-button @click="closeDialog()"> </el-button>
<el-button type="primary" @click="submitForm()"> </el-button>
</div>
</el-dialog>
<!-- 修改人:Ld 修改时间:2026-07-06 08:45:45 -->
<!-- 工序工价拷贝弹窗仅保留零件名称工序号和工艺名称预览 -->
<el-dialog v-el-drag-dialog :visible.sync="copyVisible" title="工序工价拷贝" center width="760px">
<el-row style="margin-bottom: 10px">
<el-input v-model="copyForm.零件筛选" clearable placeholder="零件图号或零件名称筛选" size="small" style="width: 260px">
<el-button slot="append" icon="el-icon-right" @click="searchCopyParts()" />
</el-input>
<el-select v-model="copyForm.源零件图号" clearable filterable size="small" style="width: 260px;margin-left: 10px" placeholder="源零件" @change="searchCopyProcess()">
<el-option v-for="item in copyPartList" :key="item.value" :label="item.label" :value="item.value">
<span style="float: left">{{ item.label }}</span>
<span style="float: right; color: #8492a6; font-size: 13px">{{ item.name }}</span>
</el-option>
</el-select>
</el-row>
<el-table :data="copyProcessList" border highlight-current-row stripe size="mini" height="420" style="width: 100%;">
<el-table-column type="index" label="序号" align="center" width="60" />
<el-table-column label="零件名称" align="center" show-overflow-tooltip min-width="180">
<template slot-scope="scope">
{{ scope.row.零件名称 }}
</template>
</el-table-column>
<el-table-column label="工序号" align="center" width="90">
<template slot-scope="scope">
{{ scope.row.工序顺序 }}
</template>
</el-table-column>
<el-table-column label="工艺名称" align="center" show-overflow-tooltip min-width="180">
<template slot-scope="scope">
{{ scope.row.工艺名称 }}
</template>
</el-table-column>
</el-table>
<div slot="footer" class="dialog-footer">
<el-button size="small" @click="copyVisible = false">取消</el-button>
<el-button type="primary" size="small" @click="submitCopy()">确定</el-button>
</div>
</el-dialog>
<!-- 修改人:Ld 修改时间:2026-07-02 15:33:23 -->
<!-- 历史定价弹窗 -->
<el-dialog v-el-drag-dialog :visible.sync="historyVisible" title="历史定价" center width="980px">
<el-table :data="historyData" border stripe size="mini" height="420" style="width: 100%;">
<el-table-column type="index" label="序号" align="center" width="60" />
<el-table-column label="工价流水号" align="center" width="110">
<template slot-scope="scope">
{{ scope.row.工价流水号 }}
</template>
</el-table-column>
<el-table-column label="操作类型" align="center" width="90">
<template slot-scope="scope">
{{ scope.row.操作类型 }}
</template>
</el-table-column>
<el-table-column label="工艺名称" align="center" show-overflow-tooltip width="120">
<template slot-scope="scope">
{{ scope.row.工艺名称 }}
</template>
</el-table-column>
<el-table-column label="工序名称" align="center" show-overflow-tooltip width="150">
<template slot-scope="scope">
{{ scope.row.工序名称 }}
</template>
</el-table-column>
<el-table-column label="变更前" align="center" show-overflow-tooltip min-width="150">
<template slot-scope="scope">
{{ scope.row.变更前 }}
</template>
</el-table-column>
<el-table-column label="变更后" align="center" show-overflow-tooltip min-width="150">
<template slot-scope="scope">
{{ scope.row.变更后 }}
</template>
</el-table-column>
<el-table-column label="操作人" align="center" width="100">
<template slot-scope="scope">
{{ scope.row.操作人 }}
</template>
</el-table-column>
<el-table-column label="操作时间" align="center" width="140">
<template slot-scope="scope">
{{ scope.row.操作时间 }}
</template>
</el-table-column>
</el-table>
<div slot="footer" class="dialog-footer">
<el-button @click="historyVisible = false"> </el-button>
</div>
</el-dialog>
</div>
</template>
<script>
export default {
data() {
return {
// 修改人:Ld 修改时间:2026-07-06 08:36:02
// 查询条件参考制定工艺组件,表格显示字段保持不变
queryForm: {
订单流水号: '',
组件流水号: '',
工艺计划流水号: '',
工序名称: '',
是否启用: ''
},
// 修改人:Ld 修改时间:2026-07-06 08:36:02
// 制定工艺查询入口下拉数据
orderNumberType: [],
productName: [],
partName: [],
// 修改人:Ld 修改时间:2026-07-02 15:33:23
// 下拉选项
statusOptions: [
{ label: '启用', value: 1 },
{ label: '停用', value: 0 }
],
// 修改人:Ld 修改时间:2026-07-02 15:33:23
// 表格与分页
loading: false,
tableData: [],
historyData: [],
total: 0,
pageCurrent: 1,
pageSize: 100,
// 修改人:Ld 修改时间:2026-07-02 15:33:23
// 弹窗状态
dialogFormVisible: false,
dialogTitle: '设置工序工价',
dialogMode: 'edit',
historyVisible: false,
// 修改人:Ld 修改时间:2026-07-06 08:45:45
// 工序工价拷贝数据,参考制定工艺拷贝但去掉工艺编辑功能
copyVisible: false,
copyForm: {
零件筛选: '',
源零件图号: ''
},
copyPartList: [],
copyProcessList: [],
// 修改人:Ld 修改时间:2026-07-02 15:33:23
// 表单主键
form: {
工价流水号: '',
工艺名称: '',
工序名称: '',
零件名称: '',
图号: '',
机动时间s: 0,
辅助时间s: 0,
总时间s: 0,
'单装数量(件)': 0,
操作台数: 0,
'日产能(件)': 0,
'最终单价(元/件)': 0,
生效日期: '',
变更次数: 0,
是否启用: 1,
备注: '',
工序流水号: ''
},
rules: {
工艺名称: [{ required: true, message: '请输入工艺名称', trigger: 'blur' }],
工序名称: [{ required: true, message: '请输入工序名称', trigger: 'blur' }],
零件名称: [{ required: true, message: '请输入零件名称', trigger: 'blur' }],
图号: [{ required: true, message: '请输入图号', trigger: 'blur' }],
是否启用: [{ required: true, message: '请选择启用状态', trigger: 'change' }]
}
}
},
created() {
this.getOrderNumberType()
this.searchTable()
},
methods: {
// 修改人:Ld 修改时间:2026-07-06 08:36:02
// 获取制定工艺组件同源订单下拉
getOrderNumberType() {
this.orderNumberType = []
var param = []
var Data = this.CreateData('11', '精工车间_制定工艺_订单查询', param)
this.ExecDatabase(Data).then(response => {
for (let i = 0; i < response.data.length; i++) {
this.orderNumberType.push({
label: response.data[i].订单号,
value: response.data[i].订单流水号
})
}
})
},
// 修改人:Ld 修改时间:2026-07-06 08:36:02
// 订单切换后按制定工艺组件口径加载产品
handleOrderChange() {
this.queryForm.组件流水号 = ''
this.queryForm.工艺计划流水号 = ''
this.productName = []
this.partName = []
this.getproductName()
this.pageCurrent = 1
this.searchTable()
},
// 修改人:Ld 修改时间:2026-07-06 08:36:02
// 获取制定工艺组件同源产品下拉
getproductName() {
if (!this.queryForm.订单流水号) {
return
}
var param = []
param[0] = ['订单流水号', this.queryForm.订单流水号]
var Data = this.CreateData('11', '订单信息_产品信息_查询数据', param)
this.ExecDatabase(Data).then(response => {
for (let i = 0; i < response.data.length; i++) {
this.productName.push({
label: response.data[i].产品名称,
value: response.data[i].组件流水号
})
}
})
},
// 修改人:Ld 修改时间:2026-07-06 08:36:02
// 产品切换后按制定工艺组件口径加载零件
handleProductChange() {
this.queryForm.工艺计划流水号 = ''
this.partName = []
this.getpartName()
this.pageCurrent = 1
this.searchTable()
},
// 修改人:Ld 修改时间:2026-07-06 08:36:02
// 获取制定工艺组件同源零件下拉
getpartName() {
if (!this.queryForm.组件流水号) {
return
}
var param = []
param[0] = ['组件流水号', this.queryForm.组件流水号]
var Data = this.CreateData('11', '精工车间_制定工艺_零件名称_查询', param)
this.ExecDatabase(Data).then(response => {
for (let i = 0; i < response.data.length; i++) {
this.partName.push({
label: response.data[i].零件名称,
name: response.data[i].零件图号,
value: response.data[i].工艺计划流水号
})
}
})
},
// 修改人:Ld 修改时间:2026-07-06 08:36:02
// 查询列表
searchTable() {
this.loading = true
var param = []
param[0] = ['订单流水号', this.queryForm.订单流水号]
param[1] = ['订单流水号_check', this.queryForm.订单流水号 ? 1 : 0]
param[2] = ['组件流水号', this.queryForm.组件流水号]
param[3] = ['组件流水号_check', this.queryForm.组件流水号 ? 1 : 0]
param[4] = ['工艺计划流水号', this.queryForm.工艺计划流水号]
param[5] = ['工艺计划流水号_check', this.queryForm.工艺计划流水号 ? 1 : 0]
param[6] = ['工序名称', this.queryForm.工序名称]
param[7] = ['工序名称_check', this.queryForm.工序名称 ? 1 : 0]
param[8] = ['工艺名称', this.queryForm.工序名称]
param[9] = ['工艺名称_check', this.queryForm.工序名称 ? 1 : 0]
param[10] = ['是否启用', this.queryForm.是否启用]
param[11] = ['是否启用_check', this.queryForm.是否启用 === '' || this.queryForm.是否启用 === null || typeof this.queryForm.是否启用 === 'undefined' ? 0 : 1]
var Data = this.CreateData('11', '车间生产管理工艺_工序工价_查询数据', param, this.pageSize, this.pageCurrent)
this.ExecDatabase(Data).then(response => {
this.tableData = response.data && response.data.rows ? response.data.rows : response.data
this.total = response.data && response.data.total ? response.data.total : (this.tableData ? this.tableData.length : 0)
this.loading = false
}).catch(() => {
this.loading = false
})
},
// 修改人:Ld 修改时间:2026-07-06 08:45:45
// 打开工序工价拷贝
openCopyDialog() {
if (!this.queryForm.工艺计划流水号) {
this.$message.warning('请先选择要复制到的零件')
return
}
this.copyVisible = true
this.copyForm = {
零件筛选: '',
源零件图号: ''
}
this.copyPartList = []
this.copyProcessList = []
},
// 修改人:Ld 修改时间:2026-07-06 08:45:45
// 参考制定工艺拷贝的源零件查询
searchCopyParts() {
this.copyPartList = []
this.copyForm.源零件图号 = ''
this.copyProcessList = []
var param = []
param[0] = ['零件图号_check', this.copyForm.零件筛选 ? 1 : 0]
param[1] = ['零件图号', this.copyForm.零件筛选]
var Data = this.CreateData('11', '精工车间_制定工艺_零件名称_查询_工艺拷贝', param)
this.ExecDatabase(Data).then(response => {
for (let i = 0; i < response.data.length; i++) {
this.copyPartList.push({
label: response.data[i].零件名称,
name: response.data[i].零件图号,
value: response.data[i].零件图号
})
}
})
},
// 修改人:Ld 修改时间:2026-07-06 08:45:45
// 源零件工序预览,仅显示零件名称、工序号和工艺名称
searchCopyProcess() {
this.copyProcessList = []
if (!this.copyForm.源零件图号) {
return
}
var param = []
param[0] = ['零件图号', this.copyForm.源零件图号]
var Data = this.CreateData('11', '车间生产管理工艺_工序工价_复制源_查询数据', param)
this.ExecDatabase(Data).then(response => {
this.copyProcessList = response.data
})
},
// 修改人:Ld 修改时间:2026-07-06 08:45:45
// 将源零件已维护的工价按工序号和工艺名称复制到当前零件
submitCopy() {
if (!this.queryForm.工艺计划流水号) {
this.$message.warning('请先选择要复制到的零件')
return
}
if (!this.copyForm.源零件图号 || this.copyProcessList.length === 0) {
this.$message.warning('请先选择源零件')
return
}
var param = []
param[0] = ['目标工艺计划流水号', this.queryForm.工艺计划流水号]
param[1] = ['源零件图号', this.copyForm.源零件图号]
var Data = this.CreateData('12', '车间生产管理工艺_工序工价_复制数据', param)
this.ExecDatabase(Data).then(response => {
if (response.data && response.data[0] && response.data[0].result === '1') {
this.$message.success('拷贝成功')
this.copyVisible = false
this.searchTable()
} else {
this.$message.error(response.data && response.data[0] && response.data[0].message ? response.data[0].message : '拷贝失败')
}
})
},
// 修改人:Ld 修改时间:2026-07-02 15:33:23
// 打开编辑
openEditDialog(row) {
this.dialogMode = 'edit'
this.dialogTitle = '设置工序工价'
this.dialogFormVisible = true
this.form = {
工价流水号: row.工价流水号,
工艺名称: row.工艺名称,
工序名称: row.工序名称,
零件名称: row.零件名称,
图号: row.图号,
机动时间s: Number(row.机动时间s || 0),
辅助时间s: Number(row.辅助时间s || 0),
总时间s: Number(row.总时间s || 0),
'单装数量(件)': Number(row['单装数量(件)'] || 0),
操作台数: Number(row.操作台数 || 0),
'日产能(件)': Number(row['日产能(件)'] || 0),
'最终单价(元/件)': Number(row['最终单价(元/件)'] || 0),
生效日期: row.生效日期,
变更次数: Number(row.变更次数 || 0),
是否启用: row.是否启用 === '' || row.是否启用 === null || typeof row.是否启用 === 'undefined' ? 1 : Number(row.是否启用),
备注: row.备注,
工序流水号: row.工序流水号
}
},
// 修改人:Ld 修改时间:2026-07-02 15:33:23
// 提交新增或编辑
submitForm() {
this.$refs['form'].validate((valid) => {
if (!valid) {
return false
}
var param = []
param[0] = ['工价流水号', this.form.工价流水号]
param[1] = ['工艺名称', this.form.工艺名称]
param[2] = ['工序名称', this.form.工序名称]
param[3] = ['零件名称', this.form.零件名称]
param[4] = ['图号', this.form.图号]
param[5] = ['机动时间s', this.form.机动时间s]
param[6] = ['辅助时间s', this.form.辅助时间s]
param[7] = ['总时间s', this.form.总时间s]
// 修改人:Ld 修改时间:2026-07-03 08:02:29
// 带括号字段提交给存储过程时使用安全参数名,查询返回仍保持原字段名
param[8] = ['单装数量件', this.form['单装数量(件)']]
param[9] = ['操作台数', this.form.操作台数]
param[10] = ['日产能件', this.form['日产能(件)']]
param[11] = ['最终单价元件', this.form['最终单价(元/件)']]
param[12] = ['生效日期', this.form.生效日期]
param[13] = ['变更次数', this.form.变更次数]
param[14] = ['是否启用', this.form.是否启用]
param[15] = ['备注', this.form.备注]
param[16] = ['工序流水号', this.form.工序流水号]
var Data = this.CreateData('12', '车间生产管理工艺_工序工价_编辑数据', param)
this.ExecDatabase(Data).then(response => {
if (response.data && response.data[0] && response.data[0].result === '1') {
this.$message.success('设置成功')
this.dialogFormVisible = false
this.searchTable()
} else {
this.$message.error('设置失败')
}
})
})
},
// 修改人:Ld 修改时间:2026-07-02 15:33:23
// 重置表单
resetForm() {
if (this.$refs['form'] !== undefined) {
this.$refs['form'].resetFields()
}
this.form = {
工价流水号: '',
工艺名称: '',
工序名称: '',
零件名称: '',
图号: '',
机动时间s: 0,
辅助时间s: 0,
总时间s: 0,
'单装数量(件)': 0,
操作台数: 0,
'日产能(件)': 0,
'最终单价(元/件)': 0,
生效日期: '',
变更次数: 0,
是否启用: 1,
备注: '',
工序流水号: ''
}
},
// 修改人:Ld 修改时间:2026-07-02 15:33:23
// 关闭弹窗
closeDialog() {
this.dialogFormVisible = false
this.resetForm()
},
// 修改人:Ld 修改时间:2026-07-02 15:33:23
// 停用工价
handleDisable(row) {
this.$confirm('确定停用该工序工价吗?', '提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning'
}).then(() => {
var param = []
param[0] = ['工价流水号', row.工价流水号]
var Data = this.CreateData('12', '车间生产管理工艺_工序工价_删除数据', param)
this.ExecDatabase(Data).then(response => {
if (response.data && response.data[0] && response.data[0].result === '1') {
this.$message.success('停用成功')
this.searchTable()
} else {
this.$message.error('停用失败')
}
})
})
},
// 修改人:Ld 修改时间:2026-07-06 09:00:29
// 打开该零件该工序名称的历史定价
openHistoryDialog(row) {
this.historyVisible = true
var param = []
param[0] = ['零件名称_check', row.零件名称 ? 1 : 0]
param[1] = ['零件名称', row.零件名称]
param[2] = ['图号_check', row.图号 ? 1 : 0]
param[3] = ['图号', row.图号]
param[4] = ['工序名称_check', row.工序名称 ? 1 : 0]
param[5] = ['工序名称', row.工序名称]
var Data = this.CreateData('11', '车间生产管理工艺_工序工价_历史_查询数据', param)
this.ExecDatabase(Data).then(response => {
this.historyData = response.data
})
},
// 修改人:Ld 修改时间:2026-07-02 15:33:23
// 分页条数变化
handleSizeChange(val) {
this.pageCurrent = 1
this.pageSize = val
this.searchTable()
},
// 修改人:Ld 修改时间:2026-07-02 15:33:23
// 页码变化
handleCurrentChange(val) {
this.pageCurrent = val
this.searchTable()
}
}
}
</script>
<style scoped>
.toolbar {
display: flex;
flex-wrap: wrap;
gap: 10px;
align-items: center;
padding: 10px 0 12px;
}
.el-card {
padding: 0;
}
</style>

View File

@@ -0,0 +1,457 @@
<!-- 生产完成审核组件 修改人:Ld 修改时间:2026-07-02 13:57:18; -->
<template>
<div class="app-container production-completion-audit">
<el-card>
<div class="search-bar">
<el-input
v-model="searchForm.操作者"
style="width: 140px"
placeholder="操作者"
size="small"
clearable
@keyup.enter.native="resetSearch"/>
<el-select
v-model="searchForm.审核类型"
style="width: 130px"
placeholder="审核类型"
size="small"
clearable>
<el-option label="加工完成" value="加工完成"/>
<el-option label="结束整修" value="结束整修"/>
</el-select>
<el-select
v-model="searchForm.审核状态"
style="width: 130px"
placeholder="审核状态"
size="small"
clearable>
<el-option label="待审核" value="待审核"/>
<el-option label="审核通过" value="审核通过"/>
<el-option label="审核不通过" value="审核不通过"/>
</el-select>
<span class="date-label">提交时间</span>
<el-date-picker
v-model="dateRange"
size="small"
type="daterange"
align="center"
style="width: 240px"
value-format="yyyy-MM-dd"
format="yyyy-MM-dd"
range-separator=""
start-placeholder="开始日期"
end-placeholder="结束日期"/>
<el-button icon="el-icon-search" type="primary" plain size="small" @click="resetSearch">查询</el-button>
<el-button icon="el-icon-refresh" plain size="small" @click="resetForm">重置</el-button>
</div>
<el-table
v-loading="loading"
ref="table"
:data="tableData"
border
stripe
highlight-current-row
size="mini"
height="750px"
style="width: 100%; margin-top: 7px">
<el-table-column label="审核状态" align="center" width="95">
<template slot-scope="scope">
<el-tag :type="getAuditStateType(scope.row.审核状态)" size="mini">
{{ scope.row.审核状态 }}
</el-tag>
</template>
</el-table-column>
<el-table-column label="审核类型" prop="审核类型" align="center" width="95"/>
<el-table-column label="订单号" prop="订单号" align="center" width="150" show-overflow-tooltip/>
<el-table-column label="零件名称" prop="零件名称" align="center" width="140" show-overflow-tooltip/>
<el-table-column label="零件图号" prop="零件图号" align="center" width="140" show-overflow-tooltip/>
<el-table-column label="工序" prop="工序" align="center" width="110" show-overflow-tooltip/>
<el-table-column label="工作者" prop="工作者姓名" align="center" width="90" show-overflow-tooltip/>
<el-table-column label="完成数量" prop="完成数量" align="center" width="90"/>
<el-table-column label="投产数量" prop="投产数量" align="center" width="90"/>
<el-table-column label="已完成数" prop="已完成数" align="center" width="90"/>
<el-table-column label="工位号" prop="工位号" align="center" width="120" show-overflow-tooltip/>
<el-table-column label="工位设备名称" prop="工位设备名称" align="center" width="150" show-overflow-tooltip/>
<el-table-column label="设备号" prop="设备号" align="center" width="120" show-overflow-tooltip/>
<el-table-column label="设备名" prop="设备名" align="center" width="150" show-overflow-tooltip/>
<el-table-column label="整修状态" align="center" width="90">
<template slot-scope="scope">
{{ getRepairStateText(scope.row.整修状态) }}
</template>
</el-table-column>
<el-table-column label="整修方案" prop="整修方案" align="center" min-width="180" show-overflow-tooltip/>
<el-table-column label="备注" prop="备注" align="center" min-width="160" show-overflow-tooltip/>
<el-table-column label="开始时间" prop="开始时间" align="center" width="155"/>
<el-table-column label="结束时间" prop="结束时间" align="center" width="155"/>
<el-table-column label="提交时间" prop="提交时间" align="center" width="155"/>
<el-table-column label="操作" align="center" width="170" fixed="right">
<template slot-scope="scope">
<el-button type="text" size="mini" icon="el-icon-view" @click="openDetail(scope.row)">查看</el-button>
<el-button
:disabled="scope.row.审核状态 !== '待审核'"
type="text"
size="mini"
icon="el-icon-check"
@click="approveRow(scope.row)">通过</el-button>
<el-button
:disabled="scope.row.审核状态 !== '待审核'"
type="text"
size="mini"
icon="el-icon-edit"
@click="openEditDialog(scope.row)">修改数量/时间</el-button>
</template>
</el-table-column>
</el-table>
<div class="block" style="margin-top: 10px">
<el-pagination
:current-page="pageCurrent"
:page-sizes="[10, 20, 30, 40, 100]"
:page-size="pageSize"
:total="total"
layout="total, sizes, prev, pager, next, jumper"
@size-change="handleSizeChange"
@current-change="handleCurrentChange"/>
</div>
</el-card>
<el-dialog v-el-drag-dialog :visible.sync="detailVisible" title="审核详情" width="760px">
<el-table
v-if="currentRow"
:data="detailData"
border
size="mini"
class="detail-table"
max-height="520">
<el-table-column label="字段" prop="label" align="center" width="150"/>
<el-table-column label="内容" prop="value" align="left" show-overflow-tooltip/>
</el-table>
</el-dialog>
<el-dialog v-el-drag-dialog :visible.sync="editVisible" title="修改审核数据" width="420px">
<el-form ref="editForm" :model="editForm" label-width="110px" size="small">
<el-form-item v-if="editForm.审核类型 === '加工完成'" label="完成数量">
<el-input-number v-model="editForm.完成数量" :min="1" :step="1" step-strictly style="width: 220px"/>
</el-form-item>
<el-form-item v-if="editForm.审核类型 === '加工完成'" label="加工开始时间">
<el-date-picker
v-model="editForm.加工开始时间"
type="datetime"
value-format="yyyy-MM-dd HH:mm:ss"
format="yyyy-MM-dd HH:mm:ss"
placeholder="选择加工开始时间"
style="width: 220px"/>
</el-form-item>
<el-form-item v-if="editForm.审核类型 === '加工完成'" label="加工完成时间">
<el-date-picker
v-model="editForm.加工完成时间"
type="datetime"
value-format="yyyy-MM-dd HH:mm:ss"
format="yyyy-MM-dd HH:mm:ss"
placeholder="选择加工完成时间"
style="width: 220px"/>
</el-form-item>
<el-form-item v-if="editForm.审核类型 === '结束整修'" label="整修开始时间">
<el-date-picker
v-model="editForm.整修开始时间"
type="datetime"
value-format="yyyy-MM-dd HH:mm:ss"
format="yyyy-MM-dd HH:mm:ss"
placeholder="选择整修开始时间"
style="width: 220px"/>
</el-form-item>
<el-form-item v-if="editForm.审核类型 === '结束整修'" label="整修结束时间">
<el-date-picker
v-model="editForm.整修结束时间"
type="datetime"
value-format="yyyy-MM-dd HH:mm:ss"
format="yyyy-MM-dd HH:mm:ss"
placeholder="选择整修结束时间"
style="width: 220px"/>
</el-form-item>
<el-form-item v-if="editForm.审核类型 === '结束整修'" label="整修方案">
<el-input v-model="editForm.整修方案" type="textarea" :rows="3" style="width: 220px"/>
</el-form-item>
</el-form>
<div slot="footer" class="dialog-footer">
<el-button size="small" @click="editVisible = false">取消</el-button>
<el-button size="small" type="primary" @click="confirmEditApprove">确定</el-button>
</div>
</el-dialog>
</div>
</template>
<script>
import { mapGetters } from 'vuex'
export default {
data() {
return {
loading: false,
tableData: [],
total: 0,
pageCurrent: 1,
pageSize: 100,
dateRange: '',
detailVisible: false,
editVisible: false,
currentRow: null,
detailData: [],
editRow: null,
editForm: {
审核类型: '',
完成数量: 1,
加工开始时间: '',
加工完成时间: '',
整修开始时间: '',
整修结束时间: '',
整修方案: ''
},
searchForm: {
操作者: '',
审核类型: '',
审核状态: '待审核'
}
}
},
computed: {
...mapGetters([
'id',
'token'
])
},
updated() {
this.$nextTick(function() {
if (this.$refs.table) {
this.$refs.table.doLayout()
}
})
},
created() {
this.searchTable()
},
methods: {
// 生产完成审核查询 修改人:Ld 修改时间:2026-07-02 13:57:18;
searchTable() {
var dateRangeCheck = this.dateRange ? 1 : 0
var param = []
param[0] = ['审核状态_check', this.searchForm.审核状态 ? 1 : 0]
param[1] = ['审核状态', this.searchForm.审核状态]
param[2] = ['审核类型_check', this.searchForm.审核类型 ? 1 : 0]
param[3] = ['审核类型', this.searchForm.审核类型]
param[4] = ['操作者_check', this.searchForm.操作者 ? 1 : 0]
param[5] = ['操作者', this.searchForm.操作者]
param[6] = ['时间_check', dateRangeCheck]
param[7] = ['开始时间', dateRangeCheck ? this.dateRange[0] : '']
param[8] = ['结束时间', dateRangeCheck ? this.dateRange[1] : '']
this.loading = true
var Data = this.CreateData('11', '机加工MES_加工完成整修审核_查询数据', param, this.pageSize, this.pageCurrent)
this.ExecDatabase(Data).then(response => {
this.tableData = response.data.rows || []
this.total = Number(response.data.total || 0)
}).catch(() => {
this.tableData = []
this.total = 0
this.$message.error('查询生产完成审核数据失败')
}).then(() => {
this.loading = false
})
},
resetSearch() {
this.pageCurrent = 1
this.searchTable()
},
resetForm() {
this.searchForm = {
操作者: '',
审核类型: '',
审核状态: '待审核'
}
this.dateRange = ''
this.resetSearch()
},
openDetail(row) {
this.currentRow = row
// 详情弹窗使用 Element UI 2.13 兼容的表格展示 修改人:Ld 修改时间:2026-07-02 13:57:18;
this.detailData = [
{ label: '审核流水号', value: row.id },
{ label: '审核状态', value: row.审核状态 },
{ label: '审核类型', value: row.审核类型 },
{ label: '订单号', value: row.订单号 },
{ label: '产品名称', value: row.产品名称 },
{ label: '零件名称', value: row.零件名称 },
{ label: '零件图号', value: row.零件图号 },
{ label: '工序', value: row.工序 },
{ label: '物料编码', value: row.物料编码 },
{ label: '材料', value: row.材料 },
{ label: '工艺计划流水号', value: row.工艺计划流水号 },
{ label: '工序流水号', value: row.工序流水号 },
{ label: '工作者考勤编号', value: row.工作者考勤编号 },
{ label: '工作者姓名', value: row.工作者姓名 },
{ label: '完成类型', value: row.完成类型 },
{ label: '完成数量', value: row.完成数量 },
{ label: '投产数量', value: row.投产数量 },
{ label: '已完成数', value: row.已完成数 },
{ label: '工序顺序', value: row.工序顺序 },
{ label: '剩余数量', value: row.剩余数量 },
{ label: '剩余工时', value: row.剩余工时 },
{ label: '录工票人员编号', value: row.录工票人员编号 },
{ label: '录工票人员姓名', value: row.录工票人员姓名 },
{ label: '工位号', value: row.工位号 },
{ label: '工位设备名称', value: row.工位设备名称 },
{ label: '设备号', value: row.设备号 },
{ label: '设备名', value: row.设备名 },
{ label: '操作者编号', value: row.操作者 },
{ label: '操作者姓名', value: row.操作者姓名 },
{ label: '整修状态', value: this.getRepairStateText(row.整修状态) },
{ label: '整修记录id', value: row.整修记录id },
{ label: '开始时间', value: row.开始时间 },
{ label: '结束时间', value: row.结束时间 },
{ label: '提交时间', value: row.提交时间 },
{ label: '审核人', value: row.审核人 },
{ label: '审核时间', value: row.审核时间 },
{ label: '整修方案', value: row.整修方案 },
{ label: '备注', value: row.备注 },
{ label: '审核意见', value: row.审核意见 }
]
this.detailVisible = true
},
// 生产完成审核通过 修改人:Ld 修改时间:2026-07-02 13:57:18;
approveRow(row) {
this.$confirm('确定审核通过该生产完成记录?', '提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning'
}).then(() => {
this.submitAudit(row, '审核通过', '')
}).catch(() => {
this.$message({
type: 'info',
message: '已取消操作'
})
})
},
// 修改完成数量和时间后按原 MES 链路审核通过 修改人:Ld 修改时间:2026-07-03 16:47:02;
openEditDialog(row) {
this.editRow = row
this.editForm = {
审核类型: row.审核类型,
完成数量: row.完成数量 ? Number(row.完成数量) : 1,
加工开始时间: row.开始时间 || '',
加工完成时间: row.结束时间 || '',
整修开始时间: row.开始时间 || '',
整修结束时间: row.结束时间 || '',
整修方案: row.整修方案 || ''
}
this.editVisible = true
},
confirmEditApprove() {
if (!this.editRow) {
return
}
if (this.editForm.审核类型 === '加工完成') {
if (!this.editForm.完成数量 || Number(this.editForm.完成数量) <= 0 || Number(this.editForm.完成数量) % 1 !== 0) {
this.$message.error('完成数量必须为大于 0 的整数')
return
}
this.submitAudit(this.editRow, '审核通过', '修改完成数量和加工完成时间后通过', {
finishQuantity: Number(this.editForm.完成数量),
startTime: this.editForm.加工开始时间,
finishTime: this.editForm.加工完成时间
})
} else if (this.editForm.审核类型 === '结束整修') {
this.submitAudit(this.editRow, '审核通过', '修改整修开始和结束时间后通过', {
repairStartTime: this.editForm.整修开始时间,
repairEndTime: this.editForm.整修结束时间,
repairPlan: this.editForm.整修方案
})
}
this.editVisible = false
},
submitAudit(row, state, opinion, editData) {
var param = []
param[0] = ['审核流水号', row.id]
param[1] = ['审核状态', state]
param[2] = ['审核人', this.id]
param[3] = ['审核意见', opinion]
if (editData && editData.finishQuantity !== undefined) {
// 仅修改数量通过时传审核完成数量,普通通过沿用审核单原完成数量 修改人:Ld 修改时间:2026-07-02 15:04:16;
param.push(['审核完成数量', editData.finishQuantity])
}
if (editData && editData.startTime) {
// 加工完成审核可修正实际加工开始时间 修改人:Ld 修改时间:2026-07-06 08:11:25;
param.push(['审核加工开始时间', editData.startTime])
}
if (editData && editData.finishTime) {
// 加工完成审核可修正实际加工完成时间 修改人:Ld 修改时间:2026-07-03 16:47:02;
param.push(['审核加工完成时间', editData.finishTime])
}
if (editData && editData.repairStartTime) {
// 整修审核可修正整修开始时间 修改人:Ld 修改时间:2026-07-06 08:11:25;
param.push(['审核整修开始时间', editData.repairStartTime])
}
if (editData && editData.repairEndTime) {
// 整修审核可修正整修结束时间 修改人:Ld 修改时间:2026-07-03 16:47:02;
param.push(['审核整修结束时间', editData.repairEndTime])
}
if (editData && editData.repairPlan !== undefined) {
param.push(['审核整修方案', editData.repairPlan])
}
var Data = this.CreateData('12', '机加工MES_加工完成整修审核_审核数据', param)
this.ExecDatabase(Data).then(response => {
if (response.data[0] && response.data[0].result === '1') {
this.$message.success('审核成功')
this.searchTable()
} else {
this.$message.error(response.data[0] && response.data[0].message ? response.data[0].message : '审核失败')
}
}).catch(() => {
this.$message.error('审核失败')
})
},
getAuditStateType(state) {
if (state === '审核通过') {
return 'success'
} else if (state === '审核不通过') {
return 'danger'
}
return 'warning'
},
getRepairStateText(state) {
if (state === null || state === undefined || state === '') {
return ''
}
return Number(state) === 1 ? '整修中' : '已结束'
},
handleSizeChange(val) {
this.pageCurrent = 1
this.pageSize = val
this.searchTable()
},
handleCurrentChange(val) {
this.pageCurrent = val
this.searchTable()
}
}
}
</script>
<style scoped>
.production-completion-audit .search-bar {
display: flex;
align-items: center;
flex-wrap: wrap;
gap: 8px;
margin-top: 7px;
}
.production-completion-audit .date-label {
font-size: 13px;
color: #333;
}
.production-completion-audit .detail-table >>> .el-table__body td {
vertical-align: top;
}
</style>

View File

@@ -20,7 +20,8 @@
@change="searchTable"/> @change="searchTable"/>
<el-button type="success" plain icon="el-icon-download" size="small" style="margin-left: 60px" @click="exportExcel()">导出</el-button> <el-button type="success" plain icon="el-icon-download" size="small" style="margin-left: 60px" @click="exportExcel()">导出</el-button>
</div> </div>
<el-col style="margin-left: 7px;width: 281px"> <!-- 修改人:Ld 修改时间:2026-07-06 09:12:38; 增加总价列后调整员工汇总表宽度 -->
<el-col style="margin-left: 7px;width: 371px">
<!-- <el-card>--> <!-- <el-card>-->
<div style="margin-top: 10px"> <div style="margin-top: 10px">
<el-table <el-table
@@ -32,7 +33,7 @@
border border
stripe stripe
size="mini" size="mini"
style="width: 281px;margin-top: 10px" style="width: 371px;margin-top: 10px"
height="740" height="740"
@row-click="searchTable1"> @row-click="searchTable1">
<el-table-column :width="setColumnWidth('操作者')" label="操作者" align="center" prop=""> <el-table-column :width="setColumnWidth('操作者')" label="操作者" align="center" prop="">
@@ -50,12 +51,18 @@
{{ scope.row.加工工时 }} {{ scope.row.加工工时 }}
</template> </template>
</el-table-column> </el-table-column>
<!-- 修改人:Ld 修改时间:2026-07-06 09:12:38; 员工汇总显示按工序工价计算的总价 -->
<el-table-column width="90px" label="总价" align="center" show-overflow-tooltip prop="总价">
<template slot-scope="scope">
{{ scope.row.总价 }}
</template>
</el-table-column>
</el-table> </el-table>
</div> </div>
<!-- </el-card>--> <!-- </el-card>-->
</el-col> </el-col>
<el-col style="margin-left: 10px;width: 1361px"> <el-col style="margin-left: 10px;width: 1271px">
<!-- <el-card>--> <!-- <el-card>-->
<div style="margin-top: 10px"> <div style="margin-top: 10px">
<el-table <el-table
@@ -68,7 +75,7 @@
border border
stripe stripe
size="mini" size="mini"
style="width: 1361px;margin-top: 10px" style="width: 1271px;margin-top: 10px"
height="740" height="740"
@sort-change="sortChange"> @sort-change="sortChange">
<el-table-column :width="setColumnWidth('序号')" type="index" label="序号" align="center"/> <el-table-column :width="setColumnWidth('序号')" type="index" label="序号" align="center"/>
@@ -102,6 +109,17 @@
{{ scope.row.完成数 }} {{ scope.row.完成数 }}
</template> </template>
</el-table-column> </el-table-column>
<!-- 修改人:Ld 修改时间:2026-07-06 09:12:38; 员工明细显示工序工价组件维护的工价和按数量计算的总价 -->
<el-table-column width="80px" label="工价" align="center" show-overflow-tooltip prop="工价">
<template slot-scope="scope">
{{ scope.row.工价 }}
</template>
</el-table-column>
<el-table-column width="90px" label="总价" align="center" show-overflow-tooltip prop="总价">
<template slot-scope="scope">
{{ scope.row.总价 }}
</template>
</el-table-column>
<el-table-column :width="setColumnWidth('加工工时M')" label="加工工时M" align="center" show-overflow-tooltip prop="加工时长"> <el-table-column :width="setColumnWidth('加工工时M')" label="加工工时M" align="center" show-overflow-tooltip prop="加工时长">
<template slot-scope="scope"> <template slot-scope="scope">
{{ scope.row.加工时长 }} {{ scope.row.加工时长 }}
@@ -161,7 +179,8 @@
@change="searchTable2"/> @change="searchTable2"/>
<!-- <el-button type="success" plain icon="el-icon-download" size="small" style="margin-left: 760px" @click="exportExcel()">导出</el-button>--> <!-- <el-button type="success" plain icon="el-icon-download" size="small" style="margin-left: 760px" @click="exportExcel()">导出</el-button>-->
</div> </div>
<el-col style="margin-left: 7px;width: 321px"> <!-- 修改人:Ld 修改时间:2026-07-06 09:12:38; 增加总价列后调整设备汇总表宽度 -->
<el-col style="margin-left: 7px;width: 413px">
<!-- <el-card>--> <!-- <el-card>-->
<div style="margin-top: 10px"> <div style="margin-top: 10px">
<el-table <el-table
@@ -173,7 +192,7 @@
border border
stripe stripe
size="mini" size="mini"
style="width: 323px;margin-top: 10px" style="width: 413px;margin-top: 10px"
height="740" height="740"
@row-click="searchTable3"> @row-click="searchTable3">
<el-table-column label="设备" align="center" prop=""> <el-table-column label="设备" align="center" prop="">
@@ -191,12 +210,18 @@
{{ scope.row.加工工时 }} {{ scope.row.加工工时 }}
</template> </template>
</el-table-column> </el-table-column>
<!-- 修改人:Ld 修改时间:2026-07-06 09:12:38; 设备汇总显示按工序工价计算的总价 -->
<el-table-column width="90px" label="总价" align="center" show-overflow-tooltip prop="总价">
<template slot-scope="scope">
{{ scope.row.总价 }}
</template>
</el-table-column>
</el-table> </el-table>
</div> </div>
<!-- </el-card>--> <!-- </el-card>-->
</el-col> </el-col>
<el-col style="margin-left: 10px;width: 1301px"> <el-col style="margin-left: 10px;width: 1209px">
<!-- <el-card>--> <!-- <el-card>-->
<div style="margin-top: 10px"> <div style="margin-top: 10px">
<el-table <el-table
@@ -209,7 +234,7 @@
border border
stripe stripe
size="mini" size="mini"
style="width: 1301px;margin-top: 10px" style="width: 1209px;margin-top: 10px"
height="740" height="740"
@sort-change="sortChange1"> @sort-change="sortChange1">
<el-table-column :width="setColumnWidth('序号')" type="index" label="序号" align="center"/> <el-table-column :width="setColumnWidth('序号')" type="index" label="序号" align="center"/>
@@ -243,6 +268,17 @@
{{ scope.row.完成数 }} {{ scope.row.完成数 }}
</template> </template>
</el-table-column> </el-table-column>
<!-- 修改人:Ld 修改时间:2026-07-06 09:12:38; 设备明细显示工序工价组件维护的工价和按数量计算的总价 -->
<el-table-column width="80px" label="工价" align="center" show-overflow-tooltip prop="工价">
<template slot-scope="scope">
{{ scope.row.工价 }}
</template>
</el-table-column>
<el-table-column width="90px" label="总价" align="center" show-overflow-tooltip prop="总价">
<template slot-scope="scope">
{{ scope.row.总价 }}
</template>
</el-table-column>
<el-table-column :width="setColumnWidth('加工工时M')" label="加工工时M" align="center" show-overflow-tooltip prop="加工时长"> <el-table-column :width="setColumnWidth('加工工时M')" label="加工工时M" align="center" show-overflow-tooltip prop="加工时长">
<template slot-scope="scope"> <template slot-scope="scope">
{{ scope.row.加工时长 }} {{ scope.row.加工时长 }}

View File

@@ -2,9 +2,9 @@
<div class="app-container"> <div class="app-container">
<el-card style="height: 850px; display: flex; flex-direction: column;"> <el-card style="height: 850px; display: flex; flex-direction: column;">
<div style="margin-top: 7px; margin-bottom: 7px; flex-shrink: 0;"> <div style="margin-top: 7px; margin-bottom: 7px; flex-shrink: 0;">
<el-input v-model="materialCodeValue" style="width:150px" placeholder="物料编码" size="small" clearable/>
<el-input v-model="materialNameValue" style="width:150px" placeholder="物料名称" size="small" clearable/> <el-input v-model="materialNameValue" style="width:150px" placeholder="物料名称" size="small" clearable/>
<el-input v-model="materialToolValue" style="width:150px" placeholder="图号/型号" size="small" clearable/> <el-input v-model="materialToolValue" style="width:150px" placeholder="图号/型号" size="small" clearable/>
<el-input v-model="materialCodeValue" style="width:150px" placeholder="物料编码" size="small" clearable/>
<el-select <el-select
v-model="materialTypeValue" v-model="materialTypeValue"
style="width:100px;" style="width:100px;"
@@ -856,8 +856,9 @@ export default {
}, },
exportTableData() { exportTableData() {
if (this.tableData.length !== 0) { if (this.tableData.length !== 0) {
let materialToolValue_check, materialNameValue_check, materialTypeValue_check, dateRange_check, checked_check let materialToolValue_check, materialCodeValue_check, materialNameValue_check, materialTypeValue_check, dateRange_check, checked_check
this.materialToolValue ? materialToolValue_check = 1 : materialToolValue_check = 0 this.materialToolValue ? materialToolValue_check = 1 : materialToolValue_check = 0
this.materialCodeValue ? materialCodeValue_check = 1 : materialCodeValue_check = 0 // 备注:修改人:Ld 修改时间:2026-06-29 14:18:00
this.materialNameValue ? materialNameValue_check = 1 : materialNameValue_check = 0 this.materialNameValue ? materialNameValue_check = 1 : materialNameValue_check = 0
this.materialTypeValue ? materialTypeValue_check = 1 : materialTypeValue_check = 0 this.materialTypeValue ? materialTypeValue_check = 1 : materialTypeValue_check = 0
this.checked ? checked_check = 1 : checked_check = 0 this.checked ? checked_check = 1 : checked_check = 0
@@ -884,6 +885,8 @@ export default {
param[12] = ['PageSize', 9999999] param[12] = ['PageSize', 9999999]
param[13] = ['PageCount', '1111', 'int', '1'] param[13] = ['PageCount', '1111', 'int', '1']
param[14] = ['ItemCount', '1111', 'int', '1'] param[14] = ['ItemCount', '1111', 'int', '1']
param[15] = ['物料编码_check', materialCodeValue_check] // 备注:修改人:Ld 修改时间:2026-06-29 14:18:00
param[16] = ['物料编码', this.materialCodeValue] // 备注:修改人:Ld 修改时间:2026-06-29 14:18:00
var Data = this.CreateData('2001', '物料管理_查询数据_分页', param) var Data = this.CreateData('2001', '物料管理_查询数据_分页', param)
this.exportExcel_NPOI(Data) this.exportExcel_NPOI(Data)
} else { } else {

View File

@@ -140,13 +140,6 @@
</el-table-column> </el-table-column>
<el-table-column width="110px" label="操作" align="center"> <el-table-column width="110px" label="操作" align="center">
<template slot-scope="scope"> <template slot-scope="scope">
<el-tooltip :open-delay="700" effect="dark" content="查看图纸" placement="top">
<el-button
type="text"
icon="el-icon-picture-outline"
size="mini"
@click="getNum(scope.row)"/>
</el-tooltip>
<el-tooltip :open-delay="700" effect="dark" content="改制" placement="top"> <el-tooltip :open-delay="700" effect="dark" content="改制" placement="top">
<el-button <el-button
type="text" type="text"
@@ -264,7 +257,6 @@
<script> <script>
import { mapGetters } from 'vuex' import { mapGetters } from 'vuex'
import request, { MESDownloadFile } from '@/utils/request'
export default { export default {
data() { data() {
@@ -399,15 +391,16 @@ export default {
this.form = { this.form = {
原订单流水号: this.currentOrderId, 原订单流水号: this.currentOrderId,
原组件流水号: row.组件流水号 || '', 原组件流水号: row.组件流水号 || '',
原基本件流水号: row.基本件流水号 || '', // 修改人:Ld 修改时间:2026-07-01 14:36:07; 列表显示改制目标时仍使用接口保留的原基本件和原零件信息发起新改制。
原基本件流水号: row.基本件流水号 || row.流水号 || '',
原工艺计划流水号: row.工艺计划流水号 || '', 原工艺计划流水号: row.工艺计划流水号 || '',
原订单编号: this.currentOrderNo, 原订单编号: this.currentOrderNo,
原零件名称: row.零件名称 || '', 原零件名称: row.原零件名称 || row.零件名称 || '',
原零件图号: row.零件图号 || row.图号或型号 || '', 原零件图号: row.原零件图号 || row.零件图号 || row.图号或型号 || '',
原数量: row.数量 || '', 原数量: row.数量 || '',
改制目标: '', 改制目标: '',
改制零件名称: row.零件名称 || '', 改制零件名称: '',
改制零件图号: row.零件图号 || row.图号或型号 || '', 改制零件图号: '',
改制数量: row.数量 ? Number(row.数量) : 1, 改制数量: row.数量 ? Number(row.数量) : 1,
是否毛坯: '', 是否毛坯: '',
物料编号: '', 物料编号: '',
@@ -463,6 +456,11 @@ export default {
submitForm(formName) { submitForm(formName) {
var oldDrawingNo = (this.form.原零件图号 || '').toString().trim() var oldDrawingNo = (this.form.原零件图号 || '').toString().trim()
var newDrawingNo = (this.form.改制零件图号 || '').toString().trim() var newDrawingNo = (this.form.改制零件图号 || '').toString().trim()
var newPartName = (this.form.改制零件名称 || '').toString().trim()
if (!newPartName || !newDrawingNo) {
this.$message.warning('请填写已维护的新物料名称和图号')
return
}
if (oldDrawingNo && newDrawingNo && oldDrawingNo === newDrawingNo) { if (oldDrawingNo && newDrawingNo && oldDrawingNo === newDrawingNo) {
this.$message.warning('改制零件图号不能与原零件图号相同') this.$message.warning('改制零件图号不能与原零件图号相同')
return return
@@ -479,6 +477,8 @@ export default {
param[6] = ['发起人', this.id] param[6] = ['发起人', this.id]
param[7] = ['原零件名称', this.form.原零件名称] param[7] = ['原零件名称', this.form.原零件名称]
param[8] = ['原零件图号', this.form.原零件图号] param[8] = ['原零件图号', this.form.原零件图号]
// 修改人:Ld 修改时间:2026-07-01 14:45:00; 发起改制时传入点击行基本件流水号,后端按订单、组件、基本件精确回显改制目标。
param[9] = ['原基本件流水号', this.form.原基本件流水号]
var Data = this.CreateData('12', '技术中心_改制订单_发起改制', param) var Data = this.CreateData('12', '技术中心_改制订单_发起改制', param)
this.ExecDatabase(Data).then(response => { this.ExecDatabase(Data).then(response => {
if (response.data[0].result === '1') { if (response.data[0].result === '1') {
@@ -547,35 +547,7 @@ export default {
this.loadingPart = false this.loadingPart = false
}) })
}, },
getNum(row) {
this.dialogVisible = true
this.getFileList(row.零件图号 || row.图号或型号)
},
getFileList(value) {
this.hadFile = []
if (value) {
request({
url: '',
method: 'post',
data: {
type: '3',
name: "select * from 机加工MES_零件图纸PDF表 where 是否启用 = 1 and name = '" + value + "'"
}
}).then(data => {
if (data.data.length > 0) {
var server = ('' + MESDownloadFile).split('/')
data.data.map(item => {
this.hadFile.push({
url: 'http://' + server[2] + '/webpage/part/' + item.uid + '.' + item.suffix,
name: item.name + '.' + item.suffix,
suffix: item.suffix,
id: item.uid
})
})
}
})
}
},
handleSizeChanges(val) { handleSizeChanges(val) {
this.pageCurrent = 1 this.pageCurrent = 1
this.pageSize = val this.pageSize = val

View File

@@ -3,7 +3,7 @@
<el-card style="height: 850px"> <el-card style="height: 850px">
<div style="margin-top: 7px; margin-bottom: 7px"> <div style="margin-top: 7px; margin-bottom: 7px">
<!--{{ $t('m.music') }}--> <!--{{ $t('m.music') }}-->
<el-input v-model="materialCode" style="width: 150px " size="small" clearable placeholder="物料编"/> <el-input v-model="materialCode" style="width: 150px " size="small" clearable placeholder="物料编"/><!-- 备注修改人:Ld 修改时间:2026-06-29 14:24:00 -->
<el-input v-model="materialName" style="width: 150px " size="small" clearable placeholder="物料名称"/> <el-input v-model="materialName" style="width: 150px " size="small" clearable placeholder="物料名称"/>
<el-input v-model="specificationsModel" style="width: 150px " size="small" clearable placeholder="图号或型号"/> <el-input v-model="specificationsModel" style="width: 150px " size="small" clearable placeholder="图号或型号"/>
<el-input v-model="LocationName" style="width: 100px " size="small" clearable placeholder="库位"/> <el-input v-model="LocationName" style="width: 100px " size="small" clearable placeholder="库位"/>

View File

@@ -5,7 +5,7 @@
<el-input <el-input
v-model="materialCodeValue" v-model="materialCodeValue"
style="width:200px" style="width:200px"
placeholder="物料编" placeholder="物料编"
size="small" size="small"
clearable clearable
@keyup.enter.native="pageCurrent=1;searchTable()"/> @keyup.enter.native="pageCurrent=1;searchTable()"/>
@@ -93,7 +93,7 @@
style="width:962px" style="width:962px"
height="258px" height="258px"
size="small"> size="small">
<el-table-column label="物料编" align="center" prop="物料码"> <el-table-column label="物料编" align="center" prop="物料码"><!-- 备注:修改人:Ld 修改时间:2026-06-29 14:24:00 -->
<template slot-scope="scope"> <template slot-scope="scope">
{{ scope.row.物料编码 }} {{ scope.row.物料编码 }}
</template> </template>
@@ -143,7 +143,7 @@
</el-table-column> </el-table-column>
<el-table-column <el-table-column
width="140px" width="140px"
label="物料编" label="物料编"
align="center" align="center"
show-overflow-tooltip show-overflow-tooltip
sortable="物料编码" sortable="物料编码"
@@ -476,7 +476,7 @@ export default {
}) })
}, },
handleEdit(row, column) { handleEdit(row, column) {
if (column.label === '物料编') { if (column.label === '物料编') { // 备注:修改人:Ld 修改时间:2026-06-29 14:24:00
this.materialSerialNumber = row.物料流水号 this.materialSerialNumber = row.物料流水号
this.tableData9 = [] this.tableData9 = []
this.searchTable2() this.searchTable2()
@@ -559,7 +559,7 @@ export default {
Promise.all(promises).then(function(results) { Promise.all(promises).then(function(results) {
var data = [] var data = []
// 表头 // 表头
data.push(['物料编', '物料名称', '图号型号', '库位', '库存', '需求数', '可用库存', '加工中', '采购中', '毛坯数', '单位', '类型', '库存批次', '待入库', '最低库存', '安全库存', '最高库存', '', '物料编', '物料名称', '图号/型号', '类型', '出/入库数', '出/入库日期', '批次编码']) data.push(['物料编', '物料名称', '图号型号', '库位', '库存', '需求数', '可用库存', '加工中', '采购中', '毛坯数', '单位', '类型', '库存批次', '待入库', '最低库存', '安全库存', '最高库存', '', '物料编', '物料名称', '图号/型号', '类型', '出/入库数', '出/入库日期', '批次编码']) // 备注:修改人:Ld 修改时间:2026-06-29 14:24:00
results.forEach(function(item) { results.forEach(function(item) {
var row = item.row var row = item.row
var mainRow = [ var mainRow = [

View File

@@ -2,7 +2,8 @@
<div class="app-container"> <div class="app-container">
<el-card style="height: 850px"> <el-card style="height: 850px">
<div style="margin-top: 7px"> <div style="margin-top: 7px">
<el-input v-model="production" style="width: 200px ; margin-left: 10px" size="small" clearable placeholder="物料名称/编号/规格/型号" @keyup.enter.native="pageCurrent=1;pageSize=20;searchTable()"/> <el-input v-model="materialCodeValue" style="width: 160px ; margin-left: 10px" size="small" clearable placeholder="物料编码" @keyup.enter.native="pageCurrent=1;pageSize=20;searchTable()"/><!-- 备注修改人:Ld 修改时间:2026-06-29 14:18:00 -->
<el-input v-model="production" style="width: 200px ; margin-left: 10px" size="small" clearable placeholder="物料名称/规格/型号" @keyup.enter.native="pageCurrent=1;pageSize=20;searchTable()"/><!-- 备注修改人:Ld 修改时间:2026-06-29 14:18:00 -->
<span style="font-size: 17px;color: black ; margin-left: 24px">时间</span> <span style="font-size: 17px;color: black ; margin-left: 24px">时间</span>
<el-date-picker <el-date-picker
v-model="dateRange" v-model="dateRange"
@@ -21,7 +22,7 @@
<div style="margin-top: 10px"> <div style="margin-top: 10px">
<el-table v-loading="loading" ref="table" :data="tableData" highlight-current-row show-summary border stripe size="small" style="width: 971px" height="740px"> <el-table v-loading="loading" ref="table" :data="tableData" highlight-current-row show-summary border stripe size="small" style="width: 971px" height="740px">
<el-table-column width="70px" label="序号" type="index" align="center"/> <el-table-column width="70px" label="序号" type="index" align="center"/>
<el-table-column width="130px" label="物料编" align="center" show-overflow-tooltip> <el-table-column width="130px" label="物料编" align="center" show-overflow-tooltip><!-- 备注修改人:Ld 修改时间:2026-06-29 14:31:00 -->
<template slot-scope="scope"> <template slot-scope="scope">
{{ scope.row.物料编码 }} {{ scope.row.物料编码 }}
</template> </template>
@@ -83,6 +84,7 @@ export default {
data() { data() {
return { return {
dateRange: '', // 提交日期 dateRange: '', // 提交日期
materialCodeValue: '', // 物料编码 备注:修改人:Ld 修改时间:2026-06-29 14:18:00
production: '', production: '',
loading: false, // 数据加载 loading: false, // 数据加载
total: 0, // 分页总数 total: 0, // 分页总数
@@ -108,15 +110,18 @@ export default {
// 导出表 8.10 // 导出表 8.10
exportExcel() { exportExcel() {
if (this.tableData.length !== 0) { if (this.tableData.length !== 0) {
let dateRange_check, production_check let dateRange_check, materialCodeValue_check, production_check
this.dateRange ? dateRange_check = 1 : (dateRange_check = 0, this.dateRange = '') this.dateRange ? dateRange_check = 1 : (dateRange_check = 0, this.dateRange = '')
this.materialCodeValue ? materialCodeValue_check = 1 : materialCodeValue_check = 0 // 备注:修改人:Ld 修改时间:2026-06-29 14:18:00
this.production ? production_check = 1 : production_check = 0 this.production ? production_check = 1 : production_check = 0
var param = [] var param = []
param[0] = ['物料名称_check', production_check] param[0] = ['物料名称_check', production_check]
param[1] = ['物料名称', this.production] param[1] = ['物料名称', this.production]
param[2] = ['时间_check', dateRange_check] param[2] = ['物料编码_check', materialCodeValue_check] // 备注:修改人:Ld 修改时间:2026-06-29 14:18:00
param[3] = ['开始时间', this.dateRange[0]] param[3] = ['物料编码', this.materialCodeValue] // 备注:修改人:Ld 修改时间:2026-06-29 14:18:00
param[4] = ['结束时间', this.dateRange[1]] param[4] = ['时间_check', dateRange_check]
param[5] = ['开始时间', this.dateRange[0]]
param[6] = ['结束时间', this.dateRange[1]]
var Data = this.CreateData('2001', '报表_仓储管理_盘点记录_查询', param) var Data = this.CreateData('2001', '报表_仓储管理_盘点记录_查询', param)
this.exportExcel_NPOI(Data) this.exportExcel_NPOI(Data)
} else { } else {
@@ -124,15 +129,18 @@ export default {
} }
}, },
searchTable() { searchTable() {
let dateRange_check, production_check let dateRange_check, materialCodeValue_check, production_check
this.dateRange ? dateRange_check = 1 : (dateRange_check = 0, this.dateRange = '') this.dateRange ? dateRange_check = 1 : (dateRange_check = 0, this.dateRange = '')
this.materialCodeValue ? materialCodeValue_check = 1 : materialCodeValue_check = 0 // 备注:修改人:Ld 修改时间:2026-06-29 14:18:00
this.production ? production_check = 1 : production_check = 0 this.production ? production_check = 1 : production_check = 0
var param = [] var param = []
param[0] = ['物料名称_check', production_check] param[0] = ['物料名称_check', production_check]
param[1] = ['物料名称', this.production] param[1] = ['物料名称', this.production]
param[2] = ['时间_check', dateRange_check] param[2] = ['物料编码_check', materialCodeValue_check] // 备注:修改人:Ld 修改时间:2026-06-29 14:18:00
param[3] = ['开始时间', this.dateRange[0]] param[3] = ['物料编码', this.materialCodeValue] // 备注:修改人:Ld 修改时间:2026-06-29 14:18:00
param[4] = ['结束时间', this.dateRange[1]] param[4] = ['时间_check', dateRange_check]
param[5] = ['开始时间', this.dateRange[0]]
param[6] = ['结束时间', this.dateRange[1]]
var Data = this.CreateData('11', '仓储管理_盘点记录_查询', param, this.pageSize, this.pageCurrent) var Data = this.CreateData('11', '仓储管理_盘点记录_查询', param, this.pageSize, this.pageCurrent)
this.ExecDatabase(Data).then(response => { this.ExecDatabase(Data).then(response => {
this.tableData = response.data.rows this.tableData = response.data.rows
@@ -156,4 +164,3 @@ export default {
width: 50px!important; width: 50px!important;
} }
</style> </style>

View File

@@ -2,7 +2,7 @@
<div class="app-container"> <div class="app-container">
<el-card style="height: 850px"> <el-card style="height: 850px">
<div style="margin-top: 7px; margin-bottom: 7px"> <div style="margin-top: 7px; margin-bottom: 7px">
<el-input v-model="MaterialCode" style="width: 160px " size="small" clearable placeholder="物料编"/> <el-input v-model="MaterialCode" style="width: 160px " size="small" clearable placeholder="物料编"/><!-- 备注修改人:Ld 修改时间:2026-06-29 14:24:00 -->
<el-input v-model="MaterialName" style="width: 200px " size="small" clearable placeholder="物料名称/规格"/> <el-input v-model="MaterialName" style="width: 200px " size="small" clearable placeholder="物料名称/规格"/>
<el-input v-model="DrawingNo" style="width: 200px " size="small" clearable placeholder="图号/型号"/> <el-input v-model="DrawingNo" style="width: 200px " size="small" clearable placeholder="图号/型号"/>
<el-input v-model="locationWarehouseValue" style="width:200px" placeholder="库位" size="small" clearable/> <el-input v-model="locationWarehouseValue" style="width:200px" placeholder="库位" size="small" clearable/>
@@ -11,7 +11,7 @@
<div> <div>
<el-table v-loading="loading" :data="tableData" highlight-current-row show-summary border stripe size="small" style="width: 731px" height="740px"> <el-table v-loading="loading" :data="tableData" highlight-current-row show-summary border stripe size="small" style="width: 731px" height="740px">
<el-table-column :width="setColumnWidth('序号')" type="index" label="序号" align="center"/> <el-table-column :width="setColumnWidth('序号')" type="index" label="序号" align="center"/>
<el-table-column label="物料编" align="center" show-overflow-tooltip> <el-table-column label="物料编" align="center" show-overflow-tooltip><!-- 备注修改人:Ld 修改时间:2026-06-29 14:24:00 -->
<template slot-scope="scope"> <template slot-scope="scope">
{{ scope.row.物料编号 }} {{ scope.row.物料编号 }}
</template> </template>

View File

@@ -2,7 +2,8 @@
<div class="app-container"> <div class="app-container">
<el-card style="height: 850px"> <el-card style="height: 850px">
<div style="margin-top: 7px"> <div style="margin-top: 7px">
<el-input v-model="production" style="width: 200px ; margin-left: 10px" size="small" clearable placeholder="物料名称/编号/规格/型号" @keyup.enter.native="pageCurrent=1;pageSize=20;searchTable();searchNumber()"/> <el-input v-model="materialCodeValue" style="width: 160px ; margin-left: 10px" size="small" clearable placeholder="物料编码" @keyup.enter.native="pageCurrent=1;pageSize=20;searchTable();searchNumber()"/><!-- 备注修改人:Ld 修改时间:2026-06-29 14:18:00 -->
<el-input v-model="production" style="width: 200px ; margin-left: 10px" size="small" clearable placeholder="物料名称/规格/型号" @keyup.enter.native="pageCurrent=1;pageSize=20;searchTable();searchNumber()"/><!-- 备注修改人:Ld 修改时间:2026-06-29 14:18:00 -->
<span style="font-size: 17px;color: black ; margin-left: 24px">时间</span> <span style="font-size: 17px;color: black ; margin-left: 24px">时间</span>
<el-date-picker <el-date-picker
v-model="dateRange" v-model="dateRange"
@@ -32,7 +33,7 @@
style="width: 1061px" style="width: 1061px"
height="740px"> height="740px">
<el-table-column width="70px" label="序号" type="index" align="center"/> <el-table-column width="70px" label="序号" type="index" align="center"/>
<el-table-column width="130px" label="物料编" align="center" show-overflow-tooltip> <el-table-column width="130px" label="物料编" align="center" show-overflow-tooltip><!-- 备注修改人:Ld 修改时间:2026-06-29 14:31:00 -->
<template slot-scope="scope"> <template slot-scope="scope">
{{ scope.row.物料编码 }} {{ scope.row.物料编码 }}
</template> </template>
@@ -99,6 +100,7 @@ export default {
data() { data() {
return { return {
dateRange: '', // 提交日期 dateRange: '', // 提交日期
materialCodeValue: '', // 物料编码 备注:修改人:Ld 修改时间:2026-06-29 14:18:00
production: '', production: '',
loading: false, // 数据加载 loading: false, // 数据加载
stockInQuantity: 0, // 入库数 stockInQuantity: 0, // 入库数
@@ -127,15 +129,18 @@ export default {
// 导出表 8.10 // 导出表 8.10
exportExcel() { exportExcel() {
if (this.tableData.length !== 0) { if (this.tableData.length !== 0) {
let dateRange_check, production_check let dateRange_check, materialCodeValue_check, production_check
this.dateRange ? dateRange_check = 1 : (dateRange_check = 0, this.dateRange = '') this.dateRange ? dateRange_check = 1 : (dateRange_check = 0, this.dateRange = '')
this.materialCodeValue ? materialCodeValue_check = 1 : materialCodeValue_check = 0 // 备注:修改人:Ld 修改时间:2026-06-29 14:18:00
this.production ? production_check = 1 : production_check = 0 this.production ? production_check = 1 : production_check = 0
var param = [] var param = []
param[0] = ['物料名称_check', production_check] param[0] = ['物料名称_check', production_check]
param[1] = ['物料名称', this.production] param[1] = ['物料名称', this.production]
param[2] = ['时间_check', dateRange_check] param[2] = ['物料编码_check', materialCodeValue_check] // 备注:修改人:Ld 修改时间:2026-06-29 14:18:00
param[3] = ['开始时间', this.dateRange[0]] param[3] = ['物料编码', this.materialCodeValue] // 备注:修改人:Ld 修改时间:2026-06-29 14:18:00
param[4] = ['结束时间', this.dateRange[1]] param[4] = ['时间_check', dateRange_check]
param[5] = ['开始时间', this.dateRange[0]]
param[6] = ['结束时间', this.dateRange[1]]
var Data = this.CreateData('2001', '报表_仓储管理_物料记录_查询', param) var Data = this.CreateData('2001', '报表_仓储管理_物料记录_查询', param)
this.exportExcel_NPOI(Data) this.exportExcel_NPOI(Data)
} else { } else {
@@ -144,8 +149,9 @@ export default {
}, },
searchTable() { searchTable() {
if (this.dateRange) { if (this.dateRange) {
let dateRange_check, production_check let dateRange_check, materialCodeValue_check, production_check
this.dateRange ? dateRange_check = 1 : (dateRange_check = 0, this.dateRange = '') this.dateRange ? dateRange_check = 1 : (dateRange_check = 0, this.dateRange = '')
this.materialCodeValue ? materialCodeValue_check = 1 : materialCodeValue_check = 0 // 备注:修改人:Ld 修改时间:2026-06-29 14:18:00
this.production ? production_check = 1 : production_check = 0 this.production ? production_check = 1 : production_check = 0
// var param = [] // var param = []
// param[0] = ['物料名称_check', production_check] // param[0] = ['物料名称_check', production_check]
@@ -166,9 +172,11 @@ export default {
var param = [] var param = []
param[0] = ['物料名称_check', production_check] param[0] = ['物料名称_check', production_check]
param[1] = ['物料名称', this.production] param[1] = ['物料名称', this.production]
param[2] = ['时间_check', dateRange_check] param[2] = ['物料编码_check', materialCodeValue_check] // 备注:修改人:Ld 修改时间:2026-06-29 14:18:00
param[3] = ['开始时间', this.dateRange[0]] param[3] = ['物料编码', this.materialCodeValue] // 备注:修改人:Ld 修改时间:2026-06-29 14:18:00
param[4] = ['结束时间', this.dateRange[1]] param[4] = ['时间_check', dateRange_check]
param[5] = ['开始时间', this.dateRange[0]]
param[6] = ['结束时间', this.dateRange[1]]
var Data = this.CreateData('11', '仓储管理_物料记录_查询新', param, this.pageSize, this.pageCurrent) var Data = this.CreateData('11', '仓储管理_物料记录_查询新', param, this.pageSize, this.pageCurrent)
this.ExecDatabase(Data).then(response => { this.ExecDatabase(Data).then(response => {
console.log(response, 6666) console.log(response, 6666)
@@ -180,15 +188,18 @@ export default {
} }
}, },
searchNumber() { searchNumber() {
let dateRange_check, production_check let dateRange_check, materialCodeValue_check, production_check
this.dateRange ? dateRange_check = 1 : (dateRange_check = 0, this.dateRange = '') this.dateRange ? dateRange_check = 1 : (dateRange_check = 0, this.dateRange = '')
this.materialCodeValue ? materialCodeValue_check = 1 : materialCodeValue_check = 0 // 备注:修改人:Ld 修改时间:2026-06-29 14:18:00
this.production ? production_check = 1 : production_check = 0 this.production ? production_check = 1 : production_check = 0
var param = [] var param = []
param[0] = ['物料名称_check', production_check] param[0] = ['物料名称_check', production_check]
param[1] = ['物料名称', this.production] param[1] = ['物料名称', this.production]
param[2] = ['时间_check', dateRange_check] param[2] = ['物料编码_check', materialCodeValue_check] // 备注:修改人:Ld 修改时间:2026-06-29 14:18:00
param[3] = ['开始时间', this.dateRange[0]] param[3] = ['物料编码', this.materialCodeValue] // 备注:修改人:Ld 修改时间:2026-06-29 14:18:00
param[4] = ['结束时间', this.dateRange[1]] param[4] = ['时间_check', dateRange_check]
param[5] = ['开始时间', this.dateRange[0]]
param[6] = ['结束时间', this.dateRange[1]]
var Data = this.CreateData('11', '仓储管理_物料记录_查询', param) var Data = this.CreateData('11', '仓储管理_物料记录_查询', param)
this.ExecDatabase(Data).then(response => { this.ExecDatabase(Data).then(response => {
this.stockInQuantity = response.data[0].入库数 this.stockInQuantity = response.data[0].入库数
@@ -230,4 +241,3 @@ export default {
width: 50px!important; width: 50px!important;
} }
</style> </style>

View File

@@ -2,7 +2,8 @@
<div class="app-container"> <div class="app-container">
<el-card style="height: 850px"> <el-card style="height: 850px">
<div style="margin-top: 7px"> <div style="margin-top: 7px">
<el-input v-model="production" style="width: 200px ; margin-left: 10px" size="small" clearable placeholder="物料名称/编号/规格/型号" @keyup.enter.native="pageCurrent=1;pageSize=20;searchTable()"/> <el-input v-model="materialCodeValue" style="width: 160px ; margin-left: 10px" size="small" clearable placeholder="物料编码" @keyup.enter.native="pageCurrent=1;pageSize=20;searchTable()"/><!-- 备注修改人:Ld 修改时间:2026-06-29 14:18:00 -->
<el-input v-model="production" style="width: 200px ; margin-left: 10px" size="small" clearable placeholder="物料名称/规格/型号" @keyup.enter.native="pageCurrent=1;pageSize=20;searchTable()"/><!-- 备注修改人:Ld 修改时间:2026-06-29 14:18:00 -->
<el-input v-model="purchaseNumber" style="width: 200px ; margin-left: 10px" size="small" clearable placeholder="采购合同编号" @keyup.enter.native="pageCurrent=1;pageSize=20;searchTable()"/> <el-input v-model="purchaseNumber" style="width: 200px ; margin-left: 10px" size="small" clearable placeholder="采购合同编号" @keyup.enter.native="pageCurrent=1;pageSize=20;searchTable()"/>
<el-input v-model="supplier" style="width: 200px ; margin-left: 10px" size="small" clearable placeholder="供应商" @keyup.enter.native="pageCurrent=1;pageSize=20;searchTable()"/> <el-input v-model="supplier" style="width: 200px ; margin-left: 10px" size="small" clearable placeholder="供应商" @keyup.enter.native="pageCurrent=1;pageSize=20;searchTable()"/>
<span style="font-size: 17px;color: black ; margin-left: 10px">时间</span> <span style="font-size: 17px;color: black ; margin-left: 10px">时间</span>
@@ -245,6 +246,7 @@ export default {
return { return {
NowTime: getNowDAY(), NowTime: getNowDAY(),
dateRange: '', // 提交日期 dateRange: '', // 提交日期
materialCodeValue: '', // 物料编码 备注:修改人:Ld 修改时间:2026-06-29 14:18:00
production: '', production: '',
purchaseNumber: '', purchaseNumber: '',
supplier: '', supplier: '',
@@ -469,8 +471,9 @@ export default {
} }
}, },
searchTable() { searchTable() {
let dateRange_check, production_check, purchaseNumber_check, supplier_check let dateRange_check, materialCodeValue_check, production_check, purchaseNumber_check, supplier_check
this.dateRange ? dateRange_check = 1 : (dateRange_check = 0, this.dateRange = '') this.dateRange ? dateRange_check = 1 : (dateRange_check = 0, this.dateRange = '')
this.materialCodeValue ? materialCodeValue_check = 1 : materialCodeValue_check = 0 // 备注:修改人:Ld 修改时间:2026-06-29 14:18:00
this.production ? production_check = 1 : production_check = 0 this.production ? production_check = 1 : production_check = 0
this.purchaseNumber ? purchaseNumber_check = 1 : purchaseNumber_check = 0 this.purchaseNumber ? purchaseNumber_check = 1 : purchaseNumber_check = 0
this.supplier ? supplier_check = 1 : supplier_check = 0 this.supplier ? supplier_check = 1 : supplier_check = 0
@@ -481,9 +484,11 @@ export default {
param[3] = ['采购合同', this.purchaseNumber] param[3] = ['采购合同', this.purchaseNumber]
param[4] = ['供应商_check', supplier_check] param[4] = ['供应商_check', supplier_check]
param[5] = ['供应商', this.supplier] param[5] = ['供应商', this.supplier]
param[6] = ['时间_check', dateRange_check] param[6] = ['物料编码_check', materialCodeValue_check] // 备注:修改人:Ld 修改时间:2026-06-29 14:18:00
param[7] = ['开始时间', this.dateRange[0]] param[7] = ['物料编码', this.materialCodeValue] // 备注:修改人:Ld 修改时间:2026-06-29 14:18:00
param[8] = ['结束时间', this.dateRange[1]] param[8] = ['时间_check', dateRange_check]
param[9] = ['开始时间', this.dateRange[0]]
param[10] = ['结束时间', this.dateRange[1]]
var Data = this.CreateData('11', '仓储管理_入库记录退货_条件查询', param, this.pageSize, this.pageCurrent) var Data = this.CreateData('11', '仓储管理_入库记录退货_条件查询', param, this.pageSize, this.pageCurrent)
this.ExecDatabase(Data).then(response => { this.ExecDatabase(Data).then(response => {
this.tableData = response.data.rows this.tableData = response.data.rows
@@ -507,4 +512,3 @@ export default {
width: 50px!important; width: 50px!important;
} }
</style> </style>

View File

@@ -0,0 +1,962 @@
<template>
<div class="app-container">
<el-card>
<!-- 顶部筛选与操作区 -->
<div style="margin-top: 7px; margin-bottom: 7px">
<span style="font-size: 13px; color: black">排号筛选</span>
<el-select
v-model="rowFilter"
clearable
filterable
placeholder="选择排号"
size="small"
style="width: 120px; margin-right: 10px"
@change="handleRowFilterChange">
<el-option
v-for="item in rowOptions"
:key="item.value"
:label="item.label"
:value="item.value"/>
</el-select>
<span style="font-size: 13px; color: black; margin-left: 10px">库位类型</span>
<el-select
v-model="statusFilter"
clearable
filterable
placeholder="状态筛选"
size="small"
style="width: 120px; margin-right: 10px"
@change="handleStatusFilterChange">
<el-option
v-for="item in statusOptions"
:key="item.value"
:label="item.label"
:value="item.value"/>
</el-select>
<span style="font-size: 13px; color: black; margin-left: 10px">库位编号</span>
<el-input
v-model="locationCodeSearch"
placeholder="输入库位编号"
size="small"
clearable
style="width: 150px; margin-right: 10px"
@keyup.enter.native="handleSearch"/>
<el-button
type="primary"
size="small"
icon="el-icon-search"
style="margin-left: 10px"
@click="handleSearch">
搜索
</el-button>
<el-button
type="default"
size="small"
icon="el-icon-refresh"
style="margin-left: 10px"
@click="resetFilters">
重置
</el-button>
<el-button
type="success"
size="small"
icon="el-icon-refresh-left"
style="margin-left: 10px"
@click="refreshData">
刷新数据
</el-button>
<span style="font-size: 13px; color: black; margin-left: 20px">显示模式</span>
<el-switch
v-model="showCellText"
active-text="文字"
inactive-text="图标"
active-value="text"
inactive-value="icon"
style="margin-left: 5px"
@change="handleDisplayChange"/>
<span style="font-size: 13px; color: black; margin-left: 20px">自动刷新</span>
<el-switch
v-model="autoRefresh"
active-text=""
inactive-text=""
style="margin-left: 5px"
@change="handleAutoRefreshChange"/>
<el-select
v-if="autoRefresh"
v-model="refreshInterval"
size="small"
style="width: 90px; margin-left: 5px"
@change="handleRefreshIntervalChange">
<el-option
v-for="item in refreshOptions"
:key="item.value"
:label="item.label"
:value="item.value"/>
</el-select>
</div>
<!-- 统计信息卡片区 -->
<el-row :gutter="10" style="margin: 10px 0">
<el-col :span="4">
<el-card shadow="hover" style="text-align: center; padding: 10px 0">
<div style="color: #909399; font-size: 12px">总库位数</div>
<div style="color: #303133; font-size: 20px; font-weight: bold">{{ statistics.total }}</div>
</el-card>
</el-col>
<el-col :span="4">
<el-card shadow="hover" style="text-align: center; padding: 10px 0">
<div style="color: #909399; font-size: 12px">有库存</div>
<div style="color: #4caf50; font-size: 20px; font-weight: bold">{{ statistics.withStock }}</div>
</el-card>
</el-col>
<el-col :span="4">
<el-card shadow="hover" style="text-align: center; padding: 10px 0">
<div style="color: #909399; font-size: 12px">有物料/无库存</div>
<div style="color: #ff9800; font-size: 20px; font-weight: bold">{{ statistics.preOccupied }}</div>
</el-card>
</el-col>
<el-col :span="4">
<el-card shadow="hover" style="text-align: center; padding: 10px 0">
<div style="color: #909399; font-size: 12px">空闲库位</div>
<div style="color: #9e9e9e; font-size: 20px; font-weight: bold">{{ statistics.empty }}</div>
</el-card>
</el-col>
<el-col :span="4">
<el-card shadow="hover" style="text-align: center; padding: 10px 0">
<div style="color: #909399; font-size: 12px">使用率</div>
<div style="color: #2196f3; font-size: 20px; font-weight: bold">{{ statistics.usageRate }}%</div>
</el-card>
</el-col>
</el-row>
<!-- 状态图例区 -->
<div style="margin-bottom: 15px; display: flex; align-items: center; justify-content: center; gap: 20px; flex-wrap: wrap">
<div style="display: flex; align-items: center">
<div class="legend-color" style="background-color: #4caf50"/>
<span style="margin-left: 5px; font-size: 12px">有库存 ()</span>
</div>
<div style="display: flex; align-items: center">
<div class="legend-color" style="background-color: #ff9800"/>
<span style="margin-left: 5px; font-size: 12px">有物料/无库存 ()</span>
</div>
<div style="display: flex; align-items: center">
<div class="legend-color" style="background-color: #e0e0e0"/>
<span style="margin-left: 5px; font-size: 12px">空闲 ()</span>
</div>
<div style="display: flex; align-items: center">
<div class="legend-color" style="background-color: #bbdefb; border: 2px solid #2196f3"/>
<span style="margin-left: 5px; font-size: 12px">选中库位</span>
</div>
</div>
<!-- 三楼仓库库位网格矩阵区 -->
<div v-loading="loading" style="height: 580px; overflow: auto; border: 1px solid #e4e7ed; border-radius: 4px; padding: 15px; background: #f5f7fa">
<!-- 数据为空提示 -->
<div v-if="groupedData.length === 0 && !loading" style="text-align: center; padding: 100px; color: #909399">
<span style="font-size: 14px">暂无库位数据</span>
</div>
<!-- 按排号分组的库位矩阵 -->
<div v-else>
<div v-for="group in groupedData" :key="group.排号" class="warehouse-group">
<div style="text-align: center; margin-bottom: 10px; color: #303133; font-weight: bold; background: #e8f4fd; padding: 5px; border-radius: 4px">
排号{{ group.排号 }} - 三楼仓库库位
<span style="margin-left: 20px; color: #909399; font-weight: normal; font-size: 12px">最后更新: {{ lastUpdateTime }}</span>
</div>
<div style="overflow-x: auto; margin-bottom: 10px">
<table class="warehouse-table">
<!-- 列标题 -->
<thead>
<tr>
<th class="table-header row-header">层号</th>
<th
v-for="col in columnKeys"
:key="col"
:class="{ 'highlighted-column': selectedCell && selectedCell.column === col && selectedCell.排号 === group.排号 }"
class="table-header column-header">
{{ col }}
</th>
</tr>
</thead>
<!-- 数据行层号 -->
<tbody>
<tr
v-for="layer in group.rows"
:key="layer.层号"
:class="{ 'highlighted-row': highlightedRow === layer.层号 && highlightedGroup === group.排号 }"
class="table-row">
<td class="row-label-cell">{{ layer.层号 }}</td>
<td
v-for="col in columnKeys"
:key="col"
:data-row="group.排号 + '-' + layer.层号"
:data-col="col"
:class="[
'status-' + (layer.cells[col] ? layer.cells[col].状态 : -1),
{
'selected-cell': selectedCell &&
selectedCell.排号 === group.排号 &&
selectedCell.层号 === layer.层号 &&
selectedCell.column === col,
'search-highlight': isSearchHighlighted(group.排号, layer.层号, col)
}
]"
class="location-cell"
@click="selectLocation(group.排号, layer.层号, col, layer.cells[col])"
@mouseenter="onCellHover(group.排号, layer.层号, col)"
@mouseleave="onCellLeave">
<div class="cell-content">
<span v-if="showCellText === 'text'" class="cell-text">
{{ getStatusLabel(layer.cells[col] ? layer.cells[col].状态 : -1) }}
</span>
<span v-else class="cell-icon">
<i :class="getStatusIcon(layer.cells[col] ? layer.cells[col].状态 : -1)"/>
</span>
<div v-if="isHoveredCell(group.排号, layer.层号, col)" class="cell-tooltip">
{{ layer.cells[col] ? (layer.cells[col].库位编号 + ' - ' + getStatusDescription(layer.cells[col].状态)) : '无库位' }}
</div>
</div>
</td>
</tr>
</tbody>
</table>
</div>
</div>
</div>
</div>
<!-- 库位详情弹窗 -->
<el-dialog
:visible.sync="detailDialogVisible"
:title="'库位详情 - ' + detailInfo.库位编号"
center
width="500px">
<el-descriptions :column="1" border size="small">
<el-descriptions-item label="库位编号">{{ detailInfo.库位编号 }}</el-descriptions-item>
<el-descriptions-item label="库位名称">{{ detailInfo.库位名称 }}</el-descriptions-item>
<el-descriptions-item label="排号">{{ detailInfo.排号 }}</el-descriptions-item>
<el-descriptions-item label="层号">{{ detailInfo.层号 }}</el-descriptions-item>
<el-descriptions-item label="当前状态">
<el-tag :type="getStatusTagType(detailInfo.状态值)" size="small">{{ detailInfo.状态 }}</el-tag>
</el-descriptions-item>
<el-descriptions-item label="状态描述">{{ detailInfo.状态描述 }}</el-descriptions-item>
</el-descriptions>
<div slot="footer" class="dialog-footer">
<el-button size="small" @click="detailDialogVisible = false">关闭</el-button>
</div>
</el-dialog>
<!-- 物料信息弹窗 -->
<el-dialog
:visible.sync="materialDialogVisible"
:title="'库位物料信息 - ' + materialLocationCode"
center
width="900px">
<el-table
v-loading="materialLoading"
:data="materialList"
stripe
size="small"
style="width: 100%"
height="350">
<el-table-column
prop="物料编号"
label="物料编号"
width="150"
show-overflow-tooltip/>
<el-table-column
prop="物料名称"
label="物料名称"
width="120"
show-overflow-tooltip/>
<el-table-column
prop="图号"
label="图号"
width="150"
show-overflow-tooltip/>
<el-table-column
prop="规格型号"
label="规格型号"
width="150"
show-overflow-tooltip/>
<el-table-column
label="库存数量"
width="100"
align="right">
<template slot-scope="scope">
<span :style="{ color: scope.row.库存数量 > 0 ? '#67C23A' : '#F56C6C', fontWeight: 'bold' }">
{{ formatNumber(scope.row.库存数量) }}
</span>
<div style="font-size: 10px; color: #909399">
{{ scope.row.单位 || '台' }}
</div>
</template>
</el-table-column>
</el-table>
<div v-if="materialList.length === 0 && !materialLoading" slot="append" style="text-align: center; padding: 20px; color: #909399">
暂无物料数据
</div>
<div slot="footer" class="dialog-footer">
<el-button size="small" @click="materialDialogVisible = false">关闭</el-button>
</div>
</el-dialog>
</el-card>
</div>
</template>
<script>
import { ExecDatabase } from '@/main'
export default {
name: 'ThirdFloorWarehouse',
data() {
return {
// ========== 筛选条件 ==========
rowFilter: '',
statusFilter: '',
locationCodeSearch: '',
rowOptions: [],
statusOptions: [
{ label: '全部', value: '' },
{ label: '有库存', value: 2 },
{ label: '有物料/无库存', value: 1 },
{ label: '空闲', value: 0 }
],
// ========== 自动刷新 ==========
autoRefresh: false,
refreshInterval: 60,
refreshTimer: null,
refreshOptions: [
{ label: '30秒', value: 30 },
{ label: '1分钟', value: 60 },
{ label: '5分钟', value: 300 }
],
// ========== 矩阵数据 ==========
locationRawData: [],
allLayers: [],
columnKeys: [],
groupedData: [],
// ========== 选中与交互状态 ==========
selectedCell: null,
highlightedRow: null,
highlightedGroup: null,
hoveredCell: null,
// ========== 统计信息 ==========
statistics: {
total: 0,
withStock: 0,
preOccupied: 0,
empty: 0,
usageRate: 0
},
// ========== 弹窗 ==========
detailDialogVisible: false,
detailInfo: {},
materialDialogVisible: false,
materialLoading: false,
materialList: [],
materialLocationCode: '',
// ========== 显示设置 ==========
showCellText: 'text',
loading: false,
lastUpdateTime: ''
}
},
created() {
this.loadLocationData()
},
beforeDestroy() {
this.stopAutoRefresh()
},
methods: {
// ========== 数据加载与转换 ==========
loadLocationData() {
var self = this
self.loading = true
var param = []
param[0] = ['排号_check', self.rowFilter ? 1 : 0]
param[1] = ['排号', self.rowFilter]
param[2] = ['库位编号_check', self.locationCodeSearch ? 1 : 0]
param[3] = ['库位编号', self.locationCodeSearch]
param[4] = ['库位状态_check', self.statusFilter !== '' ? 1 : 0]
param[5] = ['库位状态', self.statusFilter]
var Data = self.CreateData('11', '仓储管理_三楼仓库库位_查询数据', param)
ExecDatabase(Data).then(function(response) {
var rows = []
if (response.data && response.data.rows) {
rows = response.data.rows
} else if (response.data && Array.isArray(response.data)) {
rows = response.data
}
self.locationRawData = rows
self.buildMatrix(rows)
self.updateRowOptions()
self.updateLastUpdateTime()
self.loading = false
}).catch(function() {
self.loading = false
})
},
// 构建矩阵固定8排24列3层全空也显示
buildMatrix(list) {
var self = this
// 固定维度8排 24列 3层
var rowKeys = ['01', '02', '03', '04', '05', '06', '07', '08']
var layers = ['03', '02', '01']
var cols = []
for (var i = 1; i <= 24; i++) {
cols.push(i)
}
self.allLayers = layers
self.columnKeys = cols
// 按排号-层号-列号索引实际数据
var dataMap = {}
list.forEach(function(item) {
var key = item.排号 + '-' + item.层号 + '-' + item.列号
dataMap[key] = {
库位编号: item.库位编号,
库位名称: item.库位编号,
状态: item.状态,
排号: item.排号,
层号: item.层号,
列号: item.列号
}
})
// 构建分组数据8排全部显示
var grouped = []
rowKeys.forEach(function(rowKey) {
var rows = []
layers.forEach(function(layer) {
var layerCells = {}
cols.forEach(function(col) {
var key = rowKey + '-' + layer + '-' + col
if (dataMap[key]) {
layerCells[col] = dataMap[key]
} else {
layerCells[col] = {
库位编号: rowKey + '-' + (col < 10 ? '0' + col : col) + '-' + layer,
库位名称: rowKey + '-' + (col < 10 ? '0' + col : col) + '-' + layer,
状态: 0,
排号: rowKey,
层号: layer,
列号: col
}
}
})
rows.push({ 层号: layer, cells: layerCells })
})
grouped.push({ 排号: rowKey, rows: rows })
})
self.groupedData = grouped
self.updateStatistics()
},
updateRowOptions() {
var self = this
var rowSet = {}
self.locationRawData.forEach(function(item) {
if (item.排号) {
rowSet[item.排号] = true
}
})
var rows = Object.keys(rowSet).sort()
self.rowOptions = rows.map(function(r) {
return { label: r + '排', value: r }
})
},
updateLastUpdateTime() {
this.lastUpdateTime = new Date().toLocaleString()
},
// ========== 筛选与搜索 ==========
handleRowFilterChange() {
this.loadLocationData()
},
handleStatusFilterChange() {
this.loadLocationData()
},
handleSearch() {
this.loadLocationData()
},
resetFilters() {
this.rowFilter = ''
this.statusFilter = ''
this.locationCodeSearch = ''
this.loadLocationData()
this.$message.info('筛选条件已重置')
},
refreshData() {
this.loadLocationData()
},
// ========== 统计计算 ==========
updateStatistics() {
var withStock = 0
var preOccupied = 0
var empty = 0
this.groupedData.forEach(function(group) {
group.rows.forEach(function(layer) {
Object.keys(layer.cells).forEach(function(colKey) {
var cell = layer.cells[colKey]
if (!cell) return
var status = cell.状态
if (status === 2) withStock++
else if (status === 1) preOccupied++
else if (status === 0) empty++
})
})
})
var total = withStock + preOccupied + empty
var usageRate = total > 0 ? (((withStock + preOccupied) / total) * 100).toFixed(1) : 0
this.statistics = { total: total, withStock: withStock, preOccupied: preOccupied, empty: empty, usageRate: usageRate }
},
// ========== 单元格交互 ==========
selectLocation(rowKey, layerKey, colKey, locationInfo) {
this.selectedCell = { 排号: rowKey, 层号: layerKey, column: colKey }
this.highlightedRow = layerKey
this.highlightedGroup = rowKey
if (!locationInfo) return
if (locationInfo.状态 === 2) {
this.loadMaterialDetail(locationInfo.库位编号)
} else {
this.showLocationDetail(locationInfo)
}
},
loadMaterialDetail(locationCode) {
var self = this
self.materialLoading = true
self.materialLocationCode = locationCode
self.materialList = []
var param = []
param[0] = ['库位编号_check', 1]
param[1] = ['库位编号', locationCode]
var Data = self.CreateData('11', '仓储管理_三楼仓库库位物料_查询数据', param)
ExecDatabase(Data).then(function(response) {
var rows = []
if (response.data && response.data.rows) {
rows = response.data.rows
} else if (response.data && Array.isArray(response.data)) {
rows = response.data
}
// 按物料编号合并,库存数量累加
var merged = {}
rows.forEach(function(item) {
var key = item.物料编号
if (!merged[key]) {
merged[key] = {
物料编号: item.物料编号,
物料名称: item.物料名称,
图号: item.图号,
规格型号: item.规格型号,
库存数量: 0,
单位: item.单位
}
}
merged[key].库存数量 += parseFloat(item.库存数量) || 0
})
self.materialList = Object.values(merged)
self.materialDialogVisible = true
self.materialLoading = false
}).catch(function() {
self.materialList = []
self.materialDialogVisible = true
self.materialLoading = false
})
},
showLocationDetail(locationInfo) {
this.detailInfo = {
库位编号: locationInfo.库位编号,
库位名称: locationInfo.库位名称,
排号: locationInfo.排号,
层号: locationInfo.层号,
状态: this.getStatusLabel(locationInfo.状态),
状态值: locationInfo.状态,
状态描述: this.getStatusDescription(locationInfo.状态)
}
this.detailDialogVisible = true
},
onCellHover(rowKey, layerKey, colKey) {
this.hoveredCell = { 排号: rowKey, 层号: layerKey, column: colKey }
},
onCellLeave() {
this.hoveredCell = null
},
isHoveredCell(rowKey, layerKey, colKey) {
return this.hoveredCell &&
this.hoveredCell.排号 === rowKey &&
this.hoveredCell.层号 === layerKey &&
this.hoveredCell.column === colKey
},
isSearchHighlighted(rowKey, layerKey, colKey) {
if (!this.locationCodeSearch || !this.selectedCell) return false
return this.selectedCell.排号 === rowKey &&
this.selectedCell.层号 === layerKey &&
this.selectedCell.column === colKey
},
// ========== 状态映射方法 ==========
getStatusLabel(status) {
var map = { 0: '空', 1: '待', 2: '存' }
return map[status] || '-'
},
getStatusDescription(status) {
var map = {
0: '空闲库位,可存放物料',
1: '有物料但无库存',
2: '有库存,库位上存放有物料'
}
return map[status] || '无库位'
},
getStatusIcon(status) {
var map = {
0: 'el-icon-minus',
1: 'el-icon-time',
2: 'el-icon-box'
}
return map[status] || 'el-icon-question'
},
getStatusTagType(status) {
var map = {
0: 'info',
1: 'warning',
2: 'success'
}
return map[status] || 'info'
},
formatNumber(num) {
var n = parseFloat(num)
if (isNaN(n)) return '0.000'
return n.toFixed(3)
},
// ========== 显示模式 ==========
handleDisplayChange() {
this.$message.info('已切换为' + (this.showCellText === 'text' ? '显示文字' : '显示图标') + '模式')
},
// ========== 自动刷新 ==========
handleAutoRefreshChange(val) {
if (val) {
this.startAutoRefresh()
} else {
this.stopAutoRefresh()
}
},
startAutoRefresh() {
var self = this
self.stopAutoRefresh()
self.refreshTimer = setInterval(function() {
self.loadLocationData()
}, self.refreshInterval * 1000)
},
stopAutoRefresh() {
if (this.refreshTimer) {
clearInterval(this.refreshTimer)
this.refreshTimer = null
}
},
handleRefreshIntervalChange() {
if (this.autoRefresh) {
this.startAutoRefresh()
}
}
}
}
</script>
<style lang="scss" scoped>
.app-container {
padding: 20px;
}
/deep/ .el-card__body {
padding: 15px !important;
}
.legend-color {
width: 20px;
height: 20px;
border-radius: 4px;
border: 1px solid #ddd;
}
.warehouse-group {
margin-bottom: 20px;
padding: 15px;
background: white;
border-radius: 4px;
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
}
.warehouse-table {
width: 100%;
border-collapse: collapse;
margin: 0 auto;
min-width: 1200px;
.table-header {
background-color: #f5f7fa;
color: #303133;
font-weight: bold;
text-align: center;
padding: 8px;
border: 1px solid #e4e7ed;
min-width: 40px;
height: 40px;
font-size: 12px;
&.row-header {
background-color: #e8f4fd;
color: #2196f3;
min-width: 80px;
font-size: 12px;
}
&.highlighted-column {
background-color: #bbdefb;
color: #1976d2;
font-weight: bold;
}
}
.table-row {
&.highlighted-row {
background-color: #f0f9ff;
.row-label-cell {
background-color: #bbdefb;
color: #1976d2;
font-weight: bold;
}
}
&:hover {
background-color: #f5f7fa;
}
}
.row-label-cell {
background-color: #f5f7fa;
color: #303133;
font-weight: bold;
text-align: center;
padding: 8px;
border: 1px solid #e4e7ed;
width: 80px;
font-size: 12px;
}
.location-cell {
position: relative;
text-align: center;
padding: 0;
border: 1px solid #e4e7ed;
cursor: pointer;
transition: all 0.2s;
min-width: 40px;
height: 40px;
&:hover {
transform: scale(1.1);
z-index: 10;
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.2);
}
&.selected-cell {
box-shadow: 0 0 0 2px #2196f3;
z-index: 20;
position: relative;
&::after {
content: '';
position: absolute;
top: -2px;
left: -2px;
right: -2px;
bottom: -2px;
border: 2px solid #2196f3;
border-radius: 2px;
pointer-events: none;
}
}
&.search-highlight {
animation: highlightPulse 1.5s ease-in-out 3;
}
&.status-2 {
background-color: #4caf50;
color: white;
&:hover {
background-color: #388e3c;
}
}
&.status-1 {
background-color: #ff9800;
color: white;
&:hover {
background-color: #f57c00;
}
}
&.status-0 {
background-color: #e0e0e0;
color: #666;
&:hover {
background-color: #bdbdbd;
}
}
&.status--1 {
background-color: #fafafa;
color: #ccc;
}
.cell-content {
display: flex;
align-items: center;
justify-content: center;
width: 100%;
height: 100%;
position: relative;
}
.cell-text {
font-size: 14px;
font-weight: bold;
}
.cell-icon {
font-size: 18px;
}
.cell-tooltip {
position: absolute;
bottom: 100%;
left: 50%;
transform: translateX(-50%);
background-color: rgba(0, 0, 0, 0.8);
color: white;
padding: 4px 8px;
border-radius: 4px;
font-size: 12px;
white-space: nowrap;
z-index: 30;
margin-bottom: 5px;
&::after {
content: '';
position: absolute;
top: 100%;
left: 50%;
transform: translateX(-50%);
border-width: 5px;
border-style: solid;
border-color: rgba(0, 0, 0, 0.8) transparent transparent transparent;
}
}
}
}
@keyframes highlightPulse {
0% { box-shadow: 0 0 0 0 rgba(33, 150, 243, 0.4); }
50% { box-shadow: 0 0 0 6px rgba(33, 150, 243, 0.2); }
100% { box-shadow: 0 0 0 0 rgba(33, 150, 243, 0); }
}
// 响应式调整
@media (max-width: 1400px) {
.warehouse-table {
min-width: 900px;
.location-cell {
min-width: 35px;
height: 35px;
.cell-text {
font-size: 12px;
}
.cell-icon {
font-size: 16px;
}
}
}
}
@media (max-width: 992px) {
.warehouse-table {
min-width: 700px;
.location-cell {
min-width: 30px;
height: 30px;
.cell-text {
font-size: 11px;
}
.cell-icon {
font-size: 14px;
}
}
.row-label-cell {
width: 60px;
font-size: 10px;
padding: 4px;
}
}
}
</style>

View File

@@ -12,7 +12,7 @@
<el-input <el-input
v-model="materialCodeValue" v-model="materialCodeValue"
clearable clearable
placeholder="物料编" placeholder="物料编"
size="small" size="small"
style="width:160px" style="width:160px"
@keyup.enter.native="searchTable()"/> @keyup.enter.native="searchTable()"/>
@@ -134,7 +134,7 @@
</el-table-column> </el-table-column>
<el-table-column <el-table-column
align="center" align="center"
label="物料编" label="物料编"
prop="物料码" prop="物料码"
show-overflow-tooltip show-overflow-tooltip
sortable="物料码" sortable="物料码"
@@ -519,7 +519,7 @@ export default {
returns: [], returns: [],
contractNumber: '', // 合同 contractNumber: '', // 合同
supplierSelectionName: '', // 选择供应商名称 supplierSelectionName: '', // 选择供应商名称
materialCodeValue: '', // 物料编 materialCodeValue: '', // 物料编码 备注:修改人:Ld 修改时间:2026-06-29 14:24:00
materialNameTypeValue: '', // 物料名称规格型号 materialNameTypeValue: '', // 物料名称规格型号
materialNameType: [], // 物料名称规格型号数组 materialNameType: [], // 物料名称规格型号数组
入库单号Value: '', // 入库单号 入库单号Value: '', // 入库单号

View File

@@ -4,8 +4,8 @@ export const name1_config = `OP1000`
export const name3_config = `OP2000` export const name3_config = `OP2000`
export const name4_config = `OP9999` export const name4_config = `OP9999`
// //
var url = `http://192.168.1.27:8030` // 测试环境 接口端口号 http://192.168.1.27:8031 测试环境管理系统 0001 654321 var url = `http://192.168.1.27:8030` // 测试环境 接口端口号 http://192.168.1.27:8031 测试环境管理系统 用户名称:0001 密码:654321
// var url = `http://192.168.1.27:8010` // 正式环境 接口端口号 http://192.168.1.27:8001 正式环境管理系统 0000 0000 // var url = `http://192.168.1.27:8010` // 正式环境 接口端口号 http://192.168.1.27:8001 正式环境管理系统 用户名称:0000 密码:0000
var url1 = `http://192.168.1.27:10006` // 立库数据库的接口端口号 var url1 = `http://192.168.1.27:10006` // 立库数据库的接口端口号
// var url = `http://127.0.0.1:10250` // var url = `http://127.0.0.1:10250`
// var url = `http://124.220.15.242:8602` // var url = `http://124.220.15.242:8602`