This commit is contained in:
2026-08-07 20:07:37 +08:00
parent 28d0b81c5a
commit 99413ee155
27 changed files with 1065 additions and 595 deletions
@@ -336,4 +336,33 @@ describe('LocationsView', () => {
status: '',
})
})
it('keeps the latest detail when an older location request finishes last', async () => {
const secondLocation = { ...availableLocation, id: '9223372036854775800', locationCode: 'A1-03' }
const firstDetail = { location: availableLocation, warehouseCode: warehouse.warehouseCode, warehouseName: warehouse.warehouseName }
const secondDetail = { location: secondLocation, warehouseCode: warehouse.warehouseCode, warehouseName: warehouse.warehouseName }
let resolveFirst!: (value: typeof firstDetail) => void
let resolveSecond!: (value: typeof secondDetail) => void
vi.mocked(getPlatformLocation).mockImplementation((_warehouseId, locationId) => new Promise((resolve) => {
if (String(locationId) === String(availableLocation.id)) resolveFirst = resolve
else resolveSecond = resolve
}))
const wrapper = await mountView()
const vm = wrapper.vm as unknown as {
drawerOpen: boolean
detail: typeof firstDetail | null
loadDetail(row: PlatformLocationResource, mode: 'view' | 'edit'): Promise<void>
}
void vm.loadDetail(availableLocation, 'view')
vm.drawerOpen = false
await wrapper.vm.$nextTick()
void vm.loadDetail(secondLocation, 'view')
resolveSecond(secondDetail)
await flushPromises()
resolveFirst(firstDetail)
await flushPromises()
expect(vm.detail?.location.locationCode).toBe('A1-03')
})
})
@@ -61,6 +61,7 @@ const actionLoadingIds = ref(new Set<string>())
const formRef = ref<FormInstance>()
let warehouseLoadSequence = 0
let locationLoadSequence = 0
let drawerLoadSequence = 0
const filters = ref<LocationFilters>({ warehouseId: '', zoneCode: '', locationCode: '', locationType: '', status: '' })
const appliedFilters = ref<AppliedLocationFilters>({ warehouseId: '', zoneCode: '', locationCode: '', locationType: '', status: '' })
@@ -335,6 +336,7 @@ async function loadDetail(row: PlatformLocationResource, mode: 'view' | 'edit')
ElMessage.warning('仅支持编辑国内仓库位')
return
}
const sequence = ++drawerLoadSequence
const scope = recordScope(row)
drawerMode.value = mode
drawerOpen.value = true
@@ -343,6 +345,7 @@ async function loadDetail(row: PlatformLocationResource, mode: 'view' | 'edit')
detail.value = null
try {
const result = await getPlatformLocation(scope.warehouseId, row.id)
if (sequence !== drawerLoadSequence || !drawerOpen.value) return
detail.value = result
if (mode === 'edit') {
assignForm(result.location)
@@ -350,9 +353,10 @@ async function loadDetail(row: PlatformLocationResource, mode: 'view' | 'edit')
void formRef.value?.clearValidate()
}
} catch (error) {
if (sequence !== drawerLoadSequence) return
drawerError.value = getApiErrorDetails(error, '库位详情加载失败,请稍后重试')
} finally {
drawerLoading.value = false
if (sequence === drawerLoadSequence) drawerLoading.value = false
}
}
@@ -475,6 +479,13 @@ watch(
)
watch([page, pageSize], () => { void loadLocations() })
watch(drawerOpen, (open) => {
if (open) return
drawerLoadSequence += 1
drawerLoading.value = false
drawerError.value = null
detail.value = null
})
watch(() => form.warehouseId, (warehouseId) => {
if (drawerMode.value !== 'create') return
const warehouse = warehouses.value.find((item) => String(item.id) === warehouseId)
@@ -333,4 +333,55 @@ describe('PalletsView', () => {
expect(document.body.textContent).not.toContain('托盘状态')
expect(document.body.textContent).not.toContain('最大承重')
})
it('keeps the latest detail when an older pallet request finishes last', async () => {
const secondPallet = { ...pallet, id: '20002', palletCode: 'TP-002' }
let resolveFirst!: (value: PlatformPalletResource) => void
let resolveSecond!: (value: PlatformPalletResource) => void
vi.mocked(getPlatformPallet).mockImplementation((_warehouseId, palletId) => new Promise((resolve) => {
if (String(palletId) === String(pallet.id)) resolveFirst = resolve
else resolveSecond = resolve
}))
const wrapper = await mountView()
const vm = wrapper.vm as unknown as {
detailOpen: boolean
detail: PlatformPalletResource | null
openDetail(row: PlatformPalletResource): Promise<void>
}
void vm.openDetail(pallet)
vm.detailOpen = false
await wrapper.vm.$nextTick()
void vm.openDetail(secondPallet)
resolveSecond(secondPallet)
await flushPromises()
resolveFirst(pallet)
await flushPromises()
expect(vm.detail?.palletCode).toBe('TP-002')
})
it('keeps the latest pallet selected for editing', async () => {
const secondPallet = { ...pallet, id: '20002', palletCode: 'TP-002', color: '蓝色' }
let resolveFirst!: (value: PlatformPalletResource) => void
let resolveSecond!: (value: PlatformPalletResource) => void
vi.mocked(getPlatformPallet).mockImplementation((_warehouseId, palletId) => new Promise((resolve) => {
if (String(palletId) === String(pallet.id)) resolveFirst = resolve
else resolveSecond = resolve
}))
const wrapper = await mountView()
const vm = wrapper.vm as unknown as {
form: { palletCode: string; color: string }
openEdit(row: PlatformPalletResource): Promise<void>
}
void vm.openEdit(pallet)
void vm.openEdit(secondPallet)
resolveSecond(secondPallet)
await flushPromises()
resolveFirst(pallet)
await flushPromises()
expect(vm.form).toMatchObject({ palletCode: 'TP-002', color: '蓝色' })
})
})
@@ -38,6 +38,8 @@ const deletingIds = ref(new Set<string>())
const formRef = ref<FormInstance>()
let warehouseSequence = 0
let palletSequence = 0
let detailSequence = 0
let editorSequence = 0
type PalletFilters = QueryModel & { warehouseId: string; palletCode: string; palletType: string }
type AppliedPalletFilters = Pick<PalletFilters, 'warehouseId' | 'palletCode' | 'palletType'>
@@ -226,6 +228,7 @@ function resetFilters() {
}
function openCreate() {
editorSequence += 1
Object.assign(form, emptyForm())
form.warehouseId = isActiveDomesticWarehouse(filters.value.warehouseId) ? filters.value.warehouseId : ''
editorOpen.value = true
@@ -254,16 +257,20 @@ async function fetchDetail(row: PlatformPalletResource) {
}
async function openDetail(row: PlatformPalletResource) {
const sequence = ++detailSequence
detailLoading.value = true
detailOpen.value = true
detail.value = null
try {
detail.value = await fetchDetail(row)
const result = await fetchDetail(row)
if (sequence !== detailSequence || !detailOpen.value) return
detail.value = result
} catch (error) {
if (sequence !== detailSequence) return
detailOpen.value = false
ElMessage.error(errorMessage(getApiErrorDetails(error, '托盘详情加载失败,请稍后重试')))
} finally {
detailLoading.value = false
if (sequence === detailSequence) detailLoading.value = false
}
}
@@ -272,9 +279,13 @@ async function openEdit(row: PlatformPalletResource) {
ElMessage.warning('仅支持编辑国内仓托盘')
return
}
const sequence = ++editorSequence
try {
assignForm(await fetchDetail(row))
const result = await fetchDetail(row)
if (sequence !== editorSequence) return
assignForm(result)
} catch (error) {
if (sequence !== editorSequence) return
ElMessage.error(errorMessage(getApiErrorDetails(error, '托盘详情加载失败,请稍后重试')))
}
}
@@ -341,6 +352,12 @@ watch([page, pageSize], ([nextPage, nextSize], [previousPage, previousSize]) =>
if (nextPage === previousPage && nextSize === previousSize) return
void loadPallets()
})
watch(detailOpen, (open) => {
if (open) return
detailSequence += 1
detailLoading.value = false
detail.value = null
})
watch(() => access.can(editorPermission.value), (canWrite) => {
if (!canWrite && editorOpen.value) editorOpen.value = false
}, { flush: 'sync' })