Release/test #7

Merged
admin merged 11 commits from release/test into main 2026-09-20 19:49:09 +08:00
2 changed files with 36 additions and 11 deletions
Showing only changes of commit 2e9e8819b6 - Show all commits
@@ -78,4 +78,16 @@ describe('overseas warehouse 1920px layout acceptance', () => {
expect(lastMileDetail).toContain(':title="isSingleLineBusinessField(field) ? String(field.value) : undefined"')
expect(lastMileDetail).toContain('.detail-field-value--business { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }')
})
it('keeps the inbound detail compact and puts pallet facts before appointment metadata', () => {
const inbound = page('InboundOrderDetailView.vue')
expect(inbound).toContain('grid-template-columns: repeat(5, minmax(0, 1fr))')
expect(inbound).toContain('class="section-heading"')
expect(inbound).toContain('.detail-section { min-width: 0; padding: 0;')
expect(inbound).toContain(':deep(.density-detail-header) { border-bottom: 1px solid var(--cc-border); }')
expect(inbound).toContain('.appointment-fields { grid-template-columns:repeat(4,minmax(0,1fr)); }')
expect(inbound).toContain('class="compact-section-heading"')
expect(inbound.indexOf('class="detail-section pallet-section"')).toBeLessThan(inbound.indexOf('class="detail-section appointment-section"'))
expect(inbound).not.toContain("fields: ['状态', '预约状态'")
})
})
@@ -28,14 +28,14 @@ const fieldValues = computed<Record<string, string | number>>(() => ({
海外仓: receivingWarehouse(detail.value?.overseasWarehouseCode, detail.value?.overseasWarehouseName), FBA仓库: text(firstLine.value?.fbaWarehouseCode), 总箱数: detail.value?.expectedPackageCount ?? detail.value?.lines.reduce((sum, line) => sum + line.requiredPackageCount, 0) ?? 0,
应拣货数: detail.value?.expectedPackageCount ?? detail.value?.lines.reduce((sum, line) => sum + line.requiredPackageCount, 0) ?? 0, 实际拣货数: detail.value?.pickedPackageCount ?? detail.value?.allocations.reduce((sum, item) => sum + item.pickedPackageCount, 0) ?? 0,
'货物毛重(kg)': Number(detail.value?.totalGrossWeightKg || 0), '货物净重(kg)': Number(detail.value?.totalNetWeightKg || 0),
'计费体积(m³)': Number(detail.value?.totalVolumeCbm || 0), 总托盘数: Number(detail.value?.palletCount || 0), 状态: status(detail.value?.status),
'计费体积(m³)': Number(detail.value?.totalVolumeCbm || 0), 总托盘数: Number(detail.value?.palletCount || 0),
预约状态: '—', 预约送仓时间: '—', 预计装车时间: '—', 排车状态: '—', 创建时间: formatOverseasDateTime(detail.value?.createdAt), 更新时间: formatOverseasDateTime(detail.value?.updatedAt), 备注: text(detail.value?.remark),
}))
const groups = [
const summaryGroups = [
{ title: '单据信息', fields: ['入库单号', '入仓码', '类型', '货主', '关联订单'] },
{ title: '仓储信息', fields: ['海外仓', 'FBA仓库', '总箱数', '应拣货数', '实际拣货数', '货物毛重(kg)', '货物净重(kg)', '计费体积(m³)', '总托盘数'] },
{ title: '预约与排车', fields: ['状态', '预约状态', '预约送仓时间', '预计装车时间', '排车状态', '创建时间', '更新时间', '备注'] },
]
const appointmentFields = ['预约状态', '预约送仓时间', '预计装车时间', '排车状态', '创建时间', '更新时间', '备注']
const feeColumns: DataTableColumn[] = [{ key: 'index', label: '序号', width: 70, align: 'center' }, { key: 'name', label: '费用项目', minWidth: 180 }, { key: 'currency', label: '币种', width: 100 }, { key: 'amount', label: '金额', width: 140, align: 'right' }, { key: 'remark', label: '备注', minWidth: 200 }]
const palletColumns: DataTableColumn[] = [
{ key: 'inboundCode', prop: 'inboundCode', label: '入仓码', minWidth: 150 },
@@ -60,18 +60,31 @@ onMounted(load)
<template><OverseasDetailShell class="admin-density" dense title="入库单详情" reference-label="入库单号" :reference-value="referenceValue" back-label="返回入库单" domain="入库单详情" :pending="false" :status-text="detail ? status(detail.status) : '加载中'" @back="back">
<LoadErrorState v-if="loadError" title="入库单详情加载失败" :message="loadError.message" :loading="loading" @retry="load"><template #details><ApiErrorMeta :details="loadError" /></template></LoadErrorState>
<template v-else><section v-loading="loading" class="detail-section" aria-label="入库单基本信息"><div class="detail-groups"><section v-for="group in groups" :key="group.title" class="detail-group" :aria-label="group.title"><h2>{{ group.title }}</h2><dl class="detail-fields density-fields"><div v-for="label in group.fields" :key="label"><dt>{{ label }}</dt><dd>{{ fieldValues[label] }}</dd></div></dl></section></div></section>
<section class="detail-section pallet-section" aria-labelledby="inbound-pallet-heading"><h2 id="inbound-pallet-heading">入库单托盘明细</h2><p class="pallet-note">PDA 合托后,参与合托的入库单会分别展示同一托盘及本单对应箱数。</p><DataTable :data="palletRows" :columns="palletColumns" column-settings-mode="hide" row-key="id" empty-text="暂无托盘明细" /></section>
<section class="detail-section fee-section" aria-labelledby="inbound-fees-heading"><h2 id="inbound-fees-heading">应收费用明细</h2><DataTable :data="[]" :columns="feeColumns" column-settings-mode="hide" empty-text="当前入库计划详情接口未提供应收费用" /><footer class="fee-total"><span>应收费用合计(USD)</span><strong>—</strong></footer></section></template>
<template v-else><section v-loading="loading" class="detail-section" aria-label="入库单基本信息"><div class="detail-groups"><section v-for="group in summaryGroups" :key="group.title" class="detail-group" :aria-label="group.title"><h2>{{ group.title }}</h2><dl class="detail-fields density-fields"><div v-for="label in group.fields" :key="label"><dt>{{ label }}</dt><dd>{{ fieldValues[label] }}</dd></div></dl></section></div></section>
<section class="detail-section pallet-section" aria-labelledby="inbound-pallet-heading"><div class="section-heading"><div><h2 id="inbound-pallet-heading">入库单托盘明细</h2><p class="pallet-note">PDA 合托后,参与合托的入库单会分别展示同一托盘及本单对应箱数。</p></div><span class="section-count">{{ palletRows.length }} 条</span></div><DataTable :data="palletRows" :columns="palletColumns" column-settings-mode="hide" row-key="id" empty-text="暂无托盘明细" /></section>
<section class="detail-section appointment-section" aria-labelledby="inbound-appointment-heading"><div class="compact-section-heading"><h2 id="inbound-appointment-heading">预约与排车</h2></div><dl class="detail-fields appointment-fields density-fields"><div v-for="label in appointmentFields" :key="label" :class="{ 'is-wide': label === '备注' }"><dt>{{ label }}</dt><dd>{{ fieldValues[label] }}</dd></div></dl></section>
<section class="detail-section fee-section" aria-labelledby="inbound-fees-heading"><div class="compact-section-heading"><h2 id="inbound-fees-heading">应收费用明细</h2><span>费用结果以服务端为准</span></div><DataTable :data="[]" :columns="feeColumns" column-settings-mode="hide" empty-text="当前入库计划详情接口未提供应收费用" /><footer class="fee-total"><span>应收费用合计(USD)</span><strong>—</strong></footer></section></template>
</OverseasDetailShell></template>
<style scoped>
.detail-group:nth-child(2) { border-right: 0; }.detail-group:last-child { grid-column: 1 / -1; border-right: 0; border-bottom: 0; }.detail-group h2,.fee-section h2 { margin: 0 0 var(--admin-space-5); color: var(--cc-text); font-size: var(--admin-font-section); }.fee-section { overflow:hidden; padding-top:var(--admin-space-5); }.fee-section h2 { margin-right:var(--admin-space-5); margin-left:var(--admin-space-5); }.fee-total { display:flex; min-height:48px; align-items:center; justify-content:flex-end; gap:40px; padding:var(--admin-space-4) var(--admin-space-5); border-top:1px solid var(--cc-border); }.fee-total strong { min-width:120px; font-size:var(--admin-font-section); }
.pallet-section { overflow: hidden; padding-top: var(--admin-space-5); }.pallet-section h2 { margin: 0 var(--admin-space-5) var(--admin-space-1); color: var(--cc-text); font-size: var(--admin-font-section); }.pallet-note { margin: 0 var(--admin-space-5) var(--admin-space-5); color: var(--cc-muted); font-size: var(--admin-font-caption); }
@media(max-width:1200px){.detail-groups,.detail-fields,.detail-group:last-child .detail-fields{grid-template-columns:1fr}.detail-group:last-child{grid-column:auto}.detail-group{border-right:0}}
.detail-section { min-width: 0; padding: 0; border: 0; background: #fff; }
.detail-group h2 { margin: 0 0 var(--admin-space-3); color: var(--cc-text); font-size: var(--admin-font-section); }
.compact-section-heading { display:flex; min-height:42px; align-items:center; justify-content:space-between; gap:var(--admin-space-5); padding:var(--admin-space-2) var(--admin-space-5); border-bottom:1px solid var(--cc-border); }
.compact-section-heading h2 { margin:0; color:var(--cc-text); font-size:var(--admin-font-section); }
.compact-section-heading span { color:var(--cc-muted); font-size:var(--admin-font-caption); }
.fee-section { overflow:hidden; }.fee-total { display:flex; min-height:44px; align-items:center; justify-content:flex-end; gap:40px; padding:var(--admin-space-3) var(--admin-space-5); border-top:1px solid var(--cc-border); }.fee-total strong { min-width:120px; font-size:var(--admin-font-section); }
.pallet-section { overflow: hidden; }.section-heading { display:flex; min-height:50px; align-items:center; justify-content:space-between; gap:var(--admin-space-5); padding:var(--admin-space-3) var(--admin-space-5); border-bottom:1px solid var(--cc-border); }.pallet-section h2 { margin: 0 0 var(--admin-space-1); color: var(--cc-text); font-size: var(--admin-font-section); }.pallet-note { margin: 0; color: var(--cc-muted); font-size: var(--admin-font-caption); }.section-count { flex:0 0 auto; color:var(--cc-muted); font-size:var(--admin-font-caption); font-variant-numeric:tabular-nums; }
.appointment-section,.fee-section { border-top:1px solid var(--cc-border); }
.appointment-section { padding:0 var(--admin-space-5) var(--admin-space-4); }
.appointment-section .compact-section-heading { margin:0 calc(0px - var(--admin-space-5)) var(--admin-space-3); }
.appointment-fields { grid-template-columns:repeat(4,minmax(0,1fr)); }
.appointment-fields > .is-wide { grid-column:span 2; }
@media(max-width:1400px){.detail-fields{grid-template-columns:repeat(4,minmax(0,1fr))}}
@media(max-width:1200px){.detail-fields,.appointment-fields{grid-template-columns:repeat(2,minmax(0,1fr))}.appointment-fields > .is-wide{grid-column:span 2}}
.detail-section { min-width: 0; border: 0; background: #fff; }
.detail-groups { display: grid; grid-template-columns: minmax(0, 1fr); }
.detail-group { min-width: 0; padding: var(--admin-space-5) var(--admin-space-5) var(--admin-space-5); border-right: 0; border-bottom: 1px solid var(--cc-border); }
.detail-group { min-width: 0; padding: var(--admin-space-3) var(--admin-space-5) var(--admin-space-4); border-bottom: 1px solid var(--cc-border); }
.detail-fields { --admin-field-label-width: 108px; grid-template-columns: repeat(5, minmax(0, 1fr)); }
:deep(.density-detail-header) { border-bottom: 1px solid var(--cc-border); }
</style>