parent
01907553a0
commit
5893e95e75
@ -0,0 +1,315 @@
|
||||
export const productqcInfo = {
|
||||
qcCode: 'QC20260315001',
|
||||
batchCode: 'FB20260315001',
|
||||
productCode: 'PRD-20260301',
|
||||
productName: '12R22.5 18PR 全钢子午线轮胎',
|
||||
spec: '12R22.5 18PR PT67',
|
||||
qcTime: '2026-03-15 14:30:00',
|
||||
qcType: '成品检验',
|
||||
inspector: '张伟',
|
||||
result: '合格',
|
||||
checkItems: [
|
||||
{ itemName: '外观检验', standard: '无气泡、无杂质、表面光洁', actual: '符合要求', result: '合格' },
|
||||
{ itemName: '尺寸检验', standard: '直径 1084±10mm', actual: '1082mm', result: '合格' },
|
||||
{ itemName: '重量检验', standard: '65±2kg', actual: '64.8kg', result: '合格' },
|
||||
{ itemName: '动平衡', standard: '≤500g·cm', actual: '380g·cm', result: '合格' },
|
||||
{ itemName: '硬度检验', standard: '60-70 Shore A', actual: '65 Shore A', result: '合格' }
|
||||
]
|
||||
};
|
||||
|
||||
export const customerInfo = {
|
||||
hasOutbound: true,
|
||||
data: {
|
||||
customerCode: 'CUST-001',
|
||||
customerName: '北京轮胎商贸有限公司',
|
||||
contactPerson: '王经理',
|
||||
contactPhone: '010-12345678',
|
||||
deliveryAddress: '北京市朝阳区轮胎路88号',
|
||||
outboundTime: '2026-03-16 09:30:00',
|
||||
outboundQty: 100,
|
||||
invoiceNo: 'INV20260316001'
|
||||
}
|
||||
};
|
||||
|
||||
export const customerInfoNoOutbound = {
|
||||
hasOutbound: false,
|
||||
data: null
|
||||
};
|
||||
|
||||
export const productionOrderInfo = {
|
||||
orderCode: 'PO20260315001',
|
||||
batchCode: 'FB20260315001',
|
||||
productCode: 'PRD-20260301',
|
||||
productName: '12R22.5 18PR 全钢子午线轮胎',
|
||||
dispatchType: 1,
|
||||
dispatchTypeName: '产线',
|
||||
dispatchInfo: 'CX-Line01',
|
||||
planQty: 1000,
|
||||
dispatchedQty: 1000,
|
||||
completedQty: 980,
|
||||
startTime: '2026-03-15 08:00:00',
|
||||
endTime: '2026-03-15 20:00:00',
|
||||
status: '已完成'
|
||||
};
|
||||
|
||||
export const workOrderInfoList = [
|
||||
{
|
||||
workOrderCode: 'WO20260315001',
|
||||
processSeq: 1,
|
||||
processCode: 'PROC001',
|
||||
processName: '密炼',
|
||||
machineNo: 'ML-001',
|
||||
machineName: '密炼机1号',
|
||||
startTime: '2026-03-15 08:00:00',
|
||||
endTime: '2026-03-15 10:30:00',
|
||||
worker: '李明',
|
||||
status: '已完成'
|
||||
},
|
||||
{
|
||||
workOrderCode: 'WO20260315002',
|
||||
processSeq: 2,
|
||||
processCode: 'PROC002',
|
||||
processName: '混炼',
|
||||
machineNo: 'HX-002',
|
||||
machineName: '混炼机2号',
|
||||
startTime: '2026-03-15 10:30:00',
|
||||
endTime: '2026-03-15 12:00:00',
|
||||
worker: '王强',
|
||||
status: '已完成'
|
||||
},
|
||||
{
|
||||
workOrderCode: 'WO20260315003',
|
||||
processSeq: 3,
|
||||
processCode: 'PROC003',
|
||||
processName: '压延',
|
||||
machineNo: 'YY-003',
|
||||
machineName: '压延机3号',
|
||||
startTime: '2026-03-15 12:00:00',
|
||||
endTime: '2026-03-15 14:00:00',
|
||||
worker: '赵丽',
|
||||
status: '已完成'
|
||||
},
|
||||
{
|
||||
workOrderCode: 'WO20260315004',
|
||||
processSeq: 4,
|
||||
processCode: 'PROC004',
|
||||
processName: '成型',
|
||||
machineNo: 'CX-401',
|
||||
machineName: '成型机401',
|
||||
startTime: '2026-03-15 14:00:00',
|
||||
endTime: '2026-03-15 17:00:00',
|
||||
worker: '陈刚',
|
||||
status: '已完成'
|
||||
},
|
||||
{
|
||||
workOrderCode: 'WO20260315005',
|
||||
processSeq: 5,
|
||||
processCode: 'PROC005',
|
||||
processName: '硫化',
|
||||
machineNo: 'LH-101',
|
||||
machineName: '硫化机101',
|
||||
startTime: '2026-03-15 17:00:00',
|
||||
endTime: '2026-03-15 18:30:00',
|
||||
worker: '周磊',
|
||||
status: '已完成'
|
||||
}
|
||||
];
|
||||
|
||||
const materialInputsMap = {
|
||||
'WO20260315001': [
|
||||
{
|
||||
materialCode: 'MAT-NR-001',
|
||||
materialName: '天然橡胶NR',
|
||||
batchCode: 'NR20260301001',
|
||||
supplier: '泰国罗实橡胶',
|
||||
qty: 500,
|
||||
unit: 'kg',
|
||||
inTime: '2026-03-15 08:05:00',
|
||||
qcCode: 'QC-MAT-001',
|
||||
qcResult: '合格',
|
||||
checkItems: [
|
||||
{ itemName: '杂质含量', standard: '≤0.05%', actual: '0.02%', result: '合格' },
|
||||
{ itemName: '水分含量', standard: '≤0.8%', actual: '0.5%', result: '合格' },
|
||||
{ itemName: '灰分含量', standard: '≤0.5%', actual: '0.3%', result: '合格' }
|
||||
]
|
||||
},
|
||||
{
|
||||
materialCode: 'MAT-CB-002',
|
||||
materialName: '炭黑N330',
|
||||
batchCode: 'CB20260302001',
|
||||
supplier: '卡博特中国',
|
||||
qty: 300,
|
||||
unit: 'kg',
|
||||
inTime: '2026-03-15 08:10:00',
|
||||
qcCode: 'QC-MAT-002',
|
||||
qcResult: '合格',
|
||||
checkItems: [
|
||||
{ itemName: '粒径分布', standard: '26-35nm', actual: '30nm', result: '合格' },
|
||||
{ itemName: 'DBP吸油值', standard: '100-120ml/100g', actual: '108ml/100g', result: '合格' },
|
||||
{ itemName: 'pH值', standard: '7-10', actual: '8.5', result: '合格' }
|
||||
]
|
||||
},
|
||||
{
|
||||
materialCode: 'MAT-SI-003',
|
||||
materialName: '二氧化硅',
|
||||
batchCode: 'SI20260303001',
|
||||
supplier: '赢创中国',
|
||||
qty: 150,
|
||||
unit: 'kg',
|
||||
inTime: '2026-03-15 08:15:00',
|
||||
qcCode: 'QC-MAT-003',
|
||||
qcResult: '合格',
|
||||
checkItems: [
|
||||
{ itemName: '比表面积', standard: '170-200m²/g', actual: '185m²/g', result: '合格' },
|
||||
{ itemName: '水分含量', standard: '≤6%', actual: '4.2%', result: '合格' },
|
||||
{ itemName: 'pH值', standard: '5-8', actual: '6.5', result: '合格' }
|
||||
]
|
||||
}
|
||||
],
|
||||
'WO20260315002': [
|
||||
{
|
||||
materialCode: 'MAT-MB-001',
|
||||
materialName: '母炼胶',
|
||||
batchCode: 'MB20260315001',
|
||||
supplier: '内部供应',
|
||||
qty: 950,
|
||||
unit: 'kg',
|
||||
inTime: '2026-03-15 10:35:00',
|
||||
qcCode: 'QC-MAT-INTERNAL-001',
|
||||
qcResult: '合格',
|
||||
checkItems: [
|
||||
{ itemName: '可塑度', standard: '0.40-0.55', actual: '0.48', result: '合格' },
|
||||
{ itemName: '门尼粘度', standard: '45-65', actual: '55', result: '合格' }
|
||||
]
|
||||
},
|
||||
{
|
||||
materialCode: 'MAT-ZN-004',
|
||||
materialName: '氧化锌',
|
||||
batchCode: 'ZN20260304001',
|
||||
supplier: '柳州锌品',
|
||||
qty: 25,
|
||||
unit: 'kg',
|
||||
inTime: '2026-03-15 10:40:00',
|
||||
qcCode: 'QC-MAT-004',
|
||||
qcResult: '合格',
|
||||
checkItems: [
|
||||
{ itemName: '主含量', standard: '≥99%', actual: '99.5%', result: '合格' },
|
||||
{ itemName: '重金属', standard: '≤0.001%', actual: '0.0005%', result: '合格' }
|
||||
]
|
||||
},
|
||||
{
|
||||
materialCode: 'MAT-SA-005',
|
||||
materialName: '硬脂酸',
|
||||
batchCode: 'SA20260305001',
|
||||
supplier: '益海嘉里',
|
||||
qty: 15,
|
||||
unit: 'kg',
|
||||
inTime: '2026-03-15 10:42:00',
|
||||
qcCode: 'QC-MAT-005',
|
||||
qcResult: '合格',
|
||||
checkItems: [
|
||||
{ itemName: '酸值', standard: '195-210mgKOH/g', actual: '202mgKOH/g', result: '合格' },
|
||||
{ itemName: '水分', standard: '≤0.2%', actual: '0.1%', result: '合格' }
|
||||
]
|
||||
}
|
||||
],
|
||||
'WO20260315003': [
|
||||
{
|
||||
materialCode: 'MAT-HM-002',
|
||||
materialName: '混炼胶',
|
||||
batchCode: 'HM20260315002',
|
||||
supplier: '内部供应',
|
||||
qty: 980,
|
||||
unit: 'kg',
|
||||
inTime: '2026-03-15 12:05:00',
|
||||
qcCode: 'QC-MAT-INTERNAL-002',
|
||||
qcResult: '合格',
|
||||
checkItems: [
|
||||
{ itemName: '可塑度', standard: '0.40-0.55', actual: '0.46', result: '合格' },
|
||||
{ itemName: '硬度', standard: '60-70 Shore A', actual: '65 Shore A', result: '合格' }
|
||||
]
|
||||
}
|
||||
],
|
||||
'WO20260315004': [
|
||||
{
|
||||
materialCode: 'MAT-YY-003',
|
||||
materialName: '压延胶片',
|
||||
batchCode: 'YY20260315003',
|
||||
supplier: '内部供应',
|
||||
qty: 450,
|
||||
unit: 'kg',
|
||||
inTime: '2026-03-15 14:05:00',
|
||||
qcCode: 'QC-MAT-INTERNAL-003',
|
||||
qcResult: '合格',
|
||||
checkItems: [
|
||||
{ itemName: '厚度', standard: '2.0±0.2mm', actual: '2.02mm', result: '合格' },
|
||||
{ itemName: '宽度', standard: '800±10mm', actual: '798mm', result: '合格' }
|
||||
]
|
||||
},
|
||||
{
|
||||
materialCode: 'MAT-SF-006',
|
||||
materialName: '钢丝帘线',
|
||||
batchCode: 'SF20260306001',
|
||||
supplier: '贝卡尔特',
|
||||
qty: 80,
|
||||
unit: 'kg',
|
||||
inTime: '2026-03-15 14:10:00',
|
||||
qcCode: 'QC-MAT-006',
|
||||
qcResult: '合格',
|
||||
checkItems: [
|
||||
{ itemName: '抗拉强度', standard: '≥2800MPa', actual: '2950MPa', result: '合格' },
|
||||
{ itemName: '镀层重量', standard: '≥60g/kg', actual: '65g/kg', result: '合格' }
|
||||
]
|
||||
}
|
||||
],
|
||||
'WO20260315005': [
|
||||
{
|
||||
materialCode: 'MAT-CX-004',
|
||||
materialName: '成型半成品',
|
||||
batchCode: 'CX20260315004',
|
||||
supplier: '内部供应',
|
||||
qty: 1,
|
||||
unit: '条',
|
||||
inTime: '2026-03-15 17:05:00',
|
||||
qcCode: 'QC-MAT-INTERNAL-004',
|
||||
qcResult: '合格',
|
||||
checkItems: [
|
||||
{ itemName: '外观检验', standard: '无气泡、无杂质', actual: '符合要求', result: '合格' },
|
||||
{ itemName: '重量', standard: '65±2kg', actual: '64.8kg', result: '合格' }
|
||||
]
|
||||
}
|
||||
]
|
||||
};
|
||||
|
||||
export const getMaterialInputsByWorkOrder = (workOrderCode) => {
|
||||
return new Promise((resolve) => {
|
||||
setTimeout(() => {
|
||||
resolve({
|
||||
code: 200,
|
||||
message: 'success',
|
||||
data: materialInputsMap[workOrderCode] || []
|
||||
});
|
||||
}, 300);
|
||||
});
|
||||
};
|
||||
|
||||
export const reverseTraceByBatch = (batchCode) => {
|
||||
return {
|
||||
code: 200,
|
||||
message: 'success',
|
||||
data: {
|
||||
productInfo: {
|
||||
batchCode: batchCode || 'FB20260315001',
|
||||
productCode: 'PRD-20260301',
|
||||
productName: '12R22.5 18PR 全钢子午线轮胎',
|
||||
spec: '12R22.5 18PR PT67',
|
||||
productionDate: '2026-03-15',
|
||||
status: '已入库'
|
||||
},
|
||||
qcInfo: productqcInfo,
|
||||
customerInfo: customerInfo,
|
||||
productionOrder: productionOrderInfo,
|
||||
workOrderList: workOrderInfoList
|
||||
}
|
||||
};
|
||||
};
|
||||
@ -0,0 +1,463 @@
|
||||
<template>
|
||||
<div class="reverse-trace-container">
|
||||
<el-card class="query-card" shadow="never">
|
||||
<el-form :model="queryParams" :inline="true" label-width="100px">
|
||||
<el-form-item label="成品批次码">
|
||||
<el-input
|
||||
v-model="queryParams.batchCode"
|
||||
placeholder="扫描或输入成品批次码"
|
||||
clearable
|
||||
style="width: 280px"
|
||||
@keyup.enter="handleQuery"
|
||||
>
|
||||
<template #append>
|
||||
<el-button icon="Scan" @click="handleScan" />
|
||||
</template>
|
||||
</el-input>
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<el-button type="primary" icon="Search" @click="handleQuery">追溯</el-button>
|
||||
<el-button icon="Refresh" @click="resetQuery">重置</el-button>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
</el-card>
|
||||
|
||||
<div v-if="traceData" class="trace-content">
|
||||
<el-row :gutter="10">
|
||||
<el-col :span="24">
|
||||
<el-card shadow="hover" class="product-info-card">
|
||||
<template #header>
|
||||
<span class="card-title">成品信息</span>
|
||||
</template>
|
||||
<el-descriptions :column="4" border size="small">
|
||||
<el-descriptions-item label="批次码">{{ traceData.productInfo.batchCode }}</el-descriptions-item>
|
||||
<el-descriptions-item label="产品编码">{{ traceData.productInfo.productCode }}</el-descriptions-item>
|
||||
<el-descriptions-item label="产品名称">{{ traceData.productInfo.productName }}</el-descriptions-item>
|
||||
<el-descriptions-item label="规格">{{ traceData.productInfo.spec }}</el-descriptions-item>
|
||||
<el-descriptions-item label="生产日期">{{ traceData.productInfo.productionDate }}</el-descriptions-item>
|
||||
<el-descriptions-item label="状态">
|
||||
<el-tag :type="traceData.productInfo.status === '已入库' ? 'success' : 'info'">
|
||||
{{ traceData.productInfo.status }}
|
||||
</el-tag>
|
||||
</el-descriptions-item>
|
||||
</el-descriptions>
|
||||
</el-card>
|
||||
</el-col>
|
||||
</el-row>
|
||||
|
||||
<el-row :gutter="10" class="mt-2" v-if="traceData.customerInfo && traceData.customerInfo.hasOutbound">
|
||||
<el-col :span="24">
|
||||
<el-card shadow="hover">
|
||||
<template #header>
|
||||
<span class="card-title">客户信息</span>
|
||||
</template>
|
||||
<el-descriptions :column="4" border size="small">
|
||||
<el-descriptions-item label="客户编码">{{ traceData.customerInfo.data.customerCode }}</el-descriptions-item>
|
||||
<el-descriptions-item label="客户名称">{{ traceData.customerInfo.data.customerName }}</el-descriptions-item>
|
||||
<el-descriptions-item label="联系人">{{ traceData.customerInfo.data.contactPerson }}</el-descriptions-item>
|
||||
<el-descriptions-item label="联系电话">{{ traceData.customerInfo.data.contactPhone }}</el-descriptions-item>
|
||||
<el-descriptions-item label="交货地址" :span="2">{{ traceData.customerInfo.data.deliveryAddress }}</el-descriptions-item>
|
||||
<el-descriptions-item label="出库时间">{{ traceData.customerInfo.data.outboundTime }}</el-descriptions-item>
|
||||
<el-descriptions-item label="出库数量">{{ traceData.customerInfo.data.outboundQty }}</el-descriptions-item>
|
||||
</el-descriptions>
|
||||
</el-card>
|
||||
</el-col>
|
||||
</el-row>
|
||||
|
||||
<el-row :gutter="10" class="mt-2">
|
||||
<el-col :span="24">
|
||||
<el-card shadow="hover">
|
||||
<template #header>
|
||||
<span class="card-title">质检信息</span>
|
||||
</template>
|
||||
<el-descriptions :column="4" border size="small" class="mb-3">
|
||||
<el-descriptions-item label="质检单号">{{ traceData.qcInfo.qcCode }}</el-descriptions-item>
|
||||
<el-descriptions-item label="批次码">{{ traceData.qcInfo.batchCode }}</el-descriptions-item>
|
||||
<el-descriptions-item label="质检时间">{{ traceData.qcInfo.qcTime }}</el-descriptions-item>
|
||||
<el-descriptions-item label="质检类型">{{ traceData.qcInfo.qcType }}</el-descriptions-item>
|
||||
<el-descriptions-item label="质检员">{{ traceData.qcInfo.inspector }}</el-descriptions-item>
|
||||
<el-descriptions-item label="结果">
|
||||
<el-tag :type="traceData.qcInfo.result === '合格' ? 'success' : 'danger'">
|
||||
{{ traceData.qcInfo.result }}
|
||||
</el-tag>
|
||||
</el-descriptions-item>
|
||||
</el-descriptions>
|
||||
<el-table :data="traceData.qcInfo.checkItems" border size="small" max-height="200">
|
||||
<el-table-column prop="itemName" label="检验项目" min-width="120" />
|
||||
<el-table-column prop="standard" label="标准" min-width="180" show-overflow-tooltip />
|
||||
<el-table-column prop="actual" label="实际值" min-width="120" />
|
||||
<el-table-column prop="result" label="结果" min-width="80" align="center">
|
||||
<template #default="{ row }">
|
||||
<el-tag :type="row.result === '合格' ? 'success' : 'danger'" size="small">
|
||||
{{ row.result }}
|
||||
</el-tag>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
</el-card>
|
||||
</el-col>
|
||||
</el-row>
|
||||
|
||||
<el-row :gutter="10" class="mt-2">
|
||||
<el-col :span="24">
|
||||
<el-card shadow="hover">
|
||||
<template #header>
|
||||
<span class="card-title">生产订单信息</span>
|
||||
</template>
|
||||
<el-descriptions :column="4" border size="small">
|
||||
<el-descriptions-item label="订单号">{{ traceData.productionOrder.orderCode }}</el-descriptions-item>
|
||||
<el-descriptions-item label="批次码">{{ traceData.productionOrder.batchCode }}</el-descriptions-item>
|
||||
<el-descriptions-item label="产品名称">{{ traceData.productionOrder.productName }}</el-descriptions-item>
|
||||
<el-descriptions-item label="派工类型">
|
||||
{{ traceData.productionOrder.dispatchType }} - {{ traceData.productionOrder.dispatchTypeName }}
|
||||
</el-descriptions-item>
|
||||
<el-descriptions-item label="派工信息">{{ traceData.productionOrder.dispatchInfo }}</el-descriptions-item>
|
||||
<el-descriptions-item label="计划数量">{{ traceData.productionOrder.planQty }}</el-descriptions-item>
|
||||
<el-descriptions-item label="已派工数量">{{ traceData.productionOrder.dispatchedQty }}</el-descriptions-item>
|
||||
<el-descriptions-item label="完成数量">{{ traceData.productionOrder.completedQty }}</el-descriptions-item>
|
||||
<el-descriptions-item label="开始时间">{{ traceData.productionOrder.startTime }}</el-descriptions-item>
|
||||
<el-descriptions-item label="完成时间">{{ traceData.productionOrder.endTime }}</el-descriptions-item>
|
||||
<el-descriptions-item label="订单状态">
|
||||
<el-tag :type="traceData.productionOrder.status === '已完成' ? 'success' : 'warning'" size="small">
|
||||
{{ traceData.productionOrder.status }}
|
||||
</el-tag>
|
||||
</el-descriptions-item>
|
||||
</el-descriptions>
|
||||
</el-card>
|
||||
</el-col>
|
||||
</el-row>
|
||||
|
||||
<el-row :gutter="10" class="mt-2">
|
||||
<el-col :span="24">
|
||||
<el-card shadow="hover">
|
||||
<template #header>
|
||||
<span class="card-title">生产工单信息</span>
|
||||
</template>
|
||||
<el-table ref="workOrderTableRef" :data="traceData.workOrderList" border size="small" max-height="400" row-key="workOrderCode" :expand-row-keys="expandedRowKeys" @expand-change="handleExpandChange">
|
||||
<el-table-column type="expand" width="50" align="center">
|
||||
<template #default="{ row }">
|
||||
<div class="expand-content" v-if="row.materialInputs">
|
||||
<el-table :data="row.materialInputs" border size="small" class="material-input-table" v-loading="row.loading">
|
||||
<el-table-column prop="materialCode" label="物料编码" min-width="120" />
|
||||
<el-table-column prop="materialName" label="物料名称" min-width="150" />
|
||||
<el-table-column prop="batchCode" label="批次码" min-width="140" />
|
||||
<el-table-column prop="supplier" label="供应商" min-width="150" show-overflow-tooltip />
|
||||
<el-table-column prop="qty" label="投料数量" min-width="100" align="right" />
|
||||
<el-table-column prop="unit" label="单位" min-width="60" align="center" />
|
||||
<el-table-column prop="inTime" label="投料时间" min-width="160" />
|
||||
<el-table-column prop="qcCode" label="质检单号" min-width="120" />
|
||||
<el-table-column prop="qcResult" label="质检结果" min-width="90" align="center">
|
||||
<template #default="{ row: materialRow }">
|
||||
<el-tag :type="materialRow.qcResult === '合格' ? 'success' : 'danger'" size="small">
|
||||
{{ materialRow.qcResult }}
|
||||
</el-tag>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="操作" width="80" align="center">
|
||||
<template #default="{ row: materialRow }">
|
||||
<el-button type="primary" link size="small" @click="showMaterialQcDetail(materialRow)">
|
||||
检验明细
|
||||
</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
</div>
|
||||
<div v-else class="expand-loading">
|
||||
<el-icon class="el-icon-loading"><Loading /></el-icon>
|
||||
<span>加载中...</span>
|
||||
</div>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="processSeq" label="工序序号" width="90" align="center" />
|
||||
<el-table-column prop="workOrderCode" label="工单编码" min-width="130" />
|
||||
<el-table-column prop="processCode" label="工序编码" min-width="100" />
|
||||
<el-table-column prop="processName" label="工序名称" min-width="100" />
|
||||
<el-table-column prop="machineNo" label="机台编号" min-width="100" />
|
||||
<el-table-column prop="machineName" label="机台名称" min-width="120" />
|
||||
<el-table-column prop="startTime" label="开始时间" min-width="160" />
|
||||
<el-table-column prop="endTime" label="结束时间" min-width="160" />
|
||||
<el-table-column prop="worker" label="作业员" min-width="80" />
|
||||
<el-table-column prop="status" label="状态" min-width="80" align="center">
|
||||
<template #default="{ row }">
|
||||
<el-tag :type="row.status === '已完成' ? 'success' : 'warning'" size="small">
|
||||
{{ row.status }}
|
||||
</el-tag>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
</el-card>
|
||||
</el-col>
|
||||
</el-row>
|
||||
</div>
|
||||
|
||||
<el-empty v-else-if="!loading && hasSearched" description="请输入成品批次码进行追溯" />
|
||||
|
||||
<el-dialog v-model="materialQcDialogVisible" title="原材料检验明细" width="700px" append-to-body>
|
||||
<el-descriptions :column="2" border size="small" class="mb-3">
|
||||
<el-descriptions-item label="物料编码">{{ currentMaterialInput?.materialCode }}</el-descriptions-item>
|
||||
<el-descriptions-item label="物料名称">{{ currentMaterialInput?.materialName }}</el-descriptions-item>
|
||||
<el-descriptions-item label="批次码">{{ currentMaterialInput?.batchCode }}</el-descriptions-item>
|
||||
<el-descriptions-item label="质检单号">{{ currentMaterialInput?.qcCode }}</el-descriptions-item>
|
||||
</el-descriptions>
|
||||
<el-table :data="currentMaterialInput?.checkItems" border size="small" max-height="300">
|
||||
<el-table-column prop="itemName" label="检验项目" min-width="120" />
|
||||
<el-table-column prop="standard" label="标准" min-width="180" show-overflow-tooltip />
|
||||
<el-table-column prop="actual" label="实际值" min-width="120" />
|
||||
<el-table-column prop="result" label="结果" min-width="80" align="center">
|
||||
<template #default="{ row }">
|
||||
<el-tag :type="row.result === '合格' ? 'success' : 'danger'" size="small">
|
||||
{{ row.result }}
|
||||
</el-tag>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
<template #footer>
|
||||
<el-button @click="materialQcDialogVisible = false">关闭</el-button>
|
||||
</template>
|
||||
</el-dialog>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts" name="ReverseTrace">
|
||||
import { reactive, ref } from 'vue';
|
||||
import { ElMessage } from 'element-plus';
|
||||
import { Loading } from '@element-plus/icons-vue';
|
||||
import { reverseTraceByBatch, getMaterialInputsByWorkOrder } from './data/mockData';
|
||||
|
||||
interface CheckItem {
|
||||
itemName: string;
|
||||
standard: string;
|
||||
actual: string;
|
||||
result: string;
|
||||
}
|
||||
|
||||
interface MaterialInput {
|
||||
materialCode: string;
|
||||
materialName: string;
|
||||
batchCode: string;
|
||||
supplier: string;
|
||||
qty: number;
|
||||
unit: string;
|
||||
inTime: string;
|
||||
qcCode: string;
|
||||
qcResult: string;
|
||||
checkItems: CheckItem[];
|
||||
}
|
||||
|
||||
interface WorkOrder {
|
||||
workOrderCode: string;
|
||||
processSeq: number;
|
||||
processCode: string;
|
||||
processName: string;
|
||||
machineNo: string;
|
||||
machineName: string;
|
||||
startTime: string;
|
||||
endTime: string;
|
||||
worker: string;
|
||||
status: string;
|
||||
materialInputs?: MaterialInput[];
|
||||
loading?: boolean;
|
||||
}
|
||||
|
||||
interface ProductionOrder {
|
||||
orderCode: string;
|
||||
batchCode: string;
|
||||
productCode: string;
|
||||
productName: string;
|
||||
dispatchType: number;
|
||||
dispatchTypeName: string;
|
||||
dispatchInfo: string;
|
||||
planQty: number;
|
||||
dispatchedQty: number;
|
||||
completedQty: number;
|
||||
startTime: string;
|
||||
endTime: string;
|
||||
status: string;
|
||||
}
|
||||
|
||||
interface CustomerInfo {
|
||||
hasOutbound: boolean;
|
||||
data: {
|
||||
customerCode: string;
|
||||
customerName: string;
|
||||
contactPerson: string;
|
||||
contactPhone: string;
|
||||
deliveryAddress: string;
|
||||
outboundTime: string;
|
||||
outboundQty: number;
|
||||
invoiceNo: string;
|
||||
} | null;
|
||||
}
|
||||
|
||||
interface TraceData {
|
||||
productInfo: {
|
||||
batchCode: string;
|
||||
productCode: string;
|
||||
productName: string;
|
||||
spec: string;
|
||||
productionDate: string;
|
||||
status: string;
|
||||
};
|
||||
qcInfo: {
|
||||
qcCode: string;
|
||||
batchCode: string;
|
||||
productCode: string;
|
||||
productName: string;
|
||||
spec: string;
|
||||
qcTime: string;
|
||||
qcType: string;
|
||||
inspector: string;
|
||||
result: string;
|
||||
checkItems: CheckItem[];
|
||||
};
|
||||
customerInfo?: CustomerInfo;
|
||||
productionOrder: ProductionOrder;
|
||||
workOrderList: WorkOrder[];
|
||||
}
|
||||
|
||||
const queryParams = reactive({
|
||||
batchCode: ''
|
||||
});
|
||||
|
||||
const loading = ref(false);
|
||||
const hasSearched = ref(false);
|
||||
const traceData = ref<TraceData | null>(null);
|
||||
const workOrderTableRef = ref();
|
||||
const expandedRowKeys = ref<string[]>([]);
|
||||
const materialQcDialogVisible = ref(false);
|
||||
const currentMaterialInput = ref<MaterialInput | null>(null);
|
||||
|
||||
const handleQuery = () => {
|
||||
if (!queryParams.batchCode) {
|
||||
ElMessage.warning('请输入成品批次码');
|
||||
return;
|
||||
}
|
||||
loading.value = true;
|
||||
hasSearched.value = true;
|
||||
expandedRowKeys.value = [];
|
||||
setTimeout(() => {
|
||||
const result = reverseTraceByBatch(queryParams.batchCode);
|
||||
if (result.code === 200) {
|
||||
traceData.value = result.data;
|
||||
ElMessage.success('追溯成功');
|
||||
} else {
|
||||
traceData.value = null;
|
||||
ElMessage.error(result.message || '追溯失败');
|
||||
}
|
||||
loading.value = false;
|
||||
}, 300);
|
||||
};
|
||||
|
||||
const resetQuery = () => {
|
||||
queryParams.batchCode = '';
|
||||
traceData.value = null;
|
||||
hasSearched.value = false;
|
||||
expandedRowKeys.value = [];
|
||||
};
|
||||
|
||||
const handleScan = () => {
|
||||
ElMessage.info('扫描功能开发中,请手动输入批次码');
|
||||
};
|
||||
|
||||
const handleExpandChange = async (row: WorkOrder, expanded?: boolean) => {
|
||||
const key = row.workOrderCode;
|
||||
if (expanded) {
|
||||
if (!row.materialInputs && !row.loading) {
|
||||
row.loading = true;
|
||||
if (!expandedRowKeys.value.includes(key)) {
|
||||
expandedRowKeys.value.push(key);
|
||||
}
|
||||
try {
|
||||
const result = await getMaterialInputsByWorkOrder(row.workOrderCode) as any;
|
||||
if (result.code === 200) {
|
||||
row.materialInputs = result.data;
|
||||
}
|
||||
} finally {
|
||||
row.loading = false;
|
||||
}
|
||||
} else if (!expandedRowKeys.value.includes(key)) {
|
||||
expandedRowKeys.value.push(key);
|
||||
}
|
||||
} else {
|
||||
const index = expandedRowKeys.value.indexOf(key);
|
||||
if (index > -1) {
|
||||
expandedRowKeys.value.splice(index, 1);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
const showMaterialQcDetail = (row: MaterialInput) => {
|
||||
currentMaterialInput.value = row;
|
||||
materialQcDialogVisible.value = true;
|
||||
};
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.reverse-trace-container {
|
||||
padding: 10px;
|
||||
}
|
||||
|
||||
.query-card {
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
|
||||
.trace-content {
|
||||
animation: fadeIn 0.3s ease-in-out;
|
||||
}
|
||||
|
||||
@keyframes fadeIn {
|
||||
from {
|
||||
opacity: 0;
|
||||
transform: translateY(10px);
|
||||
}
|
||||
to {
|
||||
opacity: 1;
|
||||
transform: translateY(0);
|
||||
}
|
||||
}
|
||||
|
||||
.card-title {
|
||||
font-weight: 600;
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
.mt-2 {
|
||||
margin-top: 10px;
|
||||
}
|
||||
|
||||
.mb-3 {
|
||||
margin-bottom: 12px;
|
||||
}
|
||||
|
||||
.expand-content {
|
||||
padding: 10px 10px 10px 50px;
|
||||
}
|
||||
|
||||
.expand-loading {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
padding: 20px;
|
||||
color: #909399;
|
||||
}
|
||||
|
||||
.expand-loading .el-icon-loading {
|
||||
margin-right: 8px;
|
||||
}
|
||||
|
||||
.material-input-table {
|
||||
background-color: #f5f7fa;
|
||||
}
|
||||
|
||||
.flex {
|
||||
display: flex;
|
||||
}
|
||||
|
||||
.justify-between {
|
||||
justify-content: space-between;
|
||||
}
|
||||
|
||||
.items-center {
|
||||
align-items: center;
|
||||
}
|
||||
</style>
|
||||
Loading…
Reference in New Issue