This commit is contained in:
2026-08-06 15:32:02 +08:00
parent 9e7e1afac8
commit 33a0c48b78
22 changed files with 685 additions and 402 deletions
@@ -47,23 +47,22 @@ describe('platform location API', () => {
await expect(listPlatformLocations({
page: 2,
size: 20,
tenantId: '9223372036854775806',
warehouseId: '190000000000000101',
zoneCode: ' A ',
locationCode: ' A1 ',
locationType: 'SHELF',
status: 'AVAILABLE',
})).resolves.toEqual({ records: [], page: 2, size: 20, total: 21, pages: 2 })
await expect(getPlatformLocation('9223372036854775806', '190000000000000101', '19001')).resolves.toEqual(detail)
await expect(getPlatformLocation('190000000000000101', '19001')).resolves.toEqual(detail)
expect(http.get).toHaveBeenNthCalledWith(1, '/platform/v1/locations', {
params: {
tenantId: '9223372036854775806', page: 2, size: 20, warehouseId: '190000000000000101',
page: 2, size: 20, warehouseId: '190000000000000101',
zoneCode: 'A', locationCode: 'A1', locationType: 'SHELF', status: 'AVAILABLE',
},
})
expect(http.get).toHaveBeenNthCalledWith(2, '/platform/v1/locations/19001', {
params: { tenantId: '9223372036854775806', warehouseId: '190000000000000101' },
params: { tenantId: 0, warehouseId: '190000000000000101' },
})
})
@@ -74,7 +73,6 @@ describe('platform location API', () => {
await expect(listPlatformLocations({
page: 1,
size: 20,
tenantId: '',
warehouseId: '',
zoneCode: '',
locationCode: '',
@@ -93,20 +91,20 @@ describe('platform location API', () => {
vi.mocked(http.patch).mockResolvedValue({ code: '200', message: 'success', data: null })
vi.mocked(http.delete).mockResolvedValue({ code: '200', message: 'success', data: null })
await expect(createPlatformLocation(10001, payload)).resolves.toBe('19001')
await expect(updatePlatformLocation(10001, payload.warehouseId, '19001', payload)).resolves.toBeNull()
await expect(changePlatformLocationStatus(10001, payload.warehouseId, '19001', 'DISABLED', 3)).resolves.toBeNull()
await expect(deletePlatformLocation(10001, payload.warehouseId, '19001', 4)).resolves.toBeNull()
await expect(createPlatformLocation(payload)).resolves.toBe('19001')
await expect(updatePlatformLocation(payload.warehouseId, '19001', payload)).resolves.toBeNull()
await expect(changePlatformLocationStatus(payload.warehouseId, '19001', 'DISABLED', 3)).resolves.toBeNull()
await expect(deletePlatformLocation(payload.warehouseId, '19001', 4)).resolves.toBeNull()
expect(http.post).toHaveBeenCalledWith('/platform/v1/locations', payload, { params: { tenantId: 10001 } })
expect(http.post).toHaveBeenCalledWith('/platform/v1/locations', payload, { params: { tenantId: 0 } })
expect(http.put).toHaveBeenCalledWith('/platform/v1/locations/19001', payload, {
params: { tenantId: 10001, warehouseId: payload.warehouseId },
params: { tenantId: 0, warehouseId: payload.warehouseId },
})
expect(http.patch).toHaveBeenCalledWith('/platform/v1/locations/19001/status', { status: 'DISABLED', version: 3 }, {
params: { tenantId: 10001, warehouseId: payload.warehouseId },
params: { tenantId: 0, warehouseId: payload.warehouseId },
})
expect(http.delete).toHaveBeenCalledWith('/platform/v1/locations/19001', {
params: { tenantId: 10001, warehouseId: payload.warehouseId, version: 4 },
params: { tenantId: 0, warehouseId: payload.warehouseId, version: 4 },
})
})
})
@@ -41,7 +41,6 @@ export interface PlatformLocationPage {
export interface PlatformLocationQuery {
page?: number
size?: number
tenantId?: number | string
warehouseId?: number | string
zoneCode?: string
locationCode?: string
@@ -63,6 +62,7 @@ export interface SavePlatformLocationRequest {
}
const basePath = '/platform/v1/locations'
const platformResourceScope = 0
export async function listPlatformLocations(query: PlatformLocationQuery) {
const zoneCode = query.zoneCode?.trim()
@@ -71,7 +71,6 @@ export async function listPlatformLocations(query: PlatformLocationQuery) {
params: {
page: query.page ?? 1,
size: query.size ?? 20,
...(query.tenantId ? { tenantId: query.tenantId } : {}),
...(query.warehouseId ? { warehouseId: query.warehouseId } : {}),
...(zoneCode ? { zoneCode } : {}),
...(locationCode ? { locationCode } : {}),
@@ -90,38 +89,35 @@ export async function listPlatformLocations(query: PlatformLocationQuery) {
}
export async function getPlatformLocation(
tenantId: number | string,
warehouseId: number | string,
id: number | string,
) {
const response = await http.get<ApiEnvelope<PlatformLocationDetail>, ApiEnvelope<PlatformLocationDetail>>(
`${basePath}/${id}`,
{ params: { tenantId, warehouseId } },
{ params: { tenantId: platformResourceScope, warehouseId } },
)
return unwrapApiResponse(response)
}
export async function createPlatformLocation(tenantId: number | string, payload: SavePlatformLocationRequest) {
export async function createPlatformLocation(payload: SavePlatformLocationRequest) {
const response = await http.post<ApiEnvelope<number | string>, ApiEnvelope<number | string>>(basePath, payload, {
params: { tenantId },
params: { tenantId: platformResourceScope },
})
return unwrapApiResponse(response)
}
export async function updatePlatformLocation(
tenantId: number | string,
warehouseId: number | string,
id: number | string,
payload: SavePlatformLocationRequest,
) {
const response = await http.put<ApiEnvelope<null>, ApiEnvelope<null>>(`${basePath}/${id}`, payload, {
params: { tenantId, warehouseId },
params: { tenantId: platformResourceScope, warehouseId },
})
return unwrapApiResponse(response)
}
export async function changePlatformLocationStatus(
tenantId: number | string,
warehouseId: number | string,
id: number | string,
status: EditablePlatformLocationStatus,
@@ -130,19 +126,18 @@ export async function changePlatformLocationStatus(
const response = await http.patch<ApiEnvelope<null>, ApiEnvelope<null>>(
`${basePath}/${id}/status`,
{ status, version },
{ params: { tenantId, warehouseId } },
{ params: { tenantId: platformResourceScope, warehouseId } },
)
return unwrapApiResponse(response)
}
export async function deletePlatformLocation(
tenantId: number | string,
warehouseId: number | string,
id: number | string,
version: number,
) {
const response = await http.delete<ApiEnvelope<null>, ApiEnvelope<null>>(`${basePath}/${id}`, {
params: { tenantId, warehouseId, version },
params: { tenantId: platformResourceScope, warehouseId, version },
})
return unwrapApiResponse(response)
}
@@ -151,7 +151,7 @@ describe('LocationsView', () => {
vi.mocked(createPlatformLocation).mockReset()
})
it('loads all warehouse candidates for querying while restricting write scope to domestic warehouses', async () => {
it('loads only domestic warehouse candidates for querying and writes', async () => {
const wrapper = await mountView()
const toolbar = wrapper.findComponent(QueryToolbar)
const fields = toolbar.props('fields') as QueryField[]
@@ -160,14 +160,12 @@ describe('LocationsView', () => {
expect(fields[0]?.placeholder).toBe('全部仓库')
expect(fields[0]?.options).toEqual([
{ value: warehouseId, label: '义乌收货仓(CN-YW-01)' },
{ value: fbaWarehouse.id, label: 'ONT8 FBA 仓(FBA-ONT8)' },
{ value: overseasWarehouse.id, label: '洛杉矶海外仓(US-LAX-01)' },
])
expect(fields.map(({ key, width }) => [key, width])).toEqual([
['warehouseId', 300], ['zoneCode', 210],
['locationCode', 220], ['locationType', 170], ['status', 160],
])
expect(listAllPlatformWarehouses).toHaveBeenCalledWith()
expect(listAllPlatformWarehouses).toHaveBeenCalledWith({ warehouseType: 'DOMESTIC' })
expect(listPlatformLocations).toHaveBeenCalledWith({
page: 1,
size: 20,
@@ -196,7 +194,7 @@ describe('LocationsView', () => {
expect(panelHeading.text()).toContain('共 2 个库位')
expect(panelHeading.text()).toContain('新增库位')
expect(wrapper.findComponent(QueryToolbar).text()).not.toContain('新增库位')
expect(listAllPlatformWarehouses).toHaveBeenCalledWith()
expect(listAllPlatformWarehouses).toHaveBeenCalledWith({ warehouseType: 'DOMESTIC' })
expect(listPlatformLocations).toHaveBeenLastCalledWith({
page: 1,
size: 20,
@@ -274,7 +272,7 @@ describe('LocationsView', () => {
await detailButton.trigger('click')
await flushPromises()
expect(getPlatformLocation).toHaveBeenCalledWith(tenantId, warehouseId, availableLocation.id)
expect(getPlatformLocation).toHaveBeenCalledWith(warehouseId, availableLocation.id)
expect(document.body.textContent).toContain('库位详情')
expect(document.body.textContent).toContain('义乌收货仓(CN-YW-01)')
expect(document.body.textContent).toContain('资源作用域平台公共资源')
@@ -105,7 +105,6 @@ const queryFields = computed<QueryField[]>(() => [
const emptyForm = () => ({
id: '',
customerId: '',
warehouseId: '',
zoneCode: '',
zoneName: '',
@@ -236,11 +235,11 @@ function requireCreateScope() {
ElMessage.warning('请选择国内仓')
return null
}
return { customerId: apiId(String(selectedWarehouse.value.tenantId)), warehouseId: apiId(form.warehouseId) }
return { warehouseId: apiId(form.warehouseId) }
}
function recordScope(row: PlatformLocationResource) {
return { customerId: apiId(String(row.tenantId)), warehouseId: apiId(String(row.warehouseId)) }
return { warehouseId: apiId(String(row.warehouseId)) }
}
async function loadWarehouses() {
@@ -249,9 +248,11 @@ async function loadWarehouses() {
warehouseError.value = null
warehouses.value = []
try {
const records = await listAllPlatformWarehouses()
// 库位只属于国内仓,查询候选仓库时直接限制仓库类型,避免把 FBA/海外仓带入页面。
const records = await listAllPlatformWarehouses({ warehouseType: 'DOMESTIC' })
if (sequence !== warehouseLoadSequence) return
warehouses.value = records
// 保留前端兜底过滤,避免旧接口或异常响应返回其他仓库类型。
warehouses.value = records.filter((warehouse) => warehouse.warehouseType === 'DOMESTIC')
} catch (error) {
if (sequence !== warehouseLoadSequence) return
warehouseError.value = getApiErrorDetails(error, '仓库列表加载失败,请稍后重试')
@@ -303,7 +304,6 @@ function applyFilters(model: QueryModel) {
function assignForm(resource: PlatformLocationResource) {
Object.assign(form, {
id: String(resource.id),
customerId: String(resource.tenantId),
warehouseId: String(resource.warehouseId),
zoneCode: resource.zoneCode,
zoneName: resource.zoneName,
@@ -320,7 +320,6 @@ function assignForm(resource: PlatformLocationResource) {
function openCreate() {
Object.assign(form, emptyForm())
form.warehouseId = isActiveDomesticWarehouse(selectedWarehouseId.value) ? selectedWarehouseId.value : ''
form.customerId = selectedWarehouse.value ? String(selectedWarehouse.value.tenantId) : ''
form.status = selectedWarehouse.value?.status === 'INACTIVE' ? 'DISABLED' : 'AVAILABLE'
detail.value = null
drawerError.value = null
@@ -342,7 +341,7 @@ async function loadDetail(row: PlatformLocationResource, mode: 'view' | 'edit')
drawerError.value = null
detail.value = null
try {
const result = await getPlatformLocation(scope.customerId, scope.warehouseId, row.id)
const result = await getPlatformLocation(scope.warehouseId, row.id)
detail.value = result
if (mode === 'edit') {
assignForm(result.location)
@@ -381,15 +380,13 @@ async function saveLocation() {
ElMessage.error(form.id ? '库位仅支持归属国内仓' : '新增库位仅支持选择启用的国内仓')
return
}
const scope = form.id
? { customerId: apiId(form.customerId), warehouseId: apiId(form.warehouseId) }
: requireCreateScope()
const scope = form.id ? { warehouseId: apiId(form.warehouseId) } : requireCreateScope()
if (!scope) return
saving.value = true
try {
const payload = buildPayload()
if (form.id) await updatePlatformLocation(scope.customerId, scope.warehouseId, form.id, payload)
else await createPlatformLocation(scope.customerId, payload)
if (form.id) await updatePlatformLocation(scope.warehouseId, form.id, payload)
else await createPlatformLocation(payload)
drawerOpen.value = false
ElMessage.success(form.id ? '库位资料已更新' : '库位已创建')
await loadLocations()
@@ -426,7 +423,7 @@ async function toggleStatus(row: PlatformLocationResource) {
}
setActionLoading(row.id, true)
try {
await changePlatformLocationStatus(scope.customerId, scope.warehouseId, row.id, nextStatus, row.version)
await changePlatformLocationStatus(scope.warehouseId, row.id, nextStatus, row.version)
ElMessage.success(`库位 ${row.locationCode} 已${action}`)
await loadLocations()
} catch (error) {
@@ -451,7 +448,7 @@ async function removeLocation(row: PlatformLocationResource) {
}
setActionLoading(row.id, true)
try {
await deletePlatformLocation(scope.customerId, scope.warehouseId, row.id, row.version)
await deletePlatformLocation(scope.warehouseId, row.id, row.version)
ElMessage.success(`库位 ${row.locationCode} 已删除`)
await loadLocations()
} catch (error) {
@@ -480,7 +477,6 @@ watch([page, pageSize], () => { void loadLocations() })
watch(() => form.warehouseId, (warehouseId) => {
if (drawerMode.value !== 'create') return
const warehouse = warehouses.value.find((item) => String(item.id) === warehouseId)
form.customerId = warehouse ? String(warehouse.tenantId) : ''
form.status = warehouse?.status === 'INACTIVE' ? 'DISABLED' : 'AVAILABLE'
})