优化比对

This commit is contained in:
wuweihua
2026-10-26 16:03:12 +08:00
parent 209d545d5b
commit 7f4fc3df8c
12 changed files with 153 additions and 30 deletions
@@ -1,7 +1,7 @@
<template>
<el-drawer
v-model="visible"
size="720px"
size="780px"
:title="drawerTitle"
append-to-body
destroy-on-close
@@ -45,7 +45,34 @@
/>
<div class="json-panel__head">
<span>缺失转单号(样本)</span>
<span>状态不一致(样本 {{ statusMismatchCount }})</span>
<el-button
type="primary"
link
:disabled="!canFillMismatch"
@click="fillMismatchToSearch"
>回填到单号搜索</el-button>
</div>
<el-table
v-if="statusMismatchRows.length"
:data="statusMismatchRows"
border
size="small"
max-height="320"
class="mb12"
>
<el-table-column type="index" width="55" label="#" />
<el-table-column prop="transferNo" label="转单号" min-width="180" show-overflow-tooltip />
<el-table-column prop="upstreamStatusLabel" label="上游状态" width="110" />
<el-table-column prop="localStatusLabel" label="本地状态" width="110" />
</el-table>
<el-empty
v-else-if="!running"
description="暂无状态不一致"
/>
<div class="json-panel__head">
<span>缺失转单号(样本 {{ missingCount }})</span>
<el-button
type="primary"
link
@@ -53,22 +80,20 @@
@click="fillToSearch"
>回填到单号搜索</el-button>
</div>
<el-table :data="missingRows" border size="small" max-height="360">
<el-table
v-if="missingRows.length"
:data="missingRows"
border
size="small"
max-height="280"
>
<el-table-column type="index" width="55" label="#" />
<el-table-column prop="transferNo" label="转单号" min-width="220" show-overflow-tooltip />
</el-table>
<el-empty v-if="!running && !(progress.missingTransferNos || []).length" description="暂无缺失转单号" />
<div class="json-panel__head">
<span>状态不一致(样本)</span>
</div>
<el-table :data="statusMismatchRows" border size="small" max-height="280" class="mb12">
<el-table-column type="index" width="55" label="#" />
<el-table-column prop="transferNo" label="转单号" min-width="180" show-overflow-tooltip />
<el-table-column prop="upstreamStatusLabel" label="上游状态" width="110" />
<el-table-column prop="localStatusLabel" label="本地状态" width="110" />
</el-table>
<el-empty v-if="!running && !(progress.statusMismatchSamples || []).length" description="暂无状态不一致" />
<el-empty
v-else-if="!running"
description="暂无缺失转单号"
/>
</div>
</el-drawer>
@@ -154,28 +179,66 @@ function labelStatus(v) {
return orderStatusMap[k] || k
}
function normalizeMismatchList(raw) {
if (!Array.isArray(raw)) return []
return raw.map(row => {
if (row == null) return null
if (typeof row === 'string') {
return { transferNo: row, upstreamStatus: null, localStatus: null }
}
return {
transferNo: row.transferNo || row.transfer_no || '',
upstreamStatus: row.upstreamStatus ?? row.upstream_status ?? null,
localStatus: row.localStatus ?? row.local_status ?? null
}
}).filter(Boolean)
}
const statusMismatchRows = computed(() => {
const list = progress.value?.statusMismatchSamples || []
return list.map(row => ({
transferNo: row.transferNo || row.transfer_no || '',
upstreamStatusLabel: labelStatus(row.upstreamStatus ?? row.upstream_status),
localStatusLabel: labelStatus(row.localStatus ?? row.local_status)
const samples = normalizeMismatchList(progress.value?.statusMismatchSamples)
if (samples.length) {
return samples.map(row => ({
transferNo: row.transferNo,
upstreamStatusLabel: labelStatus(row.upstreamStatus),
localStatusLabel: labelStatus(row.localStatus)
}))
}
// fallback: flat transfer_no list when map samples missing
const flat = progress.value?.statusMismatchTransferNos || []
return (Array.isArray(flat) ? flat : []).map(tn => ({
transferNo: tn,
upstreamStatusLabel: '-',
localStatusLabel: '-'
}))
})
const statusMismatchCount = computed(() => {
const n = Number(progress.value?.statusMismatch)
if (!Number.isNaN(n) && n > 0) return n
return statusMismatchRows.value.length
})
const missingRows = computed(() => {
const list = progress.value?.missingTransferNos || []
return list.map(tn => ({ transferNo: tn }))
return (Array.isArray(list) ? list : []).map(tn => ({ transferNo: tn }))
})
const missingCount = computed(() => {
const n = Number(progress.value?.missing)
if (!Number.isNaN(n) && n > 0) return n
return missingRows.value.length
})
const canFillSearch = computed(() => {
return !running.value && (progress.value?.missingTransferNos || []).length > 0
return !running.value && missingRows.value.length > 0
})
const canFillMismatch = computed(() => {
return !running.value && statusMismatchRows.value.length > 0
})
function fillToSearch() {
const list = (progress.value?.missingTransferNos || [])
.map(s => String(s || '').trim())
.filter(Boolean)
const list = missingRows.value.map(r => String(r.transferNo || '').trim()).filter(Boolean)
if (!list.length) {
ElMessage.warning('暂无可回填的缺失转单号')
return
@@ -185,6 +248,18 @@ function fillToSearch() {
visible.value = false
}
function fillMismatchToSearch() {
const list = statusMismatchRows.value.map(r => String(r.transferNo || '').trim()).filter(Boolean)
if (!list.length) {
ElMessage.warning('暂无可回填的状态不一致转单号')
return
}
const truncated = !!(progress.value?.statusMismatchTruncated)
|| (Number(progress.value?.statusMismatch || 0) > list.length)
emit('fill-search', { transferNos: list, truncated })
visible.value = false
}
function clearTimer() {
if (timer) {
clearInterval(timer)
@@ -216,7 +291,7 @@ function open(q) {
ElMessage.error('启动比对任务失败')
return
}
progress.value = { status: 'PENDING', percent: 0, message: 'queued', scanned: 0, matched: 0, missing: 0 }
progress.value = { status: 'PENDING', percent: 0, message: 'queued', scanned: 0, matched: 0, missing: 0, statusMismatch: 0 }
poll()
timer = setInterval(poll, 1500)
}).catch(() => {
@@ -238,6 +238,7 @@ const columns = [
{ label: '产品底级代码', prop: 'productFloorCode', minWidth: 130, showOverflowTooltip: true },
{ label: '国家', prop: 'country', minWidth: 140, slot: 'country', showOverflowTooltip: true },
{ label: '收件人邮编', prop: 'consigneePostcode', minWidth: 120, showOverflowTooltip: true },
{ label: '客户确认重', prop: 'confirmWeight', align: 'center', width: 110 },
{ label: '计费重', prop: 'dimensionalWeightFactor', align: 'center', width: 100 },
{ label: '体积重', prop: 'volumeWeight', align: 'center', width: 100 },
{ label: '实重', prop: 'weight', align: 'center', width: 100 },