refactor(wms): 重构钢卷追溯功能为独立组件
feat(wms): 新增钢卷追溯结果展示组件 fix(wms): 修正产品信息组件参数传递问题 style(sidebar): 调整菜单项边距样式 chore(config): 更新生产环境数据库配置
This commit is contained in:
@@ -58,9 +58,9 @@ spring:
|
|||||||
driverClassName: com.mysql.cj.jdbc.Driver
|
driverClassName: com.mysql.cj.jdbc.Driver
|
||||||
# jdbc 所有参数配置参考 https://lionli.blog.csdn.net/article/details/122018562
|
# jdbc 所有参数配置参考 https://lionli.blog.csdn.net/article/details/122018562
|
||||||
# rewriteBatchedStatements=true 批处理优化 大幅提升批量插入更新删除性能(对数据库有性能损耗 使用批量操作应考虑性能问题)
|
# rewriteBatchedStatements=true 批处理优化 大幅提升批量插入更新删除性能(对数据库有性能损耗 使用批量操作应考虑性能问题)
|
||||||
url: jdbc:mysql://140.143.206.120:3306/klp-oa?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8&autoReconnect=true&rewriteBatchedStatements=true
|
url: jdbc:mysql://140.143.206.120:13306/klp-oa?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8&autoReconnect=true&rewriteBatchedStatements=true
|
||||||
username: klp
|
username: klp
|
||||||
password: KeLunPu123@
|
password: KeLunPu@123
|
||||||
# 从库数据源
|
# 从库数据源
|
||||||
slave:
|
slave:
|
||||||
lazy: true
|
lazy: true
|
||||||
|
|||||||
@@ -99,7 +99,7 @@
|
|||||||
white-space: nowrap !important;
|
white-space: nowrap !important;
|
||||||
color: var(--text-regular); // 菜单项文本偏黑
|
color: var(--text-regular); // 菜单项文本偏黑
|
||||||
border-radius: 4px;
|
border-radius: 4px;
|
||||||
margin: 0 6px;
|
margin: 0;
|
||||||
transition: all 0.2s ease;
|
transition: all 0.2s ease;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -301,7 +301,6 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#app .sidebar-container .el-menu-item,
|
#app .sidebar-container .nest-menu .el-submenu .el-submenu__title {
|
||||||
#app .sidebar-container .el-submenu__title {
|
margin: 0 4px;
|
||||||
margin: 0;
|
|
||||||
}
|
}
|
||||||
409
klp-ui/src/views/wms/coil/panels/CoilTraceResult.vue
Normal file
409
klp-ui/src/views/wms/coil/panels/CoilTraceResult.vue
Normal file
@@ -0,0 +1,409 @@
|
|||||||
|
<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">{{ 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;
|
||||||
|
},
|
||||||
|
// 获取分组标签类型
|
||||||
|
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>
|
||||||
@@ -11,12 +11,8 @@
|
|||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item label="数据状态">
|
<el-form-item label="数据状态">
|
||||||
<el-select v-model="queryParams.dataType" placeholder="请选择数据状态" clearable>
|
<el-select v-model="queryParams.dataType" placeholder="请选择数据状态" clearable>
|
||||||
<el-option :value="0" label="历史数据">
|
<el-option :value="0" label="历史数据">历史数据</el-option>
|
||||||
历史数据
|
<el-option :value="1" label="当前数据">当前数据</el-option>
|
||||||
</el-option>
|
|
||||||
<el-option :value="1" label="当前数据">
|
|
||||||
当前数据
|
|
||||||
</el-option>
|
|
||||||
</el-select>
|
</el-select>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item label="厂家卷号" prop="supplierCoilNo">
|
<el-form-item label="厂家卷号" prop="supplierCoilNo">
|
||||||
@@ -70,7 +66,7 @@
|
|||||||
<el-table-column label="净重" align="center" prop="netWeight" />
|
<el-table-column label="净重" align="center" prop="netWeight" />
|
||||||
<el-table-column label="物品" align="center" prop="itemName">
|
<el-table-column label="物品" align="center" prop="itemName">
|
||||||
<template slot-scope="scope">
|
<template slot-scope="scope">
|
||||||
<ProductInfo v-if="scope.row.itemType == 'product'" productId=" scope.row.itemId">
|
<ProductInfo v-if="scope.row.itemType == 'product'" productId="scope.row.itemId">
|
||||||
<template slot-scope="{ product }">
|
<template slot-scope="{ product }">
|
||||||
{{ product.productName }}({{ product.productCode }})
|
{{ product.productName }}({{ product.productCode }})
|
||||||
</template>
|
</template>
|
||||||
@@ -143,167 +139,9 @@
|
|||||||
</div>
|
</div>
|
||||||
</el-dialog>
|
</el-dialog>
|
||||||
|
|
||||||
<!-- 钢卷追溯对话框 -->
|
<!-- 钢卷追溯对话框(使用封装的组件) -->
|
||||||
<el-dialog title="钢卷追溯" :visible.sync="traceOpen" width="90%" append-to-body>
|
<el-dialog title="钢卷追溯" :visible.sync="traceOpen" width="90%" append-to-body>
|
||||||
<div class="trace-result-container" v-loading="loading">
|
<coil-trace-result :trace-result="traceResult"></coil-trace-result>
|
||||||
<!-- 二维码信息 -->
|
|
||||||
<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">{{ 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>
|
|
||||||
</el-dialog>
|
</el-dialog>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
@@ -319,6 +157,8 @@ import BomInfoMini from "@/components/KLPService/Renderer/BomInfoMini";
|
|||||||
import RawMaterialInfo from "@/components/KLPService/Renderer/RawMaterialInfo";
|
import RawMaterialInfo from "@/components/KLPService/Renderer/RawMaterialInfo";
|
||||||
import RightToolbar from "@/components/RightToolbar";
|
import RightToolbar from "@/components/RightToolbar";
|
||||||
import Pagination from "@/components/Pagination";
|
import Pagination from "@/components/Pagination";
|
||||||
|
// 引入封装的追溯结果组件
|
||||||
|
import CoilTraceResult from "./CoilTraceResult.vue"; // 路径根据实际存放位置调整
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: "MaterialCoil",
|
name: "MaterialCoil",
|
||||||
@@ -330,7 +170,8 @@ export default {
|
|||||||
RawMaterialInfo,
|
RawMaterialInfo,
|
||||||
BomInfoMini,
|
BomInfoMini,
|
||||||
RightToolbar,
|
RightToolbar,
|
||||||
Pagination
|
Pagination,
|
||||||
|
CoilTraceResult // 注册组件
|
||||||
},
|
},
|
||||||
props: {
|
props: {
|
||||||
qrcode: {
|
qrcode: {
|
||||||
@@ -366,7 +207,7 @@ export default {
|
|||||||
open: false,
|
open: false,
|
||||||
// 追溯对话框显示
|
// 追溯对话框显示
|
||||||
traceOpen: false,
|
traceOpen: false,
|
||||||
// 追溯结果数据
|
// 追溯结果数据(传递给组件)
|
||||||
traceResult: null,
|
traceResult: null,
|
||||||
// 查询参数
|
// 查询参数
|
||||||
queryParams: {
|
queryParams: {
|
||||||
@@ -376,7 +217,6 @@ export default {
|
|||||||
enterCoilNo: undefined,
|
enterCoilNo: undefined,
|
||||||
currentCoilNo: undefined,
|
currentCoilNo: undefined,
|
||||||
supplierCoilNo: undefined,
|
supplierCoilNo: undefined,
|
||||||
dataType: 1,
|
|
||||||
warehouseId: undefined,
|
warehouseId: undefined,
|
||||||
nextWarehouseId: undefined,
|
nextWarehouseId: undefined,
|
||||||
qrcodeRecordId: undefined,
|
qrcodeRecordId: undefined,
|
||||||
@@ -407,38 +247,6 @@ export default {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
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;
|
|
||||||
}
|
|
||||||
},
|
|
||||||
created() {
|
created() {
|
||||||
this.getList();
|
this.getList();
|
||||||
},
|
},
|
||||||
@@ -455,71 +263,18 @@ export default {
|
|||||||
/** 追溯按钮操作 */
|
/** 追溯按钮操作 */
|
||||||
handleTrace(row) {
|
handleTrace(row) {
|
||||||
this.traceOpen = true;
|
this.traceOpen = true;
|
||||||
this.traceResult = null;
|
this.traceResult = null; // 清空历史数据
|
||||||
this.loading = true;
|
|
||||||
getMaterialCoilTrace({
|
getMaterialCoilTrace({
|
||||||
enterCoilNo: row.enterCoilNo,
|
enterCoilNo: row.enterCoilNo,
|
||||||
currentCoilNo: row.currentCoilNo,
|
currentCoilNo: row.currentCoilNo,
|
||||||
}).then(res => {
|
}).then(res => {
|
||||||
this.traceResult = res.data;
|
this.traceResult = res.data; // 将结果传递给组件
|
||||||
console.log('溯源结果:', this.traceResult);
|
|
||||||
this.loading = false;
|
|
||||||
}).catch(err => {
|
}).catch(err => {
|
||||||
console.error('溯源查询失败:', err);
|
console.error('溯源查询失败:', err);
|
||||||
this.$message.error('溯源查询失败,请重试');
|
this.$message.error('溯源查询失败,请重试');
|
||||||
this.loading = false;
|
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
// 按操作类型分组
|
/** 下载二维码 */
|
||||||
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;
|
|
||||||
},
|
|
||||||
// 获取分组标签类型
|
|
||||||
getGroupTypeTag(color) {
|
|
||||||
switch(color) {
|
|
||||||
case 'split': return 'warning';
|
|
||||||
case 'merge': return 'success';
|
|
||||||
default: return 'primary';
|
|
||||||
}
|
|
||||||
},
|
|
||||||
handleDownloadQRCode(row) {
|
handleDownloadQRCode(row) {
|
||||||
try {
|
try {
|
||||||
saveAsImage(
|
saveAsImage(
|
||||||
@@ -616,11 +371,7 @@ export default {
|
|||||||
this.title = "修改钢卷物料";
|
this.title = "修改钢卷物料";
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
transferCoil() {},
|
||||||
transferCoil() {
|
|
||||||
|
|
||||||
},
|
|
||||||
|
|
||||||
/** 提交按钮 */
|
/** 提交按钮 */
|
||||||
submitForm() {
|
submitForm() {
|
||||||
this.$refs["form"].validate(valid => {
|
this.$refs["form"].validate(valid => {
|
||||||
@@ -669,155 +420,4 @@ export default {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
</script>
|
</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>
|
|
||||||
Reference in New Issue
Block a user