feat: show overseas funding and pallet summaries

This commit is contained in:
2026-09-05 22:26:37 +08:00
parent 92b24cc9a6
commit ccf16b823b
19 changed files with 116 additions and 28 deletions
@@ -21,6 +21,7 @@ export interface PlatformPalletPage {
total: number
pages: number
}
export interface PlatformPalletSummary { totalCount: number; idleCount: number; occupiedCount: number }
export interface PlatformPalletQuery {
page: number
@@ -61,6 +62,10 @@ export async function listPlatformPallets(query: PlatformPalletQuery) {
pages: Number(result.pages),
}
}
export async function getPlatformPalletSummary(query: PlatformPalletQuery) {
const response = await http.get<ApiEnvelope<PlatformPalletSummary>, ApiEnvelope<PlatformPalletSummary>>(`${basePath}/summary`, { params: { tenantId: platformResourceScope, warehouseId: query.warehouseId || undefined, palletCode: query.palletCode?.trim() || undefined, palletType: query.palletType?.trim() || undefined, page: 1, size: 1 } })
const value = unwrapApiResponse(response); return { totalCount: Number(value.totalCount), idleCount: Number(value.idleCount), occupiedCount: Number(value.occupiedCount) }
}
export async function getPlatformPallet(
warehouseId: number | string,
@@ -12,6 +12,7 @@ import QueryToolbar from '@/shared/components/QueryToolbar.vue'
import {
createPlatformPallet,
getPlatformPallet,
getPlatformPalletSummary,
listPlatformPallets,
type PlatformPalletResource,
} from '../api/platformPallets'
@@ -22,6 +23,7 @@ const palletsSource = readFileSync(resolve(process.cwd(), 'src/modules/warehouse
vi.mock('@/modules/warehouses', () => ({ listAllPlatformWarehouses: vi.fn() }))
vi.mock('../api/platformPallets', () => ({
listPlatformPallets: vi.fn(),
getPlatformPalletSummary: vi.fn(),
getPlatformPallet: vi.fn(),
createPlatformPallet: vi.fn(),
updatePlatformPallet: vi.fn(),
@@ -134,6 +136,7 @@ describe('PalletsView', () => {
document.body.innerHTML = ''
vi.mocked(listAllPlatformWarehouses).mockReset().mockResolvedValue([warehouse, fbaWarehouse, overseasWarehouse])
vi.mocked(listPlatformPallets).mockReset().mockResolvedValue({ records: [pallet], page: 1, size: 20, total: 1, pages: 1 })
vi.mocked(getPlatformPalletSummary).mockReset().mockResolvedValue({ totalCount: 1, idleCount: 1, occupiedCount: 0 })
vi.mocked(getPlatformPallet).mockReset().mockResolvedValue(pallet)
vi.mocked(createPlatformPallet).mockReset().mockResolvedValue('20002')
})
@@ -16,9 +16,11 @@ import {
createPlatformPallet,
deletePlatformPallet,
getPlatformPallet,
getPlatformPalletSummary,
listPlatformPallets,
updatePlatformPallet,
type PlatformPalletResource,
type PlatformPalletSummary,
type SavePlatformPalletRequest,
} from '../api/platformPallets'
@@ -32,6 +34,7 @@ const loadError = ref<ApiErrorDetails | null>(null)
const page = ref(1)
const pageSize = ref(20)
const total = ref(0)
const summary = ref<PlatformPalletSummary>({ totalCount: 0, idleCount: 0, occupiedCount: 0 })
const editorOpen = ref(false)
const saving = ref(false)
const deletingIds = ref(new Set<string>())
@@ -187,16 +190,18 @@ async function loadPallets() {
loadError.value = null
loading.value = true
try {
const result = await listPlatformPallets({
const query = {
page: page.value,
size: pageSize.value,
...(appliedFilters.value.warehouseId ? { warehouseId: apiId(appliedFilters.value.warehouseId) } : {}),
...(appliedFilters.value.palletCode ? { palletCode: appliedFilters.value.palletCode } : {}),
...(appliedFilters.value.palletType ? { palletType: appliedFilters.value.palletType } : {}),
})
}
const [result, summaryResult] = await Promise.all([listPlatformPallets(query), getPlatformPalletSummary(query)])
if (sequence !== palletSequence) return
rows.value = result.records
total.value = result.total
summary.value = summaryResult
} catch (error) {
if (sequence !== palletSequence) return
loadError.value = getApiErrorDetails(error, '托盘列表加载失败,请稍后重试')
@@ -339,6 +344,11 @@ onMounted(() => {
<template>
<AdminPage as="div" class="pallet-page">
<section class="summary-grid" aria-label="托盘数量概览">
<article><span>托盘总数</span><strong>{{ summary.totalCount }}</strong></article>
<article><span>闲置托盘</span><strong class="idle">{{ summary.idleCount }}</strong></article>
<article><span>占用托盘</span><strong class="occupied">{{ summary.occupiedCount }}</strong></article>
</section>
<ListPageLayout aria-label="托盘列表页面">
<template #toolbar>
<QueryToolbar
@@ -468,6 +478,9 @@ onMounted(() => {
<style scoped>
.pallet-page { display: grid; min-width: 0; gap: 16px; }
.summary-grid { display:grid; grid-template-columns:repeat(3,minmax(0,1fr)); gap:16px; }
.summary-grid article { display:grid; gap:8px; padding:18px 20px; border:1px solid var(--cc-border); border-radius:8px; background:#fff; }
.summary-grid span { color:var(--cc-muted); font-size:12px; }.summary-grid strong { font-size:26px; }.summary-grid .idle { color:var(--el-color-success); }.summary-grid .occupied { color:var(--el-color-warning); }
.surface-panel { overflow: hidden; border: 1px solid var(--cc-border); border-radius: 8px; background: #fff; }
.table-panel { min-width: 0; }
.context-empty { padding: 56px 20px; color: var(--cc-muted); text-align: center; }
@@ -489,6 +502,7 @@ onMounted(() => {
.editor-form :deep(.el-form-item) { margin-bottom: 18px; }
.editor-form :deep(.el-form-item__label) { padding-bottom: 7px; color: #344054; font-size: 12px; font-weight: 650; line-height: 1.4; }
@media (max-width: 720px) {
.summary-grid { grid-template-columns:1fr; }
.editor-field-grid { grid-template-columns: minmax(0, 1fr); }
}
.editor-remark-field { margin-bottom: 0 !important; }