@@ -52,13 +52,8 @@ const isRejected = computed(() => detail.value?.measureReviewStatus === 'REJECTE
const reviewStatusLabel = computed ( ( ) => inboundStatusLabel ( detail . value ? . measureReviewStatus , inboundReviewStatusLabels , '未提交' ) )
const displayCustomerName = computed ( ( ) => detail . value ? . companyName ? . trim ( ) || props . customerName ? . trim ( ) || '客户未命名' )
const displayChannelName = computed ( ( ) => detail . value ? . channelName ? . trim ( ) || detail . value ? . channelCode ? . trim ( ) || props . channelName ? . trim ( ) || props . channelCode ? . trim ( ) || '渠道未填写' )
const sourceLabels : Record < string , string > = {
THIRD _PARTY : '第三方设备' ,
DEVICE : '第三方设备' ,
OPENAPI : '第三方设备' ,
MANUAL : '平台人工' ,
}
const sourceLabel = computed ( ( ) => sourceLabels [ detail . value ? . sourceType || '' ] || ( detail . value ? . sourceType ? '未知来源' : '尚未记录' ) )
const measurementCount = computed ( ( ) => detail . value ? . items . length || 0 )
const weightCount = computed ( ( ) => detail . value ? . weightResults . length || 0 )
function formatNumber ( value : number | null | undefined , maximumFractionDigits = 3 ) {
if ( value === null || value === undefined || ! Number . isFinite ( value ) ) return '—'
@@ -180,18 +175,18 @@ defineExpose({ confirmApprove, isPending, canReview, actionLoading })
< section class = "review-panel" aria -labelledby = " measurement -review -title " >
< h2 id = "measurement-review-title" class = "sr-only" > 测量审核内容 < / h2 >
< div class = "review-toolbar" aria -label = " 测量审核操作 " >
< div class = "review-toolbar__actions" >
< el-button v-if = "isPending && canReview" type="primary" plain @click="correctionMode = true"><Pencil :size="16" / > 修改重量 < / el-button >
< el-button v-if = "isPending && canReview" type="primary" :loading="actionLoading === 'approve' || postApproveLoading" :disabled="approvalCompleted" @click="confirmApprove"><Check :size="16" / > { { approvalCompleted ? '审核已通过' : approvalButtonLabel } } < / el-button >
< / div >
< div class = "review-toolbar__status" >
< StatusBadge v-if = "detail" :status="reviewStatusLabel" / >
< span v-if = "isPending" > 通过后进入待分柜 < / span >
< span v-if = "isPending" > 通过后进入 {{ approvalTargetLabel }} < / span >
< span v-else-if = "isRejected" > 历史记录为审核驳回 , 仅供查看 < / span >
< span v-else > 当前记录不可审核 < / span >
< span v-if = "detail" class="review-toolbar__context" > 客户 : {{ displayCustomerName }} · 渠道 : {{ displayChannelName }} < / span >
< / div >
< div class = "review-toolbar__actions" >
< el-button v-if = "isPending && canReview" type="primary" plain @click="correctionMode = true"><Pencil :size="16" / > 修改重量 < / el-button >
< el-button v-if = "isPending && canReview" type="primary" :loading="actionLoading === 'approve' || postApproveLoading" :disabled="approvalCompleted" @click="confirmApprove"><Check :size="16" / > { { approvalCompleted ? '审核已通过' : approvalButtonLabel } } < / el-button >
< el-button :loading = "loading" aria -label = " 刷新审核数据 " @click ="reload" > < RotateCcw :size = "16" / > 刷新 < / el-button >
< / div >
< el -button class = "review-refresh" :loading = "loading" aria -label = " 刷新审核数据 " @click ="reload" > < RotateCcw :size = "16" / > 刷新 < / el-button >
< / div >
< el-alert v-if = "loadError" type="error" :closable="false" show-icon role="alert" >
@@ -204,12 +199,7 @@ defineExpose({ confirmApprove, isPending, canReview, actionLoading })
< el -alert v-if = "detail.reviewReason" type="warning" :closable="false" show-icon :title="`最近审核说明:${detail.reviewReason}`" / >
< section class = "review-data" aria -labelledby = " review -data -title " >
< header class = "review-section-heading" >
< div >
< h3 id = "review-data-title" > 审核数据总览 < / h3 >
< / div >
< el-tag effect = "plain" > { { sourceLabel } } < / el-tag >
< / header >
< header class = "review-section-heading" > < h3 id = "review-data-title" > 审核数据总览 < / h3 > < / header >
< div class = "review-comparison" >
< div class = "review-comparison__row review-comparison__row--declared" >
@@ -223,7 +213,7 @@ defineExpose({ confirmApprove, isPending, canReview, actionLoading })
< div class = "review-comparison__row" >
< strong > 平台实测 < / strong >
< dl class = "review-metrics" aria -label = " 平台实测结果汇总 " >
< div > < dt > 箱数 < / dt > < dd > { { formatNumber ( detail . actualPackageCount , 0 ) } } < small v-if = "formatDifference(detail.actualPackageCount, detail.originalPackageCount, 0)" > {{ formatDifference ( detail.actualPackageCount , detail.originalPackageCount , 0 ) }} < / small > < / dd > < / div >
< div > < dt > 箱数 < / dt > < dd > { { formatNumber ( detail . actualPackageCount , 0 ) } } { { formatDifference ( detail . actualPackageCount , detail . originalPackageCount , 0 ) ? ` ${ formatDifference ( detail . actualPackageCount , detail . originalPackageCount , 0 ) } ` : '' } } < / dd > < / div >
< div > < dt > 毛重 < / dt > < dd > { { formatNumber ( detail . actualGrossWeightKg ) } } < small > kg < span v-if = "formatDifference(detail.actualGrossWeightKg, detail.originalGrossWeightKg, 3, ' kg')" > · {{ formatDifference ( detail.actualGrossWeightKg , detail.originalGrossWeightKg , 3 , ' kg ' ) }} < / span > < / small > < / dd > < / div >
< div class = "review-metric--primary" > < dt > 货物净重 < / dt > < dd > { { formatNumber ( detail . actualNetWeightKg ) } } < small > kg < / small > < / dd > < / div >
< div > < dt > 体积 < / dt > < dd > { { formatNumber ( detail . actualVolumeCbm , 4 ) } } < small > m³ < span v-if = "formatDifference(detail.actualVolumeCbm, detail.originalVolumeCbm, 4, ' m³')" > · {{ formatDifference ( detail.actualVolumeCbm , detail.originalVolumeCbm , 4 , ' m ³ ' ) }} < / span > < / small > < / dd > < / div >
@@ -238,12 +228,12 @@ defineExpose({ confirmApprove, isPending, canReview, actionLoading })
< div >
< h3 id = "review-items-title" > 箱规测量明细 < / h3 >
< / div >
< span > { { detail . items . length } } 条 < / span >
< span > { { measurementCount } } 条 < / span >
< / header >
< div v-if = "detail.items.length" class="review-table-scroll" >
< el -table :data = "detail.items" border stripe table -layout = " fixed " class = "review-table" >
< el-table-column type = "index" label = "#" width = "44" align = "center" / >
< el-table-column label = "箱号" width = "24 0" show -overflow -tooltip >
< el-table-column label = "箱号" width = "16 0" show -overflow -tooltip >
< template # default = "{ row }" > { { row . boxCode || row . itemNo || '—' } } < / template >
< / el-table-column >
< el-table-column label = "测量图片" width = "98" align = "center" >
@@ -281,12 +271,31 @@ defineExpose({ confirmApprove, isPending, canReview, actionLoading })
< el-empty v-else description = "暂无箱规测量明细" :image-size = "48" / >
< / section >
< section class = "review-items review-weight-items" aria -labelledby = " review -weight -title " >
< header class = "review-section-heading" > < h3 id = "review-weight-title" > ⚖ 称重明细 < / h3 > < div class = "review-weight-totals" > < span > 实测毛重 < strong > { { formatNumber ( detail . actualGrossWeightKg , 3 ) } } KG < / strong > < / span > < span > 货物重量 < strong > { { formatNumber ( detail . actualNetWeightKg , 3 ) } } KG < / strong > < / span > < / div > < / header >
< div v-if = "weightCount" class="review-table-scroll" >
< el -table :data = "detail.weightResults" border stripe table -layout = " fixed " class = "review-table review-weight-table" >
< el-table-column type = "index" label = "#" width = "44" align = "center" / >
< el-table-column label = "称重图片" width = "112" align = "center" > < template # default = "{ row }" > < MeasurementEvidenceThumbnail :customer-id = "customerId" :inbound-id = "inboundId" :file-id = "row.fileId" : alt = "`${row.palletCode || '托盘'}称重图片`" empty -text = " 无图片 " @open ="openImagePreview(row.fileId, row.palletCode || '托盘')" / > < / template > < / el-table-column >
< el-table-column prop = "palletCode" label = "托盘编码" min -width = " 120 " / >
< el-table-column prop = "palletType" label = "托盘类型" min -width = " 120 " / >
< el-table-column label = "库位" min -width = " 130 " > < template # default = "{ row }" > < span class = "review-location" > { { row . locationCode || '—' } } < template v-if = "row.locationCode" > · {{ row.slotStatus = = = ' BOUND ' ? ' 待上架 ' : row.slotStatus | | ' 待上架 ' }} < / template > < / span > < / template > < / el -table -column >
< el-table-column label = "毛重(KG) " min -width = " 120 " align = "right" > < template # default = "{ row }" > { { formatNumber ( row . grossWeightKg , 3 ) } } < / template > < / el-table-column >
< el-table-column label = "托盘皮重(kg)" min -width = " 120 " align = "right" > < template # default = "{ row }" > { { formatNumber ( row . palletTareWeightKg , 3 ) } } < / template > < / el-table-column >
< el-table-column label = "货物重量(kg)" min -width = " 120 " align = "right" > < template # default = "{ row }" > < strong class = "review-weight-value" > { { formatNumber ( row . netWeightKg , 3 ) } } < / strong > < / template > < / el-table-column >
< el-table-column label = "称重时间" min -width = " 150 " > < template # default = "{ row }" > { { formatDate ( row . confirmedAt || row . adjustedAt ) } } < / template > < / el-table-column >
< / el-table >
< / div >
< el-empty v-else description = "暂无称重明细" :image-size = "48" / >
< / section >
< WeightOcrPanel
review -mode
:correction-mode = "correctionMode"
:customer-id = "customerId"
:inbound-id = "inboundId"
@changed ="handleWeightChanged"
: class = "{ 'review-weight-editor--hidden': !correctionMode }"
/ >
< / template >
@@ -306,7 +315,7 @@ defineExpose({ confirmApprove, isPending, canReview, actionLoading })
< style scoped >
. review - panel { display : grid ; gap : var ( -- admin - space - 5 , 12 px ) ; color : var ( -- cc - text ) ; }
. review - toolbar { display : flex ; align - items : center ; justify - content : space - between ; gap : 14 px ; position : sticky ; top : - 12 px ; z - index : 3 ; flex - wrap : wrap ; margin : - var ( -- admin - space - 5 , 12 px ) - var ( -- admin - space - 6 , 16 px ) 0 ; padding : var ( -- admin - space - 3 , 8 px ) var ( -- admin - space - 6 , 16 px ) ; border - bottom : 1 px solid var ( -- cc - border ) ; background : var ( -- admin - surface , # fff ) ; }
. review - toolbar { display : flex ; align - items : center ; justify - content : space - between ; gap : 14 px ; position : sticky ; top : - 12 px ; z - index : 3 ; flex - wrap : wrap ; margin : - var ( -- admin - space - 5 , 12 px ) - var ( -- admin - space - 6 , 16 px ) 0 ; padding : var ( -- admin - space - 3 , 8 px ) var ( -- admin - space - 6 , 16 px ) ; border - bottom : 1 px solid var ( -- cc - border ) ; background : linear - gradient ( 100 deg , # f3f6ff 0 % , # fff 48 % , # eefaf7 100 % ) ; }
. review - toolbar _ _status , . review - toolbar _ _actions { display : flex ; min - width : 0 ; align - items : center ; flex - wrap : wrap ; gap : var ( -- admin - space - 3 , 8 px ) ; }
. review - toolbar _ _status > span { color : var ( -- cc - muted ) ; font - size : var ( -- admin - font - caption , 12 px ) ; }
. review - toolbar _ _actions { justify - content : flex - end ; }
@@ -337,6 +346,23 @@ defineExpose({ confirmApprove, isPending, canReview, actionLoading })
. review - table : deep ( . el - table _ _cell ) { padding : 7 px 0 ; }
. review - table : deep ( . review - time - cell . cell ) { white - space : nowrap ; }
. review - table : deep ( . measurement - evidence - thumb ) { min - width : 72 px ; border - radius : var ( -- admin - radius , 4 px ) ; }
. review - data { border : 1 px solid # dfe5ef ; border - radius : 8 px ; overflow : hidden ; background : # fff ; }
. review - data . review - section - heading { margin : 0 ; padding : 10 px 14 px 6 px ; border - bottom : 0 ; }
. review - comparison _ _row { padding : 10 px 14 px ; }
. review - comparison _ _row -- declared { background : linear - gradient ( 90 deg , # ddf5e9 , # eaf9f1 ) ; box - shadow : inset 4 px 0 # 25 a879 ; }
. review - comparison _ _row -- declared > strong { color : # 16845 d ; }
. review - comparison _ _row + . review - comparison _ _row { border - top : 1 px dashed # dfe4ed ; }
. review - comparison _ _row > strong { font - size : 14 px ; }
. review - declaration dd , . review - metrics dd { font - size : 16 px ; }
. review - metric -- primary dd , . review - weight - value , . review - weight - totals strong { color : # 138154 ! important ; font - weight : 750 ; }
. review - weight - items { padding - top : 0 ; }
. review - weight - totals { display : flex ; gap : 18 px ; color : var ( -- cc - muted ) ; font - size : 12 px ; }
. review - weight - totals span { padding : 4 px 8 px ; border - radius : 7 px ; background : # f0faf5 ; }
. review - weight - totals strong { margin - left : 6 px ; font - size : 16 px ; }
. review - weight - table : deep ( . el - table _ _header th ) { background : linear - gradient ( 180 deg , # f1f4fc , # e9eef8 ) ; }
. review - weight - table : deep ( . el - table _ _cell ) { padding : 9 px 0 ; }
. review - location { display : inline - block ; padding : 3 px 7 px ; border : 1 px solid # e2e8f2 ; border - radius : 5 px ; background : # f3f6fb ; color : # 53627 a ; white - space : nowrap ; }
. review - weight - editor -- hidden { display : none ; }
. review - image - preview { display : grid ; min - height : 240 px ; place - items : center ; }
. review - image - preview img { display : block ; width : auto ; max - width : 100 % ; max - height : 70 vh ; object - fit : contain ; }
. review - image - preview _ _error { display : grid ; justify - items : center ; gap : var ( -- admin - space - 3 , 8 px ) ; color : var ( -- el - color - danger ) ; }
@@ -346,6 +372,7 @@ defineExpose({ confirmApprove, isPending, canReview, actionLoading })
. review - toolbar _ _actions { display : grid ; width : 100 % ; grid - template - columns : 1 fr ; justify - content : stretch ; }
. review - toolbar _ _actions : deep ( . el - button ) { width : 100 % ; min - height : 44 px ; }
. review - section - heading { align - items : stretch ; flex - direction : column ; }
. review - weight - totals { flex - wrap : wrap ; gap : 6 px ; }
. review - comparison _ _row { grid - template - columns : 78 px minmax ( 0 , 1 fr ) ; align - items : start ; }
. review - metrics , . review - declaration { grid - template - columns : repeat ( 2 , minmax ( 0 , 1 fr ) ) ; }
}