diff --git a/src/modules/overseas-warehouse/pages/DeliveryOrderDetailView.vue b/src/modules/overseas-warehouse/pages/DeliveryOrderDetailView.vue index 64982697..64152d13 100644 --- a/src/modules/overseas-warehouse/pages/DeliveryOrderDetailView.vue +++ b/src/modules/overseas-warehouse/pages/DeliveryOrderDetailView.vue @@ -22,13 +22,14 @@ const customerId = computed(() => String(route.query.customerId || '').trim()) const statusLabels: Record = { WAIT_DELIVERY: '待派送', DELIVERING: '派送中', DELIVERED: '派送完成', SIGNED: '已签收', REJECTED: '已拒签', RETURN_PENDING: '退货处理中', CANCELLED: '已取消' } const methodLabels: Record = { FBA_PICKUP: 'FBA自提', CUSTOMER_PICKUP: '客户自提', TRUCK: '卡车派送', TRUCK_PALLET: '卡派打托', TRUCK_FLOOR: '卡派地板', EXPRESS: '快递', OUTSOURCED: '外配', DEDICATED_TRUCK: '专车直送', LTL: '零担派送', SELF_DELIVERY: '自送', THIRD_PARTY: '第三方配送' } -const pickupLabels: Record = { WAREHOUSE_PICKUP: '仓库提货', DOOR_PICKUP: '上门提货', SELF_PICKUP: '自提' } -const loadingLabels: Record = { PALLET: '打托装车', FLOOR: '地板装车', CARTON: '散箱装车' } +const pickupLabels: Record = { ONE_PICKUP_ONE_DROP: '一提一卸', ONE_PICKUP_MULTI_DROP: '一提多卸', MULTI_PICKUP_ONE_DROP: '多提一卸', MULTI_PICKUP_MULTI_DROP: '多提多卸', WAREHOUSE_PICKUP: '仓库自提', DOOR_PICKUP: '上门提货', SELF_PICKUP: '自提' } +const loadingLabels: Record = { PALLET: '托盘', FLOOR: '地板', MIXED: '混装', CARTON: '散箱' } const feeLabels: Record = { DELIVERY_FEE: '派送费用', EXPRESS_FEE: '快递费用', LOADING_FEE: '装车费', APPOINTMENT_FEE: '买约费用', OTHER: '其他费用' } const operationLabels: Record = { CREATE_DELIVERY: '创建派送单', ASSIGN_VEHICLE: '车队分配', DISPATCH: '开始派送', SIGN: '签收', COMPLETE_DELIVERY: '完成派送', UPDATE_DELIVERY_STATUS: '更新派送状态', CUSTOMER_VISIT: '客户回访', MARK_RETURN: '标记退货', CANCEL_OUTBOUND: '取消出库' } const resultLabels: Record = { CREATED: '已创建' } function show(value: unknown) { const text = String(value ?? '').trim(); return text || '—' } +function displayPerson(value: unknown) { const text = String(value ?? '').trim(); return text && !/^\d+$/.test(text) ? text : '—' } function quantity(value: number | null | undefined, unit: string) { return value === null || value === undefined ? '—' : `${value} ${unit}` } function customerConfirmation() { const signedAt = detail.value?.order.signedAt; return signedAt ? `已签收 · ${formatOverseasDateTime(signedAt)}` : '—' } function back() { void router.push({ name: 'overseas-delivery-orders' }) } @@ -67,7 +68,7 @@ watch([deliveryNo, customerId], () => { void load() }, { immediate: true })

订单信息

