--- name: Production Issue Module overview: Create the full production material requisition (生产领料单) module under Warehouse, including 3 API files, router configuration, list page, and a form page with header/line/detail three-level data management, following existing codebase patterns. todos: - id: api-layer content: "创建 3 个 API 文件: src/api/warehouse/issue.ts, issueLine.ts, issueDetail.ts,包含类型定义、状态常量和所有 CRUD + 业务接口" status: completed - id: router-config content: 在 router/index.ts 中追加 /warehouse 路由组,包含 issue 的 list/new/edit/view 四条路由 status: completed - id: list-page content: 创建 src/views/Warehouse/Issue/index.vue 列表页:搜索区(7字段) + 工具栏(4按钮) + 表格(11列+操作列) + 分页 + 删除/出库校验逻辑 status: completed - id: form-header content: 创建 src/views/Warehouse/Issue/form.vue 表头部分:页面框架 + el-collapse 表头表单(16字段, 4列布局) + 模式判断(isAdd/isEdit/isView) + 保存/取消/收起按钮 status: completed - id: form-line-table content: form.vue 领料行子表:可编辑 el-table + 添加行 + 物料选择 + 领料数量输入 + 行CRUD status: completed - id: form-detail-table content: form.vue 出库明细子表:选中行后展示 + 仓库/库区/库位三级联动 el-select + 出库数量 + 明细CRUD status: completed - id: form-dialogs content: form.vue 4个选择弹窗:工单选择、物料选择、客户选择、工作站选择,搜索+表格+单选确认 status: completed - id: form-business content: form.vue 业务逻辑:执行出库(checkQuantity + executeIssue)、数据加载(编辑/查看模式)、表单校验、状态控制 status: completed - id: test-verify content: 整体联调验证:编译检查、页面路由跳转、列表加载、新增/编辑/查看模式切换 status: completed isProject: false --- # 生产领料单模块开发计划 ## 背景 根据 [PRD 文档](prd/mom系统生产领料单-页面开发说明文档.md),开发仓储管理下的「生产领料」功能。该模块是项目中首个 Warehouse 模块,采用 **头(Header) -> 行(Line) -> 明细(Detail)** 三层数据结构,比现有的 WorkOrder(头+只读BOM子表)复杂度更高。 ## 核心参考 - 现有最相似模块:[Production/WorkOrder](erp-frontend-vue/src/views/Production/WorkOrder/) (index.vue + form.vue) - API 模式:[workOrder.ts](erp-frontend-vue/src/api/workOrder.ts) (类型定义 + 状态常量 + API 函数) - 路由模式:[router/index.ts](erp-frontend-vue/src/router/index.ts) (Layout 子路由,list/new/edit/view 四条) ## 架构概览 ```mermaid graph TD subgraph pages [页面层] ListPage["index.vue 列表页"] FormPage["form.vue 新增/编辑/查看页"] end subgraph api [API 层] IssueAPI["issue.ts 领料单头"] IssueLineAPI["issueLine.ts 领料行"] IssueDetailAPI["issueDetail.ts 出库明细"] end subgraph backend [后端接口] HeaderAPI["/mes/wm/issueheader/*"] LineAPI["/mes/wm/issueline/*"] DetailAPI["/mes/wm/issuedetail/*"] WorkorderAPI["/mes/pro/workorder/list"] ItemAPI["/mes/md/mditem/list"] WarehouseAPI["/mes/wm/warehouse|location|area/list"] end ListPage --> IssueAPI FormPage --> IssueAPI FormPage --> IssueLineAPI FormPage --> IssueDetailAPI IssueAPI --> HeaderAPI IssueLineAPI --> LineAPI IssueDetailAPI --> DetailAPI FormPage --> WorkorderAPI FormPage --> ItemAPI FormPage --> WarehouseAPI ``` ## 文件清单 ``` erp-frontend-vue/src/ ├── api/ │ └── warehouse/ │ ├── issue.ts # 领料单头 API + 类型 + 状态常量 │ ├── issueLine.ts # 领料行 CRUD API + 类型 │ └── issueDetail.ts # 出库明细 CRUD API + 类型 ├── views/ │ └── Warehouse/ │ └── Issue/ │ ├── index.vue # 列表页 │ └── form.vue # 新增/编辑/查看页(含行表+明细表+弹窗) └── router/ └── index.ts # 追加 /warehouse 路由组 ``` --- ## 1. API 层(3 个文件) ### 1.1 `src/api/warehouse/issue.ts` - 类型:`IssueHeader`, `IssueHeaderQuery`, `IssueHeaderListResponse` - 状态常量:`STATUS_MAP` (PREPARE/CONFIRMED/APPROVED/FINISHED) - API 函数: - `getIssueHeaderList(params)` -> GET `/mes/wm/issueheader/list` - `getIssueHeaderDetail(issueId)` -> GET `/mes/wm/issueheader/{issueId}` - `createIssueHeader(data)` -> POST `/mes/wm/issueheader` - `updateIssueHeader(data)` -> PUT `/mes/wm/issueheader` - `deleteIssueHeader(ids)` -> DELETE `/mes/wm/issueheader/{ids}` - `executeIssue(issueId)` -> PUT `/mes/wm/issueheader/{issueId}` (执行出库) - `checkQuantity(issueId)` -> GET `/mes/wm/issueheader/checkQuantity/{issueId}` - `exportIssueHeader(params)` -> POST `/mes/wm/issueheader/export` - 辅助 API(弹窗选择): - `getWorkorderSelectList(params)` -> GET `/mes/pro/workorder/list` - `getItemSelectList(params)` -> GET `/mes/md/mditem/list` - `getClientSelectList(params)` -> 复用现有客户接口 - `getWarehouseList()` -> GET `/mes/wm/warehouse/list` - `getLocationList(warehouseId)` -> GET `/mes/wm/location/list` - `getAreaList(locationId)` -> GET `/mes/wm/area/list` ### 1.2 `src/api/warehouse/issueLine.ts` - 类型:`IssueLine` - API:`getIssueLineList(params)`, `createIssueLine(data)`, `updateIssueLine(data)`, `deleteIssueLine(ids)` ### 1.3 `src/api/warehouse/issueDetail.ts` - 类型:`IssueDetail` - API:`getIssueDetailList(params)`, `createIssueDetail(data)`, `updateIssueDetail(data)`, `deleteIssueDetail(ids)` --- ## 2. 路由配置 在 [router/index.ts](erp-frontend-vue/src/router/index.ts) 最后的 `]` 前追加 `/warehouse` 路由组: ```typescript { path: '/warehouse', component: Layout, redirect: '/warehouse/issue', meta: { title: '仓储管理' }, children: [ { path: 'issue', name: 'IssueList', component: () => import('@/views/Warehouse/Issue/index.vue'), meta: { title: '生产领料' } }, { path: 'issue/new', name: 'IssueNew', component: () => import('@/views/Warehouse/Issue/form.vue'), meta: { title: '新增领料单' } }, { path: 'issue/edit/:id', name: 'IssueEdit', component: () => import('@/views/Warehouse/Issue/form.vue'), meta: { title: '编辑领料单' } }, { path: 'issue/view/:id', name: 'IssueView', component: () => import('@/views/Warehouse/Issue/form.vue'), meta: { title: '查看领料单' } } ] } ``` --- ## 3. 列表页 `index.vue` 遵循 WorkOrder/index.vue 模式: - **搜索区**:7 个字段 (issueCode, issueName, workorderCode, workstationName, status下拉, beginDate, endDate) + 搜索/重置按钮 - **工具栏**:新增(success) / 修改(primary) / 删除(danger) / 导出(warning) 四个按钮 - **表格**:复选框 + 11 列 (issueCode蓝色链接, issueName, workorderCode, taskCode, workstationName, clientName, issueDate, requiredTime, status标签, 操作列) - **操作列**:根据 status 动态显隐 — 草稿显示:查看/编辑/删除/执行出库;已完成仅显示:查看 - **分页**:el-pagination,sizes=[10,20,50,100] - **删除校验**:仅 PREPARE 状态允许,非草稿提示 "只能删除草稿状态的单据!" - **执行出库**:调用 `checkQuantity` 校验 -> `executeIssue` -> 刷新列表 --- ## 4. 表单页 `form.vue` (重点,三层数据) 这是本模块最复杂的部分,包含 **表头表单 + 领料行子表 + 出库明细子表 + 4个选择弹窗**。 ### 4.1 页面顶部操作栏 - 新增/编辑模式:保存 + 取消 + 执行出库(编辑模式) + 收起/展开 - 查看模式:新增 + 编辑(仅草稿) + 收起/展开 ### 4.2 表头表单 (el-collapse + el-form) - 4 列布局 (`el-col :span="6"`) - 字段:issueCode(必填), issueName(必填), 工单(选择弹窗), workorderCode(只读), 任务(选择), taskCode(只读), 工作站(选择), workstationCode/Name(只读), 客户(选择), clientCode/Name(只读), issueDate(日期), requiredTime(日期), status(标签), remark(textarea) - 选择按钮通过 `el-input` 的 `#append` 插槽实现,与 WorkOrder 一致 ### 4.3 领料行子表 (el-table, 可编辑) - 数据源:`lineList: IssueLine[]` - 列:序号, 物料编码(带选择按钮), 物料名称(只读), 规格型号(只读), 单位(只读), 领料数量(el-input-number), 批次号, 备注, 操作(编辑明细/删除) - 「添加行」按钮:push 空行到 lineList - 行点击/「编辑明细」:设置 `selectedLineIndex`,展示该行的出库明细 - 保存流程:表头保存后,逐行调用 `createIssueLine` / `updateIssueLine`;删除行调用 `deleteIssueLine` ### 4.4 出库明细子表 (el-table, 可编辑) - 仅当选中某领料行时显示 - 数据源:`detailList: IssueDetail[]` (按 lineId 过滤) - 列:序号, 物料编码/名称(只读,从行带入), 仓库(el-select), 库区(el-select,联动), 库位(el-select,联动), 批次号, 出库数量(el-input-number), 备注, 操作(删除) - 仓库/库区/库位**三级联动**:选择仓库 -> 加载库区 -> 选择库区 -> 加载库位 - 保存:调用 `createIssueDetail` / `updateIssueDetail` / `deleteIssueDetail` ### 4.5 选择弹窗(4 个) | 弹窗 | 数据来源 | 选择模式 | 回填字段 | | ----- | ------------------------- | ----- | -------------------------------------------------------- | | 选择工单 | `/mes/pro/workorder/list` | 单选 | workorderId, workorderCode | | 选择物料 | `/mes/md/mditem/list` | 单选/多选 | itemId, itemCode, itemName, specification, unitOfMeasure | | 选择客户 | `/mes/md/client/list` | 单选 | clientId, clientCode, clientName | | 选择工作站 | workstation接口 | 单选 | workstationId, workstationCode, workstationName | 弹窗结构遵循 WorkOrder form.vue 的 `el-dialog` + 搜索区 + `el-table` + highlight-current-row + 确定/取消 模式。 ### 4.6 数据加载流程(编辑/查看) ```mermaid sequenceDiagram participant Page as form.vue participant API as API Layer participant BE as Backend Page->>API: getIssueHeaderDetail(id) API->>BE: GET /mes/wm/issueheader/{id} BE-->>Page: 表头数据 Page->>API: getIssueLineList(issueId) API->>BE: GET /mes/wm/issueline/list?issueId=xx BE-->>Page: 领料行列表 Page->>API: getIssueDetailList(issueId) API->>BE: GET /mes/wm/issuedetail/list?issueId=xx BE-->>Page: 出库明细列表 ``` ### 4.7 保存流程 1. 表单校验 (issueCode必填, issueName必填) 2. 新增:`createIssueHeader` -> 获取 issueId -> `router.replace` 到编辑页 3. 编辑:`updateIssueHeader` -> 成功提示 4. 领料行的增删改在保存表头后独立操作(行级 CRUD) 5. 出库明细的增删改同样独立操作 ### 4.8 执行出库流程 1. 前端校验:至少 1 条领料行,每行有明细数据 2. 调用 `checkQuantity(issueId)` 校验数量匹配 3. 调用 `executeIssue(issueId)` 执行出库 4. 成功后刷新页面数据,status 变为 FINISHED --- ## 5. 关键实现要点 - **三级联动**:仓库 -> 库区 -> 库位,使用 watch 监听上级变化,清空下级选项并重新加载 - **行级编辑**:领料行和出库明细均为表格内编辑(inline edit),非弹窗编辑 - **状态控制**:所有编辑操作受 `isView` 和 `formData.status` 双重控制;FINISHED 状态只读 - **样式复用**:直接复用 WorkOrder 的 `.form-container`, `.page-header`, `.main-card`, `.section-header`, `.dialog-search` 等 CSS 类