This commit is contained in:
2026-08-11 19:35:28 +08:00
parent 886c7d3529
commit c690a30422
48 changed files with 935 additions and 171 deletions
@@ -13,12 +13,14 @@ import FormSection from '@/shared/components/FormSection.vue'
import ListPageLayout from '@/shared/components/ListPageLayout.vue'
import LoadErrorState from '@/shared/components/LoadErrorState.vue'
import QueryToolbar, { type QueryField, type QueryModel } from '@/shared/components/QueryToolbar.vue'
import { firstLegBusinessTypeLabel, firstLegContainerModeLabel, firstLegDestinationTypeLabel, firstLegTaxModeLabel } from '@/shared/utils/firstLegBusinessLabels'
import { listPlatformTenants, type PlatformTenantResource } from '@/modules/iam'
import { listPlatformWarehouses } from '@/modules/warehouses'
import { downloadInboundCartonLabels, getPlatformInbound, listPlatformInbounds } from '../core/api'
import InboundHistoryPanel from '../core/InboundHistoryPanel.vue'
import InboundSummaryPanel from '../core/InboundSummaryPanel.vue'
import type { InboundListTab, InboundOrderDetail, InboundOrderSummary } from '../core/types'
import { inboundFeeStatusLabels, inboundLoadingStatusLabels, inboundOrderStatusLabels, inboundProcessStatusLabels, inboundReviewStatusLabels, inboundStatusLabel } from '../status'
type FilterModel = QueryModel & {
customerId: string
@@ -100,7 +102,7 @@ const allQueryFields = computed<QueryField[]>(() => [
{ label: '待计费', value: 'WAIT_PRICING' }, { label: '费用处理中', value: 'FEE_CONFIRMING' },
{ label: '入库处理中', value: 'INBOUNDING' }, { label: '已入库', value: 'INBOUNDED' }, { label: '已作废', value: 'VOIDED' },
] },
{ key: 'orderStatus', type: 'input', width: 200, label: '订单状态码', placeholder: '订单状态码' },
{ key: 'orderStatus', type: 'select', width: 180, label: '订单状态', placeholder: '全部订单状态', options: Object.entries(inboundOrderStatusLabels).map(([value, label]) => ({ value, label })) },
{ key: 'measureReviewStatus', type: 'select', width: 160, label: '测量审核状态', placeholder: '测量审核状态', options: [
{ label: '待审核', value: 'PENDING' }, { label: '审核通过', value: 'APPROVED' }, { label: '审核驳回', value: 'REJECTED' },
] },
@@ -108,7 +110,7 @@ const allQueryFields = computed<QueryField[]>(() => [
{ label: '未计费', value: 'UNPRICED' }, { label: '已试算', value: 'CALCULATED' },
{ label: '已确认', value: 'CONFIRMED' }, { label: '已发送', value: 'SENT' }, { label: '已作废', value: 'VOIDED' },
] },
{ key: 'feeReviewStatus', type: 'input', width: 200, label: '费用审核状态码', placeholder: '费用审核状态码' },
{ key: 'feeReviewStatus', type: 'select', width: 180, label: '费用审核状态', placeholder: '全部审核状态', options: Object.entries(inboundReviewStatusLabels).map(([value, label]) => ({ value, label })) },
{ key: 'customerName', type: 'input', width: 260, label: '客户名称', placeholder: '客户名称' },
{ key: 'destinationCode', type: 'input', width: 220, label: '目的仓编码', placeholder: '目的仓编码' },
{ key: 'holdFlag', type: 'select', width: 160, label: '挂起状态', placeholder: '挂起状态', options: [{ label: '已挂起', value: 'true' }, { label: '未挂起', value: 'false' }] },
@@ -348,7 +350,7 @@ function formatDate(value: string | null) {
}
function text(value: string | number | null | undefined) { return value === null || value === undefined || value === '' ? '—' : String(value) }
function statusLabel(status: string) {
return ({ WAIT_MEASURE: '待测量', MEASURING: '测量中', MEASURE_PENDING: '待审核', MEASURE_REJECTED: '测量驳回', WAIT_PRICING: '待计费', FEE_CONFIRMING: '待发送费用', INBOUNDING: '入库处理中', INBOUNDED: '已入库', VOIDED: '已作废' } as Record<string, string>)[status] || status || '未知状态'
return inboundStatusLabel(status, inboundProcessStatusLabels, '未知状态')
}
function statusType(status: string) {
if (status === 'INBOUNDED') return 'success'
@@ -356,13 +358,10 @@ function statusType(status: string) {
if (status === 'MEASURING' || status === 'INBOUNDING') return 'info'
return 'warning'
}
function codeLabel(status: string | null | undefined, labels: Record<string, string>) { return status ? labels[status] || status : '—' }
const measureReviewLabels: Record<string, string> = { PENDING: '待审核', APPROVED: '审核通过', REJECTED: '审核驳回' }
const feeStatusLabels: Record<string, string> = { UNPRICED: '未计费', CALCULATED: '已试算', CONFIRMED: '已确认', SENT: '已发送', VOIDED: '已作废' }
const loadingStatusLabels: Record<string, string> = { NOT_LOADED: '未配载', LOADING: '配载中', LOADED: '已配载' }
const taxModeLabels: Record<string, string> = { TAX_INCLUDED: '包税', TAX_EXCLUDED: '不包税', DDP: '包税', DDU: '不包税' }
const containerModeLabels: Record<string, string> = { FCL: '整柜', LCL: '拼箱' }
function codeLabel(status: string | null | undefined, labels: Record<string, string>) { return inboundStatusLabel(status, labels) }
const measureReviewLabels = inboundReviewStatusLabels
const feeStatusLabels = inboundFeeStatusLabels
const loadingStatusLabels = inboundLoadingStatusLabels
function resetFilters() {
selectedCustomerId.value = ''
showAdvancedFilters.value = false
@@ -453,10 +452,10 @@ onBeforeUnmount(() => { disposed = true; loadRequestId += 1; detailRequestId +=
<template #pagination-left>当前显示 {{ currentPageCount }} 条 · 共 {{ result.total }} 条</template>
<template #actions="{ row }"><div class="row-actions"><el-button link type="primary" @click="openWorkspace(row as InboundOrderSummary)"><ClipboardCheck :size="15" />处理</el-button><el-button link :loading="printingInboundId === (row as InboundOrderSummary).id" :disabled="Boolean(printingInboundId)" @click="printCartonLabels(row as InboundOrderSummary)"><Printer :size="15" />打印箱唛</el-button><el-button link @click="openDetail(row as InboundOrderSummary)"><Eye :size="15" />查看</el-button></div></template>
<template #inbound="{ row }"><div class="primary-cell"><strong>{{ text((row as InboundOrderSummary).inboundCode) }}</strong><span>订单 {{ text((row as InboundOrderSummary).orderNo) }}</span></div></template>
<template #orderStatus="{ row }"><div class="status-stack"><el-tag :type="statusType((row as InboundOrderSummary).processStatus)" effect="light">{{ statusLabel((row as InboundOrderSummary).processStatus) }}</el-tag><span>订单:{{ text((row as InboundOrderSummary).orderStatusSnapshot) }}</span></div></template>
<template #orderStatus="{ row }"><div class="status-stack"><el-tag :type="statusType((row as InboundOrderSummary).processStatus)" effect="light">{{ statusLabel((row as InboundOrderSummary).processStatus) }}</el-tag><span>订单:{{ codeLabel((row as InboundOrderSummary).orderStatusSnapshot, inboundOrderStatusLabels) }}</span></div></template>
<template #measureReviewStatus="{ row }">{{ codeLabel((row as InboundOrderSummary).measureReviewStatus, measureReviewLabels) }}</template>
<template #expectedArrivalAt="{ row }">{{ formatDate((row as InboundOrderSummary).expectedArrivalAt) }}</template>
<template #feeStatus="{ row }"><div class="status-stack"><span>{{ codeLabel((row as InboundOrderSummary).feeStatus, feeStatusLabels) }}</span><small v-if="(row as InboundOrderSummary).feeReviewStatus">审核:{{ text((row as InboundOrderSummary).feeReviewStatus) }}</small></div></template>
<template #feeStatus="{ row }"><div class="status-stack"><span>{{ codeLabel((row as InboundOrderSummary).feeStatus, feeStatusLabels) }}</span><small v-if="(row as InboundOrderSummary).feeReviewStatus">审核:{{ codeLabel((row as InboundOrderSummary).feeReviewStatus, inboundReviewStatusLabels) }}</small></div></template>
<template #customerName="{ row }">{{ text((row as InboundOrderSummary).customerName) }}</template>
<template #warehouseName="{ row }">{{ text((row as InboundOrderSummary).warehouseName) }}</template>
<template #deliveryWarehouseName="{ row }">{{ text((row as InboundOrderSummary).deliveryWarehouseName) }}</template>
@@ -466,10 +465,10 @@ onBeforeUnmount(() => { disposed = true; loadRequestId += 1; detailRequestId +=
<template #containerNo="{ row }">{{ text((row as InboundOrderSummary).containerNo) }}</template>
<template #cabinetNo="{ row }">{{ text((row as InboundOrderSummary).cabinetNo) }}</template>
<template #companyName="{ row }">{{ text((row as InboundOrderSummary).companyName) }}</template>
<template #businessType="{ row }">{{ text((row as InboundOrderSummary).businessType) }}</template>
<template #businessType="{ row }">{{ firstLegBusinessTypeLabel((row as InboundOrderSummary).businessType) }}</template>
<template #channelName="{ row }"><div class="primary-cell"><strong>{{ text((row as InboundOrderSummary).channelName) }}</strong><span>{{ text((row as InboundOrderSummary).channelCode) }}</span></div></template>
<template #taxMode="{ row }">{{ codeLabel((row as InboundOrderSummary).taxMode, taxModeLabels) }}</template>
<template #containerMode="{ row }">{{ codeLabel((row as InboundOrderSummary).containerMode, containerModeLabels) }}</template>
<template #taxMode="{ row }">{{ firstLegTaxModeLabel((row as InboundOrderSummary).taxMode) }}</template>
<template #containerMode="{ row }">{{ firstLegContainerModeLabel((row as InboundOrderSummary).containerMode) }}</template>
<template #customsInspection="{ row }">{{ (row as InboundOrderSummary).customsInspection === null ? '—' : (row as InboundOrderSummary).customsInspection ? '是' : '否' }}</template>
<template #sailingAt="{ row }">{{ formatDate((row as InboundOrderSummary).sailingAt) }}</template>
<template #portArrivalAt="{ row }">{{ formatDate((row as InboundOrderSummary).portArrivalAt) }}</template>
@@ -482,7 +481,7 @@ onBeforeUnmount(() => { disposed = true; loadRequestId += 1; detailRequestId +=
<template #locationCodes="{ row }">{{ text((row as InboundOrderSummary).locationCodes) }}</template>
<template #volumeWeightKg="{ row }">{{ formatNumber((row as InboundOrderSummary).volumeWeightKg) }}</template>
<template #actualNetWeightKg="{ row }">{{ formatNumber((row as InboundOrderSummary).actualNetWeightKg) }}</template>
<template #destinationType="{ row }">{{ text((row as InboundOrderSummary).destinationType) }}</template>
<template #destinationType="{ row }">{{ firstLegDestinationTypeLabel((row as InboundOrderSummary).destinationType) }}</template>
<template #destinationName="{ row }"><div class="primary-cell"><strong>{{ text((row as InboundOrderSummary).destinationName) }}</strong><span>{{ text((row as InboundOrderSummary).destinationCode) }}</span></div></template>
<template #measureCompletedAt="{ row }">{{ formatDate((row as InboundOrderSummary).measureCompletedAt) }}</template>
<template #inboundedAt="{ row }">{{ formatDate((row as InboundOrderSummary).inboundedAt) }}</template>