派送单号
{{ show(detail.order.deliveryNo) }}
状态
{{ statusLabels[detail.order.status] || detail.order.status }}
-
仓库
{{ show(detail.order.overseasWarehouseName || detail.order.overseasWarehouseId) }}
运单号
{{ show(detail.order.waybillNo) }}
+
仓库
{{ show(detail.order.overseasWarehouseName) }}
运单号
{{ show(detail.order.waybillNo) }}
派送人
{{ show(detail.order.carrierName) }}
派送时间
{{ formatOverseasDateTime(detail.order.dispatchedAt || detail.order.plannedDeliveryAt) }}
提货方式
{{ pickupLabels[detail.order.pickupMethod || ''] || show(detail.order.pickupMethod) }}
装车类型
{{ loadingLabels[detail.order.loadingType || ''] || show(detail.order.loadingType) }}
派送方式
{{ methodLabels[detail.order.deliveryMethod || ''] || show(detail.order.deliveryMethod) }}
司机/车队
{{ show(detail.order.driverName) }}
@@ -106,7 +107,7 @@ watch([deliveryNo, customerId], () => { void load() }, { immediate: true }) - + diff --git a/src/modules/overseas-warehouse/pages/DeliveryOrdersView.vue b/src/modules/overseas-warehouse/pages/DeliveryOrdersView.vue index 56f523d1..e354e744 100644 --- a/src/modules/overseas-warehouse/pages/DeliveryOrdersView.vue +++ b/src/modules/overseas-warehouse/pages/DeliveryOrdersView.vue @@ -50,8 +50,8 @@ const columns: DataTableColumn[] = [ { key: 'driverName', prop: 'driverName', label: '司机/车队', minWidth: 140 }, { key: 'plannedDeliveryAt', prop: 'plannedDeliveryAt', label: '期望派送时间', minWidth: 170, formatter: (row: DeliveryOrderRow) => formatOverseasDateTime(row.plannedDeliveryAt) }, { key: 'dispatchedAt', prop: 'dispatchedAt', label: '派送时间', minWidth: 170, formatter: (row: DeliveryOrderRow) => formatOverseasDateTime(row.dispatchedAt) }, - { key: 'pickupMethod', prop: 'pickupMethod', label: '提货方式', width: 110 }, - { key: 'loadingType', prop: 'loadingType', label: '装车类型', width: 110 }, + { key: 'pickupMethod', prop: 'pickupMethod', label: '提货方式', width: 110, formatter: (row: DeliveryOrderRow) => pickupMethodLabel(row.pickupMethod) }, + { key: 'loadingType', prop: 'loadingType', label: '装车类型', width: 110, formatter: (row: DeliveryOrderRow) => loadingTypeLabel(row.loadingType) }, { key: 'packageCount', prop: 'packageCount', label: '总箱数', width: 90, align: 'right' }, { key: 'totalWeightKg', prop: 'totalWeightKg', label: '总重量(kg)', width: 120, align: 'right' }, { key: 'totalVolumeCbm', prop: 'totalVolumeCbm', label: '总体积(m³)', width: 120, align: 'right' }, @@ -61,6 +61,8 @@ const columns: DataTableColumn[] = [ ] const statusLabels: Record = { WAIT_DELIVERY: '待派送', DELIVERING: '派送中', DELIVERED: '派送完成', SIGNED: '已签收', REJECTED: '已拒签', RETURN_PENDING: '退货处理中', CANCELLED: '已取消' } function deliveryMethodLabel(value?: string | null) { return ({ FBA_PICKUP: 'FBA自提', CUSTOMER_PICKUP: '客户自提', TRUCK_PALLET: '卡派打托', TRUCK_FLOOR: '卡派地板', EXPRESS: '快递', OUTSOURCED: '外配', DEDICATED_TRUCK: '专车直送', LTL: '零担派送', SELF_DELIVERY: '自送', THIRD_PARTY: '第三方配送' } as Record)[String(value)] || value || '—' } +function pickupMethodLabel(value?: string | null) { return ({ ONE_PICKUP_ONE_DROP: '一提一卸', ONE_PICKUP_MULTI_DROP: '一提多卸', MULTI_PICKUP_ONE_DROP: '多提一卸', MULTI_PICKUP_MULTI_DROP: '多提多卸', WAREHOUSE_PICKUP: '仓库自提', DOOR_PICKUP: '上门提货', SELF_PICKUP: '自提' } as Record)[String(value)] || value || '—' } +function loadingTypeLabel(value?: string | null) { return ({ PALLET: '托盘', FLOOR: '地板', MIXED: '混装', CARTON: '散箱' } as Record)[String(value)] || value || '—' } async function load(model: QueryModel = filters.value) { Object.assign(filters.value, model); loading.value = true; error.value = null; try { const range = Array.isArray(filters.value.plannedAt) ? filters.value.plannedAt.map(String) : []; const result = await listDeliveryOrders({ page: page.value, size: pageSize.value, documentNo: text('documentNo'), dispatchNo: text('dispatchNo'), waybillNo: text('waybillNo'), warehouseId: text('warehouseId'), status: text('status'), vehiclePlate: text('vehiclePlate'), driverName: text('driverName'), deliveryMethod: text('deliveryMethod'), plannedFrom: range[0] ? `${range[0]}T00:00:00` : undefined, plannedTo: range[1] ? `${range[1]}T23:59:59` : undefined }); rows.value = result.records; total.value = result.total } catch (cause) { rows.value = []; total.value = 0; error.value = getApiErrorDetails(cause, '派送单列表加载失败') } finally { loading.value = false } } function text(key: string) { return String(filters.value[key] || '').trim() || undefined } function open(row: DeliveryOrderRow) { void router.push({ name: 'overseas-delivery-order-detail', params: { deliveryNo: row.deliveryNo }, query: { customerId: row.customerId } }) } diff --git a/src/modules/overseas-warehouse/pages/DispatchesView.test.ts b/src/modules/overseas-warehouse/pages/DispatchesView.test.ts index 7e9e8f3a..025d7d2e 100644 --- a/src/modules/overseas-warehouse/pages/DispatchesView.test.ts +++ b/src/modules/overseas-warehouse/pages/DispatchesView.test.ts @@ -70,7 +70,8 @@ describe('DispatchesView', () => { }) expect(wrapper.text()).toContain('PC-1') expect(wrapper.text()).toContain('待发车') - expect(wrapper.text()).toContain('FBA-1 · CONFIRMED') + expect(wrapper.text()).toContain('FBA-1 · 已确认') + expect(wrapper.text()).toContain('已预约') }) it('keeps long dispatch identifiers as strings', async () => { diff --git a/src/modules/overseas-warehouse/pages/DispatchesView.vue b/src/modules/overseas-warehouse/pages/DispatchesView.vue index 5ae0dfce..781c48fa 100644 --- a/src/modules/overseas-warehouse/pages/DispatchesView.vue +++ b/src/modules/overseas-warehouse/pages/DispatchesView.vue @@ -108,9 +108,20 @@ function statusLabel(value: unknown) { return statusOptions.find((option) => option.value === status)?.label || text(value) } +function appointmentStatusLabel(value: unknown) { + const code = String(value || '') + const labels: Record = { + PENDING: '待预约', + BOOKED: '已预约', + CONFIRMED: '已确认', + CANCELLED: '已取消', + } + return labels[code] || text(value) +} + function appointmentLabel(numberValue: unknown, statusValue: unknown) { const appointmentNo = text(numberValue) - const appointmentStatus = text(statusValue) + const appointmentStatus = appointmentStatusLabel(statusValue) if (appointmentNo === '—') return appointmentStatus return appointmentStatus === '—' ? appointmentNo : `${appointmentNo} · ${appointmentStatus}` } @@ -128,7 +139,7 @@ function toListItem(dto: DispatchSummaryDto): DispatchListItem { overseasWarehouse: text(dto.overseasWarehouseName || '仓库名称待补充'), departAt: formatOverseasDateTime(dto.departAt), fbaAppointment: appointmentLabel(dto.fbaAppointmentNo, dto.fbaAppointmentStatus), - vehicleAppointment: text(dto.vehicleAppointmentStatus), + vehicleAppointment: appointmentStatusLabel(dto.vehicleAppointmentStatus), estimatedArrivalAt: formatOverseasDateTime(dto.estimatedArrivalAt), status: statusLabel(dto.status), statusCode: String(dto.status || ''), diff --git a/src/modules/overseas-warehouse/pages/ExceptionOrdersView.test.ts b/src/modules/overseas-warehouse/pages/ExceptionOrdersView.test.ts index b63191de..ee6fd783 100644 --- a/src/modules/overseas-warehouse/pages/ExceptionOrdersView.test.ts +++ b/src/modules/overseas-warehouse/pages/ExceptionOrdersView.test.ts @@ -26,6 +26,28 @@ describe('ExceptionOrdersView permissions and creation', () => { wrapper.unmount() }) + it('keeps the detail action available and hides numeric operator identifiers', async () => { + vi.mocked(listExceptionOrders).mockResolvedValue({ + records: [{ + id: '19', exceptionNo: 'EXC-1', exceptionType: 'DAMAGED', status: 'PROCESSING', reason: '包装破损', + customerId: '100', customerName: '示例客户', overseasWarehouseName: '洛杉矶仓', handlerName: '1000001', + exceptionAt: '2026-09-03T09:00:00', updatedAt: '2026-09-03T10:00:00', + }], + page: 1, size: 10, total: 1, pages: 1, + }) + const wrapper = mountView() + await flushPromises() + const table = wrapper.find('[data-testid="data-table"]') + expect(table.text()).toContain('查看') + await table.find('button').trigger('click') + await flushPromises() + const detail = wrapper.find('[data-dialog="异常订单详情"]') + expect(detail.text()).toContain('示例客户') + expect(detail.text()).toContain('包装破损') + expect(detail.text()).not.toContain('1000001') + wrapper.unmount() + }) + it('validates the required relation before submitting', async () => { canPermission.mockImplementation(code => code.endsWith(':create')) const wrapper = mountView() diff --git a/src/modules/overseas-warehouse/pages/ExceptionOrdersView.vue b/src/modules/overseas-warehouse/pages/ExceptionOrdersView.vue index 5771eee4..12072d25 100644 --- a/src/modules/overseas-warehouse/pages/ExceptionOrdersView.vue +++ b/src/modules/overseas-warehouse/pages/ExceptionOrdersView.vue @@ -1,6 +1,6 @@