This commit is contained in:
2026-10-08 17:08:03 +08:00
parent cc37a42298
commit 7b0df1db37
44 changed files with 574 additions and 405 deletions
@@ -3,6 +3,14 @@ import { ApiResponseError, http, unwrapApiResponse, type ApiEnvelope } from '@/s
export type ExportTaskStatus = 'PENDING' | 'RUNNING' | 'SUCCEEDED' | 'FAILED' | 'EXPIRED'
export type KnownExportTaskType =
| 'LAST_MILE_ORDER_LIST'
| 'OVERSEAS_INVENTORY_BALANCE'
| 'OVERSEAS_INVENTORY_LEDGER'
| 'OVERSEAS_QUOTE_LIST'
| 'MONTHLY_EXCHANGE_RATE_LIST'
| 'VEHICLE_LIST'
| 'FLEET_QUOTE_LIST'
| 'TRIP_OPERATIONS_LIST'
| 'CUSTOMER_LIST'
| 'DOMESTIC_WAREHOUSE_ORDER_LIST'
| 'FINANCE_CUSTOMER_ACCOUNT_LIST'
+1
View File
@@ -1 +1,2 @@
export * from './api/platformExportTasks'
export { useExportTask } from './useExportTask'
@@ -26,6 +26,16 @@ type DownloadFilters = QueryModel & {
}
const exportTypeMeta: Record<string, { label: string; retryPermission: string }> = {
LAST_MILE_ORDER_LIST: { label: '尾程订单', retryPermission: 'platform:overseas-warehouse:last-mile-order:export' },
OVERSEAS_INVENTORY_BALANCE: { label: '库存余额', retryPermission: 'platform:overseas-warehouse:inventory:export' },
OVERSEAS_INVENTORY_LEDGER: { label: '进销存记录', retryPermission: 'platform:overseas-warehouse:inventory:export' },
OVERSEAS_QUOTE_LIST: { label: '海外报价', retryPermission: 'platform:overseas-master-data:quote:export' },
MONTHLY_EXCHANGE_RATE_LIST: { label: '月度汇率', retryPermission: 'platform:overseas-master-data:exchange-rate:export' },
VEHICLE_LIST: { label: '车辆', retryPermission: 'platform:overseas-master-data:vehicle:export' },
FLEET_QUOTE_LIST: { label: '车队报价', retryPermission: 'platform:fleet:quote:export' },
TRIP_OPERATIONS_LIST: { label: '出车记录', retryPermission: 'platform:fleet:operations:export' },
FINANCE_RECEIVABLE_STATISTICS: { label: '应收统计', retryPermission: 'platform:finance:receivable-statistics:export' },
LOADING_LIST_BUY_DECLARATION_ITEMS: { label: '买单报关明细', retryPermission: 'platform:firstleg:customs:manage' },
CUSTOMER_LIST: { label: '客户列表', retryPermission: 'platform:customer:export' },
DOMESTIC_WAREHOUSE_ORDER_LIST: { label: '国内仓订单列表', retryPermission: 'platform:order:export' },
FINANCE_CUSTOMER_ACCOUNT_LIST: { label: '客户账户', retryPermission: 'platform:finance:customer-account:export' },
@@ -0,0 +1,48 @@
import { beforeEach, describe, expect, it, vi } from 'vitest'
import { readFileSync } from 'node:fs'
import { createPlatformExportTask } from './api/platformExportTasks'
import { showExportTaskCreatedDialog } from '@/shared/components/exportTaskCreatedDialog'
import { useExportTask } from './useExportTask'
const { push } = vi.hoisted(() => ({ push: vi.fn() }))
vi.mock('vue-router', () => ({ useRouter: () => ({ push }) }))
vi.mock('./api/platformExportTasks', () => ({ createPlatformExportTask: vi.fn() }))
vi.mock('@/shared/components/exportTaskCreatedDialog', () => ({ showExportTaskCreatedDialog: vi.fn() }))
beforeEach(() => {
vi.clearAllMocks()
vi.mocked(createPlatformExportTask).mockResolvedValue({ taskNo: 'EXP-1' } as Awaited<ReturnType<typeof createPlatformExportTask>>)
vi.mocked(showExportTaskCreatedDialog).mockResolvedValue(false)
})
describe('download center export submission', () => {
it('exports all matching rows and preserves false, zero, stage and business filters', async () => {
const filters = { page: 3, size: 20, detained: false, count: 0, orderNo: '', warehouse: undefined, sailingStage: 'BEFORE_DEPARTURE', relabelNo: 'RL-1' }
await useExportTask()('LAST_MILE_ORDER_LIST', '尾程订单', filters)
expect(createPlatformExportTask).toHaveBeenCalledWith({ exportType: 'LAST_MILE_ORDER_LIST', taskName: '尾程订单', format: 'XLSX',
parameters: { detained: false, count: 0, sailingStage: 'BEFORE_DEPARTURE', relabelNo: 'RL-1' } })
expect(filters.page).toBe(3)
expect(showExportTaskCreatedDialog).toHaveBeenCalledWith({ taskName: '尾程订单', taskNo: 'EXP-1', dense: true })
expect(push).not.toHaveBeenCalled()
})
it('opens the download center only after the user chooses it', async () => {
vi.mocked(showExportTaskCreatedDialog).mockResolvedValue(true)
await useExportTask()('VEHICLE_LIST', '车辆', {})
expect(push).toHaveBeenCalledWith({ name: 'download-center' })
})
it('preserves submission failure diagnostics without a success prompt or navigation', async () => {
const error = { message: '无导出权限', requestId: 'export-request' }
vi.mocked(createPlatformExportTask).mockRejectedValue(error)
await expect(useExportTask()('VEHICLE_LIST', '车辆', {})).rejects.toBe(error)
expect(showExportTaskCreatedDialog).not.toHaveBeenCalled()
expect(push).not.toHaveBeenCalled()
})
it.each([["overseas-warehouse/pages/LastMileOrdersView.vue","LAST_MILE_ORDER_LIST","platform:overseas-warehouse:last-mile-order:export"],["overseas-warehouse/pages/InventoryView.vue","OVERSEAS_INVENTORY_BALANCE","platform:overseas-warehouse:inventory:export"],["overseas-warehouse/pages/InventoryTransactionsView.vue","OVERSEAS_INVENTORY_LEDGER","platform:overseas-warehouse:inventory:export"],["overseas-master-data/pages/OverseasQuotesView.vue","OVERSEAS_QUOTE_LIST","platform:overseas-master-data:quote:export"],["overseas-master-data/pages/ExchangeRatesView.vue","MONTHLY_EXCHANGE_RATE_LIST","platform:overseas-master-data:exchange-rate:export"],["overseas-master-data/pages/VehiclesView.vue","VEHICLE_LIST","platform:overseas-master-data:vehicle:export"],["overseas-master-data/pages/FleetQuotesView.vue","FLEET_QUOTE_LIST","platform:fleet:quote:export"],["overseas-master-data/pages/TripOperationsView.vue","TRIP_OPERATIONS_LIST","platform:fleet:operations:export"]])('connects %s with the correct type and download-center retry permission', (path, type, permission) => {
const page = readFileSync(new URL('../' + path, import.meta.url), 'utf8')
expect(page).toContain("await submitExport('" + type + "'")
expect(page).not.toMatch(/saveCsv\(|saveFleetCsv\(/)
const center = readFileSync('src/modules/downloads/pages/DownloadCenterView.vue', 'utf8')
expect(center).toContain(type + ": { label:")
expect(center).toContain("retryPermission: '" + permission + "'")
})
})
+16
View File
@@ -0,0 +1,16 @@
import { useRouter } from 'vue-router'
import { showExportTaskCreatedDialog } from '@/shared/components/exportTaskCreatedDialog'
import { createPlatformExportTask, type CreatePlatformExportTaskRequest, type KnownExportTaskType } from './api/platformExportTasks'
export function useExportTask() {
const router = useRouter()
return async (exportType: KnownExportTaskType, taskName: string, query: object) => {
const parameters = Object.fromEntries(Object.entries(query).filter(([key, value]) =>
key !== 'page' && key !== 'size' && value !== undefined && value !== null && value !== '',
)) as CreatePlatformExportTaskRequest['parameters']
const task = await createPlatformExportTask({ exportType, taskName, format: 'XLSX', parameters })
if (await showExportTaskCreatedDialog({ taskName, taskNo: task.taskNo, dense: true })) {
await router.push({ name: 'download-center' })
}
}
}