feat(phase3): complete loading workbenches

This commit is contained in:
2026-08-10 17:42:17 +08:00
parent 820432a381
commit 1595fbcae2
34 changed files with 1352 additions and 159 deletions
@@ -43,11 +43,11 @@ const detail = {
describe('platform loading lists API', () => {
beforeEach(() => vi.restoreAllMocks())
it('queries preload plans with required warehouse and fixed LOADING status', async () => {
it('queries preload plans across all warehouses with fixed LOADING status', async () => {
const get = vi.spyOn(http, 'get').mockResolvedValue({ code: '200', message: 'ok', data: { records: [preloadSummary], page: '1', size: '20', total: '1', pages: '1' } })
const result = await listPreloadPlans({ page: 1, size: 20, warehouseId: '300', keyword: 'PL' })
const result = await listPreloadPlans({ page: 1, size: 20, keyword: 'PL' })
expect(get).toHaveBeenCalledWith('/platform/v1/first-leg/loading-plans', { params: { page: 1, size: 20, warehouseId: '300', keyword: 'PL', status: 'LOADING' } })
expect(get).toHaveBeenCalledWith('/platform/v1/first-leg/loading-plans', { params: { page: 1, size: 20, keyword: 'PL', status: 'LOADING' } })
expect(result.total).toBe(1)
expect(result.records[0]?.planId).toBe('1900000000000000001')
expect(result.records[0]?.customers[0]?.accountId).toBe('1900000000000000002')
@@ -76,10 +76,11 @@ describe('platform loading lists API', () => {
.mockResolvedValueOnce({ code: '200', message: 'ok', data: { records: [confirmed], page: '1', size: '20', total: '1', pages: '1' } })
.mockResolvedValueOnce({ code: '200', message: 'ok', data: { ...detail, summary: confirmed } })
const page = await listConfirmedLoadingLists({ page: 1, size: 20, warehouseId: '300' })
const page = await listConfirmedLoadingLists({ page: 1, size: 20 })
const loaded = await getConfirmedLoadingList('100', '300')
expect(get.mock.calls[0]?.[0]).toBe('/platform/v1/first-leg/loading-lists')
expect(get.mock.calls[0]?.[1]).toEqual({ params: { page: 1, size: 20 } })
expect(get.mock.calls[1]?.[0]).toBe('/platform/v1/first-leg/loading-lists/100')
expect(page.records[0]?.createdBy).toBe('9')
expect(loaded.summary.status).toBe('COMPLETED')
@@ -110,7 +110,7 @@ export interface LoadingListPage<T extends LoadingListSummary = LoadingListSumma
export interface LoadingListQuery {
page: number
size: number
warehouseId: string
warehouseId?: string
keyword?: string
createdFrom?: string
createdTo?: string
@@ -13,10 +13,11 @@ describe('LoadingListsView', () => {
expect(source.indexOf("key: 'actions'", source.indexOf("key: 'actions'") + 1)).toBeLessThan(source.indexOf("key: 'loadingListNo'"))
})
it('requires a warehouse before sending a list request', () => {
expect(source).toContain("if (!warehouseId) return null")
expect(source).toContain("ElMessage.warning('请先选择仓库')")
expect(source).toContain("'请先选择仓库后查询'")
it('queries all warehouses when the warehouse filter is empty', () => {
expect(source).toContain("placeholder: loadingWarehouses.value ? '仓库加载中' : '全部仓库'")
expect(source).toContain('warehouseId: warehouseId || undefined')
expect(source).not.toContain("ElMessage.warning('请先选择仓库')")
expect(source).not.toContain("'请先选择仓库后查询'")
})
it('uses the shared query, table, drawer, dialog and error components', () => {
@@ -58,13 +58,11 @@ const viewPermission = computed(() => isPreload.value ? 'platform:firstleg:prelo
const canList = computed(() => access.can(listPermission.value))
const canView = computed(() => access.can(viewPermission.value))
const canEdit = computed(() => isPreload.value && access.can('platform:firstleg:preload:edit'))
const hasWarehouse = computed(() => Boolean(String(query.warehouseId || '').trim()))
const fields = computed<QueryField[]>(() => [
{
key: 'warehouseId', type: 'select', label: '仓库', placeholder: loadingWarehouses.value ? '仓库加载中' : '请选择仓库(必选)', width: 220,
key: 'warehouseId', type: 'select', label: '仓库', placeholder: loadingWarehouses.value ? '仓库加载中' : '全部仓库', width: 220,
options: warehouses.value.map((warehouse) => ({ label: warehouse.name, value: warehouse.id })),
props: { loading: loadingWarehouses.value, 'aria-label': '仓库(必选)' },
props: { loading: loadingWarehouses.value, clearable: true, 'aria-label': '仓库' },
},
{ key: 'keyword', type: 'input', label: '关键词', placeholder: isPreload.value ? '预装单号/集装箱号/柜号' : '装柜清单号/集装箱号/柜号', width: 250 },
{ key: 'createdRange', type: 'daterange', label: '创建日期', width: 260 },
@@ -117,14 +115,13 @@ function formatNumber(value?: number | null, digits = 3) {
return Number(value).toLocaleString('zh-CN', { maximumFractionDigits: digits })
}
function toQuery(): LoadingListQuery | null {
function toQuery(): LoadingListQuery {
const warehouseId = String(query.warehouseId || '').trim()
if (!warehouseId) return null
const range = Array.isArray(query.createdRange) ? query.createdRange.map(String) : []
return {
page: page.value,
size: pageSize.value,
warehouseId,
warehouseId: warehouseId || undefined,
keyword: String(query.keyword || '').trim() || undefined,
createdFrom: range[0] ? `${range[0]}T00:00:00` : undefined,
createdTo: range[1] ? `${range[1]}T23:59:59` : undefined,
@@ -146,12 +143,6 @@ async function loadWarehouses() {
async function load() {
if (!canList.value) return
const request = toQuery()
if (!request) {
rows.value = []
total.value = 0
error.value = null
return
}
loading.value = true
error.value = null
try {
@@ -166,21 +157,13 @@ async function load() {
}
function search() {
if (!hasWarehouse.value) {
rows.value = []
total.value = 0
ElMessage.warning('请先选择仓库')
return
}
if (page.value !== 1) page.value = 1
else void load()
}
function reset() {
page.value = 1
rows.value = []
total.value = 0
error.value = null
void load()
}
async function loadDetail() {
@@ -240,8 +223,11 @@ async function saveTransport() {
}
}
watch([page, pageSize], () => { if (hasWarehouse.value) void load() })
onMounted(() => void loadWarehouses())
watch([page, pageSize], () => void load())
onMounted(() => {
void loadWarehouses()
void load()
})
</script>
<template>
@@ -277,7 +263,7 @@ onMounted(() => void loadWarehouses())
:total="total"
:preference-key="`loading-lists-${mode}`"
row-key="planId"
:empty-text="hasWarehouse ? `暂无符合筛选条件的${title}` : '请先选择仓库后查询'"
:empty-text="`暂无符合筛选条件的${title}`"
:aria-label="title"
>
<template #actions="{ row }"><el-button v-if="canView" link type="primary" @click="openDetail(row)"><Eye :size="15" />查看</el-button></template>
+1 -1
View File
@@ -17,7 +17,7 @@ export const loadingListRoutes = [
component: () => import('./pages/ConfirmedLoadingListsView.vue'),
meta: {
title: '装柜清单',
description: '按仓库查看已完成且永久只读的装柜清单',
description: '查看全部仓库已完成且永久只读的装柜清单',
permission: 'platform:firstleg:loading-list:list',
},
},