| | |
| | | :value="option.id" /> |
| | | </el-select> |
| | | </el-form-item> |
| | | <el-form-item> |
| | | <el-button @click="handleBack">返回</el-button> |
| | | </el-form-item> |
| | | </el-form> |
| | | </div> |
| | | </template> |
| | |
| | | <el-descriptions-item label="生产订单号">{{ rowData.productionOrderDto?.npsNo || '-' }}</el-descriptions-item> |
| | | <el-descriptions-item label="产品名称">{{ rowData.productionOrderDto?.productName || '-' }}</el-descriptions-item> |
| | | <el-descriptions-item label="产品规格">{{ rowData.productionOrderDto?.model || '-' }}</el-descriptions-item> |
| | | <el-descriptions-item label="物料编码">{{ rowData.productionOrderDto?.materialCode || '-' }}</el-descriptions-item> |
| | | <!-- <el-descriptions-item label="物料编码">{{ rowData.productionOrderDto?.materialCode || '-' }}</el-descriptions-item> --> |
| | | <el-descriptions-item label="计划数量">{{ rowData.productionOrderDto?.quantity || 0 }} <span class="unit">{{ rowData.productionOrderDto?.unit || '-' }}</span></el-descriptions-item> |
| | | <el-descriptions-item label="当前状态"> |
| | | <el-tag :type="getStatusType(rowData.productionOrderDto?.status)"> |
| | |
| | | </el-tag> |
| | | </el-descriptions-item> |
| | | <el-descriptions-item label="客户名称">{{ rowData.productionOrderDto?.customerName || '-' }}</el-descriptions-item> |
| | | <el-descriptions-item label="开始日期">{{ rowData.productionOrderDto?.startTime || '-' }}</el-descriptions-item> |
| | | <el-descriptions-item label="开始日期">{{ parseTime(rowData.productionOrderDto?.startTime) || '-' }}</el-descriptions-item> |
| | | <el-descriptions-item label="完成进度"> |
| | | <el-progress :percentage="rowData.productionOrderDto?.completionStatus" |
| | | <el-progress :percentage="rowData.productionOrderDto?.completionStatus>=100?100:rowData.productionOrderDto?.completionStatus" |
| | | :color="customColors(rowData.productionOrderDto?.completionStatus)" |
| | | :status="rowData.productionOrderDto?.completionStatus === 100 ? 'success' : ''" |
| | | style="width: 120px;" /> |
| | | :status="rowData.productionOrderDto?.completionStatus >= 100 ? 'success' : ''" |
| | | style="width: 80%;" /> |
| | | </el-descriptions-item> |
| | | </el-descriptions> |
| | | </div> |
| | |
| | | <el-table :data="rowData.productionRecords" |
| | | border |
| | | style="width: 100%"> |
| | | <el-table-column prop="productNo" |
| | | <el-table-column prop="workOrder.workOrderNo" |
| | | label="工单编号" |
| | | align="center"> |
| | | </el-table-column> |
| | | <el-table-column prop="productName" |
| | | label="产品名称" |
| | | align="center" /> |
| | | <el-table-column prop="model" |
| | | label="规格" |
| | | align="center" /> |
| | | <el-table-column prop="processName" |
| | | label="工序名称" |
| | | align="center" /> |
| | | <el-table-column prop="requiredQuantity" |
| | | <el-table-column label="产品名称" |
| | | align="center"> |
| | | <template #default> |
| | | {{ rowData.productionOrderDto?.productName || '-' }} |
| | | </template> |
| | | </el-table-column> |
| | | <el-table-column label="规格" |
| | | align="center"> |
| | | <template #default> |
| | | {{ rowData.productionOrderDto?.model || '-' }} |
| | | </template> |
| | | </el-table-column> |
| | | <el-table-column prop="workOrder.planQuantity" |
| | | label="需求数量" |
| | | align="center" /> |
| | | <el-table-column prop="completedQuantity" |
| | | <el-table-column prop="workOrder.completeQuantity" |
| | | label="完成数量" |
| | | align="center" /> |
| | | <el-table-column label="详情" |
| | |
| | | <div class="detail-container"> |
| | | <!-- 基础信息 --> |
| | | <div class="detail-section"> |
| | | <h3 class="section-title">基础信息</h3> |
| | | <h3 class="section-title">工单基础信息</h3> |
| | | <el-descriptions :column="3" |
| | | border> |
| | | <el-descriptions-item label="生产工单号">{{ detailData.npsNo || '-' }}</el-descriptions-item> |
| | | <el-descriptions-item label="班组"> |
| | | <el-tag :type="detailData.schedule === '白班' ? 'primary' : 'warning'">{{ detailData.schedule || '-' }}</el-tag> |
| | | <el-descriptions-item label="生产工单号">{{ detailData.workOrder.workOrderNo || '-' }}</el-descriptions-item> |
| | | <el-descriptions-item label="计划数量">{{ detailData.workOrder.planQuantity || 0 }}</el-descriptions-item> |
| | | <el-descriptions-item label="完成数量">{{ detailData.workOrder.completeQuantity || 0 }}</el-descriptions-item> |
| | | <el-descriptions-item label="实际开始时间">{{ parseTime(detailData.workOrder.actualStartTime) || '-' }}</el-descriptions-item> |
| | | <el-descriptions-item label="实际结束时间">{{ parseTime(detailData.workOrder.actualEndTime) || '-' }}</el-descriptions-item> |
| | | <el-descriptions-item label="状态"> |
| | | <el-tag :type="getStatusType(detailData.workOrder.status)">{{ getStatusText(detailData.workOrder.status) }}</el-tag> |
| | | </el-descriptions-item> |
| | | <el-descriptions-item label="产品编码">{{ detailData.materialCode || '-' }}</el-descriptions-item> |
| | | <el-descriptions-item label="产品名称">{{ detailData.productName || '-' }}</el-descriptions-item> |
| | | <el-descriptions-item label="规格">{{ detailData.model || '-' }}</el-descriptions-item> |
| | | <el-descriptions-item label="合格数量"><span class="num2">{{ detailData.qualifiedQuantity || 0 }}</span> <span class="unit">{{ detailData.unit || '-' }}</span></el-descriptions-item> |
| | | <el-descriptions-item label="不合格数量"><span class="num3">{{ detailData.unqualifiedQuantity || 0 }}</span> <span class="unit">{{ detailData.unit || '-' }}</span></el-descriptions-item> |
| | | <el-descriptions-item label="总数量"><span class="num1">{{ detailData.quantity || 0 }}</span> <span class="unit">{{ detailData.unit || '-' }}</span></el-descriptions-item> |
| | | <el-descriptions-item label="开始时间">{{ detailData.reportingTime || '-' }}</el-descriptions-item> |
| | | </el-descriptions> |
| | | </div> |
| | | <div class="detail-section"> |
| | | <h3 class="section-title">报工明细</h3> |
| | | <el-table :data="[detailData]" |
| | | <el-table :data="detailData.reports" |
| | | border |
| | | style="width: 100%"> |
| | | <el-table-column label="报工单号" |
| | | prop="productNo" |
| | | align="center" /> |
| | | <el-table-column label="产出数量" |
| | | prop="qualifiedQuantity" |
| | | align="center" /> |
| | | <el-table-column label="报废数量" |
| | | prop="unqualifiedQuantity" |
| | | <el-table-column label="创建人" |
| | | prop="userName" |
| | | align="center" /> |
| | | <el-table-column label="创建时间" |
| | | prop="reportingTime" |
| | | align="center" /> |
| | | align="center"> |
| | | <template #default="{ row }"> |
| | | {{ parseTime(row.createTime) }} |
| | | </template> |
| | | </el-table-column> |
| | | <el-table-column label="操作" |
| | | align="center" |
| | | width="200"> |
| | |
| | | :key="record.id" |
| | | class="quality-record-block"> |
| | | <div class="detail-section"> |
| | | <h3 class="section-title">检测记录 {{ index + 1 }} - {{ record.checkTime }}</h3> |
| | | <h3 class="section-title">检测记录 {{ index + 1 }} - {{ parseTime(record.createTime) }}</h3> |
| | | <el-descriptions :column="3" |
| | | border> |
| | | <el-descriptions-item label="检测日期">{{ record.checkTime || '-' }}</el-descriptions-item> |
| | | <el-descriptions-item label="生产工单号">{{ record.workOrderNo || '-' }}</el-descriptions-item> |
| | | <el-descriptions-item label="工序">{{ record.process || '-' }}</el-descriptions-item> |
| | | <el-descriptions-item label="检验员">{{ record.checkName || '-' }}</el-descriptions-item> |
| | | <el-descriptions-item label="检测日期">{{ parseTime(record.createTime) || '-' }}</el-descriptions-item> |
| | | <el-descriptions-item label="报工单号">{{ record.reportNo || '-' }}</el-descriptions-item> |
| | | <el-descriptions-item label="检验员">{{ record.userName || '-' }}</el-descriptions-item> |
| | | <el-descriptions-item label="产品名称">{{ record.productName || '-' }}</el-descriptions-item> |
| | | <el-descriptions-item label="规格型号">{{ record.model || '-' }}</el-descriptions-item> |
| | | <el-descriptions-item label="数量">{{ record.quantity || 0 }} {{ record.unit || '-' }}</el-descriptions-item> |
| | | <el-descriptions-item label="检测单位">{{ record.checkCompany || '-' }}</el-descriptions-item> |
| | | <el-descriptions-item label="检测结果"> |
| | | <el-tag :type="record.checkResult === '合格' ? 'success' : 'danger'"> |
| | | {{ record.checkResult || '-' }} |
| | | {{ record.checkResult || '待检测' }} |
| | | </el-tag> |
| | | </el-descriptions-item> |
| | | </el-descriptions> |
| | | <h4 class="sub-section-title">检验指标列表</h4> |
| | | <el-table :data="record.inspectItems" |
| | | <el-table :data="record.inspectParamList" |
| | | border |
| | | style="width: 100%"> |
| | | <el-table-column label="序号" |
| | |
| | | width="60" |
| | | align="center" /> |
| | | <el-table-column label="指标" |
| | | prop="itemName" |
| | | prop="paramName" |
| | | align="center" /> |
| | | <el-table-column label="单位" |
| | | prop="unit" |
| | |
| | | <el-table-column label="标准值" |
| | | prop="standardValue" |
| | | align="center" /> |
| | | <el-table-column label="内控值" |
| | | prop="controlValue" |
| | | align="center" /> |
| | | <el-table-column label="实际值" |
| | | prop="actualValue" |
| | | prop="inputValue" |
| | | align="center" /> |
| | | </el-table> |
| | | </div> |
| | | <!-- <div class="detail-section"> |
| | | |
| | | </div> --> |
| | | <el-divider v-if="index < qualityRecords.length - 1" /> |
| | | </div> |
| | | </div> |
| | |
| | | import { ref, reactive, onMounted } from "vue"; |
| | | import { useRoute, useRouter } from "vue-router"; |
| | | import { ElMessage } from "element-plus"; |
| | | import { parseTime } from "@/utils/ruoyi"; |
| | | import InputModal from "@/views/productionManagement/productionReporting/Input.vue"; |
| | | import { |
| | | getOrderDetail, |
| | | productOrderListPage, |
| | | } from "@/api/productionManagement/productionOrder"; |
| | | |
| | | const route = useRoute(); |
| | | const router = useRouter(); |
| | |
| | | }); |
| | | const selectedNpsNo = ref(null); |
| | | const npsNoLoading = ref(false); |
| | | const npsNoOptions = ref([ |
| | | { |
| | | id: 1, |
| | | npsNo: "PO20240301001", |
| | | productName: "精密液压缸", |
| | | model: "HG-100/50-500", |
| | | materialCode: "MAT-2024-001", |
| | | quantity: 500, |
| | | unit: "件", |
| | | status: 1, |
| | | customerName: "重工机械有限公司", |
| | | startTime: "2024-03-01", |
| | | completionStatus: 65, |
| | | }, |
| | | { |
| | | id: 2, |
| | | npsNo: "PO20240301002", |
| | | productName: "工业伺服电机", |
| | | model: "SV-400W-3000", |
| | | materialCode: "MAT-2024-002", |
| | | quantity: 200, |
| | | unit: "台", |
| | | status: 2, |
| | | customerName: "自动化设备科技公司", |
| | | startTime: "2024-03-02", |
| | | completionStatus: 100, |
| | | }, |
| | | { |
| | | id: 3, |
| | | npsNo: "PO20240301003", |
| | | productName: "高压密封圈", |
| | | model: "SR-80-5", |
| | | materialCode: "MAT-2024-003", |
| | | quantity: 5000, |
| | | unit: "个", |
| | | status: 0, |
| | | customerName: "密封系统配件厂", |
| | | startTime: "2024-03-05", |
| | | completionStatus: 0, |
| | | }, |
| | | ]); |
| | | const npsNoOptions = ref([]); |
| | | |
| | | // 详情数据 |
| | | const rowData = reactive({ |
| | |
| | | |
| | | // 报工详情弹窗 |
| | | const detailDialogVisible = ref(false); |
| | | const detailData = ref({}); |
| | | const detailData = ref({ |
| | | workOrder: {}, |
| | | reports: [], |
| | | }); |
| | | |
| | | // 投入模态框 |
| | | const isShowInput = ref(false); |
| | |
| | | |
| | | // 状态处理 |
| | | const getStatusType = status => { |
| | | const typeMap = { 0: "info", 1: "primary", 2: "success" }; |
| | | const typeMap = { 1: "primary", 2: "warning", 3: "success", 5: "danger" }; |
| | | return typeMap[status] || "info"; |
| | | }; |
| | | const getStatusText = status => { |
| | | const statusMap = { 0: "未开始", 1: "生产中", 2: "已完成" }; |
| | | return statusMap[status] || "未知"; |
| | | const statusMap = { 1: "待开始", 2: "进行中", 3: "已完成", 5: "已结束" }; |
| | | return statusMap[status] || "已取消"; |
| | | }; |
| | | const customColors = percentage => { |
| | | if (percentage < 30) return "#f56c6c"; |
| | |
| | | }; |
| | | |
| | | // 模拟搜索方法 |
| | | const handleNpsNoSearch = query => { |
| | | if (query) { |
| | | npsNoLoading.value = true; |
| | | setTimeout(() => { |
| | | npsNoLoading.value = false; |
| | | }, 300); |
| | | const handleNpsNoSearch = async query => { |
| | | npsNoLoading.value = true; |
| | | try { |
| | | const res = await productOrderListPage({ |
| | | npsNo: query || "", |
| | | pageNum: 1, |
| | | pageSize: 50, |
| | | }); |
| | | // 参照 productionOrder/index.vue 的数据结构 res.data.records |
| | | npsNoOptions.value = res.data?.records || res.rows || []; |
| | | } catch (error) { |
| | | console.error(error); |
| | | } finally { |
| | | npsNoLoading.value = false; |
| | | } |
| | | }; |
| | | |
| | | const handleSearch = id => { |
| | | const handleSearch = async id => { |
| | | const selected = npsNoOptions.value.find(item => item.id === id); |
| | | if (selected) { |
| | | rowData.productionOrderDto = selected; |
| | | rowData.productionRecords = [ |
| | | { |
| | | id: 1001, |
| | | productNo: "MO-2024-001-01", |
| | | productName: selected.productName, |
| | | model: selected.model, |
| | | processName: "毛坯加工", |
| | | requiredQuantity: selected.quantity, |
| | | completedQuantity: Math.floor(selected.quantity * 0.4), |
| | | qualifiedQuantity: Math.floor(selected.quantity * 0.4) - 2, |
| | | unqualifiedQuantity: 2, |
| | | reportingTime: "2024-03-01 10:00:00", |
| | | schedule: "白班", |
| | | postName: "张三", |
| | | unit: selected.unit, |
| | | }, |
| | | { |
| | | id: 1002, |
| | | productNo: "MO-2024-001-02", |
| | | productName: selected.productName, |
| | | model: selected.model, |
| | | processName: "精加工", |
| | | requiredQuantity: Math.floor(selected.quantity * 0.4), |
| | | completedQuantity: Math.floor(selected.quantity * 0.25), |
| | | qualifiedQuantity: Math.floor(selected.quantity * 0.25), |
| | | unqualifiedQuantity: 0, |
| | | reportingTime: "2024-03-01 16:00:00", |
| | | schedule: "白班", |
| | | postName: "李四", |
| | | unit: selected.unit, |
| | | }, |
| | | ]; |
| | | try { |
| | | const res = await getOrderDetail(selected.npsNo); |
| | | if (res.code === 200) { |
| | | const { productionOrder, workOrderList } = res.data; |
| | | rowData.productionOrderDto = productionOrder || selected; |
| | | rowData.productionRecords = workOrderList || []; |
| | | } else { |
| | | rowData.productionOrderDto = selected; |
| | | rowData.productionRecords = []; |
| | | } |
| | | } catch (error) { |
| | | console.error(error); |
| | | ElMessage.error("获取订单详情失败"); |
| | | rowData.productionOrderDto = selected; |
| | | } |
| | | } |
| | | }; |
| | | |
| | |
| | | }; |
| | | |
| | | const handleClickStep = row => { |
| | | // row 是 workOrderList 中的一项,包含 workOrder, reportList, inspectList |
| | | detailData.value = { |
| | | id: row.id || Math.floor(Math.random() * 1000), |
| | | productNo: row.productNo, |
| | | npsNo: rowData.productionOrderDto.npsNo, |
| | | schedule: row.schedule, |
| | | postName: row.postName, |
| | | materialCode: rowData.productionOrderDto.materialCode, |
| | | productName: row.productName, |
| | | model: row.model, |
| | | qualifiedQuantity: row.qualifiedQuantity, |
| | | unqualifiedQuantity: row.unqualifiedQuantity || 0, |
| | | quantity: row.completedQuantity, |
| | | unit: row.unit, |
| | | reportingTime: row.reportingTime, |
| | | productionOperationParamList: [ |
| | | { id: 1, paramName: "主轴转速", inputValue: "2400", unit: "rpm" }, |
| | | { id: 2, paramName: "进给速度", inputValue: "120", unit: "mm/min" }, |
| | | { id: 3, paramName: "切削深度", inputValue: "0.5", unit: "mm" }, |
| | | { id: 4, paramName: "冷却液压力", inputValue: "0.6", unit: "Mpa" }, |
| | | ], |
| | | workOrder: row.workOrder || {}, |
| | | reports: (row.reportList || []).map(r => ({ |
| | | ...r.reportMain, |
| | | productionOperationParamList: r.reportParamList || [], |
| | | })), |
| | | }; |
| | | detailDialogVisible.value = true; |
| | | }; |
| | | |
| | | const handleClickQuality = row => { |
| | | qualityRecords.value = [ |
| | | { |
| | | id: 2001, |
| | | checkTime: "2024-03-01 11:30:00", |
| | | workOrderNo: row.productNo, |
| | | process: row.processName, |
| | | checkName: "质量部-王建国", |
| | | productName: row.productName, |
| | | model: row.model, |
| | | unit: row.unit, |
| | | quantity: row.completedQuantity, |
| | | checkCompany: "内部实验室", |
| | | checkResult: "合格", |
| | | inspectItems: [ |
| | | { |
| | | id: 1, |
| | | itemName: "外径尺寸", |
| | | unit: "mm", |
| | | standardValue: "100.00±0.05", |
| | | controlValue: "100.00±0.03", |
| | | actualValue: "100.01", |
| | | result: "合格", |
| | | }, |
| | | { |
| | | id: 2, |
| | | itemName: "内径尺寸", |
| | | unit: "mm", |
| | | standardValue: "50.00+0.02/-0", |
| | | controlValue: "50.00+0.01/-0", |
| | | actualValue: "50.01", |
| | | result: "合格", |
| | | }, |
| | | { |
| | | id: 3, |
| | | itemName: "表面粗糙度", |
| | | unit: "Ra", |
| | | standardValue: "≤1.6", |
| | | controlValue: "≤1.2", |
| | | actualValue: "0.8", |
| | | result: "合格", |
| | | }, |
| | | ], |
| | | }, |
| | | { |
| | | id: 2001, |
| | | checkTime: "2024-03-01 11:30:00", |
| | | workOrderNo: row.productNo, |
| | | process: row.processName, |
| | | checkName: "质量部-王建国", |
| | | productName: row.productName, |
| | | model: row.model, |
| | | unit: row.unit, |
| | | quantity: row.completedQuantity, |
| | | checkCompany: "内部实验室", |
| | | checkResult: "合格", |
| | | inspectItems: [ |
| | | { |
| | | id: 1, |
| | | itemName: "外径尺寸", |
| | | unit: "mm", |
| | | standardValue: "100.00±0.05", |
| | | controlValue: "100.00±0.03", |
| | | actualValue: "100.01", |
| | | result: "合格", |
| | | }, |
| | | { |
| | | id: 2, |
| | | itemName: "内径尺寸", |
| | | unit: "mm", |
| | | standardValue: "50.00+0.02/-0", |
| | | controlValue: "50.00+0.01/-0", |
| | | actualValue: "50.01", |
| | | result: "合格", |
| | | }, |
| | | { |
| | | id: 3, |
| | | itemName: "表面粗糙度", |
| | | unit: "Ra", |
| | | standardValue: "≤1.6", |
| | | controlValue: "≤1.2", |
| | | actualValue: "0.8", |
| | | result: "合格", |
| | | }, |
| | | ], |
| | | }, |
| | | ]; |
| | | // row 是 workOrderList 中的一项 |
| | | const inspects = row.inspectList || []; |
| | | qualityRecords.value = inspects.map(i => ({ |
| | | ...i.inspect, |
| | | reportNo: i.reportNo, |
| | | userName: i.reportMain?.userName || "-", |
| | | inspectParamList: i.inspectParamList || [], |
| | | inspectFileList: i.inspectFileList || [], |
| | | })); |
| | | qualityDialogVisible.value = true; |
| | | }; |
| | | |
| | | onMounted(() => { |
| | | onMounted(async () => { |
| | | // 初始加载列表 |
| | | await handleNpsNoSearch(); |
| | | |
| | | if (route.query.npsNo) { |
| | | const npsNo = route.query.npsNo; |
| | | const found = npsNoOptions.value.find(item => item.npsNo === npsNo); |
| | |
| | | selectedNpsNo.value = found.id; |
| | | handleSearch(found.id); |
| | | } else { |
| | | // 如果没找到,创建一个临时的 |
| | | const mockItem = { |
| | | id: Date.now(), |
| | | npsNo: npsNo, |
| | | productName: route.query.productName || "精密液压缸", |
| | | model: route.query.model || "HG-100/50-500", |
| | | materialCode: "MAT-2024-MOCK", |
| | | quantity: 100, |
| | | unit: "件", |
| | | status: 1, |
| | | customerName: "模拟客户", |
| | | startTime: "2024-03-01", |
| | | completionStatus: 50, |
| | | }; |
| | | npsNoOptions.value.push(mockItem); |
| | | selectedNpsNo.value = mockItem.id; |
| | | handleSearch(mockItem.id); |
| | | // 如果列表中没有(可能是分页原因),则根据 npsNo 再次精准搜索 |
| | | try { |
| | | const res = await productOrderListPage({ |
| | | npsNo, |
| | | pageNum: -1, |
| | | pageSize: -1, |
| | | }); |
| | | const records = res.data?.records || res.rows || []; |
| | | if (records.length > 0) { |
| | | const item = records[0]; |
| | | npsNoOptions.value.unshift(item); |
| | | selectedNpsNo.value = item.id; |
| | | handleSearch(item.id); |
| | | } |
| | | } catch (error) { |
| | | console.error("获取路由参数对应的订单失败", error); |
| | | } |
| | | } |
| | | } |
| | | }); |