This commit is contained in:
2026-08-19 09:14:35 +08:00
parent c188482c24
commit 80cfca5056
36 changed files with 854 additions and 1044 deletions
@@ -19,6 +19,7 @@ const payload: SavePlatformFeeItemRequest = {
category: '仓储成本',
tradeScope: 'INTERNATIONAL',
feeTypeName: '仓库租赁费',
supplierCategory: 'TRUCKING',
pickupPayable: false,
pickupReceivable: false,
warehousePayable: true,
@@ -1,4 +1,5 @@
import { http, unwrapApiResponse, type ApiEnvelope } from '@/shared/api/http'
import type { SupplierCategory } from '@/modules/suppliers'
export type FeeItemTradeScope = 'DOMESTIC' | 'INTERNATIONAL'
export type FeeItemStatus = 'ACTIVE' | 'DISABLED'
@@ -8,6 +9,7 @@ export interface PlatformFeeItemResource {
category: string
tradeScope: FeeItemTradeScope
feeCode: string | null
supplierCategory: SupplierCategory | null
feeTypeName: string
pickupPayable: boolean
pickupReceivable: boolean
@@ -26,6 +28,7 @@ export interface SavePlatformFeeItemRequest {
category: string
tradeScope: FeeItemTradeScope
feeTypeName: string
supplierCategory: SupplierCategory | null
pickupPayable: boolean
pickupReceivable: boolean
warehousePayable: boolean
@@ -16,6 +16,7 @@ import {
type PlatformFeeItemResource,
type SavePlatformFeeItemRequest,
} from '@/modules/fee-items/api/platformFeeItems'
import { categoryLabels, type SupplierCategory } from '@/modules/suppliers'
import { getApiErrorDetails, type ApiErrorDetails } from '@/shared/api/http'
import ApiErrorMeta from '@/shared/components/ApiErrorMeta.vue'
import AdminPage from '@/shared/components/AdminPage.vue'
@@ -69,6 +70,7 @@ function emptyForm(): FeeItemForm {
category: '',
tradeScope: 'DOMESTIC',
feeTypeName: '',
supplierCategory: null,
pickupPayable: false,
pickupReceivable: false,
warehousePayable: false,
@@ -84,6 +86,7 @@ const rules: FormRules<FeeItemForm> = {
tradeScope: [{ required: true, message: '请选择贸易范围', trigger: 'change' }],
feeTypeName: [{ required: true, message: '请输入费用名称', trigger: 'blur' }],
}
const hasPayableDirection = computed(() => form.pickupPayable || form.warehousePayable)
const canView = computed(() => access.can('firstleg:fee-item:view'))
const editorTitle = computed(() => form.id ? '编辑费用项目' : '新增费用项目')
@@ -117,6 +120,7 @@ const columns: DataTableColumn[] = [
{ key: 'tradeScope', label: '贸易范围', width: 110, slotName: 'tradeScope' },
{ key: 'pickup', label: '提货', minWidth: 160, slotName: 'pickup' },
{ key: 'warehouse', label: '仓库', minWidth: 160, slotName: 'warehouse' },
{ key: 'supplierCategory', label: '供应商类别', width: 120, slotName: 'supplierCategory' },
{ key: 'allocationFee', label: '分摊费', width: 100, slotName: 'allocationFee' },
{ key: 'description', label: '说明', minWidth: 220, slotName: 'description', defaultVisible: false },
{ key: 'createdByName', label: '创建人', minWidth: 120, formatter: (row: PlatformFeeItemResource) => row.createdByName || '—' },
@@ -198,6 +202,7 @@ function assignForm(item: PlatformFeeItemResource) {
category: item.category,
tradeScope: item.tradeScope,
feeTypeName: item.feeTypeName,
supplierCategory: item.supplierCategory,
pickupPayable: item.pickupPayable,
pickupReceivable: item.pickupReceivable,
warehousePayable: item.warehousePayable,
@@ -230,6 +235,7 @@ function buildPayload(): SavePlatformFeeItemRequest {
category: form.category.trim(),
tradeScope: form.tradeScope,
feeTypeName: form.feeTypeName.trim(),
supplierCategory: hasPayableDirection.value ? form.supplierCategory : null,
pickupPayable: form.pickupPayable,
pickupReceivable: form.pickupReceivable,
warehousePayable: form.warehousePayable,
@@ -242,6 +248,10 @@ function buildPayload(): SavePlatformFeeItemRequest {
async function saveFeeItem() {
const valid = await formRef.value?.validate().catch(() => false)
if (!valid) return
if (hasPayableDirection.value && !form.supplierCategory) {
ElMessage.warning('启用应付方向时必须选择供应商类别')
return
}
saving.value = true
try {
if (form.id) await updatePlatformFeeItem(form.id, buildPayload())
@@ -396,6 +406,7 @@ onMounted(() => {
<template #tradeScope="{ row }"><el-tag effect="plain">{{ (row as PlatformFeeItemResource).tradeScope === 'DOMESTIC' ? '国内' : '国际' }}</el-tag></template>
<template #pickup="{ row }">{{ directionText((row as PlatformFeeItemResource).pickupPayable, (row as PlatformFeeItemResource).pickupReceivable) }}</template>
<template #warehouse="{ row }">{{ directionText((row as PlatformFeeItemResource).warehousePayable, (row as PlatformFeeItemResource).warehouseReceivable) }}</template>
<template #supplierCategory="{ row }">{{ (row as PlatformFeeItemResource).supplierCategory ? categoryLabels[(row as PlatformFeeItemResource).supplierCategory as SupplierCategory] : '未配置' }}</template>
<template #allocationFee="{ row }">{{ (row as PlatformFeeItemResource).allocationFee ? '是' : '否' }}</template>
<template #description="{ row }"><span class="description-cell">{{ (row as PlatformFeeItemResource).description || '—' }}</span></template>
<template #status="{ row }"><el-tag :type="(row as PlatformFeeItemResource).status === 'ACTIVE' ? 'success' : 'info'">{{ (row as PlatformFeeItemResource).status === 'ACTIVE' ? '启用' : '停用' }}</el-tag></template>
@@ -432,6 +443,11 @@ onMounted(() => {
<fieldset><legend>仓库环节</legend><el-checkbox v-model="form.warehousePayable">应付</el-checkbox><el-checkbox v-model="form.warehouseReceivable">应收</el-checkbox></fieldset>
</div>
<el-checkbox v-model="form.allocationFee">作为分摊费用</el-checkbox>
<el-form-item v-if="hasPayableDirection" label="供应商类别" required>
<el-select v-model="form.supplierCategory" placeholder="请选择 Warehouse 供应商类别">
<el-option v-for="(label, value) in categoryLabels" :key="value" :label="label" :value="value" />
</el-select>
</el-form-item>
</FormSection>
<FormSection title="适用说明" :bordered="false">
<el-form-item label="说明"><el-input v-model="form.description" type="textarea" :rows="4" maxlength="500" show-word-limit placeholder="请输入适用场景或核算说明" /></el-form-item>