From 822b285312185024e2c06c882d00448beea1cf1e Mon Sep 17 00:00:00 2001 From: ouyangxq <775153912@qq.com> Date: Mon, 17 Aug 2026 18:32:41 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BC=98=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../pages/ContainersView.test.ts | 7 +-- .../pages/ContainersView.vue | 5 +- .../pages/GlobalSmartLoadingView.test.ts | 46 ++++++++++++++++- .../pages/GlobalSmartLoadingView.vue | 12 +++-- src/modules/inbounds/fee/InboundFeePanel.vue | 2 +- src/modules/inbounds/index.ts | 1 + .../InboundMeasurementDialog.test.ts | 3 ++ .../measurement/InboundMeasurementDialog.vue | 8 +-- .../InboundMeasurementPanel.test.ts | 9 ++-- .../measurement/InboundMeasurementPanel.vue | 50 +++++++++---------- .../WeightOcrPanel.behavior.test.ts | 1 + .../weight/components/WeightOcrPanel.test.ts | 7 +++ .../weight/components/WeightOcrPanel.vue | 14 +++--- .../InboundFeeDetailManager.test.ts | 7 +++ .../components/InboundFeeDetailManager.vue | 4 +- .../pages/UnifiedOrdersView.test.ts | 3 ++ .../pages/UnifiedOrdersView.vue | 7 +++ 17 files changed, 133 insertions(+), 53 deletions(-) diff --git a/src/modules/container-loading/pages/ContainersView.test.ts b/src/modules/container-loading/pages/ContainersView.test.ts index d0450448..89e6e825 100644 --- a/src/modules/container-loading/pages/ContainersView.test.ts +++ b/src/modules/container-loading/pages/ContainersView.test.ts @@ -187,14 +187,15 @@ describe('ContainersView', () => { expect(source).not.toContain('@reset=') }) - it('uses the frozen prototype modal contract for create and edit while retaining the detail drawer', () => { + it('uses centered dialogs for container detail, create and edit operations', () => { const source = readFileSync(resolve(process.cwd(), 'src/modules/container-loading/pages/ContainersView.vue'), 'utf8') - expect(source).toContain(' { void Promise.all([loadCustomers(), loadWarehouses(), loadBusin - + - + 选择文件 diff --git a/src/modules/container-loading/pages/GlobalSmartLoadingView.test.ts b/src/modules/container-loading/pages/GlobalSmartLoadingView.test.ts index ee2bb7d4..6a80fbf4 100644 --- a/src/modules/container-loading/pages/GlobalSmartLoadingView.test.ts +++ b/src/modules/container-loading/pages/GlobalSmartLoadingView.test.ts @@ -81,6 +81,23 @@ describe('GlobalSmartLoadingView', () => { expect(wrapper.text()).not.toContain('ORD-2') }) + it('uses the top-level container channel snapshot without expecting a nested snapshot', async () => { + vi.mocked(listContainers).mockResolvedValue({ + records: [{ ...container, channelCode: 'EXX_RAIL_NY', channelName: '纽约EXX海铁' }], + page: 1, + size: 100, + total: 1, + pages: 1, + }) + vi.mocked(listSmartLoadingCandidates).mockResolvedValue([{ accountId: '1', inboundId: '5', inboundDetailId: '6', orderId: '7', orderNo: 'ORD-2', inboundCode: 'IN-2', warehouseId: '8', channelCode: 'EXX_RAIL_NY', channelName: '纽约EXX海铁', destinationWarehouseId: '9', destinationWarehouseCode: 'LAX9', destinationWarehouseName: 'LAX9', customerName: '另一企业', goodsName: '鞋类', availablePackageCount: 12, unitWeightKg: 10, unitVolumeCbm: 0.2 }]) + const wrapper = mount(GlobalSmartLoadingView, { global: { plugins: [ElementPlus] } }) + await flushPromises() + + expect(wrapper.text()).toContain('纽约EXX海铁') + expect(wrapper.text()).not.toContain('缺少渠道快照') + expect(getSmartLoadingPlanByBooking).toHaveBeenCalledWith(container.id) + }) + it('shows one user-facing container number and hides internal manual or split references', async () => { vi.mocked(listContainers).mockResolvedValue({ records: [{ ...container, cabinetNo: 'CAB-20260814-01', containerNo: 'SPLIT-814022117898chain1' }], @@ -249,7 +266,34 @@ describe('GlobalSmartLoadingView', () => { expect(getSmartLoadingPlanByBooking).not.toHaveBeenCalled() expect(wrapper.text()).not.toContain('CB-3') - expect(wrapper.text()).not.toContain('装柜完成') + expect(wrapper.text()).toContain('当前柜次已完成装柜,不可继续编辑') + expect(wrapper.text()).not.toContain('缺少渠道快照') + }) + + it('isolates a missing-channel row without hiding another valid container', async () => { + const missingChannel = { ...container, id: '9007199254740997', cabinetNo: 'CB-MISSING', channelCode: null, channelName: null } + vi.mocked(listContainers).mockResolvedValue({ records: [missingChannel, container], page: 1, size: 100, total: 2, pages: 1 }) + const wrapper = mount(GlobalSmartLoadingView, { global: { plugins: [ElementPlus] } }) + await flushPromises() + + expect(wrapper.findAll('.container-option')).toHaveLength(1) + expect(wrapper.text()).toContain('CB-1') + expect(wrapper.text()).not.toContain('CB-MISSING') + expect(wrapper.text()).not.toContain('缺少渠道快照') + expect(getSmartLoadingPlanByBooking).toHaveBeenCalledWith(container.id) + }) + + it('matches candidate goods by their own formal top-level channel code', async () => { + vi.mocked(listSmartLoadingCandidates).mockResolvedValue([ + { accountId: '1', inboundId: '5', inboundDetailId: '6', orderId: '7', orderNo: 'ORD-2', inboundCode: 'IN-MATCH', warehouseId: '8', channelCode: 'ZBYHK', channelName: '美森正班海卡包税', destinationWarehouseId: '9', destinationWarehouseCode: 'LAX9', destinationWarehouseName: 'LAX9', customerName: '匹配企业', goodsName: '匹配货物', availablePackageCount: 12, unitWeightKg: 10, unitVolumeCbm: 0.2 }, + { accountId: '2', inboundId: '8', inboundDetailId: '9', orderId: '10', orderNo: 'ORD-3', inboundCode: 'IN-OTHER', warehouseId: '8', channelCode: 'OTHER', channelName: '其他渠道', destinationWarehouseId: '9', destinationWarehouseCode: 'LAX9', destinationWarehouseName: 'LAX9', customerName: '其他企业', goodsName: '其他货物', availablePackageCount: 8, unitWeightKg: 10, unitVolumeCbm: 0.2 }, + ]) + const wrapper = mount(GlobalSmartLoadingView, { global: { plugins: [ElementPlus] } }) + await flushPromises() + + expect(wrapper.text()).toContain('IN-MATCH') + expect(wrapper.text()).not.toContain('IN-OTHER') + expect(wrapper.text()).not.toContain('其他货物') }) it('refreshes the latest plan after A0409 without losing the selected container', async () => { diff --git a/src/modules/container-loading/pages/GlobalSmartLoadingView.vue b/src/modules/container-loading/pages/GlobalSmartLoadingView.vue index ef18e128..c554474f 100644 --- a/src/modules/container-loading/pages/GlobalSmartLoadingView.vue +++ b/src/modules/container-loading/pages/GlobalSmartLoadingView.vue @@ -60,10 +60,13 @@ const canAssign = computed(() => access.can('platform:firstleg:smart-loading:ass const canDelete = computed(() => access.can('platform:firstleg:smart-loading:delete')) const canPush = computed(() => access.can('platform:firstleg:smart-loading:push')) const selectedContainer = computed(() => containers.value.find((item) => item.id === selectedContainerId.value) || null) +const orchestratableContainers = computed(() => containers.value.filter((item) => ['WAIT_LOADING', 'EDITING', 'LOADING'].includes(item.planStatus))) +const completedContainerCount = computed(() => containers.value.filter((item) => item.planStatus === 'COMPLETED').length) +const missingChannelContainerCount = computed(() => orchestratableContainers.value.filter((item) => !item.channelCode).length) const channelTabs = computed(() => { const channels = new Map() - for (const item of containers.value) { - if (!['WAIT_LOADING', 'EDITING', 'LOADING'].includes(item.planStatus) || !item.channelCode) continue + for (const item of orchestratableContainers.value) { + if (!item.channelCode) continue if (!channels.has(item.channelCode)) channels.set(item.channelCode, { code: item.channelCode, name: item.channelName || item.channelCode, @@ -98,7 +101,9 @@ const filteredContainers = computed(() => containers.value.filter((item) => ( const filteredCandidates = computed(() => { const customerId = String(appliedQuery.value.customerId || '') const inboundCode = String(appliedQuery.value.inboundCode || '').trim().toLowerCase() + const channelCode = selectedContainer.value?.channelCode || activeChannelCode.value return candidates.value.filter((item) => { + if (!channelCode || item.channelCode !== channelCode) return false if (customerId && item.accountId !== customerId) return false return !inboundCode || String(item.inboundCode || '').toLowerCase().includes(inboundCode) }) @@ -404,7 +409,8 @@ onMounted(() => { void load(); void loadCustomers() })
总体积
{{ formatNumber(totalVolume) }} m³
- + + -

测量审核完成后,系统会自动生成并发布费用。

+

测量审核完成后,系统会自动生成初算费用;人工确认后才发布。

diff --git a/src/modules/inbounds/index.ts b/src/modules/inbounds/index.ts index 3aeb418e..60755eea 100644 --- a/src/modules/inbounds/index.ts +++ b/src/modules/inbounds/index.ts @@ -2,5 +2,6 @@ export { getInboundMeasurement } from './measurement/api' export { default as InboundMeasurementPanel } from './measurement/InboundMeasurementPanel.vue' export { default as InboundMeasurementDialog } from './measurement/InboundMeasurementDialog.vue' export { default as MeasurementEvidenceThumbnail } from './measurement/components/MeasurementEvidenceThumbnail.vue' +export { default as InboundFeePanel } from './fee/InboundFeePanel.vue' export { downloadWeightImage } from './weight/api/weightOcr' export type { InboundMeasurementDetail } from './measurement/types' diff --git a/src/modules/inbounds/measurement/InboundMeasurementDialog.test.ts b/src/modules/inbounds/measurement/InboundMeasurementDialog.test.ts index d5f8ec96..823dcc17 100644 --- a/src/modules/inbounds/measurement/InboundMeasurementDialog.test.ts +++ b/src/modules/inbounds/measurement/InboundMeasurementDialog.test.ts @@ -14,6 +14,9 @@ describe('InboundMeasurementDialog', () => { expect(source).toContain('height: 92vh') expect(source).toContain('
-
+
diff --git a/src/modules/unified-orders/pages/UnifiedOrdersView.test.ts b/src/modules/unified-orders/pages/UnifiedOrdersView.test.ts index 8015eb2e..a808f8d7 100644 --- a/src/modules/unified-orders/pages/UnifiedOrdersView.test.ts +++ b/src/modules/unified-orders/pages/UnifiedOrdersView.test.ts @@ -286,6 +286,9 @@ describe('UnifiedOrdersView contract', () => { expect(source).not.toContain("partyValue(detail.order.parties, 'CONSIGNEE'") expect(source).toContain("cargoTotal(detail.order.cargoes, 'netWeightKg')") expect(source).toContain('InboundFeeDetailManager') + expect(source).toContain('InboundFeePanel') + expect(source).toContain(':customer-id="String(detail.summary.tenantId)"') + expect(source).toContain('费用明细与审核') expect(source).toContain('@changed="loadDetail(true)"') expect(source).toContain('firstLegTransportModeLabel(detail.order.order?.transportMode)') expect(source).toContain('firstLegPickupMethodLabel(detail.order.order?.pickupMethod)') diff --git a/src/modules/unified-orders/pages/UnifiedOrdersView.vue b/src/modules/unified-orders/pages/UnifiedOrdersView.vue index 45585644..825ad1a4 100644 --- a/src/modules/unified-orders/pages/UnifiedOrdersView.vue +++ b/src/modules/unified-orders/pages/UnifiedOrdersView.vue @@ -51,6 +51,7 @@ import { import { downloadWeightImage, getInboundMeasurement, + InboundFeePanel, InboundMeasurementDialog, MeasurementEvidenceThumbnail, type InboundMeasurementDetail, @@ -977,6 +978,12 @@ onBeforeUnmount(() => {