This commit is contained in:
2026-08-10 09:12:06 +08:00
parent 5815649887
commit bbe93ca235
9 changed files with 437 additions and 84 deletions
@@ -145,10 +145,12 @@ describe('UnifiedOrdersView contract', () => {
expect(source).toContain('暂无费用数据')
})
it('does not expose the unconfirmed downstream workflow', () => {
expect(source).not.toContain('后半程作业')
expect(source).not.toContain('openWorkflow')
expect(source).not.toContain('workflowEligible')
it('mounts downstream progress inside the existing order detail without opening unsafe writes', () => {
expect(source).toContain('UnifiedOrderWorkflowPanel')
expect(source).toContain("{ key: 'workflow', label: '后半程作业'")
expect(source).toContain(':read-only="true"')
expect(source).toContain(':show-delivery="false"')
expect(source).toContain("detail.value?.summary.inboundId")
expect(routeSource).not.toContain('unified-order-workflow')
})
})
@@ -26,6 +26,7 @@ import LoadErrorState from '@/shared/components/LoadErrorState.vue'
import LineClampText from '@/shared/components/LineClampText.vue'
import QueryToolbar, { type QueryField, type QueryModel } from '@/shared/components/QueryToolbar.vue'
import StatusBadge from '@/shared/components/StatusBadge.vue'
import { UnifiedOrderWorkflowPanel } from '@/modules/unified-orders/workflows'
import {
downloadWeightImage,
getInboundMeasurement,
@@ -105,6 +106,10 @@ const detailTabs = [
{ key: 'other', label: '其他', icon: StickyNote },
]
const detailTabOptions = computed(() => detail.value?.summary.inboundId
? [...detailTabs, { key: 'workflow', label: '后半程作业', icon: ListChecks }]
: detailTabs)
const customerMeasurementColumns = [
{ key: 'itemNo', label: '#' }, { key: 'lengthCm', label: '箱规长(cm)' }, { key: 'widthCm', label: '箱规宽(cm)' },
{ key: 'heightCm', label: '箱规高(cm)' }, { key: 'packageCount', label: '箱数' }, { key: 'unitWeightKg', label: '每箱毛重' },
@@ -789,7 +794,7 @@ onMounted(() => {
</section>
<div class="detail-tabs" role="tablist" aria-label="订单详情模块">
<button v-for="tab in detailTabs" :id="`order-detail-tab-${tab.key}`" :key="tab.key" type="button" role="tab" :class="{ active: activeDetailTab === tab.key }" :aria-selected="activeDetailTab === tab.key" :aria-controls="`order-detail-panel-${tab.key}`" :tabindex="activeDetailTab === tab.key ? 0 : -1" @click="selectDetailTab(tab.key)"><component :is="tab.icon" :size="17" /><span>{{ tab.label }}</span></button>
<button v-for="tab in detailTabOptions" :id="`order-detail-tab-${tab.key}`" :key="tab.key" type="button" role="tab" :class="{ active: activeDetailTab === tab.key }" :aria-selected="activeDetailTab === tab.key" :aria-controls="`order-detail-panel-${tab.key}`" :tabindex="activeDetailTab === tab.key ? 0 : -1" @click="selectDetailTab(tab.key)"><component :is="tab.icon" :size="17" /><span>{{ tab.label }}</span></button>
</div>
<section :id="`order-detail-panel-${activeDetailTab}`" class="detail-panel" role="tabpanel" :aria-labelledby="`order-detail-tab-${activeDetailTab}`" tabindex="0">
@@ -922,7 +927,20 @@ onMounted(() => {
<ol v-else class="history-list" aria-label="状态历史"><li v-for="(item, index) in detail.timeline" :key="`${item.source || 'event'}-${item.occurredAt || index}`"><span class="history-marker" aria-hidden="true" /><div><div class="history-line"><strong>{{ historyActionLabel(item.action || item.eventType) }}</strong><StatusBadge :status="statusLabel(item.mainStatus)" /></div><p>{{ item.operatorName || '系统' }} · {{ formatDate(item.occurredAt) }}</p><p v-if="item.remark" class="history-remark">{{ item.remark }}</p></div></li></ol>
</template>
<template v-else-if="activeDetailTab === 'measurement'">
<template v-else-if="activeDetailTab === 'workflow'">
<UnifiedOrderWorkflowPanel
:tenant-id="String(detail.summary.tenantId)"
:inbound-id="String(detail.summary.inboundId)"
:main-status="detail.summary.mainStatus"
:inbound-version="detail.summary.inboundVersion"
:picking-version="detail.summary.loading?.pickingVersion"
:delivery-tracking-no="detail.summary.delivery?.trackingNo"
:read-only="true"
:show-delivery="false"
@updated="loadDetail(true)"
/>
</template>
<template v-else-if="activeDetailTab === 'measurement'">
<div class="panel-title"><div><h2>测量数据</h2><p>{{ detail.summary.measurement?.completedAt ? `完成于 ${formatDate(detail.summary.measurement.completedAt)}` : '尚未完成测量' }}</p></div><Ruler :size="19" /></div>
<section class="measurement-section">
<button type="button" class="measurement-section-title" :aria-expanded="!measurementCollapsed.customer" @click="toggleMeasurementSection('customer')"><h3>一、客户下单数据</h3><span class="measurement-section-summary"><span>总件数:{{ measurementTotals(detail.order.cargoes, true).count ?? '—' }}</span><span>总毛重:{{ formatNumber(measurementTotals(detail.order.cargoes, true).gross) }}</span><span>总体积:{{ formatNumber(measurementTotals(detail.order.cargoes, true).volume, 6) }}</span><span>总材积重:{{ formatNumber(measurementTotals(detail.order.cargoes, true).volumetric) }}</span><span>重量体积:{{ formatNumber(measurementTotals(detail.order.cargoes, true).weightVolume, 6) }}</span></span><ChevronUp v-if="!measurementCollapsed.customer" :size="18" /><ChevronDown v-else :size="18" /></button>