优化
This commit is contained in:
@@ -7,6 +7,12 @@ const source = readFileSync(resolve(process.cwd(), 'src/modules/unified-orders/p
|
||||
const routeSource = readFileSync(resolve(process.cwd(), 'src/modules/unified-orders/routes.ts'), 'utf8')
|
||||
|
||||
describe('UnifiedOrdersView contract', () => {
|
||||
it('blocks confirm-send when the customer has already confirmed the fee', () => {
|
||||
expect(source).toContain("snapshot.customerConfirmationStatus === 'CONFIRMED'")
|
||||
expect(source).toContain('客户已确认该费用,费用已锁定,不允许再修改或重新发送')
|
||||
expect(source).toContain('async function openFeeConfirmDialog()')
|
||||
})
|
||||
|
||||
it('only exposes the six product main statuses', () => {
|
||||
expect(unifiedOrderStatusOptions.map((item) => item.label)).toEqual([
|
||||
'待审核', '待测量数据', '待分柜', '装柜中', '装柜完成', '派送完成',
|
||||
@@ -337,35 +343,61 @@ describe('UnifiedOrdersView contract', () => {
|
||||
expect(source).toContain('getCustomerDimensionConfig')
|
||||
expect(source).toContain('matchingDimensionRule')
|
||||
expect(source).toContain('|| rules[rules.length - 1]')
|
||||
expect(source).toContain('`原尺寸 + ${values[0]}cm`')
|
||||
expect(source).toContain('`原尺寸 + ${Number(values[0]) * 2}cm(单边 +${values[0]}cm)`')
|
||||
expect(source).toContain('`原尺寸 × ${rule.lengthFactor}`')
|
||||
expect(source).toContain('label="箱规尺寸" value="ADD"')
|
||||
expect(source).toContain('label="箱规系数" value="MULTIPLY"')
|
||||
})
|
||||
|
||||
it('keeps the three section calculation modes independent and recalculates their display rows', () => {
|
||||
it('keeps preview modes independent and persists both outer-carton selectors immediately', () => {
|
||||
expect(source).toContain("measurementSectionModes = reactive<Record<MeasurementSection, MeasurementCalculationMode>>")
|
||||
expect(source).toContain(':model-value="measurementSectionModes.customer"')
|
||||
expect(source).toContain(':model-value="measurementSectionModes.outer"')
|
||||
expect(source).toContain(':model-value="measurementSectionModes.actual"')
|
||||
expect(source).toContain("updateMeasurementSectionMode('customer', $event)")
|
||||
expect(source).toContain("updateMeasurementSectionMode('outer', $event)")
|
||||
expect(source).toContain("updateMeasurementSectionMode('actual', $event)")
|
||||
expect(source).not.toContain("updateMeasurementSectionMode('outer', $event)")
|
||||
expect(source.match(/@change="selectAndSaveOuterMeasurementMode\(\$event\)"/g)).toHaveLength(2)
|
||||
expect(source.match(/:disabled="Boolean\(measurementStrategySavingId\) \|\| !can\('platform:firstleg:inbound:measure:edit'\)"/g)).toHaveLength(2)
|
||||
expect(source).toContain('const previousMode = measurementSectionModes.outer')
|
||||
expect(source).toContain('if (!saved) measurementSectionModes.outer = previousMode')
|
||||
expect(source).toContain('const saved = await updateMeasurementCalculationMode(null, mode)')
|
||||
expect(source).toContain('calculatedMeasurementRow(row, measurementSectionModes.customer, true)')
|
||||
expect(source).toContain('calculatedMeasurementRow(source, measurementSectionModes.outer)')
|
||||
expect(source).toContain('calculatedMeasurementRow(row as unknown as Record<string, unknown>, measurementSectionModes.actual)')
|
||||
expect(source).toContain("return Number(hasOuterOverride && override != null && override !== '' ? override : value)")
|
||||
expect(source).toContain('rawDimensions.map((value) => value + rule.edgeAdditionCm)')
|
||||
expect(source).toContain('rawDimensions.map((value) => value + rule.edgeAdditionCm * 2)')
|
||||
expect(source).toContain('matchedSpecificationCoefficient(chargeRule, calculationSource)')
|
||||
expect(source).toContain('listCustomerChargeRules(customerId, tenantId)')
|
||||
expect(source).toContain('matchedDimensions.map((value) => roundedUp(value * specificationCoefficient, 3))')
|
||||
expect(source).toContain("const selectedMode: 'ADD' | 'MULTIPLY' = measurementSectionModes.outer === 'MULTIPLY'")
|
||||
expect(source).toContain('? selectedMode')
|
||||
expect(source).toContain('const selectedMode: MeasurementCalculationMode = measurementSectionModes.outer')
|
||||
expect(source).not.toContain('[chargeRule.lengthFactor, chargeRule.widthFactor, chargeRule.heightFactor]')
|
||||
expect(source).not.toContain('column.key === \'coefficientMode\'')
|
||||
expect(source).not.toContain('@change="updateMeasurementCalculationMode(null, $event)"')
|
||||
})
|
||||
|
||||
it('confirms customer billing from the saved outer-carton totals', () => {
|
||||
expect(source).toContain('const outerTotals = measurementTotals(outerMeasurementRows.value)')
|
||||
expect(source).toContain("ElMessage.warning('外箱规数据不完整,请先保存外箱规尺寸和计算规则')")
|
||||
expect(source).toContain("weightSource: 'OUTER'")
|
||||
expect(source).toContain("volumeSource: 'OUTER'")
|
||||
expect(source).toContain('selectAndSaveOuterMeasurementMode($event)')
|
||||
expect(source).toContain('const saved = await updateMeasurementCalculationMode(null, mode)')
|
||||
expect(source).toContain('coefficientMode: targetIds.has(String(item.id)) ? mode')
|
||||
expect(source).not.toContain('feeConfirmVolume.value = Number(summary.measurement?.actualVolumeCbm)')
|
||||
const sendFeeSource = source.slice(source.indexOf('async function executeConfirmAndSendFee()'), source.indexOf('function handleOrderSelectionChange'))
|
||||
expect(sendFeeSource).not.toContain('saveInboundMeasurementDraft')
|
||||
expect(sendFeeSource).not.toContain('updateMeasurementCalculationMode')
|
||||
})
|
||||
|
||||
it('restores the saved outer-carton rule and server-calculated dimensions on re-entry', () => {
|
||||
expect(source).toContain("mode is MeasurementCalculationMode => mode === 'ACTUAL' || mode === 'ADD' || mode === 'MULTIPLY'")
|
||||
expect(source).toContain('measurementSectionModes.outer = savedModes.length === 1 ? savedModes[0]!')
|
||||
expect(source).toContain('row.calculatedOuterLengthCm')
|
||||
expect(source).toContain('measurementCalculationModeForRow(source) === measurementSectionModes.outer')
|
||||
expect(source).toContain('lengthCm: Number(savedDimensions[0])')
|
||||
})
|
||||
|
||||
it('binds dimension and weight evidence to their formal server records without mixing galleries', () => {
|
||||
expect(source).toContain('<el-table :data="actualMeasurementRows" row-key="id"')
|
||||
expect(source).toContain('<el-table-column label="箱号" prop="boxCode"')
|
||||
|
||||
@@ -292,7 +292,7 @@ function matchingDimensionRule(row: Record<string, unknown>): CustomerDimensionR
|
||||
function addCoefficientLabel(row?: Record<string, unknown>) {
|
||||
const rows = row ? [row] : (measurementDetail.value?.items || []) as unknown as Record<string, unknown>[]
|
||||
const values = [...new Set(rows.map((item) => matchingDimensionRule(item)?.edgeAdditionCm).filter((value) => value != null))]
|
||||
if (values.length === 1) return `原尺寸 + ${values[0]}cm`
|
||||
if (values.length === 1) return `原尺寸 + ${Number(values[0]) * 2}cm(单边 +${values[0]}cm)`
|
||||
if (measurementDimensionConfigLoading.value) return '原尺寸 + 加载中…'
|
||||
return values.length > 1 ? '原尺寸 + 按箱规匹配' : '原尺寸 + 未匹配箱规'
|
||||
}
|
||||
@@ -305,18 +305,22 @@ function multiplyCoefficientLabel() {
|
||||
|
||||
function matchedSpecificationCoefficient(rule: CustomerChargeRule, row: Record<string, unknown>) {
|
||||
const tiers = [...(rule.remark || '').matchAll(
|
||||
/(SMALL|MEDIUM|LARGE|EXTRA_LARGE):(\d+(?:\.\d+)?),(\d+(?:\.\d+)?),(\d+(?:\.\d+)?);系数:(\d+(?:\.\d+)?)/g,
|
||||
/(SMALL|MEDIUM|LARGE|EXTRA_LARGE):(\d+(?:\.\d+)?),(\d+(?:\.\d+)?),(\d+(?:\.\d+)?);系数:(\d+(?:\.\d+)?)(?:;重量:(\d+(?:\.\d+)?))?/g,
|
||||
)].map((match) => ({
|
||||
dimensions: [Number(match[2]), Number(match[3]), Number(match[4])].sort((left, right) => right - left),
|
||||
coefficient: Number(match[5]),
|
||||
maxWeightKg: match[6] == null ? null : Number(match[6]),
|
||||
})).filter((tier) => tier.dimensions.every((value) => Number.isFinite(value) && value > 0)
|
||||
&& Number.isFinite(tier.coefficient) && tier.coefficient > 0)
|
||||
&& Number.isFinite(tier.coefficient) && tier.coefficient > 0
|
||||
&& (tier.maxWeightKg == null || (Number.isFinite(tier.maxWeightKg) && tier.maxWeightKg > 0)))
|
||||
.sort((left, right) => left.dimensions.reduce((total, value) => total * value, 1)
|
||||
- right.dimensions.reduce((total, value) => total * value, 1))
|
||||
if (!tiers.length) return Number(rule.lengthFactor || 1)
|
||||
const measured = [Number(row.lengthCm), Number(row.widthCm), Number(row.heightCm)]
|
||||
.sort((left, right) => right - left)
|
||||
const matched = tiers.find((tier) => measured.every((value, index) => value <= tier.dimensions[index]))
|
||||
const unitWeight = Number(row.unitWeightKg)
|
||||
const matched = tiers.find((tier) => measured.every((value, index) => value <= tier.dimensions[index])
|
||||
&& (tier.maxWeightKg == null || !Number.isFinite(unitWeight) || unitWeight <= tier.maxWeightKg))
|
||||
return (matched || tiers[tiers.length - 1]).coefficient
|
||||
}
|
||||
|
||||
@@ -351,7 +355,7 @@ function calculatedMeasurementRow(
|
||||
if (!rawDimensions.every((value) => Number.isFinite(value) && value > 0)) return { ...source }
|
||||
|
||||
const matchedDimensions = mode === 'ADD' && rule
|
||||
? rawDimensions.map((value) => value + rule.edgeAdditionCm)
|
||||
? rawDimensions.map((value) => value + rule.edgeAdditionCm * 2)
|
||||
: rawDimensions
|
||||
const chargeRule = activeMeasurementChargeRule.value
|
||||
const specificationCoefficient = mode === 'MULTIPLY' && chargeRule
|
||||
@@ -364,9 +368,13 @@ function calculatedMeasurementRow(
|
||||
? 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 fallbackMeasuredUnitWeight = !customerSource && Number.isFinite(Number(measurementDetail.value?.actualGrossWeightKg))
|
||||
&& Number(measurementDetail.value?.actualPackageCount) > 0
|
||||
? Number(measurementDetail.value?.actualGrossWeightKg) / Number(measurementDetail.value?.actualPackageCount)
|
||||
: null
|
||||
const sourceUnitWeight = customerSource
|
||||
? Number(source.grossWeightKg) / packageCount
|
||||
: Number(source.unitWeightKg)
|
||||
: Number.isFinite(Number(source.unitWeightKg)) ? Number(source.unitWeightKg) : fallbackMeasuredUnitWeight
|
||||
const unitWeightKg = Number.isFinite(sourceUnitWeight) ? sourceUnitWeight : null
|
||||
const totalWeightKg = unitWeightKg != null && Number.isFinite(packageCount) ? unitWeightKg * packageCount : null
|
||||
return {
|
||||
@@ -383,6 +391,20 @@ const customerMeasurementRows = computed(() => (detail.value?.order.cargoes || [
|
||||
)))
|
||||
const outerMeasurementRows = computed(() => (measurementDetail.value?.items || []).map((row) => {
|
||||
const source = row as unknown as Record<string, unknown>
|
||||
const savedDimensions = [row.calculatedOuterLengthCm, row.calculatedOuterWidthCm, row.calculatedOuterHeightCm]
|
||||
if (savedDimensions.every((value) => Number.isFinite(Number(value)) && Number(value) > 0)
|
||||
&& measurementCalculationModeForRow(source) === measurementSectionModes.outer) {
|
||||
const packageCount = Number(row.packageCount)
|
||||
const unitWeightKg = Number.isFinite(Number(row.unitWeightKg)) ? Number(row.unitWeightKg) : null
|
||||
return {
|
||||
...source,
|
||||
lengthCm: Number(savedDimensions[0]),
|
||||
widthCm: Number(savedDimensions[1]),
|
||||
heightCm: Number(savedDimensions[2]),
|
||||
unitWeightKg,
|
||||
totalWeightKg: unitWeightKg != null && Number.isFinite(packageCount) ? unitWeightKg * packageCount : null,
|
||||
}
|
||||
}
|
||||
return calculatedMeasurementRow(source, measurementSectionModes.outer)
|
||||
}))
|
||||
const actualMeasurementRows = computed(() => (measurementDetail.value?.items || []).map((row) => (
|
||||
@@ -397,6 +419,18 @@ function updateMeasurementSectionMode(section: MeasurementSection, mode: Measure
|
||||
measurementSectionModes[section] = mode
|
||||
}
|
||||
|
||||
async function selectAndSaveOuterMeasurementMode(mode: MeasurementCalculationMode) {
|
||||
if (measurementStrategySavingId.value) return
|
||||
const previousMode = measurementSectionModes.outer
|
||||
if (mode === 'MULTIPLY' && !activeMeasurementChargeRule.value) {
|
||||
ElMessage.warning('该客户尚未启用系数配置,请先到客户计费规则中设置默认规则')
|
||||
return
|
||||
}
|
||||
measurementSectionModes.outer = mode
|
||||
const saved = await updateMeasurementCalculationMode(null, mode)
|
||||
if (!saved) measurementSectionModes.outer = previousMode
|
||||
}
|
||||
|
||||
const statusTabs = computed(() => [
|
||||
{ value: '' as const, label: '全部' },
|
||||
...unifiedOrderStatusOptions,
|
||||
@@ -777,6 +811,10 @@ function measurementValue(row: Record<string, unknown>, key: string, customerSou
|
||||
const count = Number(row.packageCount)
|
||||
return Number.isFinite(total) && Number.isFinite(count) && count > 0 ? formatNumber(total / count, 4) : '—'
|
||||
}
|
||||
if (key === 'unitWeightKg') {
|
||||
const value = Number(row[key])
|
||||
return Number.isFinite(value) ? formatNumber(value, 4) : '—'
|
||||
}
|
||||
if (customerSource && key === 'unitVolumeCbm') {
|
||||
const total = Number(row.volumeCbm)
|
||||
const count = Number(row.packageCount)
|
||||
@@ -804,10 +842,10 @@ function measurementCalculationModeForRow(row: Record<string, unknown>): Measure
|
||||
return measuredItem?.coefficientMode === 'MULTIPLY' ? 'MULTIPLY' : measuredItem?.coefficientMode === 'ADD' ? 'ADD' : 'ACTUAL'
|
||||
}
|
||||
|
||||
async function updateMeasurementCalculationMode(row: Record<string, unknown> | null, mode: Exclude<MeasurementCalculationMode, 'ACTUAL'>) {
|
||||
async function updateMeasurementCalculationMode(row: Record<string, unknown> | null, mode: MeasurementCalculationMode): Promise<boolean> {
|
||||
const summary = detail.value?.summary
|
||||
const measurement = measurementDetail.value
|
||||
if (!summary?.inboundId || !measurement?.measurementId || measurement.version == null || !can('platform:firstleg:inbound:measure:edit')) return
|
||||
if (!summary?.inboundId || !measurement?.measurementId || measurement.version == null || !can('platform:firstleg:inbound:measure:edit')) return false
|
||||
const itemId = normalizedIdentifier(row?.id)
|
||||
const itemNo = normalizedIdentifier(row?.itemNo)
|
||||
const targetIds = new Set(measurement.items
|
||||
@@ -815,7 +853,7 @@ async function updateMeasurementCalculationMode(row: Record<string, unknown> | n
|
||||
.map((item) => String(item.id)))
|
||||
if (!targetIds.size) {
|
||||
ElMessage.warning('当前数据尚未关联实测明细,暂不能设置计算方式')
|
||||
return
|
||||
return false
|
||||
}
|
||||
measurementStrategySavingId.value = row ? (itemId || `item-${itemNo}`) : 'all'
|
||||
try {
|
||||
@@ -826,7 +864,7 @@ async function updateMeasurementCalculationMode(row: Record<string, unknown> | n
|
||||
) === 'MULTIPLY')
|
||||
if (requiresMultiply && !activeRule) {
|
||||
ElMessage.warning('该客户尚未启用系数配置,请先到客户计费规则中设置默认规则')
|
||||
return
|
||||
return false
|
||||
}
|
||||
await saveInboundMeasurementDraft(String(summary.tenantId), String(summary.inboundId), {
|
||||
measurementId: String(measurement.measurementId),
|
||||
@@ -852,17 +890,19 @@ async function updateMeasurementCalculationMode(row: Record<string, unknown> | n
|
||||
chargeRuleId: (targetIds.has(String(item.id)) ? mode : item.coefficientMode) === 'MULTIPLY'
|
||||
? activeRule!.id
|
||||
: null,
|
||||
coefficientMode: targetIds.has(String(item.id)) ? mode : item.coefficientMode || 'ADD',
|
||||
coefficientMode: targetIds.has(String(item.id)) ? mode : item.coefficientMode || 'ACTUAL',
|
||||
remark: item.remark,
|
||||
})),
|
||||
})
|
||||
measurementLoadedKey.value = ''
|
||||
await loadMeasurementDetails()
|
||||
ElMessage.success(`${row ? '当前数据' : '全部测量数据'}的计算方式已更新,体积已重新计算`)
|
||||
return true
|
||||
} catch (error) {
|
||||
measurementLoadedKey.value = ''
|
||||
await loadMeasurementDetails()
|
||||
ElMessage.error(getApiErrorDetails(error, '计算方式更新失败').message)
|
||||
return false
|
||||
} finally {
|
||||
measurementStrategySavingId.value = ''
|
||||
}
|
||||
@@ -892,9 +932,7 @@ async function saveWarehouseOuterDimensions(row: Record<string, unknown>) {
|
||||
ElMessage.warning('仓库修改外箱尺寸必须大于 0')
|
||||
return
|
||||
}
|
||||
const selectedMode: 'ADD' | 'MULTIPLY' = measurementSectionModes.outer === 'MULTIPLY'
|
||||
? 'MULTIPLY'
|
||||
: 'ADD'
|
||||
const selectedMode: MeasurementCalculationMode = measurementSectionModes.outer
|
||||
const selectedChargeRuleId = selectedMode === 'MULTIPLY'
|
||||
? activeMeasurementChargeRule.value?.id || null
|
||||
: null
|
||||
@@ -924,7 +962,7 @@ async function saveWarehouseOuterDimensions(row: Record<string, unknown>) {
|
||||
chargeRuleId: String(item.id) === String(row.id) ? selectedChargeRuleId : item.chargeRuleId,
|
||||
coefficientMode: String(item.id) === String(row.id)
|
||||
? selectedMode
|
||||
: item.coefficientMode || 'ADD',
|
||||
: item.coefficientMode || 'ACTUAL',
|
||||
remark: item.remark,
|
||||
})),
|
||||
})
|
||||
@@ -1054,11 +1092,16 @@ async function loadMeasurementDetails() {
|
||||
loadMeasurementDimensionConfig(),
|
||||
])
|
||||
if (serial !== measurementRequestSerial) return
|
||||
const configuredMode = measurementDimensionConfig.value?.defaultCalculationMode
|
||||
measurementSectionModes.outer = configuredMode === 'MULTIPLY' && activeMeasurementChargeRule.value
|
||||
? 'MULTIPLY'
|
||||
: 'ADD'
|
||||
measurementDetail.value = response
|
||||
const savedModes = [...new Set(response.items.map((item) => item.coefficientMode)
|
||||
.filter((mode): mode is MeasurementCalculationMode => mode === 'ACTUAL' || mode === 'ADD' || mode === 'MULTIPLY'))]
|
||||
const configuredMode = measurementDimensionConfig.value?.defaultCalculationMode
|
||||
// 已保存的明细规则优先于客户默认配置,确保再次进入时回显上次选择及其计算结果。
|
||||
measurementSectionModes.outer = savedModes.length === 1 ? savedModes[0]!
|
||||
: configuredMode === 'MULTIPLY' && activeMeasurementChargeRule.value ? 'MULTIPLY'
|
||||
: configuredMode === 'ADD' ? 'ADD' : 'ACTUAL'
|
||||
measurementSectionModes.customer = measurementSectionModes.outer
|
||||
measurementSectionModes.actual = 'ACTUAL'
|
||||
measurementLoadedKey.value = key
|
||||
} catch (error) {
|
||||
if (serial !== measurementRequestSerial) return
|
||||
@@ -1286,7 +1329,7 @@ function openMeasurement(row: UnifiedOrderResource) {
|
||||
measurementDialogOpen.value = true
|
||||
}
|
||||
|
||||
function openFeeConfirmDialog() {
|
||||
async function openFeeConfirmDialog() {
|
||||
const summary = detail.value?.summary
|
||||
const reviewStatus = String(summary?.measurement?.reviewStatus ?? '').trim().toUpperCase()
|
||||
if (reviewStatus !== 'APPROVED') {
|
||||
@@ -1300,8 +1343,28 @@ function openFeeConfirmDialog() {
|
||||
if (confirmFeeSending.value) {
|
||||
return
|
||||
}
|
||||
feeConfirmWeight.value = Number(summary.measurement?.actualGrossWeightKg) || null
|
||||
feeConfirmVolume.value = Number(summary.measurement?.actualVolumeCbm) || null
|
||||
try {
|
||||
const snapshot = await getLatestInboundFee(String(summary.tenantId), String(summary.inboundId))
|
||||
if (snapshot.customerConfirmationStatus === 'CONFIRMED' || snapshot.customerConfirmedAt) {
|
||||
ElMessage.warning('客户已确认该费用,费用已锁定,不允许再修改或重新发送')
|
||||
return
|
||||
}
|
||||
} catch (error) {
|
||||
ElMessage.error(getApiErrorDetails(error, '费用状态查询失败,请刷新后重试').message)
|
||||
return
|
||||
}
|
||||
if (measurementStrategySavingId.value) {
|
||||
ElMessage.warning('外箱规计算规则正在保存,请稍后再发送费用')
|
||||
return
|
||||
}
|
||||
const outerTotals = measurementTotals(outerMeasurementRows.value)
|
||||
if (!outerMeasurementRows.value.length || !(Number(outerTotals.gross) > 0)
|
||||
|| !(Number(outerTotals.volume) > 0)) {
|
||||
ElMessage.warning('外箱规数据不完整,请先保存外箱规尺寸和计算规则')
|
||||
return
|
||||
}
|
||||
feeConfirmWeight.value = Number(outerTotals.gross)
|
||||
feeConfirmVolume.value = Number(outerTotals.volume)
|
||||
feeConfirmOpen.value = true
|
||||
}
|
||||
|
||||
@@ -1319,12 +1382,17 @@ async function executeConfirmAndSendFee() {
|
||||
const tenantId = String(summary.tenantId)
|
||||
const inboundId = String(summary.inboundId)
|
||||
let snapshot = await getLatestInboundFee(tenantId, inboundId)
|
||||
if (snapshot.customerConfirmationStatus === 'CONFIRMED' || snapshot.customerConfirmedAt) {
|
||||
ElMessage.warning('客户已确认该费用,费用已锁定,不允许再修改或重新发送')
|
||||
feeConfirmOpen.value = false
|
||||
return
|
||||
}
|
||||
if (snapshot.feeStatus === 'CALCULATED') {
|
||||
snapshot = await calculateInboundFee(tenantId, inboundId, {
|
||||
selectedWeightKg,
|
||||
selectedVolumeCbm,
|
||||
weightSource: 'ACTUAL',
|
||||
volumeSource: 'ACTUAL',
|
||||
weightSource: 'OUTER',
|
||||
volumeSource: 'OUTER',
|
||||
}, createFeeActionIdempotencyKey('calculate'))
|
||||
snapshot = await confirmInboundFee(tenantId, inboundId, createFeeActionIdempotencyKey('confirm'))
|
||||
}
|
||||
@@ -1982,7 +2050,7 @@ onBeforeUnmount(() => {
|
||||
</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 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><el-select class="measurement-section-mode" :model-value="measurementSectionModes.outer" aria-label="外箱规数据计算方式" @change="updateMeasurementSectionMode('outer', $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.outer" @click="toggleMeasurementSection('outer')"><h3>二、外箱规数据</h3><span 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><el-select class="measurement-section-mode" :model-value="measurementSectionModes.outer" aria-label="外箱规数据计算方式" :loading="Boolean(measurementStrategySavingId)" :disabled="Boolean(measurementStrategySavingId) || !can('platform:firstleg:inbound:measure:edit')" @change="selectAndSaveOuterMeasurementMode($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.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></div>
|
||||
@@ -1990,7 +2058,7 @@ onBeforeUnmount(() => {
|
||||
</section>
|
||||
<div class="measurement-rule-selector">
|
||||
<span class="measurement-rule-selector__label">箱规计算规则选择</span>
|
||||
<el-select class="measurement-rule-selector__control" :model-value="measurementSectionModes.outer" aria-label="外箱规数据计算方式" @change="updateMeasurementSectionMode('outer', $event)">
|
||||
<el-select class="measurement-rule-selector__control" :model-value="measurementSectionModes.outer" aria-label="外箱规数据计算方式" :loading="Boolean(measurementStrategySavingId)" :disabled="Boolean(measurementStrategySavingId) || !can('platform:firstleg:inbound:measure:edit')" @change="selectAndSaveOuterMeasurementMode($event)">
|
||||
<el-option label="实测原尺寸(不调整)" value="ACTUAL" />
|
||||
<el-option label="箱规尺寸" value="ADD" />
|
||||
<el-option label="箱规系数" value="MULTIPLY" :disabled="multiplyModeDisabled" />
|
||||
|
||||
Reference in New Issue
Block a user