- 公司
- {{ customerName(detail.summary) }}
- - 运输方式
- {{ detail.order.order?.transportMode || '—' }}
+ - 运输方式
- {{ firstLegTransportModeLabel(detail.order.order?.transportMode) }}
- 当前状态
- - 内部订单状态
- {{ detail.summary.internalOrderStatus || '—' }}
+ - 内部订单状态
- {{ orderStatusLabel(detail.summary.internalOrderStatus || detail.summary.mainStatus) }}
- 平台收货仓
- {{ detail.summary.receivingWarehouseName || '—' }}
- 收货仓地址
- {{ detail.order.order?.receivingWarehouseAddress || '—' }}
- 目的仓
- {{ detail.summary.destinationWarehouseName || '—' }}
@@ -860,13 +871,13 @@ onMounted(() => {
- 目的仓联系人
- {{ detail.summary.destinationContact || '—' }}
- 目的仓联系人电话
- {{ detail.summary.destinationContactPhone || '—' }}
- 渠道
- {{ detail.summary.channelName || '—' }}
- - 业务类型
- {{ detail.summary.businessType || '—' }}
- - 贸易条款
- {{ detail.order.order?.tradeTerm || '—' }}
- - 买单 / 退税
- {{ detail.order.order?.taxMode || '—' }}
- - 费用审核状态
- {{ detail.summary.feeReviewStatus || '—' }}
+ - 业务类型
- {{ firstLegBusinessTypeLabel(detail.summary.businessType) }}
+ - 贸易条款
- {{ firstLegTradeTermLabel(detail.order.order?.tradeTerm) }}
+ - 买单 / 退税
- {{ firstLegTaxModeLabel(detail.order.order?.taxMode) }}
+ - 费用审核状态
- {{ feeReviewLabel(detail.summary.feeReviewStatus) }}
- 是否扣货
- {{ displayBoolean(detail.summary.holdCargo) }}
- 扣货理由
- {{ detail.summary.holdReason || '—' }}
- - 提货方式
- {{ detail.order.order?.pickupMethod || '—' }}
+ - 提货方式
- {{ firstLegPickupMethodLabel(detail.order.order?.pickupMethod) }}
- 提货时间
- {{ formatDate(detail.summary.pickupAt) }}
- 到仓时间
- {{ detail.order.order?.receivingTime || '—' }}
- 货物到仓时间
- {{ formatDate(detail.summary.expectedArrivalAt || detail.summary.inboundCompletedAt) }}
@@ -877,9 +888,9 @@ onMounted(() => {
- 船名 / 航次
- {{ detail.summary.transport?.vesselName || '—' }} / {{ detail.summary.transport?.voyageNo || '—' }}
- 开船时间
- {{ formatDate(detail.summary.transport?.sailingAt) }}
- 到港时间
- {{ formatDate(detail.summary.transport?.portArrivalAt) }}
- - 配载状态
- {{ detail.summary.transport?.loadingStatus || '—' }}
- - 目的仓类型
- {{ detail.order.order?.destinationType || '—' }}
- - 是否整柜
- {{ detail.order.order?.containerMode || '—' }}
+ - 配载状态
- {{ unifiedOrderLoadingStatusLabel(detail.summary.transport?.loadingStatus) }}
+ - 目的仓类型
- {{ firstLegDestinationTypeLabel(detail.order.order?.destinationType) }}
+ - 是否整柜
- {{ firstLegContainerModeLabel(detail.order.order?.containerMode) }}
- 商检验
- {{ displayBoolean(detail.order.order?.customsInspection) }}
- 总箱数
- {{ detail.summary.totalPackageCount ?? '—' }} 箱
- 总托盘数
- {{ detail.summary.totalPalletCount ?? '—' }}
@@ -1097,7 +1108,7 @@ onMounted(() => {
{{ customerName(row as UnifiedOrderResource) }}客户 ID {{ (row as UnifiedOrderResource).tenantId }}
{{ (row as UnifiedOrderResource).receivingWarehouseName || '—' }}
{{ (row as UnifiedOrderResource).destinationWarehouseName || '—' }}
- {{ (row as UnifiedOrderResource).transport?.containerNo || (row as UnifiedOrderResource).transport?.loadingStatus || '—' }}{{ (row as UnifiedOrderResource).transport?.vesselName }} · {{ (row as UnifiedOrderResource).transport?.voyageNo || '—' }}
+ {{ (row as UnifiedOrderResource).transport?.containerNo || unifiedOrderLoadingStatusLabel((row as UnifiedOrderResource).transport?.loadingStatus) }}{{ (row as UnifiedOrderResource).transport?.vesselName }} · {{ (row as UnifiedOrderResource).transport?.voyageNo || '—' }}
{{ (row as UnifiedOrderResource).totalPackageCount ?? '—' }} 箱 · {{ formatNumber((row as UnifiedOrderResource).measurement?.actualGrossWeightKg) }} kg · {{ formatNumber((row as UnifiedOrderResource).measurement?.actualVolumeCbm, 3) }} m³
{{ formatDate((row as UnifiedOrderResource).expectedShipDate) }}
{{ formatDate((row as UnifiedOrderResource).updatedAt) }}
diff --git a/src/modules/unified-orders/status.test.ts b/src/modules/unified-orders/status.test.ts
new file mode 100644
index 00000000..67f1c062
--- /dev/null
+++ b/src/modules/unified-orders/status.test.ts
@@ -0,0 +1,31 @@
+import { describe, expect, it } from 'vitest'
+import {
+ unifiedOrderFulfillmentRoleLabel,
+ unifiedOrderFulfillmentStatusLabel,
+ unifiedOrderHistoryActionLabel,
+ unifiedOrderLoadingStatusLabel,
+ unifiedOrderReviewStatusLabel,
+ unifiedOrderStatusLabel,
+} from './status'
+
+describe('unified order status labels', () => {
+ it('maps order, review and loading statuses to domain-specific Chinese', () => {
+ expect(unifiedOrderStatusLabel('WAIT_SPLIT')).toBe('待分柜')
+ expect(unifiedOrderReviewStatusLabel('APPROVED')).toBe('审核通过')
+ expect(unifiedOrderLoadingStatusLabel('LOADED')).toBe('已配载')
+ })
+
+ it('never exposes unknown backend enums', () => {
+ expect(unifiedOrderStatusLabel('NEW_ORDER_STATE')).toBe('未知状态')
+ expect(unifiedOrderReviewStatusLabel('NEW_REVIEW_STATE')).toBe('未知状态')
+ expect(unifiedOrderLoadingStatusLabel('NEW_LOADING_STATE')).toBe('未知状态')
+ expect(unifiedOrderHistoryActionLabel('NEW_ACTION')).toBe('状态更新')
+ expect(unifiedOrderFulfillmentRoleLabel('NEW_ROLE')).toBe('未知类型')
+ expect(unifiedOrderFulfillmentStatusLabel('NEW_FRAGMENT_STATE', 'REMAINDER')).toBe('未知状态')
+ })
+
+ it('uses the fragment role when a fulfillment status is absent', () => {
+ expect(unifiedOrderFulfillmentStatusLabel(null, 'ACTIVE_REMAINDER')).toBe('当前余量')
+ expect(unifiedOrderFulfillmentStatusLabel(undefined, 'COMPLETED_FRAGMENT')).toBe('已完成分片')
+ })
+})
diff --git a/src/modules/unified-orders/status.ts b/src/modules/unified-orders/status.ts
new file mode 100644
index 00000000..e426c475
--- /dev/null
+++ b/src/modules/unified-orders/status.ts
@@ -0,0 +1,98 @@
+const orderStatusLabels: Record = {
+ DRAFT: '草稿',
+ SUBMITTED: '待审核',
+ APPROVED: '已审核',
+ ACCEPTED: '已受理',
+ REJECTED: '已驳回',
+ PROCESSING: '处理中',
+ COMPLETED: '已完成',
+ CANCELLED: '已取消',
+ PENDING_REVIEW: '待审核',
+ WAIT_MEASURE: '待测量数据',
+ INBOUNDED: '已入库',
+ WAIT_SPLIT: '待分柜',
+ LOADING: '装柜中',
+ LOADED: '装柜完成',
+ DELIVERED: '派送完成',
+}
+
+const reviewStatusLabels: Record = {
+ NOT_SUBMITTED: '未提交',
+ UNRECORDED: '未录入',
+ PENDING: '待审核',
+ APPROVED: '审核通过',
+ REJECTED: '审核驳回',
+ CONFIRMED: '已确认',
+}
+
+const loadingStatusLabels: Record = {
+ NOT_LOADED: '未配载',
+ WAIT_LOADING: '待配载',
+ EDITING: '预装柜中',
+ LOADING: '配载中',
+ LOADED: '已配载',
+ COMPLETED: '装柜完成',
+}
+
+const historyActionLabels: Record = {
+ CREATE: '创建订单',
+ CREATED: '创建订单',
+ SUBMITTED: '提交订单',
+ APPROVED: '审核通过',
+ ORDER_APPROVED: '订单审核通过',
+ REJECTED: '审核驳回',
+ MEASURE_APPROVE: '测量审核通过',
+ MEASURE_REJECT: '测量审核驳回',
+ INBOUND_BEGIN: '开始入库',
+ INBOUND_COMPLETE: '入库完成',
+ UI_FIXTURE_MEASURE_APPROVE: '测量数据审核通过',
+ UI_FIXTURE_INBOUND_BEGIN: '开始入库',
+ STATUS_UPDATE: '状态更新',
+}
+
+const fulfillmentRoleLabels: Record = {
+ REMAINDER: '当前余量',
+ ACTIVE_REMAINDER: '当前余量',
+ LOADED: '已完成分片',
+ COMPLETED_FRAGMENT: '已完成分片',
+ SOURCE_COMPLETED: '已完成分片',
+}
+
+function normalized(value: string | null | undefined) {
+ return value?.trim().toUpperCase() || ''
+}
+
+function statusLabel(value: string | null | undefined, labels: Record, emptyLabel = '—') {
+ const status = normalized(value)
+ if (!status) return emptyLabel
+ return labels[status] || '未知状态'
+}
+
+export function unifiedOrderStatusLabel(value: string | null | undefined, emptyLabel = '—') {
+ return statusLabel(value, orderStatusLabels, emptyLabel)
+}
+
+export function unifiedOrderReviewStatusLabel(value: string | null | undefined, emptyLabel = '—') {
+ return statusLabel(value, reviewStatusLabels, emptyLabel)
+}
+
+export function unifiedOrderLoadingStatusLabel(value: string | null | undefined, emptyLabel = '—') {
+ return statusLabel(value, loadingStatusLabels, emptyLabel)
+}
+
+export function unifiedOrderHistoryActionLabel(value: string | null | undefined) {
+ const action = normalized(value)
+ if (!action) return '状态更新'
+ return historyActionLabels[action] || '状态更新'
+}
+
+export function unifiedOrderFulfillmentRoleLabel(value: string | null | undefined) {
+ const role = normalized(value)
+ if (!role) return '分片'
+ return fulfillmentRoleLabels[role] || '未知类型'
+}
+
+export function unifiedOrderFulfillmentStatusLabel(status: string | null | undefined, role: string | null | undefined) {
+ if (!status) return unifiedOrderFulfillmentRoleLabel(role)
+ return unifiedOrderStatusLabel(status)
+}
diff --git a/src/shared/utils/firstLegBusinessLabels.test.ts b/src/shared/utils/firstLegBusinessLabels.test.ts
new file mode 100644
index 00000000..29bd8a55
--- /dev/null
+++ b/src/shared/utils/firstLegBusinessLabels.test.ts
@@ -0,0 +1,22 @@
+import { describe, expect, it } from 'vitest'
+import {
+ firstLegBusinessTypeLabel, firstLegContainerModeLabel, firstLegDestinationTypeLabel,
+ firstLegPickupMethodLabel, firstLegTaxModeLabel, firstLegTradeTermLabel, firstLegTransportModeLabel,
+} from './firstLegBusinessLabels'
+
+describe('first-leg business labels', () => {
+ it('translates business codes using the customer order contract', () => {
+ expect(firstLegTransportModeLabel('SEA')).toBe('海运')
+ expect(firstLegTradeTermLabel('FOB')).toBe('FOB(离岸价)')
+ expect(firstLegPickupMethodLabel('PICKUP')).toBe('平台上门提货')
+ expect(firstLegTaxModeLabel('BUY_DECLARATION')).toBe('买单报关')
+ expect(firstLegContainerModeLabel('FULL_CONTAINER')).toBe('整柜')
+ expect(firstLegDestinationTypeLabel('OVERSEAS')).toBe('海外仓')
+ expect(firstLegBusinessTypeLabel('EXPORT')).toBe('出口业务')
+ })
+
+ it('does not expose unknown backend codes', () => {
+ expect(firstLegTransportModeLabel('NEW_MODE')).toBe('未知类型')
+ expect(firstLegTaxModeLabel(null)).toBe('—')
+ })
+})
diff --git a/src/shared/utils/firstLegBusinessLabels.ts b/src/shared/utils/firstLegBusinessLabels.ts
new file mode 100644
index 00000000..5e2ae4c3
--- /dev/null
+++ b/src/shared/utils/firstLegBusinessLabels.ts
@@ -0,0 +1,32 @@
+const businessTypeLabels: Record = {
+ EXPORT: '出口业务', FIRST_LEG: '头程物流', FBA: 'FBA 头程', FBA_SEA: 'FBA 海运',
+}
+const transportModeLabels: Record = {
+ SEA: '海运', AIR: '空运', RAIL: '铁路运输', TRUCK: '卡车运输',
+}
+const tradeTermLabels: Record = {
+ EXW: 'EXW(工厂交货)', FCA: 'FCA(货交承运人)', FOB: 'FOB(离岸价)',
+ CFR: 'CFR(成本加运费)', CIF: 'CIF(成本、保险费加运费)',
+ DDU: 'DDU(未完税交货)', DDP: 'DDP(完税后交货)',
+}
+const pickupMethodLabels: Record = {
+ SELF_EXPRESS: '自行快递到仓', PICKUP: '平台上门提货', SELF_TRUCK: '自行送货到仓', WAREHOUSE: '送至平台仓库',
+}
+const taxModeLabels: Record = {
+ BUY_DECLARATION: '买单报关', TAX_REFUND: '退税报关', TAX_INCLUDED: '包税', TAX_EXCLUDED: '不包税', DDP: '包税', DDU: '不包税',
+}
+const containerModeLabels: Record = { FULL_CONTAINER: '整柜', FCL: '整柜', LCL: '拼箱' }
+const destinationTypeLabels: Record = { FBA: 'FBA 仓', OVERSEAS: '海外仓', PRIVATE: '私人地址' }
+
+function label(value: string | null | undefined, labels: Record) {
+ if (!value) return '—'
+ return labels[value.trim().toUpperCase()] || '未知类型'
+}
+
+export const firstLegBusinessTypeLabel = (value: string | null | undefined) => label(value, businessTypeLabels)
+export const firstLegTransportModeLabel = (value: string | null | undefined) => label(value, transportModeLabels)
+export const firstLegTradeTermLabel = (value: string | null | undefined) => label(value, tradeTermLabels)
+export const firstLegPickupMethodLabel = (value: string | null | undefined) => label(value, pickupMethodLabels)
+export const firstLegTaxModeLabel = (value: string | null | undefined) => label(value, taxModeLabels)
+export const firstLegContainerModeLabel = (value: string | null | undefined) => label(value, containerModeLabels)
+export const firstLegDestinationTypeLabel = (value: string | null | undefined) => label(value, destinationTypeLabels)