266 lines
12 KiB
Markdown
266 lines
12 KiB
Markdown
|
|
---
|
|||
|
|
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 类
|
|||
|
|
|