From 60f430ced8fecc537e755a8074e38370685d514d Mon Sep 17 00:00:00 2001 From: ouyangxq <775153912@qq.com> Date: Mon, 7 Sep 2026 11:39:55 +0800 Subject: [PATCH] perf: deduplicate order product image requests --- .../UnifiedOrdersView.fulfillment.test.ts | 18 +++++++++++++++++- .../unified-orders/pages/UnifiedOrdersView.vue | 18 +++++++++++++----- 2 files changed, 30 insertions(+), 6 deletions(-) diff --git a/src/modules/unified-orders/pages/UnifiedOrdersView.fulfillment.test.ts b/src/modules/unified-orders/pages/UnifiedOrdersView.fulfillment.test.ts index 6f67f55c..b5555066 100644 --- a/src/modules/unified-orders/pages/UnifiedOrdersView.fulfillment.test.ts +++ b/src/modules/unified-orders/pages/UnifiedOrdersView.fulfillment.test.ts @@ -1,7 +1,7 @@ import { flushPromises, shallowMount } from '@vue/test-utils' import { beforeEach, describe, expect, it, vi } from 'vitest' import { getLoadingAssociationSummary, getOverseasInboundCodeRelationship } from '@/shared/api/inboundCodeRelations' -import { getPlatformUnifiedOrder, listPlatformUnifiedOrders } from '@/modules/unified-orders/api/unifiedOrders' +import { downloadPlatformProductImage, getPlatformUnifiedOrder, listPlatformUnifiedOrders } from '@/modules/unified-orders/api/unifiedOrders' import { getPlatformInboundHold, holdPlatformInbound, releasePlatformInbound } from '@/modules/inbounds' import UnifiedOrdersView from './UnifiedOrdersView.vue' @@ -27,6 +27,7 @@ vi.mock('@/shared/api/inboundCodeRelations', () => ({ })) vi.mock('@/modules/unified-orders/api/unifiedOrders', () => ({ addPlatformUnifiedOrderNote: vi.fn(), approvePlatformUnifiedOrder: vi.fn(), batchApprovePlatformUnifiedOrders: vi.fn(), + downloadPlatformProductImage: vi.fn(), getPlatformUnifiedOrder: vi.fn(), listPlatformUnifiedOrderFeeDetails: vi.fn(), listPlatformUnifiedOrders: vi.fn(), unifiedOrderStatusOptions: [], })) @@ -75,6 +76,7 @@ describe('UnifiedOrdersView downstream fulfillment detail', () => { vi.clearAllMocks() canPermission.mockImplementation(() => true) vi.mocked(getPlatformUnifiedOrder).mockResolvedValue(detail as never) + vi.mocked(downloadPlatformProductImage).mockResolvedValue(new Blob(['image'], { type: 'image/png' })) vi.mocked(listPlatformUnifiedOrders).mockResolvedValue({ records: [], page: 1, size: 20, total: 0, pages: 0 }) vi.mocked(getPlatformInboundHold).mockResolvedValue({ inboundId: '7001', tenantId: '6001', holdFlag: false, currentHoldReason: null, version: 3, @@ -100,6 +102,20 @@ describe('UnifiedOrdersView downstream fulfillment detail', () => { }) }) + it('downloads one preview for cargo rows sharing the same product image', async () => { + vi.mocked(getPlatformUnifiedOrder).mockResolvedValue({ + ...detail, + order: { + ...detail.order, + cargoes: [1, 2, 3, 4].map((itemNo) => ({ itemNo, productImageFileId: '9901' })), + }, + } as never) + mountDetail() + await flushPromises() + expect(downloadPlatformProductImage).toHaveBeenCalledTimes(1) + expect(downloadPlatformProductImage).toHaveBeenCalledWith('6001', '9901') + }) + it('shows a compact empty state in order detail when no downstream relationship exists', async () => { const wrapper = mountDetail() await flushPromises() diff --git a/src/modules/unified-orders/pages/UnifiedOrdersView.vue b/src/modules/unified-orders/pages/UnifiedOrdersView.vue index 08e93dc1..861108e7 100644 --- a/src/modules/unified-orders/pages/UnifiedOrdersView.vue +++ b/src/modules/unified-orders/pages/UnifiedOrdersView.vue @@ -853,14 +853,22 @@ function releaseCargoImagePreviews() { async function loadCargoImagePreviews(resource: UnifiedOrderDetailResource, serial: number) { const tenantId = String(resource.summary.tenantId || '') if (!tenantId) return - await Promise.all((resource.order?.cargoes ?? []).map(async (cargo) => { - const fileId = cargo.productImageFileId - if (fileId === null || fileId === undefined || fileId === '') return + const cargoesByFileId = new Map() + for (const cargo of resource.order?.cargoes ?? []) { + const fileId = cargo.productImageFileId === null || cargo.productImageFileId === undefined + ? '' + : String(cargo.productImageFileId) + if (!fileId) continue + const cargoes = cargoesByFileId.get(fileId) ?? [] + cargoes.push(cargo) + cargoesByFileId.set(fileId, cargoes) + } + await Promise.all([...cargoesByFileId.entries()].map(async ([fileId, cargoes]) => { try { - const blob = await downloadPlatformProductImage(tenantId, String(fileId)) + const blob = await downloadPlatformProductImage(tenantId, fileId) if (serial !== detailRequestSerial || detailRouteKey.value !== `${tenantId}:${orderId.value}`) return const url = URL.createObjectURL(blob) - cargo.imageUrl = url + cargoes.forEach((cargo) => { cargo.imageUrl = url }) cargoImagePreviewUrls.add(url) } catch { // Historical files may have been removed; keep the remaining cargo fields visible.