@@ -500,10 +500,18 @@ function calculatedMeasurementRow(
const strategyDimensions = matchedDimensions . map ( ( value ) => roundedUp ( value * specificationCoefficient , 3 ) )
const [ lengthCm , widthCm , heightCm ] = strategyDimensions
const packageCount = Number ( source . packageCount )
const unitVolumeCbm = mode === 'ADD' && rule && ! hasOuterOverride
const savedDimensions = [ source . calculatedOuterLengthCm , source . calculatedOuterWidthCm , source . calculatedOuterHeightCm ]
// 不调整且尺寸与落库快照一致时沿用服务端体积,避免历史三位精度与预览四位取整产生差额。
const useSavedVolume = ! customerSource && mode === 'ACTUAL'
&& measurementCalculationModeForRow ( source ) === 'ACTUAL'
&& savedDimensions . every ( ( value , index ) => value != null
&& Math . abs ( Number ( value ) - strategyDimensions [ index ] ! ) < 0.000001 )
&& Number ( source . unitVolumeCbm ) > 0 && Number ( source . totalVolumeCbm ) > 0
const unitVolumeCbm = useSavedVolume ? Number ( source . unitVolumeCbm ) : mode === 'ADD' && rule && ! hasOuterOverride
? Math . round ( ( lengthCm * widthCm * heightCm / 1 _000 _000 ) * 1000 ) / 1000
: roundedUp ( lengthCm * widthCm * heightCm / 1 _000 _000 , 4 )
const totalVolumeCbm = Number . isFinite ( packageCount ) ? roundedUp ( unitVolumeCbm * packageCount , 4 ) : null
const totalVolumeCbm = useSavedVolume ? Number ( source . totalVolumeCbm )
: Number . isFinite ( packageCount ) ? roundedUp ( unitVolumeCbm * packageCount , 4 ) : null
const fallbackMeasuredUnitWeight = ! customerSource && Number . isFinite ( Number ( measurementDetail . value ? . actualGrossWeightKg ) )
&& Number ( measurementDetail . value ? . actualPackageCount ) > 0
? Number ( measurementDetail . value ? . actualGrossWeightKg ) / Number ( measurementDetail . value ? . actualPackageCount )
@@ -517,7 +525,8 @@ function calculatedMeasurementRow(
... source ,
lengthCm , widthCm , heightCm , unitWeightKg , unitVolumeCbm , totalWeightKg , totalVolumeCbm ,
girthCm : roundedUp ( lengthCm + 2 * ( widthCm + heightCm ) , 3 ) ,
volumeWeightKg : totalVolumeCbm == null ? null : roundedUp ( totalVolumeCbm * 167 , 3 ) ,
volumeWeightKg : useSavedVolume && Number ( source . volumeWeightKg ) > 0 ? Number ( source . volumeWeightKg )
: totalVolumeCbm == null ? null : roundedUp ( totalVolumeCbm * 167 , 3 ) ,
remark : customerSource ? source . cargoRemark : source . remark ,
}
}
@@ -866,6 +875,11 @@ function formatNumber(value: number | null | undefined, digits = 2) {
return value === null || value === undefined ? '—' : value . toLocaleString ( 'zh-CN' , { maximumFractionDigits : digits } )
}
function formatMeasurementVolume ( value : number | null | undefined ) {
return value == null || ! Number . isFinite ( value ) ? '—'
: value . toLocaleString ( 'zh-CN' , { minimumFractionDigits : 3 , maximumFractionDigits : 3 } )
}
function partyValue ( parties : Array < Record < string , unknown > > , type : 'SENDER' | 'RECEIVER' , key : string ) {
const party = parties . find ( ( item ) => String ( item . partyType || '' ) . toUpperCase ( ) === type )
const value = party ? . [ key ]
@@ -1020,11 +1034,12 @@ function measurementValue(row: Record<string, unknown>, key: string, customerSou
if ( customerSource && key === 'unitVolumeCbm' ) {
const total = Number ( row . volumeCbm )
const count = Number ( row . packageCount )
return Number . isFinite ( total ) && Number . isFinite ( count ) && count > 0 ? formatNumber ( total / count , 6 ) : '—'
return Number . isFinite ( total ) && Number . isFinite ( count ) && count > 0 ? formatMeasurementVolume ( total / count ) : '—'
}
if ( customerSource && key === 'remark' ) return String ( row . cargoRemark || '—' )
const value = row [ key ]
if ( value === null || value === undefined || value === '' ) return '—'
if ( key === 'unitVolumeCbm' || key === 'totalVolumeCbm' ) return formatMeasurementVolume ( Number ( value ) )
return typeof value === 'number' ? formatNumber ( value , 6 ) : String ( value )
}
@@ -2660,17 +2675,17 @@ function orderDialogTitle(action: string, inboundCode?: string | null) {
< / LoadErrorState >
< template v-else >
< section class = "measurement-section" >
< div class = "measurement-section-title" > < button type = "button" class = "measurement-section-toggle" :aria-expanded = "!measurementCollapsed.customer" @click ="toggleMeasurementSection('customer')" > < h3 > 一 、 客户下单数据 < / h3 > < span v-if = "measurementCollapsed.customer" class="measurement-section-summary"><span>总件数:{{ measurementTotals(customerMeasurementRows).count ?? '—' }}</span><span>总毛重:{{ formatNumber(measurementTotals(customerMeasurementRows).gross) }}</span><span>总体积:{{ formatNumber (measurementTotals(customerMeasurementRows).volume, 6 ) }}</span><span>总材积重:{{ formatNumber(measurementTotals(customerMeasurementRows).volumetric) }}</span><span>重量体积:{{ formatNumber (measurementTotals(customerMeasurementRows).weightVolume, 6 ) }}</span></span><ChevronUp v-if="!measurementCollapsed.customer" :size="18" /><ChevronDown v-else :size="18" /></button><el-select class="measurement-section-mode" :model-value="measurementSectionModes.customer" aria-label="客户下单数据计算方式" @change="updateMeasurementSectionMode('customer', $event)"><el-option label="实测原尺寸(不调整)" value="ACTUAL" /><el-option label="箱规尺寸" value="ADD" /><el-option label="箱规系数" value="MULTIPLY" :disabled="multiplyModeDisabled" / > < / el-select > < / div >
< div class = "measurement-section-title" > < button type = "button" class = "measurement-section-toggle" :aria-expanded = "!measurementCollapsed.customer" @click ="toggleMeasurementSection('customer')" > < h3 > 一 、 客户下单数据 < / h3 > < span v-if = "measurementCollapsed.customer" class="measurement-section-summary"><span>总件数:{{ measurementTotals(customerMeasurementRows).count ?? '—' }}</span><span>总毛重:{{ formatNumber(measurementTotals(customerMeasurementRows).gross) }}</span><span>总体积:{{ formatMeasurementVolume (measurementTotals(customerMeasurementRows).volume) }}</span><span>总材积重:{{ formatNumber(measurementTotals(customerMeasurementRows).volumetric) }}</span><span>重量体积:{{ formatMeasurementVolume (measurementTotals(customerMeasurementRows).weightVolume) }}</span></span><ChevronUp v-if="!measurementCollapsed.customer" :size="18" /><ChevronDown v-else :size="18" /></button><el-select class="measurement-section-mode" :model-value="measurementSectionModes.customer" aria-label="客户下单数据计算方式" @change="updateMeasurementSectionMode('customer', $event)"><el-option label="实测原尺寸(不调整)" value="ACTUAL" /><el-option label="箱规尺寸" value="ADD" /><el-option label="箱规系数" value="MULTIPLY" :disabled="multiplyModeDisabled" / > < / el-select > < / div >
< div v-if = "!measurementCollapsed.customer" >
< div class = "detail-table-wrap" > < el-table :data = "customerMeasurementRows" border stripe empty -text = " 暂无客户下单数据 " > < el-table-column v-for = "column in customerMeasurementColumns" :key="column.key" :label="column.label" :prop="column.key" min-width="120"><template #default="{ row }"><LineClampText v-if="column.key === 'remark'" :content="measurementValue(row as Record<string, unknown>, column.key)" / > < template v-else > {{ measurementValue ( row as Record < string , unknown > , column . key ) } } < / template > < / template > < / el-table-column > < / el-table > < / div >
< div class = "measurement-total" > < strong > 合计 < / strong > < span > 箱数 : { { measurementTotals ( customerMeasurementRows ) . count ? ? '—' } } < / span > < span > 总毛重 : { { formatNumber ( measurementTotals ( customerMeasurementRows ) . gross ) } } < / span > < span > 总体积 : { { formatNumber ( measurementTotals ( customerMeasurementRows ) . volume , 6 ) } } < / span > < span > 总材积重 : { { formatNumber ( measurementTotals ( customerMeasurementRows ) . volumetric ) } } < / span > < span > 重量体积 : { { formatNumber ( measurementTotals ( customerMeasurementRows ) . weightVolume , 6 ) } } < / span > < / div >
< div class = "measurement-total" > < strong > 合计 < / strong > < span > 箱数 : { { measurementTotals ( customerMeasurementRows ) . count ? ? '—' } } < / span > < span > 总毛重 : { { formatNumber ( measurementTotals ( customerMeasurementRows ) . gross ) } } < / span > < span > 总体积 : { { formatMeasurementVolume ( measurementTotals ( customerMeasurementRows ) . volume ) } } < / span > < span > 总材积重 : { { formatNumber ( measurementTotals ( customerMeasurementRows ) . volumetric ) } } < / span > < span > 重量体积 : { { formatMeasurementVolume ( measurementTotals ( customerMeasurementRows ) . weightVolume ) } } < / span > < / div >
< / div >
< / section >
< section class = "measurement-section" >
< div class = "measurement-section-title" > < button type = "button" class = "measurement-section-toggle" :aria-expanded = "!measurementCollapsed.outer" @click ="toggleMeasurementSection('outer')" > < h3 > 二 、 外箱规数据 < / h3 > < span v-if = "measurementCollapsed.outer" class="measurement-section-summary"><span>总件数:{{ measurementTotals(outerMeasurementRows).count ?? '—' }}</span><span>总毛重:{{ formatNumber(measurementTotals(outerMeasurementRows).gross) }}</span><span>总体积:{{ formatNumber (measurementTotals(outerMeasurementRows).volume, 6 ) }}</span><span>总材积重:{{ formatNumber(measurementTotals(outerMeasurementRows).volumetric) }}</span><span>重量体积:{{ formatNumber (measurementTotals(outerMeasurementRows).weightVolume, 6 ) }}</span></span><ChevronUp v-if="!measurementCollapsed.outer" :size="18" /><ChevronDown v-else :size="18" / > < / button > < / div >
< div class = "measurement-section-title" > < button type = "button" class = "measurement-section-toggle" :aria-expanded = "!measurementCollapsed.outer" @click ="toggleMeasurementSection('outer')" > < h3 > 二 、 外箱规数据 < / h3 > < span v-if = "measurementCollapsed.outer" class="measurement-section-summary"><span>总件数:{{ measurementTotals(outerMeasurementRows).count ?? '—' }}</span><span>总毛重:{{ formatNumber(measurementTotals(outerMeasurementRows).gross) }}</span><span>总体积:{{ formatMeasurementVolume (measurementTotals(outerMeasurementRows).volume) }}</span><span>总材积重:{{ formatNumber(measurementTotals(outerMeasurementRows).volumetric) }}</span><span>重量体积:{{ formatMeasurementVolume (measurementTotals(outerMeasurementRows).weightVolume) }}</span></span><ChevronUp v-if="!measurementCollapsed.outer" :size="18" /><ChevronDown v-else :size="18" / > < / button > < / div >
< div v-if = "!measurementCollapsed.outer" >
< div v-loading = "measurementLoading" class="detail-table-wrap"><el-table :data="outerMeasurementRows" border stripe empty-text="暂无外箱规数据"><el-table-column label="#" prop="itemNo" min-width="70" /><el-table-column v-for="column in outerColumns.filter((item) => item.key !== 'itemNo')" :key="column.key" :label="column.label" :prop="column.key" min-width="150"><template #default="{ row }"><LineClampText v-if="column.key === 'remark'" :content="measurementValue(row as Record<string, unknown>, column.key)" / > < template v-else > {{ measurementValue ( row as Record < string , unknown > , column . key ) } } < / template > < / template > < / el-table-column > < / el-table > < / div >
< div class = "measurement-total" > < strong > 合计 < / strong > < span > 箱数 : { { measurementTotals ( outerMeasurementRows ) . count ? ? '—' } } < / span > < span > 总毛重 : { { formatNumber ( measurementTotals ( outerMeasurementRows ) . gross ) } } < / span > < span > 总体积 : { { formatNumber ( measurementTotals ( outerMeasurementRows ) . volume , 6 ) } } < / span > < span > 总材积重 : { { formatNumber ( measurementTotals ( outerMeasurementRows ) . volumetric ) } } < / span > < span > 重量体积 : { { formatNumber ( measurementTotals ( outerMeasurementRows ) . weightVolume , 6 ) } } < / span > < / div >
< div class = "measurement-total" > < strong > 合计 < / strong > < span > 箱数 : { { measurementTotals ( outerMeasurementRows ) . count ? ? '—' } } < / span > < span > 总毛重 : { { formatNumber ( measurementTotals ( outerMeasurementRows ) . gross ) } } < / span > < span > 总体积 : { { formatMeasurementVolume ( measurementTotals ( outerMeasurementRows ) . volume ) } } < / span > < span > 总材积重 : { { formatNumber ( measurementTotals ( outerMeasurementRows ) . volumetric ) } } < / span > < span > 重量体积 : { { formatMeasurementVolume ( measurementTotals ( outerMeasurementRows ) . weightVolume ) } } < / span > < / div >
< / div >
< / section >
< div class = "measurement-rule-selector" >
@@ -2683,7 +2698,7 @@ function orderDialogTitle(action: string, inboundCode?: string | null) {
< span v-if = "!measurementStrategyEditable" class="measurement-rule-selector__hint" > {{ measurementStrategyLockedHint }} < / span >
< / div >
< section class = "measurement-section" >
< div class = "measurement-section-title" > < button type = "button" class = "measurement-section-toggle" :aria-expanded = "!measurementCollapsed.actual" @click ="toggleMeasurementSection('actual')" > < h3 > 三 、 实际测量数据 < / h3 > < span v-if = "measurementCollapsed.actual" class="measurement-section-summary"><span>总件数:{{ measurementTotals(actualMeasurementRows).count ?? '—' }}</span><span>总毛重:{{ formatNumber(measurementTotals(actualMeasurementRows).gross) }}</span><span>总体积:{{ formatNumber (measurementTotals(actualMeasurementRows).volume, 6 ) }}</span><span>总材积重:{{ formatNumber(measurementTotals(actualMeasurementRows).volumetric) }}</span><span>重量体积:{{ formatNumber (measurementTotals(actualMeasurementRows).weightVolume, 6 ) }}</span></span><ChevronUp v-if="!measurementCollapsed.actual" :size="18" /><ChevronDown v-else :size="18" /></button><el-select class="measurement-section-mode" :model-value="measurementSectionModes.actual" aria-label="实际测量数据计算方式" @change="updateMeasurementSectionMode('actual', $event)"><el-option label="实测原尺寸(不调整)" value="ACTUAL" /><el-option label="箱规尺寸" value="ADD" /><el-option label="箱规系数" value="MULTIPLY" :disabled="multiplyModeDisabled" / > < / el-select > < / div >
< div class = "measurement-section-title" > < button type = "button" class = "measurement-section-toggle" :aria-expanded = "!measurementCollapsed.actual" @click ="toggleMeasurementSection('actual')" > < h3 > 三 、 实际测量数据 < / h3 > < span v-if = "measurementCollapsed.actual" class="measurement-section-summary"><span>总件数:{{ measurementTotals(actualMeasurementRows).count ?? '—' }}</span><span>总毛重:{{ formatNumber(measurementTotals(actualMeasurementRows).gross) }}</span><span>总体积:{{ formatMeasurementVolume (measurementTotals(actualMeasurementRows).volume) }}</span><span>总材积重:{{ formatNumber(measurementTotals(actualMeasurementRows).volumetric) }}</span><span>重量体积:{{ formatMeasurementVolume (measurementTotals(actualMeasurementRows).weightVolume) }}</span></span><ChevronUp v-if="!measurementCollapsed.actual" :size="18" /><ChevronDown v-else :size="18" /></button><el-select class="measurement-section-mode" :model-value="measurementSectionModes.actual" aria-label="实际测量数据计算方式" @change="updateMeasurementSectionMode('actual', $event)"><el-option label="实测原尺寸(不调整)" value="ACTUAL" /><el-option label="箱规尺寸" value="ADD" /><el-option label="箱规系数" value="MULTIPLY" :disabled="multiplyModeDisabled" / > < / el-select > < / div >
< div v-if = "!measurementCollapsed.actual" >
< div v-loading = "measurementLoading" class="detail-table-wrap" >
< el -table :data = "actualMeasurementRows" row -key = " id " border stripe empty -text = " 暂无实际测量数据 " >
@@ -2721,7 +2736,7 @@ function orderDialogTitle(action: string, inboundCode?: string | null) {
< / el-table-column >
< / el-table >
< / div >
< div class = "measurement-total" > < strong > 合计 < / strong > < span > 箱数 : { { measurementTotals ( actualMeasurementRows ) . count ? ? '—' } } < / span > < span > 总毛重 : { { formatNumber ( measurementTotals ( actualMeasurementRows ) . gross ) } } < / span > < span > 总体积 : { { formatNumber ( measurementTotals ( actualMeasurementRows ) . volume , 6 ) } } < / span > < span > 总材积重 : { { formatNumber ( measurementTotals ( actualMeasurementRows ) . volumetric ) } } < / span > < span > 重量体积 : { { formatNumber ( measurementTotals ( actualMeasurementRows ) . weightVolume , 6 ) } } < / span > < / div >
< div class = "measurement-total" > < strong > 合计 < / strong > < span > 箱数 : { { measurementTotals ( actualMeasurementRows ) . count ? ? '—' } } < / span > < span > 总毛重 : { { formatNumber ( measurementTotals ( actualMeasurementRows ) . gross ) } } < / span > < span > 总体积 : { { formatMeasurementVolume ( measurementTotals ( actualMeasurementRows ) . volume ) } } < / span > < span > 总材积重 : { { formatNumber ( measurementTotals ( actualMeasurementRows ) . volumetric ) } } < / span > < span > 重量体积 : { { formatMeasurementVolume ( measurementTotals ( actualMeasurementRows ) . weightVolume ) } } < / span > < / div >
< section class = "weight-evidence" aria -label = " 称重图片与服务端确认重量 " >
< div class = "weight-evidence__heading" >
< div > < h4 > 称重图片与确认重量 < / h4 > < / div >