diff --git a/nl-ui/nl-ui-admin-vben/yudao-ui-admin-vben/apps/web-antdv-next/src/api/base/materialbase/index.ts b/nl-ui/nl-ui-admin-vben/yudao-ui-admin-vben/apps/web-antdv-next/src/api/base/materialbase/index.ts index 80a2090a..e0b1b6bd 100644 --- a/nl-ui/nl-ui-admin-vben/yudao-ui-admin-vben/apps/web-antdv-next/src/api/base/materialbase/index.ts +++ b/nl-ui/nl-ui-admin-vben/yudao-ui-admin-vben/apps/web-antdv-next/src/api/base/materialbase/index.ts @@ -5,7 +5,7 @@ import { requestClient } from '#/api/request'; export namespace BaseMaterialBaseApi { /** 物料基本信息信息 */ export interface MaterialBase { - materialId: number; // 物料标识 + materialId: number | string; // 物料标识 materialCode?: string; // 物料编码 materialName?: string; // 物料名称 materialSpec: string; // 规格 diff --git a/nl-ui/nl-ui-admin-vben/yudao-ui-admin-vben/apps/web-antdv-next/src/api/wms/iostorinv/index.ts b/nl-ui/nl-ui-admin-vben/yudao-ui-admin-vben/apps/web-antdv-next/src/api/wms/iostorinv/index.ts index dd930de2..197dc02b 100644 --- a/nl-ui/nl-ui-admin-vben/yudao-ui-admin-vben/apps/web-antdv-next/src/api/wms/iostorinv/index.ts +++ b/nl-ui/nl-ui-admin-vben/yudao-ui-admin-vben/apps/web-antdv-next/src/api/wms/iostorinv/index.ts @@ -67,7 +67,7 @@ export namespace WmsIostorInvApi { /** 可用库存 */ export interface AvailableInventory { - groupId: string; // 组盘记录标识 + groupId: number | string; // 组盘记录标识 vehicleCode: string; // 箱号 pcsn?: null | string; // 批次 materialId: string; // 物料标识 @@ -144,10 +144,11 @@ export function exportIostorInv(params: any) { /** 查询可用库存分页 */ export function getAvailableInventoryPage( params: WmsIostorInvApi.AvailableInventoryPageReq, + signal?: AbortSignal, ) { return requestClient.get< PageResult - >('/wms/iostor-inv/availableInventoryPage', { params }); + >('/wms/iostor-inv/availableInventoryPage', { params, signal }); } /** 按箱号展开可用库存 */ diff --git a/nl-ui/nl-ui-admin-vben/yudao-ui-admin-vben/apps/web-antdv-next/src/views/wms/iostorinv/modules/detail-builders.test.ts b/nl-ui/nl-ui-admin-vben/yudao-ui-admin-vben/apps/web-antdv-next/src/views/wms/iostorinv/modules/detail-builders.test.ts index 6c52b5da..f869193f 100644 --- a/nl-ui/nl-ui-admin-vben/yudao-ui-admin-vben/apps/web-antdv-next/src/views/wms/iostorinv/modules/detail-builders.test.ts +++ b/nl-ui/nl-ui-admin-vben/yudao-ui-admin-vben/apps/web-antdv-next/src/views/wms/iostorinv/modules/detail-builders.test.ts @@ -12,7 +12,7 @@ describe('mapExpandedInventory', () => { const rows = mapExpandedInventory([ { availableQty: 12.5, - groupId: '101', + groupId: 101, extCode: 'OUT-1', extDtlCode: 'DTL-1', extType: 'SALE', @@ -50,15 +50,15 @@ describe('mapExpandedInventory', () => { }); describe('mergeInventorySelections', () => { - it('合并当前页和跨页保留记录,并按 groupId 去重', () => { + it('合并跨页记录,并将 number/string 形式的相同 groupId 去重', () => { const reserved = [{ groupId: '1', vehicleCode: 'BOX-1' }]; const current = [ - { groupId: '1', vehicleCode: 'BOX-1' }, - { groupId: '2', vehicleCode: 'BOX-2' }, + { groupId: 1, vehicleCode: 'BOX-1' }, + { groupId: 2, vehicleCode: 'BOX-2' }, ]; expect(mergeInventorySelections(current, reserved)).toEqual([ - reserved[0], + current[0], current[1], ]); }); diff --git a/nl-ui/nl-ui-admin-vben/yudao-ui-admin-vben/apps/web-antdv-next/src/views/wms/iostorinv/modules/detail-builders.ts b/nl-ui/nl-ui-admin-vben/yudao-ui-admin-vben/apps/web-antdv-next/src/views/wms/iostorinv/modules/detail-builders.ts index b35b5cd4..df077843 100644 --- a/nl-ui/nl-ui-admin-vben/yudao-ui-admin-vben/apps/web-antdv-next/src/views/wms/iostorinv/modules/detail-builders.ts +++ b/nl-ui/nl-ui-admin-vben/yudao-ui-admin-vben/apps/web-antdv-next/src/views/wms/iostorinv/modules/detail-builders.ts @@ -40,12 +40,16 @@ export function collectVehicleCodes(rows: Array<{ vehicleCode?: string }>) { } /** 合并当前页与 VXE 跨页保留记录,以组盘记录标识去重 */ -export function mergeInventorySelections( +export function mergeInventorySelections< + T extends { groupId: number | string }, +>( current: T[], reserved: T[], ) { const selected = new Map(); - [...reserved, ...current].forEach((row) => selected.set(row.groupId, row)); + [...reserved, ...current].forEach((row) => + selected.set(String(row.groupId), row), + ); return [...selected.values()]; } diff --git a/nl-ui/nl-ui-admin-vben/yudao-ui-admin-vben/apps/web-antdv-next/src/views/wms/iostorinv/modules/inventory-select.vue b/nl-ui/nl-ui-admin-vben/yudao-ui-admin-vben/apps/web-antdv-next/src/views/wms/iostorinv/modules/inventory-select.vue index c402c769..1faaa765 100644 --- a/nl-ui/nl-ui-admin-vben/yudao-ui-admin-vben/apps/web-antdv-next/src/views/wms/iostorinv/modules/inventory-select.vue +++ b/nl-ui/nl-ui-admin-vben/yudao-ui-admin-vben/apps/web-antdv-next/src/views/wms/iostorinv/modules/inventory-select.vue @@ -28,11 +28,20 @@ const emit = defineEmits<{ const storId = ref(''); const modalOpen = ref(false); let openToken = 0; +let pageAbortController: AbortController | undefined; -async function clearGridState() { +function abortPageRequest() { + pageAbortController?.abort(); + pageAbortController = undefined; +} + +async function clearGridState(token: number) { await gridApi.grid.clearCheckboxRow(); + if (token !== openToken) return; await gridApi.grid.clearCheckboxReserve(); + if (token !== openToken) return; await gridApi.grid.loadData([]); + if (token !== openToken) return; } const [Grid, gridApi] = useVbenVxeGrid({ @@ -76,20 +85,26 @@ const [Grid, gridApi] = useVbenVxeGrid({ query: async ({ page }, formValues) => { const requestToken = openToken; const requestStorId = storId.value; - if (!modalOpen.value || !requestStorId) return { list: [], total: 0 }; + if (!modalOpen.value || !requestStorId) { + throw new DOMException('库存选择弹窗已关闭', 'AbortError'); + } + abortPageRequest(); + const controller = new AbortController(); + pageAbortController = controller; const result = await getAvailableInventoryPage({ ...formValues, pageNo: page.currentPage, pageSize: page.pageSize, storId: requestStorId, - }); + }, controller.signal); if ( requestToken !== openToken || !modalOpen.value || requestStorId !== storId.value ) { - return { list: [], total: 0 }; + throw new DOMException('库存分页请求已失效', 'AbortError'); } + if (pageAbortController === controller) pageAbortController = undefined; return result; }, }, @@ -140,15 +155,16 @@ const [Modal, modalApi] = useVbenModal({ }, async onOpenChange(open) { const token = ++openToken; + abortPageRequest(); if (!open) { modalOpen.value = false; storId.value = ''; - await clearGridState(); + await clearGridState(token); return; } modalOpen.value = true; storId.value = ''; - await clearGridState(); + await clearGridState(token); if (token !== openToken || !modalOpen.value) return; const data = modalApi.getData<{ storId: string }>(); if (!data?.storId) {