| | |
| | | # 不合格品处理单 — 前端联调文档 |
| | | # 不合格品处理单模块(QualityUnqualifiedOrder) |
| | | |
| | | ## 概述 |
| | | |
| | | 不合格品处理单是正式的不合格品处置流程模块,替代旧的不合格管理(`/quality/qualityUnqualified`)中的处置功能。旧模块的不合格品发现(新增/列表/详情)继续使用,但**处置操作统一使用本模块**。 |
| | | |
| | | ### 自动创建机制 |
| | | |
| | | 当检验单(原材料/过程/出厂检验)提交时,如果**不合格数量 > 0**,系统在创建 `QualityUnqualified` 记录的同时,**自动创建一条不合格品处理单**,`unqualifiedProcess`(不合格工序)根据检验类别自动映射: |
| | | |
| | | | 检验类别 | inspectType | unqualifiedProcess | |
| | | |----------|-------------|-------------------| |
| | | | 原材料检验 | 0 | 1(来料) | |
| | | | 过程检验 | 0 | 2(制程) | |
| | | | 出厂检验 | 0 | 3(成品) | |
| | | |
| | | 处理单初始状态为 `0`(草稿),后续可编辑处置方式并提交审批。 |
| | | |
| | | ### 与旧模块的关系 |
| | | |
| | | | | 旧:不合格管理 | 新:不合格品处理单 | |
| | | |---|---|---| |
| | | | 路径 | `/quality/qualityUnqualified` | `/qualityUnqualifiedOrder` | |
| | | | 用途 | 不合格品首次记录、查看 | 正式处置流程(含审批) | |
| | | | 处置方式 | `dealResult` 自由文本 | `disposalMethod` 结构化枚举 | |
| | | | 创建方式 | 检验单提交自动创建 / 手动新增 | 检验单提交自动创建 / 手动新增 | |
| | | |
| | | ## 涉及页面 |
| | | |
| | | - **不合格品处理单列表/详情** — 新增页面 |
| | | |
| | | ## 变更说明 |
| | | |
| | | 新增 `quality_unqualified_order` 不合格品处理单模块,支持对不合格品进行正式的处置记录,包含审批状态机(草稿→待审批→审批中→已完成/已驳回)。附件使用系统统一的 `storage_attachment` 表。 |
| | | - 不合格品处理单列表页 |
| | | - 不合格品处理单新增/编辑页 |
| | | - 不合格品处理单详情页 |
| | | |
| | | ## API |
| | | |
| | | ### 不合格品处理单 |
| | | ### 1. 新增处理单 |
| | | |
| | | | 方法 | 路径 | 说明 | |
| | | |------|------|------| |
| | | | POST | `/qualityUnqualifiedOrder/save` | 新增处理单(编号自动生成) | |
| | | | PUT | `/qualityUnqualifiedOrder/update` | 修改处理单 | |
| | | | DELETE | `/qualityUnqualifiedOrder/delete` | 批量删除(逻辑删除) | |
| | | | GET | `/qualityUnqualifiedOrder/listPage` | 分页查询 | |
| | | | GET | `/qualityUnqualifiedOrder/{id}` | 查看详情 | |
| | | | POST | /qualityUnqualifiedOrder/save | 新增不合格品处理单 | |
| | | |
| | | ### 请求/响应参数 |
| | | |
| | | **QualityUnqualifiedOrder 对象:** |
| | | **请求参数:** |
| | | |
| | | | 参数 | 类型 | 必填 | 说明 | |
| | | |------|------|------|------| |
| | | | id | Long | 否 | 主键(修改时必填) | |
| | | | orderNo | String | 否 | 处理单编号,自动生成,前缀 BHG+日期+序号 | |
| | | | unqualifiedId | Long | 否 | 关联不合格品ID | |
| | | | unqualifiedId | Long | 是 | 关联不合格品ID | |
| | | | projectName | String | 否 | 项目名称 | |
| | | | projectNo | String | 否 | 项目编号 | |
| | | | equipmentId | Long | 否 | 关联设备ID | |
| | |
| | | | materialQuality | String | 否 | 材质 | |
| | | | quantity | BigDecimal | 否 | 总数量 | |
| | | | unqualifiedQuantity | BigDecimal | 否 | 不合格数量 | |
| | | | unqualifiedProcess | Integer | 否 | 不合格工序:1=来料,2=制程,3=成品 | |
| | | | unqualifiedProcess | Integer | 否 | 不合格工序:1=来料, 2=制程, 3=成品 | |
| | | | supplierName | String | 否 | 供应商名称 | |
| | | | inspectorName | String | 否 | 检验员 | |
| | | | inspectDate | Date | 否 | 检验日期 (yyyy-MM-dd) | |
| | |
| | | | problemDescription | String | 否 | 问题描述 | |
| | | | reasonAnalysis | String | 否 | 原因分析及建议 | |
| | | | correctionAction | String | 否 | 纠正措施 | |
| | | | disposalMethod | Integer | 否 | 处置方式:1=让步接收,2=厂内维修,3=返厂维修,4=换货,5=退货,6=报废 | |
| | | | **disposalMethod** | **Integer** | **是** | **处置方式:1=让步接收, 2=厂内维修, 3=返厂维修, 4=换货, 5=退货, 6=报废** | |
| | | | repairEvaluation | String | 否 | 厂内/返厂维修评估 | |
| | | | preventiveAction | String | 否 | 预防措施 | |
| | | | status | Integer | 否 | 状态:0=草稿,1=待审批,2=审批中,3=已完成,4=已驳回 | |
| | | | remark | String | 否 | 备注 | |
| | | | storageBlobDTOs | List\<StorageBlobDTO\> | 否 | 附件上传列表 | |
| | | | storageBlobVOs | List\<StorageBlobVO\> | 否 | 附件回显列表(查询时返回) | |
| | | | deptOpinion | String | 否 | 责任部门主管意见 | |
| | | | companyDecision | String | 否 | 公司处理决定 | |
| | | | generalManagerOpinion | String | 否 | 总经理意见 | |
| | | | storageBlobDTOs | List | 否 | 附件列表 | |
| | | |
| | | ### 分页查询参数 |
| | | **自动行为:** |
| | | - 自动生成处理单编号(`BHGyyMMdd+流水号`) |
| | | - **手动新增时**:选了处置方式 → 状态自动为 `3`(已完成);没选 → 状态为 `0`(草稿) |
| | | - **质检自动创建时**:状态初始为 `0`(草稿),需通过处理接口补充处置方式 |
| | | - **当 `disposalMethod` 选择 2(厂内维修)或 3(返厂维修)时,自动创建返修生产订单** |
| | | |
| | | **响应:** `{ "code": 200, "msg": "操作成功", "data": true }` |
| | | |
| | | ### 2. 修改处理单 |
| | | |
| | | | 方法 | 路径 | 说明 | |
| | | |------|------|------| |
| | | | PUT | /qualityUnqualifiedOrder/update | 修改不合格品处理单 | |
| | | |
| | | **请求参数:** 与新增相同,额外需要 `id` 字段。 |
| | | |
| | | ### 3. 删除处理单 |
| | | |
| | | | 方法 | 路径 | 说明 | |
| | | |------|------|------| |
| | | | DELETE | /qualityUnqualifiedOrder/delete | 删除不合格品处理单 | |
| | | |
| | | **请求参数:** `[id1, id2, ...]` — ID 数组 |
| | | |
| | | ### 4. 分页查询 |
| | | |
| | | | 方法 | 路径 | 说明 | |
| | | |------|------|------| |
| | | | GET | /qualityUnqualifiedOrder/listPage | 分页查询 | |
| | | |
| | | **查询参数:** |
| | | |
| | | | 参数 | 类型 | 必填 | 说明 | |
| | | |------|------|------|------| |
| | | | pageNum | Integer | 否 | 页码,默认1 | |
| | | | pageSize | Integer | 否 | 每页条数,默认10 | |
| | | | status | Integer | 否 | 状态筛选 | |
| | | | projectName | String | 否 | 项目名称模糊搜索 | |
| | | | orderNo | String | 否 | 编号模糊搜索 | |
| | | | entryDateStart | String | 否 | 创建时间起始 | |
| | | | entryDateEnd | String | 否 | 创建时间结束 | |
| | | | page | int | 否 | 页码(默认1) | |
| | | | size | int | 否 | 每页条数(默认10) | |
| | | | status | Integer | 否 | 状态:0=草稿, 1=待审批, 2=审批中, 3=已完成, 4=已驳回 | |
| | | | projectName | String | 否 | 项目名称(模糊匹配) | |
| | | | orderNo | String | 否 | 处理单编号(模糊匹配) | |
| | | | entryDateStart | String | 否 | 创建时间起 (yyyy-MM-dd) | |
| | | | entryDateEnd | String | 否 | 创建时间止 (yyyy-MM-dd) | |
| | | |
| | | ### 删除请求体 |
| | | **响应字段:** 返回 `QualityUnqualifiedOrder` 全部字段,含 `storageBlobVOs`(附件列表)。 |
| | | |
| | | ```json |
| | | [1, 2, 3] |
| | | ``` |
| | | ### 5. 详情查询 |
| | | |
| | | ## 数据结构 |
| | | | 方法 | 路径 | 说明 | |
| | | |------|------|------| |
| | | | GET | /qualityUnqualifiedOrder/{id} | 处理单详情 | |
| | | |
| | | ### StorageBlobDTO(上传时传入) |
| | | **响应:** 返回单条 `QualityUnqualifiedOrder` 全部字段,含附件。 |
| | | |
| | | ```json |
| | | { |
| | | "id": "临时文件ID(字符串)", |
| | | "name": "文件名", |
| | | "url": "文件路径", |
| | | "fileSize": 1024 |
| | | } |
| | | ``` |
| | | ### 6. 处理(处置) |
| | | |
| | | ### StorageBlobVO(查询时返回) |
| | | | 方法 | 路径 | 说明 | |
| | | |------|------|------| |
| | | | POST | /qualityUnqualifiedOrder/deal | 对草稿状态的处理单补充处置方式并完成 | |
| | | |
| | | ```json |
| | | { |
| | | "id": 1, |
| | | "name": "检验报告.pdf", |
| | | "url": "/upload/20260613/xxx.pdf", |
| | | "fileSize": 102400, |
| | | "application": "FILE" |
| | | **请求参数:** |
| | | |
| | | | 参数 | 类型 | 必填 | 说明 | |
| | | |------|------|------|------| |
| | | | **id** | **Long** | **是** | 处理单ID | |
| | | | **disposalMethod** | **Integer** | **是** | **处置方式:1=让步接收, 2=厂内维修, 3=返厂维修, 4=换货, 5=退货, 6=报废** | |
| | | | repairEvaluation | String | 否 | 厂内/返厂维修评估 | |
| | | | reasonAnalysis | String | 否 | 原因分析及建议 | |
| | | | correctionAction | String | 否 | 纠正措施 | |
| | | | preventiveAction | String | 否 | 预防措施 | |
| | | | remark | String | 否 | 备注 | |
| | | | deptOpinion | String | 否 | 责任部门主管意见 | |
| | | | companyDecision | String | 否 | 公司处理决定 | |
| | | | generalManagerOpinion | String | 否 | 总经理意见 | |
| | | |
| | | **自动行为:** |
| | | - 状态更新为 `3`(已完成) |
| | | - 处置方式为 2(厂内维修)或 3(返厂维修)时,自动创建返修生产订单 |
| | | |
| | | **响应:** `{ "code": 200, "msg": "操作成功", "data": true }` |
| | | |
| | | ### 7. 导出处理单 |
| | | |
| | | | 方法 | 路径 | 说明 | |
| | | |------|------|------| |
| | | | GET | /qualityUnqualifiedOrder/export/{id} | 导出不合格品处理单为 Excel | |
| | | |
| | | **请求参数:** `id` — 处理单ID(路径参数) |
| | | |
| | | **响应:** 文件流,`Content-Type: application/vnd.ms-excel`,文件名 `不合格品处理单_{编号}.xls` |
| | | |
| | | **模板字段映射:** |
| | | |
| | | | 模板位置 | 字段 | |
| | | |----------|------| |
| | | | 项目名称 | projectName | |
| | | | 项目编号 | projectNo | |
| | | | 设备名称 | equipmentName | |
| | | | 设备图号 | equipmentDrawingNo | |
| | | | 物料名称 | materialName | |
| | | | 物料图号 | materialDrawingNo | |
| | | | 型号规格 | specificationModel | |
| | | | 材质 | materialQuality | |
| | | | 总数量 | quantity | |
| | | | 不合格数 | unqualifiedQuantity | |
| | | | 不合格工序 | unqualifiedProcess(勾选来料/制程/成品) | |
| | | | 供货商名称 | supplierName | |
| | | | 检验员 | inspectorName | |
| | | | 检验日期 | inspectDate | |
| | | | 责任人 | responsiblePerson | |
| | | | 责任部门 | responsibleDept | |
| | | | 问题描述 | problemDescription | |
| | | | 原因分析及建议 | reasonAnalysis | |
| | | | 纠正措施 | correctionAction | |
| | | | 处置方式 | disposalMethod(勾选对应选项) | |
| | | | 厂内/返厂维修评估 | repairEvaluation | |
| | | | 预防措施 | preventiveAction | |
| | | | 责任部门主管意见 | deptOpinion | |
| | | | 公司处理决定 | companyDecision | |
| | | | 总经理意见 | generalManagerOpinion | |
| | | |
| | | **前端调用示例:** |
| | | |
| | | ```js |
| | | // 列表页操作列增加导出按钮 |
| | | <el-button text type="primary" @click="handleExport(row.id)">导出</el-button> |
| | | |
| | | // 详情页增加导出按钮 |
| | | <el-button type="primary" @click="handleExport">导出</el-button> |
| | | |
| | | methods: { |
| | | handleExport(id) { |
| | | window.open(`/api/qualityUnqualifiedOrder/export/${id}`); |
| | | }, |
| | | } |
| | | ``` |
| | | |
| | | ## 前端修改点 |
| | | |
| | | ### 1. 不合格品处理单 — 新增/编辑表单 |
| | | ### 1. 处理单列表页 |
| | | |
| | | ```html |
| | | <el-form :model="form" :rules="rules" ref="formRef"> |
| | | <el-form-item label="项目名称" prop="projectName"> |
| | | <el-input v-model="form.projectName" /> |
| | | </el-form-item> |
| | | <el-form-item label="项目编号" prop="projectNo"> |
| | | <el-input v-model="form.projectNo" /> |
| | | </el-form-item> |
| | | <el-form-item label="设备名称" prop="equipmentName"> |
| | | <el-input v-model="form.equipmentName" /> |
| | | </el-form-item> |
| | | <el-form-item label="物料/部件名称" prop="materialName"> |
| | | <el-input v-model="form.materialName" /> |
| | | </el-form-item> |
| | | <el-form-item label="型号规格" prop="specificationModel"> |
| | | <el-input v-model="form.specificationModel" /> |
| | | </el-form-item> |
| | | <el-form-item label="材质" prop="materialQuality"> |
| | | <el-input v-model="form.materialQuality" /> |
| | | </el-form-item> |
| | | <el-form-item label="总数量" prop="quantity"> |
| | | <el-input-number v-model="form.quantity" /> |
| | | </el-form-item> |
| | | <el-form-item label="不合格数量" prop="unqualifiedQuantity"> |
| | | <el-input-number v-model="form.unqualifiedQuantity" /> |
| | | </el-form-item> |
| | | <el-form-item label="不合格工序" prop="unqualifiedProcess"> |
| | | <el-select v-model="form.unqualifiedProcess"> |
| | | <el-option label="来料" :value="1" /> |
| | | <el-option label="制程" :value="2" /> |
| | | <el-option label="成品" :value="3" /> |
| | | </el-select> |
| | | </el-form-item> |
| | | <el-form-item label="供应商名称" prop="supplierName"> |
| | | <el-input v-model="form.supplierName" /> |
| | | </el-form-item> |
| | | <el-form-item label="检验员" prop="inspectorName"> |
| | | <el-input v-model="form.inspectorName" /> |
| | | </el-form-item> |
| | | <el-form-item label="检验日期" prop="inspectDate"> |
| | | <el-date-picker v-model="form.inspectDate" type="date" value-format="yyyy-MM-dd" /> |
| | | </el-form-item> |
| | | <el-form-item label="责任人" prop="responsiblePerson"> |
| | | <el-input v-model="form.responsiblePerson" /> |
| | | </el-form-item> |
| | | <el-form-item label="责任部门" prop="responsibleDept"> |
| | | <el-input v-model="form.responsibleDept" /> |
| | | </el-form-item> |
| | | <el-form-item label="问题描述" prop="problemDescription"> |
| | | <el-input type="textarea" v-model="form.problemDescription" /> |
| | | </el-form-item> |
| | | <el-form-item label="原因分析" prop="reasonAnalysis"> |
| | | <el-input type="textarea" v-model="form.reasonAnalysis" /> |
| | | </el-form-item> |
| | | <el-form-item label="纠正措施" prop="correctionAction"> |
| | | <el-input type="textarea" v-model="form.correctionAction" /> |
| | | </el-form-item> |
| | | <el-form-item label="处置方式" prop="disposalMethod"> |
| | | <el-select v-model="form.disposalMethod"> |
| | | <el-option label="让步接收" :value="1" /> |
| | | <el-option label="厂内维修" :value="2" /> |
| | | <el-option label="返厂维修" :value="3" /> |
| | | <el-option label="换货" :value="4" /> |
| | | <el-option label="退货" :value="5" /> |
| | | <el-option label="报废" :value="6" /> |
| | | </el-select> |
| | | </el-form-item> |
| | | <el-form-item label="维修评估" prop="repairEvaluation"> |
| | | <el-input type="textarea" v-model="form.repairEvaluation" /> |
| | | </el-form-item> |
| | | <el-form-item label="预防措施" prop="preventiveAction"> |
| | | <el-input type="textarea" v-model="form.preventiveAction" /> |
| | | </el-form-item> |
| | | <el-form-item label="备注" prop="remark"> |
| | | <el-input type="textarea" v-model="form.remark" /> |
| | | </el-form-item> |
| | | <el-form-item label="附件"> |
| | | <file-upload |
| | | v-model="form.storageBlobDTOs" |
| | | :file-list="form.storageBlobVOs" |
| | | /> |
| | | </el-form-item> |
| | | </el-form> |
| | | <template> |
| | | <div class="app-container"> |
| | | <!-- 搜索栏 --> |
| | | <el-form :model="queryParams" :inline="true"> |
| | | <el-form-item label="处理单编号"> |
| | | <el-input v-model="queryParams.orderNo" placeholder="输入编号" /> |
| | | </el-form-item> |
| | | <el-form-item label="项目名称"> |
| | | <el-input v-model="queryParams.projectName" placeholder="输入项目" /> |
| | | </el-form-item> |
| | | <el-form-item label="状态"> |
| | | <el-select v-model="queryParams.status" placeholder="全部" clearable> |
| | | <el-option label="草稿" :value="0" /> |
| | | <el-option label="待审批" :value="1" /> |
| | | <el-option label="审批中" :value="2" /> |
| | | <el-option label="已完成" :value="3" /> |
| | | <el-option label="已驳回" :value="4" /> |
| | | </el-select> |
| | | </el-form-item> |
| | | <el-form-item label="创建时间"> |
| | | <el-date-picker v-model="dateRange" type="daterange" value-format="yyyy-MM-dd" |
| | | start-placeholder="开始" end-placeholder="结束" /> |
| | | </el-form-item> |
| | | <el-form-item> |
| | | <el-button type="primary" @click="handleQuery">查询</el-button> |
| | | <el-button @click="resetQuery">重置</el-button> |
| | | </el-form-item> |
| | | </el-form> |
| | | |
| | | <!-- 操作按钮 --> |
| | | <el-row :gutter="10" class="mb8"> |
| | | <el-button type="primary" @click="handleAdd">新增处理单</el-button> |
| | | <el-button type="danger" :disabled="!selectedIds.length" @click="handleDelete">删除</el-button> |
| | | </el-row> |
| | | |
| | | <!-- 表格 --> |
| | | <el-table :data="list" @selection-change="handleSelectionChange"> |
| | | <el-table-column type="selection" width="55" /> |
| | | <el-table-column label="处理单编号" prop="orderNo" width="160" /> |
| | | <el-table-column label="项目名称" prop="projectName" /> |
| | | <el-table-column label="型号规格" prop="specificationModel" width="120" /> |
| | | <el-table-column label="不合格数量" prop="unqualifiedQuantity" width="100" /> |
| | | <el-table-column label="处置方式" width="110"> |
| | | <template #default="{ row }"> |
| | | {{ disposalMethodMap[row.disposalMethod] }} |
| | | </template> |
| | | </el-table-column> |
| | | <el-table-column label="状态" width="80"> |
| | | <template #default="{ row }"> |
| | | <el-tag :type="statusTagType(row.status)">{{ statusMap[row.status] }}</el-tag> |
| | | </template> |
| | | </el-table-column> |
| | | <el-table-column label="检验员" prop="inspectorName" width="100" /> |
| | | <el-table-column label="检验日期" prop="inspectDate" width="110" /> |
| | | <el-table-column label="创建时间" prop="createTime" width="160" /> |
| | | <el-table-column label="操作" width="120" fixed="right"> |
| | | <template #default="{ row }"> |
| | | <el-button text type="primary" @click="handleDetail(row.id)">详情</el-button> |
| | | <el-button text type="primary" @click="handleEdit(row)">编辑</el-button> |
| | | </template> |
| | | </el-table-column> |
| | | </el-table> |
| | | |
| | | <pagination :total="total" v-model:page="page" v-model:limit="size" |
| | | @pagination="loadList" /> |
| | | </div> |
| | | </template> |
| | | ``` |
| | | |
| | | ### 2. 不合格品处理单 — 列表页 |
| | | ```js |
| | | data() { |
| | | return { |
| | | list: [], |
| | | total: 0, |
| | | page: 1, |
| | | size: 10, |
| | | selectedIds: [], |
| | | dateRange: [], |
| | | queryParams: { |
| | | orderNo: '', |
| | | projectName: '', |
| | | status: null, |
| | | }, |
| | | disposalMethodMap: { 1: '让步接收', 2: '厂内维修', 3: '返厂维修', 4: '换货', 5: '退货', 6: '报废' }, |
| | | statusMap: { 0: '草稿', 1: '待审批', 2: '审批中', 3: '已完成', 4: '已驳回' }, |
| | | } |
| | | }, |
| | | methods: { |
| | | statusTagType(status) { |
| | | const map = { 0: 'info', 1: 'warning', 2: '', 3: 'success', 4: 'danger' }; |
| | | return map[status] || 'info'; |
| | | }, |
| | | loadList() { |
| | | const params = { ...this.queryParams, page: this.page, size: this.size }; |
| | | if (this.dateRange && this.dateRange.length === 2) { |
| | | params.entryDateStart = this.dateRange[0]; |
| | | params.entryDateEnd = this.dateRange[1]; |
| | | } |
| | | listPage(params).then(res => { |
| | | this.list = res.rows; |
| | | this.total = res.total; |
| | | }); |
| | | }, |
| | | handleQuery() { this.page = 1; this.loadList(); }, |
| | | resetQuery() { |
| | | this.queryParams = { orderNo: '', projectName: '', status: null }; |
| | | this.dateRange = []; |
| | | this.handleQuery(); |
| | | }, |
| | | handleSelectionChange(selection) { this.selectedIds = selection.map(i => i.id); }, |
| | | handleAdd() { this.$router.push('/quality/unqualified-order/add'); }, |
| | | handleEdit(row) { this.$router.push({ path: '/quality/unqualified-order/edit', query: { id: row.id } }); }, |
| | | handleDetail(id) { this.$router.push({ path: '/quality/unqualified-order/detail', query: { id } }); }, |
| | | handleDelete() { |
| | | this.$confirm('确认删除选中的处理单?').then(() => { |
| | | deleteOrders(this.selectedIds).then(() => { |
| | | this.$message.success('删除成功'); |
| | | this.loadList(); |
| | | }); |
| | | }); |
| | | }, |
| | | } |
| | | ``` |
| | | |
| | | ### 2. 新增/编辑处理单页 |
| | | |
| | | ```html |
| | | <el-table :data="tableData" border> |
| | | <el-table-column prop="orderNo" label="处理单编号" /> |
| | | <el-table-column prop="projectName" label="项目名称" /> |
| | | <el-table-column prop="materialName" label="物料名称" /> |
| | | <el-table-column prop="specificationModel" label="型号规格" /> |
| | | <el-table-column prop="unqualifiedQuantity" label="不合格数量" /> |
| | | <el-table-column prop="disposalMethod" label="处置方式"> |
| | | <template #default="{ row }"> |
| | | {{ disposalMethodMap[row.disposalMethod] }} |
| | | </template> |
| | | </el-table-column> |
| | | <el-table-column prop="status" label="状态"> |
| | | <template #default="{ row }"> |
| | | <el-tag :type="statusTagType(row.status)">{{ statusMap[row.status] }}</el-tag> |
| | | </template> |
| | | </el-table-column> |
| | | <el-table-column label="操作"> |
| | | <template #default="{ row }"> |
| | | <el-button type="text" @click="handleDetail(row.id)">详情</el-button> |
| | | <el-button type="text" @click="handleEdit(row)">编辑</el-button> |
| | | <el-button type="text" @click="handleDelete(row.id)">删除</el-button> |
| | | </template> |
| | | </el-table-column> |
| | | </el-table> |
| | | ``` |
| | | <template> |
| | | <div class="app-container"> |
| | | <el-form ref="form" :model="form" :rules="rules" label-width="120px"> |
| | | <el-row :gutter="20"> |
| | | <el-col :span="12"> |
| | | <el-form-item label="关联不合格品" prop="unqualifiedId"> |
| | | <el-select v-model="form.unqualifiedId" placeholder="选择不合格品" filterable> |
| | | <el-option v-for="item in unqualifiedList" :key="item.id" |
| | | :label="item.productName + ' ' + item.model + ' (' + item.quantity + ')'" |
| | | :value="item.id" /> |
| | | </el-select> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="12"> |
| | | <el-form-item label="不合格工序" prop="unqualifiedProcess"> |
| | | <el-select v-model="form.unqualifiedProcess"> |
| | | <el-option label="来料" :value="1" /> |
| | | <el-option label="制程" :value="2" /> |
| | | <el-option label="成品" :value="3" /> |
| | | </el-select> |
| | | </el-form-item> |
| | | </el-col> |
| | | </el-row> |
| | | |
| | | ### 3. data 数据 |
| | | <el-divider>基本信息</el-divider> |
| | | <el-row :gutter="20"> |
| | | <el-col :span="12"> |
| | | <el-form-item label="项目名称" prop="projectName"> |
| | | <el-input v-model="form.projectName" /> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="12"> |
| | | <el-form-item label="项目编号" prop="projectNo"> |
| | | <el-input v-model="form.projectNo" /> |
| | | </el-form-item> |
| | | </el-col> |
| | | </el-row> |
| | | <el-row :gutter="20"> |
| | | <el-col :span="12"> |
| | | <el-form-item label="物料/部件名称" prop="materialName"> |
| | | <el-input v-model="form.materialName" /> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="12"> |
| | | <el-form-item label="物料图号" prop="materialDrawingNo"> |
| | | <el-input v-model="form.materialDrawingNo" /> |
| | | </el-form-item> |
| | | </el-col> |
| | | </el-row> |
| | | <el-row :gutter="20"> |
| | | <el-col :span="8"> |
| | | <el-form-item label="型号规格" prop="specificationModel"> |
| | | <el-input v-model="form.specificationModel" /> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="8"> |
| | | <el-form-item label="材质" prop="materialQuality"> |
| | | <el-input v-model="form.materialQuality" /> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="8"> |
| | | <el-form-item label="供应商" prop="supplierName"> |
| | | <el-input v-model="form.supplierName" /> |
| | | </el-form-item> |
| | | </el-col> |
| | | </el-row> |
| | | |
| | | <el-divider>不合格信息</el-divider> |
| | | <el-row :gutter="20"> |
| | | <el-col :span="8"> |
| | | <el-form-item label="总数量" prop="quantity"> |
| | | <el-input-number v-model="form.quantity" :min="0" :precision="2" style="width:100%" /> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="8"> |
| | | <el-form-item label="不合格数量" prop="unqualifiedQuantity"> |
| | | <el-input-number v-model="form.unqualifiedQuantity" :min="0" :precision="2" style="width:100%" /> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="8"> |
| | | <el-form-item label="检验日期" prop="inspectDate"> |
| | | <el-date-picker v-model="form.inspectDate" type="date" value-format="yyyy-MM-dd" style="width:100%" /> |
| | | </el-form-item> |
| | | </el-col> |
| | | </el-row> |
| | | <el-row :gutter="20"> |
| | | <el-col :span="8"> |
| | | <el-form-item label="检验员" prop="inspectorName"> |
| | | <el-input v-model="form.inspectorName" /> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="8"> |
| | | <el-form-item label="责任人" prop="responsiblePerson"> |
| | | <el-input v-model="form.responsiblePerson" /> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="8"> |
| | | <el-form-item label="责任部门" prop="responsibleDept"> |
| | | <el-input v-model="form.responsibleDept" /> |
| | | </el-form-item> |
| | | </el-col> |
| | | </el-row> |
| | | <el-form-item label="问题描述" prop="problemDescription"> |
| | | <el-input v-model="form.problemDescription" type="textarea" :rows="2" /> |
| | | </el-form-item> |
| | | |
| | | <el-divider>处置决策</el-divider> |
| | | <el-form-item label="处置方式" prop="disposalMethod"> |
| | | <el-radio-group v-model="form.disposalMethod"> |
| | | <el-radio :value="1">让步接收</el-radio> |
| | | <el-radio :value="2">厂内维修</el-radio> |
| | | <el-radio :value="3">返厂维修</el-radio> |
| | | <el-radio :value="4">换货</el-radio> |
| | | <el-radio :value="5">退货</el-radio> |
| | | <el-radio :value="6">报废</el-radio> |
| | | </el-radio-group> |
| | | </el-form-item> |
| | | <el-form-item v-if="form.disposalMethod === 2 || form.disposalMethod === 3" label="维修评估" prop="repairEvaluation"> |
| | | <el-input v-model="form.repairEvaluation" type="textarea" :rows="3" |
| | | placeholder="评估维修可行性、所需工时、物料等" /> |
| | | </el-form-item> |
| | | <el-form-item label="原因分析及建议" prop="reasonAnalysis"> |
| | | <el-input v-model="form.reasonAnalysis" type="textarea" :rows="3" /> |
| | | </el-form-item> |
| | | <el-form-item label="纠正措施" prop="correctionAction"> |
| | | <el-input v-model="form.correctionAction" type="textarea" :rows="3" /> |
| | | </el-form-item> |
| | | <el-form-item label="预防措施" prop="preventiveAction"> |
| | | <el-input v-model="form.preventiveAction" type="textarea" :rows="3" /> |
| | | </el-form-item> |
| | | |
| | | <el-divider>审批意见</el-divider> |
| | | <el-form-item label="责任部门主管意见" prop="deptOpinion"> |
| | | <el-input v-model="form.deptOpinion" type="textarea" :rows="2" /> |
| | | </el-form-item> |
| | | <el-form-item label="公司处理决定" prop="companyDecision"> |
| | | <el-input v-model="form.companyDecision" type="textarea" :rows="2" /> |
| | | </el-form-item> |
| | | <el-form-item label="总经理意见" prop="generalManagerOpinion"> |
| | | <el-input v-model="form.generalManagerOpinion" type="textarea" :rows="2" /> |
| | | </el-form-item> |
| | | |
| | | <el-divider>附件</el-divider> |
| | | <el-form-item label="附件"> |
| | | <file-upload v-model="form.storageBlobDTOs" /> |
| | | </el-form-item> |
| | | </el-form> |
| | | |
| | | <div class="text-center"> |
| | | <el-button type="primary" @click="handleSubmit">提交</el-button> |
| | | <el-button @click="handleCancel">取消</el-button> |
| | | </div> |
| | | </div> |
| | | </template> |
| | | ``` |
| | | |
| | | ```js |
| | | data() { |
| | | return { |
| | | form: { |
| | | storageBlobDTOs: [], |
| | | storageBlobVOs: [], |
| | | unqualifiedId: null, |
| | | disposalMethod: null, |
| | | }, |
| | | query: { |
| | | pageNum: 1, |
| | | pageSize: 10, |
| | | status: null, |
| | | projectName: '', |
| | | orderNo: '', |
| | | rules: { |
| | | unqualifiedId: [{ required: true, message: '请选择关联不合格品', trigger: 'change' }], |
| | | disposalMethod: [{ required: true, message: '请选择处置方式', trigger: 'change' }], |
| | | }, |
| | | statusMap: { 0: '草稿', 1: '待审批', 2: '审批中', 3: '已完成', 4: '已驳回' }, |
| | | disposalMethodMap: { 1: '让步接收', 2: '厂内维修', 3: '返厂维修', 4: '换货', 5: '退货', 6: '报废' }, |
| | | unqualifiedProcessMap: { 1: '来料', 2: '制程', 3: '成品' }, |
| | | unqualifiedList: [], |
| | | } |
| | | }, |
| | | mounted() { |
| | | // 加载待处理的不合格品列表 |
| | | loadUnqualifiedList({ inspectState: 0 }).then(res => this.unqualifiedList = res.rows); |
| | | if (this.$route.query.id) { |
| | | getDetail(this.$route.query.id).then(res => this.form = res.data); |
| | | } |
| | | }, |
| | | methods: { |
| | | handleSubmit() { |
| | | this.$refs.form.validate(valid => { |
| | | if (!valid) return; |
| | | const api = this.form.id ? updateOrder : saveOrder; |
| | | api(this.form).then(() => { |
| | | this.$message.success(this.form.id ? '修改成功' : '新增成功'); |
| | | this.$router.back(); |
| | | }); |
| | | }); |
| | | }, |
| | | handleCancel() { this.$router.back(); }, |
| | | } |
| | | ``` |
| | | |
| | | ### 4. API 调用 |
| | | ## 处置方式说明 |
| | | |
| | | ```js |
| | | import request from '@/utils/request' |
| | | | 值 | 含义 | 系统自动行为 | |
| | | |----|------|------------| |
| | | | 1 | 让步接收 | 无自动操作,需人工后续处理 | |
| | | | 2 | 厂内维修 | **自动创建返修生产订单**(FG 开头 NPS 编号),克隆原工序路线 | |
| | | | 3 | 返厂维修 | **自动创建返修生产订单**(FG 开头 NPS 编号),克隆原工序路线 | |
| | | | 4 | 换货 | 无自动操作 | |
| | | | 5 | 退货 | 无自动操作 | |
| | | | 6 | 报废 | 无自动操作(库存扣减由旧模块 `/quality/qualityUnqualified/deal` 处理) | |
| | | |
| | | // 分页查询 |
| | | export function listPage(query) { |
| | | return request({ url: '/qualityUnqualifiedOrder/listPage', method: 'get', params: query }) |
| | | } |
| | | ## 状态流转 |
| | | |
| | | // 详情 |
| | | export function getDetail(id) { |
| | | return request({ url: `/qualityUnqualifiedOrder/${id}`, method: 'get' }) |
| | | } |
| | | |
| | | // 新增 |
| | | export function save(data) { |
| | | return request({ url: '/qualityUnqualifiedOrder/save', method: 'post', data }) |
| | | } |
| | | |
| | | // 修改 |
| | | export function update(data) { |
| | | return request({ url: '/qualityUnqualifiedOrder/update', method: 'put', data }) |
| | | } |
| | | |
| | | // 删除 |
| | | export function remove(ids) { |
| | | return request({ url: '/qualityUnqualifiedOrder/delete', method: 'delete', data: ids }) |
| | | } |
| | | ``` |
| | | 质检自动创建 ──> 0(草稿) ──> 调用 /deal 选择处置方式 ──> 3(已完成) |
| | | 手动新增(没选处置方式) ──> 0(草稿) ──> 调用 /deal ──> 3(已完成) |
| | | 手动新增(选了处置方式) ──> 3(已完成) |
| | | ``` |
| | | |
| | | ## 注意事项 |
| | | |
| | | - 处理单编号 `orderNo` 由后端自动生成(前缀 "BHG" + 日期 + 3位自增序号),前端无需传入 |
| | | - 新增时 `status` 默认为 0(草稿),无需前端设置 |
| | | - 删除为逻辑删除,通过 `deleted` 字段标记 |
| | | - 附件上传使用系统已有的文件上传组件,将返回的临时文件ID通过 `storageBlobDTOs` 传入 |
| | | - 不合格品处理单可关联 `quality_unqualified` 表的记录(通过 `unqualifiedId` 字段) |
| | | - 检验单提交时,不合格数量 > 0 会自动创建处理单(状态为草稿),**无需手动新增** |
| | | - 手动新增处理单时,选了处置方式直接完成,没选则保持草稿 |
| | | - 草稿状态的处理单通过 `/qualityUnqualifiedOrder/deal` 接口补充处置方式 |
| | | - 旧的不合格管理(`/quality/qualityUnqualified`)继续用于不合格品首次记录和列表查看 |
| | | - 处置操作统一使用本模块(`/qualityUnqualifiedOrder`) |
| | | - 选择"厂内维修"或"返厂维修"时,系统自动创建返修生产订单,无需手动操作 |
| | | - 返修生产订单的 `disposalMethod` 字段标记了处置方式,可在生产订单列表区分普通订单和返修订单 |
| | | - 处理单编号自动生成,前缀为 `BHG` |
| | | - 附件通过 `storageBlobDTOs` 字段上传,查询时返回 `storageBlobVOs` |