This commit is contained in:
2026-08-10 16:24:54 +08:00
parent e119b48662
commit 820432a381
52 changed files with 1015 additions and 705 deletions
@@ -87,9 +87,20 @@ describe('ExpressCompaniesView query and table migration', () => {
expect(wrapper.text()).toContain('顺丰速运')
expect(wrapper.text()).toContain('平台公共数据 · 共 1 家快递公司')
expect(wrapper.find('.metric-strip').exists()).toBe(false)
expect(wrapper.find('.list-page-layout__state').exists()).toBe(false)
expect(listPlatformExpressCompanies).toHaveBeenCalledWith(1, 20, '', '')
})
it('renders the error state instead of an empty table panel', async () => {
vi.mocked(listPlatformExpressCompanies).mockRejectedValueOnce(new Error('Gateway unavailable'))
const wrapper = await mountView()
expect(wrapper.find('.list-page-layout__state').exists()).toBe(true)
expect(wrapper.find('.table-panel').exists()).toBe(false)
expect(wrapper.text()).toContain('快递公司加载失败')
expect(wrapper.text()).toContain('Gateway unavailable')
})
it('does not request with edited filters until search is submitted', async () => {
const wrapper = await mountView()
await wrapper.find('input[placeholder="快递公司名称或编码"]').setValue('顺丰')
@@ -1,14 +1,13 @@
<script setup lang="ts">
import { computed, onMounted, reactive, ref, watch } from 'vue'
import { ElMessage, ElMessageBox, type FormInstance, type FormRules } from 'element-plus'
import { ExternalLink, Pencil, Plus, Power, Truck, Upload } from '@lucide/vue'
import { ExternalLink, FileUp, Pencil, Plus, Power, Save, Truck } from '@lucide/vue'
import ApiErrorMeta from '@/shared/components/ApiErrorMeta.vue'
import AdminPage from '@/shared/components/AdminPage.vue'
import BatchImportDialog from '@/shared/components/BatchImportDialog.vue'
import DataTable, { type DataTableColumn } from '@/shared/components/DataTable.vue'
import FormSection from '@/shared/components/FormSection.vue'
import ListPageLayout from '@/shared/components/ListPageLayout.vue'
import PageToolbar from '@/shared/components/PageToolbar.vue'
import QueryToolbar, { type QueryField, type QueryModel } from '@/shared/components/QueryToolbar.vue'
import { useUnsavedWorkRegistration } from '@/core/unsaved-work/useUnsavedWorkRegistration'
import { getApiErrorDetails, type ApiErrorDetails } from '@/shared/api/http'
@@ -284,18 +283,12 @@ onMounted(() => {
<template>
<AdminPage>
<div class="business-page express-company-page">
<PageToolbar title="快递公司" :description="`平台公共数据 · 共 ${total} 家快递公司`">
<template #actions>
<el-button v-if="access.can('platform:express:import')" :disabled="loading" @click="openImport"><Upload :size="16" />批量导入</el-button>
<el-button v-if="access.can('platform:express:create')" type="primary" :disabled="loading" @click="openCreate"><Plus :size="16" />新增快递公司</el-button>
</template>
</PageToolbar>
<ListPageLayout ariaLabel="快递公司列表">
<template #toolbar>
<QueryToolbar v-model="filters" class="surface-panel" ariaLabel="快递公司筛选" :fields="queryFields" preference-key="express-companies-query" @search="applyFilters" />
</template>
<template #state>
<el-alert v-if="loadError" type="error" :closable="false" show-icon class="state-alert">
<template v-if="loadError" #state>
<el-alert type="error" :closable="false" show-icon class="state-alert">
<template #title>快递公司加载失败</template>
<p>{{ loadError.message }}</p>
<ApiErrorMeta :details="loadError" />
@@ -303,7 +296,7 @@ onMounted(() => {
</el-alert>
</template>
<section class="surface-panel table-panel">
<section v-if="!loadError" class="surface-panel table-panel">
<DataTable
v-model:page="page"
v-model:page-size="pageSize"
@@ -317,6 +310,7 @@ onMounted(() => {
row-key="id"
:empty-text="appliedFilters.keyword.trim() || appliedFilters.status ? '暂无符合筛选条件的快递公司' : '暂无快递公司档案'"
>
<template #toolbar-actions><div class="table-actions"><el-button v-if="access.can('platform:express:import')" :disabled="loading" @click="openImport"><FileUp :size="16" />批量导入</el-button><el-button v-if="access.can('platform:express:create')" type="primary" :disabled="loading" @click="openCreate"><Plus :size="16" />新增快递公司</el-button></div></template>
<template #actions="{ row }">
<div v-if="access.can('platform:express:edit') || access.can('platform:express:status')" class="table-actions">
<el-button
@@ -351,7 +345,7 @@ onMounted(() => {
<el-button v-if="!appliedFilters.keyword.trim() && !appliedFilters.status && access.can('platform:express:create')" type="primary" @click="openCreate"><Plus :size="16" />新增第一家快递公司</el-button>
</el-empty>
</template>
<template #pagination-left="{ total: tableTotal }"><span>共 {{ tableTotal }} 家快递公司</span></template>
<template #pagination-left="{ total: tableTotal }"><span>平台公共数据 · 共 {{ tableTotal }} 家快递公司</span></template>
</DataTable>
</section>
</ListPageLayout>
@@ -389,7 +383,7 @@ onMounted(() => {
</FormSection>
<FormSection title="备注"><el-form-item label="内部说明"><el-input v-model.trim="form.remark" type="textarea" :rows="4" maxlength="500" show-word-limit placeholder="请输入适用范围、服务限制或其他说明" /></el-form-item></FormSection>
</el-form>
<template #footer><div class="drawer-footer"><el-button :disabled="saving" @click="editorOpen = false">取消</el-button><el-button type="primary" :loading="saving" @click="saveExpressCompany">保存快递公司</el-button></div></template>
<template #footer><div class="drawer-footer"><el-button :disabled="saving" @click="editorOpen = false">取消</el-button><el-button type="primary" :loading="saving" @click="saveExpressCompany"><Save :size="16" />保存快递公司</el-button></div></template>
</el-drawer>
</div>
</AdminPage>