Files
klp-oa/klp-ui/src/views/wms/coil/panels/CoilTraceResult.vue
砂糖 c5bff55a35 feat(钢卷管理): 添加钢卷还原功能并优化界面
- 在coil.js中新增restoreMaterialCoil接口用于还原钢卷
- 在correct.vue中添加还原按钮及相关处理逻辑
- 优化CoilTraceResult.vue界面,移除部分不必要的信息展示
- 调整部分文字描述使其更简洁
2026-01-20 11:29:22 +08:00

422 lines
12 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<template>
<div class="trace-result-container">
<!-- 二维码信息 -->
<!-- <el-card shadow="hover" class="mb20" v-if="traceResult && traceResult.qrcode">
<div slot="header" class="card-header">
<span class="title-dot"></span>
<span class="title-text">二维码信息</span>
</div>
<div class="qrcode-info">
<el-row class="info-row" :gutter="10">
<el-col :span="6" class="info-label">主序列号</el-col>
<el-col :span="18" class="info-value">{{ traceResult.qrcode.serialNumber || '-' }}</el-col>
</el-row>
<el-row class="info-row" :gutter="10">
<el-col :span="6" class="info-label">创建时间</el-col>
<el-col :span="18" class="info-value">{{ traceResult.qrcode.createTime || '-' }}</el-col>
</el-row>
<el-row class="info-row" :gutter="10" v-if="traceResult.all_qrcodes && traceResult.all_qrcodes.length > 1">
<el-col :span="6" class="info-label">相关二维码</el-col>
<el-col :span="18" class="info-value">{{ traceResult.all_qrcodes.length }} </el-col>
</el-row>
</div>
</el-card> -->
<!-- 操作步骤 -->
<el-card shadow="hover" class="mb20" v-if="traceResult && traceResult.steps && traceResult.steps.length > 0">
<div slot="header" class="card-header">
<span class="title-dot"></span>
<span class="title-text">操作步骤</span>
</div>
<el-timeline>
<el-timeline-item
v-for="(step, index) in traceResult.steps"
:key="index"
:timestamp="step.display_step || step.step"
placement="top"
>
<el-card shadow="hover">
<div class="step-header">
<span class="step-action">{{ step.action }}</span>
<el-tag size="mini" type="primary" v-if="step.operation">{{ step.operation }}</el-tag>
</div>
<div class="step-details">
<el-row class="detail-row" v-if="step.current_coil_no">
<el-col :span="8" class="detail-label">当前钢卷号</el-col>
<el-col :span="16" class="detail-value">{{ step.current_coil_no }}</el-col>
</el-row>
<el-row class="detail-row" v-if="step.old_current_coil_no">
<el-col :span="8" class="detail-label">原钢卷号</el-col>
<el-col :span="16" class="detail-value">{{ step.old_current_coil_no }}</el-col>
</el-row>
<el-row class="detail-row" v-if="step.new_current_coil_no">
<el-col :span="8" class="detail-label">新钢卷号</el-col>
<el-col :span="16" class="detail-value">{{ step.new_current_coil_no }}</el-col>
</el-row>
<el-row class="detail-row" v-if="step.new_current_coil_nos">
<el-col :span="8" class="detail-label">分卷列表</el-col>
<el-col :span="16" class="detail-value">
<el-tag
v-for="coilNo in step.new_current_coil_nos.split(',')"
:key="coilNo"
type="warning"
size="mini"
class="mr8"
>
{{ coilNo.trim() }}
</el-tag>
</el-col>
</el-row>
<el-row class="detail-row" v-if="step.parent_coil_nos">
<el-col :span="8" class="detail-label">合卷来源</el-col>
<el-col :span="16" class="detail-value">
<el-tag
v-for="coilNo in step.parent_coil_nos.split(',')"
:key="coilNo"
type="success"
size="mini"
class="mr8"
>
{{ coilNo.trim() }}
</el-tag>
</el-col>
</el-row>
<el-row class="detail-row" v-if="step.child_coils && step.child_coils.length > 0">
<el-col :span="8" class="detail-label">子钢卷</el-col>
<el-col :span="16" class="detail-value">
<el-tag
v-for="coilNo in step.child_coils"
:key="coilNo"
type="info"
size="mini"
class="mr8"
>
{{ coilNo }}
</el-tag>
</el-col>
</el-row>
<!-- <el-row class="detail-row" v-if="step.qrcode_serial">
<el-col :span="8" class="detail-label">二维码序列</el-col>
<el-col :span="16" class="detail-value">{{ step.qrcode_serial }}</el-col>
</el-row> -->
<el-row class="detail-row" v-if="step.operator">
<el-col :span="8" class="detail-label">操作者</el-col>
<el-col :span="16" class="detail-value">{{ step.operator }}</el-col>
</el-row>
</div>
</el-card>
</el-timeline-item>
</el-timeline>
</el-card>
<!-- 钢卷分支图 -->
<!-- <el-card shadow="hover" class="mb20" v-if="traceResult && traceResult.records && traceResult.records.length > 0">
<div slot="header" class="card-header">
<span class="title-dot"></span>
<span class="title-text">钢卷分支图</span>
</div>
<div class="branch-container">
<div
class="branch-group"
v-for="(group, index) in groupedRecords"
:key="index"
>
<div class="branch-group-header">
<el-tag :type="getGroupTypeTag(group.groupColor)" size="medium">{{ group.title }}</el-tag>
<span class="branch-count">{{ group.coils.length }} 个钢卷</span>
</div>
<el-row :gutter="20" class="branch-coils">
<el-col
:span="8"
v-for="coil in group.coils"
:key="coil.coilId"
>
<el-card shadow="hover" class="coil-card">
<div class="coil-header">
<span class="coil-no">{{ coil.currentCoilNo }}</span>
<el-tag :type="coil.dataType === 1 ? 'success' : 'danger'" size="mini">
{{ coil.dataType === 1 ? '当前' : '历史' }}
</el-tag>
</div>
<div class="coil-info">
<p class="coil-detail">入场号{{ coil.enterCoilNo }}</p>
<p class="coil-detail" v-if="coil.team">班组{{ coil.team }}</p>
<p class="coil-detail" v-if="coil.warehouse && coil.warehouse.warehouseName">
库区{{ coil.warehouse.warehouseName }}
</p>
<p class="coil-detail" v-if="coil.parentCoilNos && coil.hasMergeSplit === 1">
<el-tag type="warning" size="mini">来自母卷{{ coil.parentCoilNos }}</el-tag>
</p>
<p class="coil-detail" v-if="coil.parentCoilNos && coil.hasMergeSplit === 0 && coil.dataType === 0">
<el-tag type="info" size="mini">分为子卷{{ coil.parentCoilNos }}</el-tag>
</p>
<p class="coil-detail" v-if="coil.parentCoilNos && coil.hasMergeSplit === 2">
<el-tag type="success" size="mini">合并自{{ coil.parentCoilNos }}</el-tag>
</p>
<p class="coil-detail">{{ coil.createTime }}</p>
</div>
</el-card>
</el-col>
</el-row>
</div>
</div>
</el-card> -->
<!-- 无记录提示 -->
<div class="empty-tip" v-if="!traceResult || (traceResult && !traceResult.records && !traceResult.steps)">
<el-empty description="未找到相关钢卷记录"></el-empty>
</div>
</div>
</template>
<script>
export default {
name: 'CoilTraceResult',
props: {
// 追溯结果数据
traceResult: {
type: Object,
default: null
}
},
computed: {
// 按时间线和分支关系分组钢卷记录
groupedRecords() {
if (!this.traceResult || !this.traceResult.records) {
return [];
}
const groups = [];
// 按创建时间排序所有记录
const sortedRecords = [...this.traceResult.records].sort((a, b) =>
new Date(a.createTime) - new Date(b.createTime)
);
// 按数据类型分组,但保持时间顺序
const currentCoils = sortedRecords.filter(record => record.dataType === 1);
const historyCoils = sortedRecords.filter(record => record.dataType === 0);
// 当前数据分组
if (currentCoils.length > 0) {
const currentByOperation = this.groupByOperation(currentCoils);
groups.push(...currentByOperation);
}
// 历史数据分组
if (historyCoils.length > 0) {
const historyByOperation = this.groupByOperation(historyCoils, true);
groups.push(...historyByOperation);
}
return groups;
}
},
methods: {
// 按操作类型分组
groupByOperation(records, isHistory = false) {
const operationGroups = {};
for (const record of records) {
let operationType = '原始数据';
let groupColor = 'default';
if (record.hasMergeSplit === 1) {
operationType = '分卷结果';
groupColor = 'split';
} else if (record.hasMergeSplit === 2) {
operationType = '合卷结果';
groupColor = 'merge';
}
const groupKey = operationType;
if (!operationGroups[groupKey]) {
operationGroups[groupKey] = {
operationType: operationType,
groupColor: groupColor,
coils: []
};
}
operationGroups[groupKey].coils.push(record);
}
// 转换为数组
const groups = [];
for (const key in operationGroups) {
const group = operationGroups[key];
groups.push({
type: isHistory ? 'history' : 'current',
operationType: group.operationType,
groupColor: group.groupColor,
title: `${group.operationType}${isHistory ? '(历史)' : '(当前)'}`,
coils: group.coils
});
}
return groups;
},
// formatTime(step) {
// const timestamp = step.upda
// }
// 获取分组标签类型
getGroupTypeTag(color) {
switch(color) {
case 'split': return 'warning';
case 'merge': return 'success';
default: return 'primary';
}
}
}
};
</script>
<style scoped>
/* 溯源结果样式 */
.trace-result-container {
padding: 10px 0;
}
.card-header {
display: flex;
align-items: center;
font-size: 16px;
font-weight: 600;
}
.title-dot {
display: inline-block;
width: 4px;
height: 16px;
background: #409EFF;
border-radius: 2px;
margin-right: 8px;
}
.title-text {
color: #333;
}
.mb20 {
margin-bottom: 20px;
}
/* 二维码信息样式 */
.qrcode-info {
padding: 10px 0;
}
.info-row {
margin-bottom: 12px;
align-items: center;
}
.info-label {
color: #666;
font-weight: 500;
}
.info-value {
color: #333;
font-weight: 500;
}
/* 操作步骤样式 */
.step-header {
display: flex;
align-items: center;
margin-bottom: 12px;
}
.step-action {
font-size: 15px;
font-weight: 600;
color: #333;
margin-right: 8px;
}
.step-details {
padding: 10px 0;
}
.detail-row {
margin-bottom: 8px;
align-items: center;
}
.detail-label {
color: #666;
font-size: 14px;
}
.detail-value {
color: #333;
font-size: 14px;
}
.mr8 {
margin-right: 8px;
margin-bottom: 8px;
}
/* 钢卷分支图样式 */
.branch-container {
padding: 10px 0;
}
.branch-group {
margin-bottom: 20px;
}
.branch-group-header {
display: flex;
align-items: center;
margin-bottom: 12px;
justify-content: space-between;
}
.branch-count {
color: #666;
font-size: 14px;
}
.branch-coils {
margin-bottom: 10px;
}
.coil-card {
height: 100%;
display: flex;
flex-direction: column;
}
.coil-header {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 10px;
}
.coil-no {
font-size: 15px;
font-weight: 600;
color: #333;
}
.coil-info {
flex: 1;
}
.coil-detail {
font-size: 13px;
color: #666;
margin-bottom: 4px;
margin: 0;
line-height: 1.5;
}
/* 空提示样式 */
.empty-tip {
text-align: center;
padding: 40px 0;
}
</style>