feat (wms/move):新增钢卷匹配进度展示

为入库钢卷功能添加匹配进度界面及对应状态、业务逻辑,实时展示匹配状态、进度占比与当前匹配项结果
This commit is contained in:
王文昊
2026-05-23 10:03:19 +08:00
parent e9de87a7b6
commit 6f5d09beef

View File

@@ -98,6 +98,30 @@
</el-table>
</div>
<!-- 匹配进度 -->
<div v-if="step === 'MATCHING'" class="matching-progress-section">
<div class="matching-progress-header">
<i class="el-icon-loading" style="font-size: 20px; color: #409eff;"></i>
<span class="matching-progress-title">正在匹配钢卷...</span>
<span class="matching-progress-percent">{{ matchingPercentage }}%</span>
</div>
<el-progress
:percentage="matchingPercentage"
:stroke-width="18"
:show-text="false"
status="success"
/>
<div class="matching-progress-detail">
<span>{{ matchingProgress }} / {{ matchingTotal }}</span>
<span v-if="currentMatchingText" class="matching-current">
当前: {{ currentMatchingText }}
<el-tag v-if="lastMatchResult === 'matched'" size="mini" type="success">已匹配</el-tag>
<el-tag v-else-if="lastMatchResult === 'conflict'" size="mini" type="warning">冲突</el-tag>
<el-tag v-else-if="lastMatchResult === 'unmatched'" size="mini" type="danger">未匹配</el-tag>
</span>
</div>
</div>
<!-- 标签页内容匹配结果 -->
<div v-if="step === 'REVIEW' || step === 'IMPORTING' || step === 'FINISHED'" class="tabs-section">
<el-tabs v-model="activeTab" type="border-card">
@@ -237,6 +261,11 @@
</el-button>
</template>
<!-- 匹配中 -->
<template v-if="step === 'MATCHING'">
<el-button disabled>匹配中 {{ matchingProgress }}/{{ matchingTotal }}...</el-button>
</template>
<!-- 导入中禁用关闭 -->
<template v-if="step === 'IMPORTING'">
<el-button disabled>导入中...</el-button>
@@ -281,16 +310,27 @@ export default {
importLoading: false,
importProgress: 0,
importedCount: 0,
// 匹配进度
matchingTotal: 0,
matchingProgress: 0,
currentMatchingText: '',
lastMatchResult: '',
};
},
computed: {
isProcessing() {
return this.step === 'MATCHING' || this.step === 'IMPORTING';
},
matchingPercentage() {
if (this.matchingTotal === 0) return 0;
return Math.round((this.matchingProgress / this.matchingTotal) * 100);
},
dialogTitle() {
switch (this.step) {
case 'PARSED':
return '导入钢卷 - 数据预览 (' + this.parsedData.length + '条)';
case 'MATCHING':
return '导入钢卷 - 匹配中 (' + this.matchingProgress + '/' + this.matchingTotal + ')';
case 'REVIEW':
case 'IMPORTING':
case 'FINISHED':
@@ -410,11 +450,18 @@ export default {
this.matchedRows = [];
this.conflictRows = [];
this.unmatchedRows = [];
this.matchingTotal = this.parsedData.length;
this.matchingProgress = 0;
this.currentMatchingText = '';
this.lastMatchResult = '';
try {
// 逐行匹配
for (const row of this.parsedData) {
this.currentMatchingText = row.enterCoilNo || row.currentCoilNo;
this.lastMatchResult = '';
await this.matchOneRow(row);
this.matchingProgress++;
}
this.step = 'REVIEW';
// 自动切换到第一个有数据的tab
@@ -447,15 +494,19 @@ export default {
if (list.length === 1) {
// 场景1精确匹配1条
this.matchedRows.push({ ...row, matchedCoil: list[0] });
this.lastMatchResult = 'matched';
} else if (list.length > 1) {
// 场景2匹配到多条需用户选择
this.conflictRows.push({ ...row, candidates: list, selectedCoilId: null });
this.lastMatchResult = 'conflict';
} else {
// 场景3未匹配
this.unmatchedRows.push({ ...row, reason: '未找到匹配的钢卷' });
this.lastMatchResult = 'unmatched';
}
} catch (error) {
this.unmatchedRows.push({ ...row, reason: '查询失败:' + error.message });
this.lastMatchResult = 'unmatched';
}
},
@@ -536,6 +587,10 @@ export default {
this.unmatchedRows = [];
this.importProgress = 0;
this.importedCount = 0;
this.matchingTotal = 0;
this.matchingProgress = 0;
this.currentMatchingText = '';
this.lastMatchResult = '';
this.activeTab = 'matched';
this.$refs.upload && this.$refs.upload.clearFiles();
}
@@ -643,6 +698,47 @@ export default {
margin-top: 10px;
}
/* 匹配进度区域 */
.matching-progress-section {
padding: 30px 20px;
}
.matching-progress-header {
display: flex;
align-items: center;
margin-bottom: 15px;
}
.matching-progress-title {
font-size: 16px;
font-weight: bold;
color: #303133;
margin-left: 8px;
}
.matching-progress-percent {
font-size: 20px;
font-weight: bold;
color: #67c23a;
margin-left: auto;
}
.matching-progress-detail {
display: flex;
align-items: center;
justify-content: space-between;
margin-top: 12px;
color: #606266;
font-size: 14px;
}
.matching-current {
display: flex;
align-items: center;
gap: 6px;
color: #909399;
}
/* 标签页区域 */
.tabs-section {
margin-top: 10px;