优化
This commit is contained in:
@@ -1,4 +1,5 @@
|
||||
<script setup lang="ts">
|
||||
import '@/styles/adminDensity.css'
|
||||
import AppDialog from '@/shared/components/AppDialog.vue'
|
||||
import type { Supplier } from '@/modules/suppliers/types'
|
||||
|
||||
@@ -7,7 +8,7 @@ const open = defineModel<boolean>({ default: false })
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<AppDialog v-model="open" :title="`营业执照查看${supplier ? ` - ${supplier.name}` : ''}`" width="min(560px, calc(100vw - 24px))" :show-confirm="false" cancel-text="关闭">
|
||||
<AppDialog class="admin-density-dialog" v-model="open" :title="`营业执照查看${supplier ? ` - ${supplier.name}` : ''}`" width="min(560px, calc(100vw - 24px))" :show-confirm="false" cancel-text="关闭">
|
||||
<div v-if="supplier" class="license-dialog">
|
||||
<p class="license-dialog__supplier">供应商:<strong>{{ supplier.name }}</strong></p>
|
||||
<section class="license-card" aria-label="营业执照信息">
|
||||
@@ -25,13 +26,13 @@ const open = defineModel<boolean>({ default: false })
|
||||
</template>
|
||||
|
||||
<style scoped>
|
||||
.license-dialog__supplier { margin: 0 0 14px; color: var(--cc-muted); font-size: 13px; }
|
||||
.license-card { max-width: 460px; margin: 0 auto; padding: 24px 28px; border: 2px solid #c0392b; border-radius: 8px; background: #fff; box-shadow: 0 4px 16px rgba(192,57,43,.12); }
|
||||
.license-dialog__supplier { margin: 0 0 var(--admin-space-5); color: var(--cc-muted); font-size: var(--admin-font-body); }
|
||||
.license-card { max-width: 460px; margin: 0 auto; padding: var(--admin-space-7) var(--admin-space-7); border: 2px solid #c0392b; border-radius: var(--admin-radius); background: #fff; box-shadow: 0 4px 16px rgba(192,57,43,.12); }
|
||||
.license-card h2 { margin: 0; color: #c0392b; font-size: 22px; letter-spacing: 6px; text-align: center; }
|
||||
.license-card__copy { margin: 2px 0 18px; color: #c0392b; font-size: 12px; text-align: center; }
|
||||
.license-card__copy { margin: 2px 0 var(--admin-space-6); color: #c0392b; font-size: var(--admin-font-caption); text-align: center; }
|
||||
.license-card dl { margin: 0; }
|
||||
.license-card dl div { display: grid; grid-template-columns: 126px minmax(0, 1fr); margin-bottom: 10px; font-size: 14px; }
|
||||
.license-card dl div { display: grid; grid-template-columns: 126px minmax(0, 1fr); margin-bottom: var(--admin-space-4); font-size: var(--admin-font-body); }
|
||||
.license-card dt { color: #444; font-weight: 700; }.license-card dd { min-width: 0; margin: 0; overflow-wrap: anywhere; }
|
||||
.license-dialog__notice { margin-top: 16px; }
|
||||
.license-dialog__notice { margin-top: var(--admin-space-6); }
|
||||
@media (max-width: 480px) { .license-card { padding: 20px 16px; } .license-card dl div { grid-template-columns: 1fr; gap: 3px; } .license-card h2 { font-size: 19px; } }
|
||||
</style>
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
<script setup lang="ts">
|
||||
import '@/styles/adminDensity.css'
|
||||
import { computed, ref, watch } from 'vue'
|
||||
import { useRoute, useRouter } from 'vue-router'
|
||||
import { ArrowLeft, FileText, Pencil } from '@lucide/vue'
|
||||
@@ -45,12 +46,12 @@ watch(supplierId, () => { void load() }, { immediate: true })
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<AdminPage width="comfortable"><DetailPageLayout aria-label="供应商详情">
|
||||
<template #header><div class="detail-header"><div><h2>{{ supplier?.name || '供应商详情' }}</h2><StatusBadge v-if="supplier" :status="statusLabels[supplier.status]" /></div><div class="detail-actions"><el-button @click="router.push({ name: 'supplier-list' })"><ArrowLeft :size="16" />返回</el-button><el-button v-if="supplier && access.can('platform:supplier:edit')" type="primary" @click="router.push({ name: 'supplier-edit', params: { id: supplier.id } })"><Pencil :size="16" />编辑</el-button></div></div></template>
|
||||
<AdminPage class="admin-density" ><DetailPageLayout class="density-detail-layout surface-panel" aria-label="供应商详情">
|
||||
<template #header><div class="density-detail-header"><div class="density-detail-heading"><el-button link class="density-back" @click="router.push({ name: 'supplier-list' })"><ArrowLeft :size="16" />返回列表</el-button><h1 class="density-detail-title">{{ supplier?.name || '供应商详情' }}</h1><StatusBadge v-if="supplier" :status="statusLabels[supplier.status]" /></div><el-button v-if="supplier && access.can('platform:supplier:edit')" type="primary" @click="router.push({ name: 'supplier-edit', params: { id: supplier.id } })"><Pencil :size="16" />编辑</el-button></div></template>
|
||||
<LoadErrorState v-if="!canView" title="暂无供应商查看权限" message="请联系管理员开通供应商查看权限。" :show-retry="false" />
|
||||
<LoadErrorState v-else-if="error" title="供应商详情加载失败" :message="error.message" :loading="loading" @retry="load"><template #details><ApiErrorMeta :details="error" /></template></LoadErrorState>
|
||||
<section v-else v-loading="loading" class="surface-panel detail-panel">
|
||||
<dl v-if="supplier" class="detail-grid"><div v-for="item in items" :key="item[0]"><dt>{{ item[0] }}</dt><dd>{{ item[1] }}</dd></div></dl>
|
||||
<section v-else v-loading="loading" class="detail-panel">
|
||||
<dl v-if="supplier" class="detail-grid density-fields"><div v-for="item in items" :key="item[0]" :class="{ 'wide-field': ['可代理船公司', '公司地址', '备注'].includes(item[0]) }"><dt>{{ item[0] }}</dt><dd>{{ item[1] }}</dd></div></dl>
|
||||
<div v-if="supplier" class="license-row"><div><strong>营业执照</strong><span>{{ supplier.licenseFileId ? '已关联资质文件' : '未上传资质文件' }}</span></div><el-button type="primary" plain @click="licenseOpen = true"><FileText :size="16" />查看营业执照</el-button></div>
|
||||
</section>
|
||||
<SupplierLicenseDialog v-model="licenseOpen" :supplier="supplier" />
|
||||
@@ -58,7 +59,8 @@ watch(supplierId, () => { void load() }, { immediate: true })
|
||||
</template>
|
||||
|
||||
<style scoped>
|
||||
.detail-header { display: flex; align-items: center; justify-content: space-between; gap: 16px; padding: 16px 20px; border: 1px solid var(--cc-border); border-radius: 8px; background: #fff; }.detail-header > div { display: flex; align-items: center; flex-wrap: wrap; gap: 12px; }.detail-header h2 { margin: 0; font-size: 16px; overflow-wrap: anywhere; }.detail-actions :deep(.el-button + .el-button) { margin-left: 0; }
|
||||
.detail-panel { padding: 22px; }.detail-grid { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); margin: 0; }.detail-grid div { min-width: 0; padding: 14px 16px; border-right: 1px solid var(--cc-border); border-bottom: 1px solid var(--cc-border); }.detail-grid div:nth-child(3n) { border-right: 0; }.detail-grid dt { margin-bottom: 6px; color: var(--cc-muted); font-size: 12px; }.detail-grid dd { margin: 0; line-height: 1.55; overflow-wrap: anywhere; }.license-row { display: flex; align-items: center; justify-content: space-between; gap: 16px; margin-top: 20px; padding: 16px; border: 1px dashed var(--cc-border); border-radius: 6px; background: #fafafa; }.license-row strong,.license-row span { display: block; }.license-row span { margin-top: 4px; color: var(--cc-muted); font-size: 12px; }
|
||||
.detail-actions :deep(.el-button + .el-button) { margin-left: 0; }
|
||||
.detail-panel { min-width: 0; }
|
||||
.detail-grid .wide-field { grid-column: span 2; }.license-row { display: flex; align-items: center; justify-content: space-between; gap: var(--admin-space-6); margin-top: var(--admin-space-7); padding: var(--admin-space-6); border: 1px dashed var(--cc-border); border-radius: var(--admin-radius); background: #fafafa; }.license-row strong,.license-row span { display: block; }.license-row span { margin-top: var(--admin-space-1); color: var(--cc-muted); font-size: var(--admin-font-caption); }
|
||||
@media (max-width: 720px) { .detail-header,.license-row { align-items: stretch; flex-direction: column; }.detail-actions { display: grid !important; grid-template-columns: 1fr 1fr; }.detail-actions :deep(.el-button) { min-height: 44px; }.detail-grid { grid-template-columns: 1fr; }.detail-grid div,.detail-grid div:nth-child(3n) { border-right: 0; }.detail-panel { padding: 16px; } }
|
||||
</style>
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
<script setup lang="ts">
|
||||
import '@/styles/adminDensity.css'
|
||||
import { computed, onActivated, onDeactivated, reactive, ref, watch } from 'vue'
|
||||
import { useRoute, useRouter } from 'vue-router'
|
||||
import { ElMessage, type FormInstance, type FormRules } from 'element-plus'
|
||||
@@ -89,15 +90,15 @@ watch(() => form.category, (category) => { if (category !== 'BOOKING') form.carr
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<AdminPage width="comfortable">
|
||||
<AdminPage class="admin-density" >
|
||||
<OperationErrorToast :details="submitError" />
|
||||
<DetailPageLayout :aria-label="editing ? '编辑供应商' : '新增供应商'">
|
||||
<template #header><div class="form-page-header"><h2>{{ editing ? '编辑供应商' : '新增供应商' }}</h2><el-button @click="router.push({ name: 'supplier-list' })"><ArrowLeft :size="16" />返回</el-button></div></template>
|
||||
<DetailPageLayout class="density-detail-layout surface-panel" :aria-label="editing ? '编辑供应商' : '新增供应商'">
|
||||
<template #header><div class="density-detail-header"><div class="density-detail-heading"><el-button link class="density-back" @click="router.push({ name: 'supplier-list' })"><ArrowLeft :size="16" />返回列表</el-button><h1 class="density-detail-title">{{ editing ? '编辑供应商' : '新增供应商' }}</h1></div></div></template>
|
||||
<LoadErrorState v-if="!access.can(requiredPermission)" title="暂无操作权限" :message="`请联系管理员开通${editing ? '供应商编辑' : '供应商新增'}权限。`" :show-retry="false" />
|
||||
<LoadErrorState v-else-if="loadError" title="供应商加载失败" :message="loadError.message" :loading="loading" @retry="load"><template #details><ApiErrorMeta :details="loadError" /></template></LoadErrorState>
|
||||
<section v-else v-loading="loading" class="surface-panel supplier-form-panel">
|
||||
<el-form ref="formRef" :model="form" :rules="rules" label-position="top" :disabled="saving">
|
||||
<FormSection title="基础信息">
|
||||
<section v-else v-loading="loading" class="supplier-form-panel">
|
||||
<el-form class="density-form" ref="formRef" :model="form" :rules="rules" label-position="top" :disabled="saving">
|
||||
<FormSection class="density-form-section" title="基础信息">
|
||||
<div class="form-grid">
|
||||
<el-form-item label="供应商名称" prop="name"><el-input v-model="form.name" maxlength="160" placeholder="请输入供应商名称" /></el-form-item>
|
||||
<el-form-item label="供应商类别" prop="category"><el-select v-model="form.category"><el-option v-for="(label, value) in categoryLabels" :key="value" :label="label" :value="value" /></el-select></el-form-item>
|
||||
@@ -112,13 +113,13 @@ watch(() => form.category, (category) => { if (category !== 'BOOKING') form.carr
|
||||
<el-form-item class="span-2" label="公司地址" prop="address"><el-input v-model="form.address" maxlength="255" placeholder="请输入公司地址" /></el-form-item>
|
||||
</div>
|
||||
</FormSection>
|
||||
<FormSection title="营业执照">
|
||||
<FormSection class="density-form-section" title="营业执照">
|
||||
<div class="form-grid">
|
||||
<el-form-item label="营业执照号" prop="businessLicenseNo"><el-input v-model="form.businessLicenseNo" maxlength="64" placeholder="统一社会信用代码" /></el-form-item>
|
||||
<el-form-item label="资质文件"><div class="file-placeholder"><FileText :size="24" /><span>{{ form.licenseFileId ? '已保留现有营业执照文件' : '暂无营业执照文件' }}</span><small>平台公共供应商资质上传接口尚未提供,当前不能新增或替换文件。</small></div></el-form-item>
|
||||
</div>
|
||||
</FormSection>
|
||||
<FormSection title="其他信息"><el-form-item label="备注" prop="remark"><el-input v-model="form.remark" type="textarea" :rows="3" maxlength="500" show-word-limit placeholder="请输入备注" /></el-form-item></FormSection>
|
||||
<FormSection class="density-form-section" title="其他信息"><el-form-item label="备注" prop="remark"><el-input v-model="form.remark" type="textarea" :rows="3" maxlength="500" show-word-limit placeholder="请输入备注" /></el-form-item></FormSection>
|
||||
</el-form>
|
||||
<footer class="form-actions"><el-button type="primary" :loading="saving" @click="save"><Save :size="16" />保存</el-button><el-button :disabled="saving" @click="router.push({ name: 'supplier-list' })">取消</el-button></footer>
|
||||
</section>
|
||||
@@ -127,10 +128,9 @@ watch(() => form.category, (category) => { if (category !== 'BOOKING') form.carr
|
||||
</template>
|
||||
|
||||
<style scoped>
|
||||
.form-page-header { display: flex; align-items: center; justify-content: space-between; gap: 16px; padding: 16px 20px; border: 1px solid var(--cc-border); border-radius: 8px; background: #fff; }.form-page-header h2 { margin: 0; font-size: 16px; }
|
||||
.supplier-form-panel { padding: 22px; }.form-grid { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 0 20px; }.span-2 { grid-column: 1 / -1; }
|
||||
.form-grid :deep(.el-select) { width: 100%; }.file-placeholder { display: flex; width: 100%; min-height: 96px; align-items: center; justify-content: center; flex-direction: column; gap: 6px; padding: 16px; border: 1px dashed #d9d9d9; border-radius: 6px; background: #fafafa; color: var(--cc-muted); text-align: center; }.file-placeholder small { max-width: 420px; line-height: 1.5; }
|
||||
.form-actions { display: flex; justify-content: center; gap: 14px; padding: 18px 0 0; border-top: 1px solid var(--cc-border); }.form-actions :deep(.el-button) { min-width: 112px; margin-left: 0; }
|
||||
.supplier-form-panel { min-width: 0; }.form-grid { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 0 var(--admin-space-7); }.span-2 { grid-column: 1 / -1; }
|
||||
.form-grid :deep(.el-select) { width: 100%; }.file-placeholder { display: flex; width: 100%; min-height: 96px; align-items: center; justify-content: center; flex-direction: column; gap: var(--admin-space-2); padding: var(--admin-space-6); border: 1px dashed #d9d9d9; border-radius: var(--admin-radius); background: #fafafa; color: var(--cc-muted); text-align: center; }.file-placeholder small { max-width: 420px; line-height: 1.5; }
|
||||
.form-actions { display: flex; justify-content: center; gap: var(--admin-space-5); padding: var(--admin-space-6) 0 0; border-top: 1px solid var(--cc-border); }.form-actions :deep(.el-button) { min-width: 112px; margin-left: 0; }
|
||||
@media (min-width: 1600px) { .form-grid { grid-template-columns: repeat(4, minmax(0, 1fr)); } }
|
||||
@media (min-width: 1280px) and (max-width: 1599px) { .form-grid { grid-template-columns: repeat(3, minmax(0, 1fr)); } }
|
||||
@media (max-width: 720px) { .supplier-form-panel { padding: 16px; } .form-grid { grid-template-columns: 1fr; }.span-2 { grid-column: auto; }.form-page-header { align-items: stretch; flex-direction: column; }.form-actions { flex-direction: column; }.form-actions :deep(.el-button) { width: 100%; min-height: 44px; } }
|
||||
|
||||
@@ -64,6 +64,20 @@ describe('supplier route reuse', () => {
|
||||
mocks.can.mockClear()
|
||||
})
|
||||
|
||||
it('retains all supplier facts with long values and the original back target', async () => {
|
||||
const name = '供应商完整长名称'.repeat(6)
|
||||
const address = '浙江省宁波市完整详细地址'.repeat(8)
|
||||
mocks.getSupplier.mockResolvedValue({ ...supplier('A', name), address, remark: '备注'.repeat(50) })
|
||||
const wrapper = mount(SupplierDetailView, { global: { plugins: [ElementPlus], stubs } })
|
||||
await flushPromises()
|
||||
expect(wrapper.get('.density-detail-title').text()).toBe(name)
|
||||
expect(wrapper.get('.density-fields').findAll('dt')).toHaveLength(12)
|
||||
expect(wrapper.get('.density-fields').text()).toContain(address)
|
||||
expect(wrapper.findAll('.wide-field')).toHaveLength(3)
|
||||
await wrapper.get('.density-back').trigger('click')
|
||||
expect(mocks.push).toHaveBeenCalledWith({ name: 'supplier-list' })
|
||||
})
|
||||
|
||||
it('reloads form A to B, ignores late A, and submits B', async () => {
|
||||
const requestA = deferred<Supplier>(); const requestB = deferred<Supplier>()
|
||||
mocks.getSupplier.mockImplementation((id: string) => id === 'A' ? requestA.promise : requestB.promise)
|
||||
|
||||
@@ -21,7 +21,8 @@ describe('supplier formal pages', () => {
|
||||
expect(source).toContain("access.can('platform:supplier:edit')")
|
||||
expect(source).toContain("access.can('platform:supplier:status')")
|
||||
expect(source).toContain("access.can('platform:supplier:list')")
|
||||
expect(source).toContain('<el-button size="small" plain type="primary" @click="router.push')
|
||||
expect(source).toContain('class="density-action"')
|
||||
expect(source).toContain('class="row-actions density-actions"')
|
||||
expect(source).toContain("statusLabels[supplierRow(row).status] ?? '—'")
|
||||
})
|
||||
|
||||
@@ -29,7 +30,10 @@ describe('supplier formal pages', () => {
|
||||
expect(source).toContain('class="supplier-list-top"')
|
||||
expect(source).toContain('class="supplier-query-panel"')
|
||||
expect(source).toContain('class="supplier-query-toolbar"')
|
||||
expect(source).toContain('grid-template-columns: repeat(4, minmax(0, 1fr)); gap: 12px')
|
||||
expect(source).toContain('class="supplier-tabs density-tabs"')
|
||||
expect(source).toContain('({{ item.value }})')
|
||||
expect(source).not.toContain('class="supplier-metrics"')
|
||||
expect(source).toContain('@click="switchCategory(item.category)"')
|
||||
expect(source).not.toContain('订舱范围')
|
||||
expect(source).not.toContain('国内/国外')
|
||||
expect(formSource).not.toContain('form.scope')
|
||||
|
||||
@@ -1,8 +1,9 @@
|
||||
<script setup lang="ts">
|
||||
import '@/styles/adminDensity.css'
|
||||
import { computed, onActivated, onMounted, ref, watch } from 'vue'
|
||||
import { useRouter } from 'vue-router'
|
||||
import { ElMessage, ElMessageBox } from 'element-plus'
|
||||
import { Eye, FileText, Pencil, Plus, Power } from '@lucide/vue'
|
||||
import { Plus } from '@lucide/vue'
|
||||
import AdminPage from '@/shared/components/AdminPage.vue'
|
||||
import ApiErrorMeta from '@/shared/components/ApiErrorMeta.vue'
|
||||
import DataTable, { type DataTableColumn } from '@/shared/components/DataTable.vue'
|
||||
@@ -97,7 +98,7 @@ async function toggleStatus(row: Supplier) {
|
||||
const next: SupplierStatus = row.status === 'ACTIVE' ? 'INACTIVE' : 'ACTIVE'
|
||||
const verb = next === 'ACTIVE' ? '启用' : '停用'
|
||||
try {
|
||||
await ElMessageBox.confirm(`确认${verb}供应商“${row.name}”吗?`, `${verb}供应商`, { type: 'warning', confirmButtonText: `确认${verb}`, cancelButtonText: '取消' })
|
||||
await ElMessageBox.confirm(`确认${verb}供应商“${row.name}”吗?`, `${verb}供应商`, { customClass: 'admin-density-confirm', type: 'warning', confirmButtonText: `确认${verb}`, cancelButtonText: '取消' })
|
||||
actionId.value = row.id
|
||||
await changeSupplierStatus(row.id, next)
|
||||
ElMessage.success(`供应商已${verb}`)
|
||||
@@ -119,18 +120,13 @@ onActivated(() => {
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<AdminPage>
|
||||
<AdminPage class="admin-density">
|
||||
<ListPageLayout aria-label="供应商列表">
|
||||
<template #toolbar>
|
||||
<div class="supplier-list-top">
|
||||
<div class="supplier-metrics" aria-label="供应商分类统计">
|
||||
<button v-for="item in metricItems" :key="item.category" type="button" :class="{ active: activeCategory === item.category }" @click="switchCategory(item.category)">
|
||||
<span>{{ item.label }}</span><strong>{{ item.value }}<small>家</small></strong>
|
||||
</button>
|
||||
</div>
|
||||
<div class="supplier-query-panel">
|
||||
<nav class="supplier-tabs" aria-label="供应商分类">
|
||||
<button v-for="item in metricItems" :key="item.category" type="button" :class="{ active: activeCategory === item.category }" @click="switchCategory(item.category)">{{ categoryLabels[item.category] }}</button>
|
||||
<nav class="supplier-tabs density-tabs" role="tablist" aria-label="供应商分类统计">
|
||||
<button role="tab" :aria-selected="activeCategory === item.category" v-for="item in metricItems" :key="item.category" type="button" :class="{ active: activeCategory === item.category }" @click="switchCategory(item.category)"><span class="density-tab-icon" aria-hidden="true">{{ ({ BOOKING: '🚢', CUSTOMS: '📋', TRUCKING: '🚚', CERTIFICATE: '📄' })[item.category] }}</span>{{ categoryLabels[item.category] }}({{ item.value }})</button>
|
||||
</nav>
|
||||
<QueryToolbar v-model="filters" class="supplier-query-toolbar" ariaLabel="供应商筛选" :fields="queryFields" @search="search" />
|
||||
</div>
|
||||
@@ -148,16 +144,16 @@ onActivated(() => {
|
||||
<el-button v-if="access.can('platform:supplier:create')" type="primary" @click="router.push({ name: 'supplier-create' })"><Plus :size="16" />新增供应商</el-button>
|
||||
</template>
|
||||
<template #actions="{ row }">
|
||||
<div class="row-actions">
|
||||
<el-button size="small" plain type="primary" @click="router.push({ name: 'supplier-detail', params: { id: row.id } })"><Eye :size="15" />详情</el-button>
|
||||
<el-button v-if="access.can('platform:supplier:edit')" size="small" plain type="primary" @click="router.push({ name: 'supplier-edit', params: { id: row.id } })"><Pencil :size="15" />编辑</el-button>
|
||||
<el-button v-if="access.can('platform:supplier:status')" size="small" plain :type="row.status === 'ACTIVE' ? 'danger' : 'success'" :loading="actionId === row.id" @click="toggleStatus(supplierRow(row))"><Power :size="15" />{{ row.status === 'ACTIVE' ? '停用' : '启用' }}</el-button>
|
||||
<div class="row-actions density-actions">
|
||||
<el-button data-tone="neutral" class="density-action" size="small" @click="router.push({ name: 'supplier-detail', params: { id: row.id } })">详情</el-button>
|
||||
<el-button data-tone="neutral" class="density-action" v-if="access.can('platform:supplier:edit')" size="small" @click="router.push({ name: 'supplier-edit', params: { id: row.id } })">编辑</el-button>
|
||||
<el-button class="density-action" v-if="access.can('platform:supplier:status')" size="small" :data-tone="row.status === 'ACTIVE' ? 'danger' : 'success'" :loading="actionId === row.id" @click="toggleStatus(supplierRow(row))">{{ row.status === 'ACTIVE' ? '停用' : '启用' }}</el-button>
|
||||
</div>
|
||||
</template>
|
||||
<template #name="{ row }"><LineClampText :content="row.name" /></template>
|
||||
<template #category="{ row }">{{ categoryLabels[row.category as SupplierCategory] }}</template>
|
||||
<template #carrierCodes="{ row }"><LineClampText :content="supplierRow(row).category === 'BOOKING' ? formatCarrierCodes(supplierRow(row).carrierCodes) : null" /></template>
|
||||
<template #license="{ row }"><el-button size="small" plain type="primary" @click="showLicense(supplierRow(row))"><FileText :size="15" />查看</el-button></template>
|
||||
<template #license="{ row }"><el-button data-tone="neutral" class="density-action" size="small" @click="showLicense(supplierRow(row))">查看</el-button></template>
|
||||
<template #status="{ row }"><StatusBadge :status="statusLabels[supplierRow(row).status] ?? '—'" /></template>
|
||||
<template #settlement="{ row }">{{ settlementLabels[supplierRow(row).settlementPeriod] }}</template>
|
||||
</DataTable>
|
||||
@@ -168,8 +164,7 @@ onActivated(() => {
|
||||
</template>
|
||||
|
||||
<style scoped>
|
||||
.supplier-list-top { display: grid; gap: 16px; }.supplier-metrics { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: 12px; }.supplier-metrics button { min-width: 0; padding: 12px 14px; border: 1px solid #e7edf5; border-radius: 8px; background: #f8fafc; color: var(--cc-text); text-align: left; cursor: pointer; }.supplier-metrics button.active { border-color: var(--cc-primary); background: #f7f8ff; box-shadow: inset 0 3px 0 var(--cc-primary); }.supplier-metrics span { display: block; margin-bottom: 6px; color: #64748b; font-size: 12px; }.supplier-metrics strong { color: #1e293b; font-size: 20px; }.supplier-metrics small { margin-left: 3px; color: #64748b; font-size: 12px; }.supplier-query-panel { overflow: hidden; border: 1px solid var(--cc-border); border-radius: 8px; background: #fff; }.supplier-query-toolbar { border: 0; }.supplier-tabs { display: flex; gap: 6px; padding: 10px 14px; overflow-x: auto; border-bottom: 1px solid var(--cc-border); background: #fafbfc; }.supplier-tabs button { min-width: 76px; padding: 7px 20px; border: 0; border-radius: 6px; background: #f1f3f5; color: #555; cursor: pointer; }.supplier-tabs button.active { background: var(--cc-primary); color: #fff; font-weight: 650; }
|
||||
.row-actions { display: flex; align-items: center; white-space: nowrap; }.row-actions :deep(.el-button + .el-button) { margin-left: 8px; }
|
||||
.supplier-list-top { display: grid; gap: var(--admin-space-6); }.supplier-query-panel { overflow: hidden; border: 1px solid var(--cc-border); border-radius: var(--admin-radius); background: #fff; }.supplier-query-toolbar { border: 0; }
|
||||
@media (max-width: 720px) { .supplier-metrics { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
|
||||
@media (max-width: 380px) { .supplier-metrics { grid-template-columns: 1fr; } }
|
||||
</style>
|
||||
|
||||
@@ -2,7 +2,7 @@ import type { RouteRecordRaw } from 'vue-router'
|
||||
|
||||
export const supplierRoutes = [
|
||||
{ path: 'suppliers', name: 'supplier-list', component: () => import('@/modules/suppliers/pages/SuppliersView.vue'), meta: { title: '供应商列表', description: '维护平台公共订舱、报关、拖车和证书供应商', permission: 'platform:supplier:list' } },
|
||||
{ path: 'suppliers/new', name: 'supplier-create', component: () => import('@/modules/suppliers/pages/SupplierFormView.vue'), meta: { title: '新增供应商', description: '新增平台公共供应商档案', permission: 'platform:supplier:create' } },
|
||||
{ path: 'suppliers/:id', name: 'supplier-detail', component: () => import('@/modules/suppliers/pages/SupplierDetailView.vue'), meta: { title: '供应商详情', description: '查看平台公共供应商完整档案', permission: 'platform:supplier:list' } },
|
||||
{ path: 'suppliers/:id/edit', name: 'supplier-edit', component: () => import('@/modules/suppliers/pages/SupplierFormView.vue'), meta: { title: '编辑供应商', description: '编辑平台公共供应商档案', permission: 'platform:supplier:edit' } },
|
||||
{ path: 'suppliers/new', name: 'supplier-create', component: () => import('@/modules/suppliers/pages/SupplierFormView.vue'), meta: { title: '新增供应商', showPageHeading: false, description: '新增平台公共供应商档案', permission: 'platform:supplier:create' } },
|
||||
{ path: 'suppliers/:id', name: 'supplier-detail', component: () => import('@/modules/suppliers/pages/SupplierDetailView.vue'), meta: { title: '供应商详情', showPageHeading: false, description: '查看平台公共供应商完整档案', permission: 'platform:supplier:list' } },
|
||||
{ path: 'suppliers/:id/edit', name: 'supplier-edit', component: () => import('@/modules/suppliers/pages/SupplierFormView.vue'), meta: { title: '编辑供应商', showPageHeading: false, description: '编辑平台公共供应商档案', permission: 'platform:supplier:edit' } },
|
||||
] satisfies RouteRecordRaw[]
|
||||
|
||||
Reference in New Issue
Block a user