diff --git a/src/modules/inbounds/core/api.test.ts b/src/modules/inbounds/core/api.test.ts index 79746e4d..fc048869 100644 --- a/src/modules/inbounds/core/api.test.ts +++ b/src/modules/inbounds/core/api.test.ts @@ -1,6 +1,6 @@ import { beforeEach, describe, expect, it, vi } from 'vitest' import { http } from '@/shared/api/http' -import { downloadInboundCartonLabels, downloadPlatformInboundHoldEvidence, getPlatformInbound, getPlatformInboundHold, holdPlatformInbound, listPlatformInbounds, releasePlatformInbound, uploadPlatformInboundHoldEvidence } from './api' +import { downloadInboundCartonLabels, downloadInboundCartonLabelsBatch, downloadPlatformInboundHoldEvidence, getPlatformInbound, getPlatformInboundHold, holdPlatformInbound, listPlatformInbounds, releasePlatformInbound, uploadPlatformInboundHoldEvidence } from './api' vi.mock('@/shared/api/http', () => ({ ApiResponseError: class ApiResponseError extends Error { @@ -117,6 +117,20 @@ describe('platform inbound query API', () => { }) }) + it('downloads one PDF for a cross-customer batch of inbound orders', async () => { + const pdf = new Blob(['pdf'], { type: 'application/pdf' }) + vi.mocked(http.post).mockResolvedValueOnce(pdf) + const items = [ + { tenantId: '10001', inboundId: '19001' }, + { tenantId: '10002', inboundId: '19002' }, + ] + + await expect(downloadInboundCartonLabelsBatch(items)).resolves.toBe(pdf) + expect(http.post).toHaveBeenCalledWith('/platform/inbounds/carton-label-pdf', items, { + responseType: 'blob', timeout: 120_000, + }) + }) + it('loads and normalizes the tenant-scoped hold state and immutable history', async () => { vi.mocked(http.get).mockResolvedValue({ data: { inboundId: 19001, tenantId: 10002, holdFlag: true, currentHoldReason: ' 待核对货款 ', version: '4', diff --git a/src/modules/inbounds/core/api.ts b/src/modules/inbounds/core/api.ts index 5709bcf8..f9f6006a 100644 --- a/src/modules/inbounds/core/api.ts +++ b/src/modules/inbounds/core/api.ts @@ -238,6 +238,25 @@ export async function downloadInboundCartonLabels(tenantId: string, inboundId: s return response } +export interface InboundCartonLabelBatchItem { + tenantId: string + inboundId: string +} + +export async function downloadInboundCartonLabelsBatch(items: InboundCartonLabelBatchItem[]) { + const response = await http.post( + `${basePath}/carton-label-pdf`, + items, + { responseType: 'blob', timeout: 120_000 }, + ) + if (response.type.includes('json')) { + const error = JSON.parse(await response.text()) as Partial> + throw new ApiResponseError(error.message || '批量箱唛生成失败', error.code || 'UNKNOWN', undefined, + error.data, error.requestId, error.traceId) + } + return response +} + export async function downloadDropshipPalletLabel(tenantId: string, inboundId: string, palletId: string) { return http.get( `/platform/v1/first-leg/pda-dropship/inbound-orders/${encodeURIComponent(inboundId)}/pallets/${encodeURIComponent(palletId)}/print`, diff --git a/src/modules/inbounds/index.ts b/src/modules/inbounds/index.ts index d55cec86..aca45480 100644 --- a/src/modules/inbounds/index.ts +++ b/src/modules/inbounds/index.ts @@ -1,5 +1,5 @@ export { getInboundMeasurement, saveInboundMeasurementDraft, updateMeasurementCalculationStrategy } from './measurement/api' -export { createInboundHoldIdempotencyKey, downloadPlatformInboundHoldEvidence, getPlatformInboundHold, holdPlatformInbound, releasePlatformInbound, uploadPlatformInboundHoldEvidence } from './core/api' +export { createInboundHoldIdempotencyKey, downloadInboundCartonLabelsBatch, downloadPlatformInboundHoldEvidence, getPlatformInboundHold, holdPlatformInbound, releasePlatformInbound, uploadPlatformInboundHoldEvidence } from './core/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' diff --git a/src/modules/unified-orders/pages/UnifiedOrdersView.test.ts b/src/modules/unified-orders/pages/UnifiedOrdersView.test.ts index cd7a6414..6a4520b2 100644 --- a/src/modules/unified-orders/pages/UnifiedOrdersView.test.ts +++ b/src/modules/unified-orders/pages/UnifiedOrdersView.test.ts @@ -521,6 +521,14 @@ describe('UnifiedOrdersView contract', () => { expect(source).not.toContain('title="更多操作"') }) + it('batch prints stable carton labels from the list toolbar instead of adding another row action', () => { + expect(source).toContain('downloadInboundCartonLabelsBatch') + expect(source).toContain('const selectedCartonLabelOrders = computed') + expect(source).toContain('@click="printSelectedCartonLabels"') + expect(source).toContain('批量箱唛-${selectedCartonLabelOrders.value.length}单.pdf') + expect(source).not.toContain("type UnifiedOrderRowAction = 'note' | 'approve' | 'printCartonLabels'") + }) + it('renders order detail as a routed full page instead of a drawer', () => { expect(source).toContain('