feat: 完善头程审核与计费信息
This commit is contained in:
@@ -3,6 +3,7 @@ import { http } from '@/shared/api/http'
|
||||
import {
|
||||
approvePlatformUnifiedOrder,
|
||||
batchApprovePlatformUnifiedOrders,
|
||||
getPlatformUnifiedOrderBatchApprovalPreview,
|
||||
addPlatformUnifiedOrderNote,
|
||||
getPlatformUnifiedOrder,
|
||||
downloadPlatformProductImage,
|
||||
@@ -134,11 +135,39 @@ describe('unified orders API contract', () => {
|
||||
} })
|
||||
|
||||
await expect(batchApprovePlatformUnifiedOrders('2089176869176389634', [
|
||||
'2089223263733518337', '2089223263733518338',
|
||||
{ orderId: '2089223263733518337', orderVersion: 3 },
|
||||
{ orderId: '2089223263733518338', orderVersion: 8 },
|
||||
])).resolves.toMatchObject({ successCount: 1, failureCount: 1 })
|
||||
expect(http.post).toHaveBeenCalledWith(
|
||||
'/platform/v1/orders/first-leg/batch-approve',
|
||||
{ orderIds: ['2089223263733518337', '2089223263733518338'] },
|
||||
{ items: [
|
||||
{ orderId: '2089223263733518337', orderVersion: 3 },
|
||||
{ orderId: '2089223263733518338', orderVersion: 8 },
|
||||
] },
|
||||
{ params: { tenantId: '2089176869176389634' } },
|
||||
)
|
||||
})
|
||||
|
||||
it('loads one batch-review preview with Chinese goods and normalizes long IDs', async () => {
|
||||
vi.mocked(http.post).mockResolvedValue({ data: {
|
||||
total: 1,
|
||||
approvableCount: 1,
|
||||
items: [{
|
||||
orderId: '2089223263733518337', orderVersion: '3', inboundCode: 'NYEXX2609080001',
|
||||
customerId: '2089176869176389634', customerName: '测试客户', chineseGoodsNames: [' 蓝牙音箱 ', ''],
|
||||
channelCode: 'NY_EXX', channelName: '纽约海运', destinationWarehouseCode: 'ONT8',
|
||||
destinationWarehouseName: 'ONT8 亚马逊仓', canApprove: true, blockReason: null,
|
||||
}],
|
||||
} })
|
||||
const items = [{ orderId: '2089223263733518337', orderVersion: 3 }]
|
||||
|
||||
await expect(getPlatformUnifiedOrderBatchApprovalPreview('2089176869176389634', items)).resolves.toMatchObject({
|
||||
total: 1, approvableCount: 1,
|
||||
items: [{ orderId: '2089223263733518337', orderVersion: 3, chineseGoodsNames: ['蓝牙音箱'] }],
|
||||
})
|
||||
expect(http.post).toHaveBeenCalledWith(
|
||||
'/platform/v1/orders/first-leg/batch-review-preview',
|
||||
{ items },
|
||||
{ params: { tenantId: '2089176869176389634' } },
|
||||
)
|
||||
})
|
||||
|
||||
@@ -540,10 +540,59 @@ export interface UnifiedOrderBatchApprovalResult {
|
||||
failedOrders: Array<{ orderId: number | string; code: string; message: string }>
|
||||
}
|
||||
|
||||
export function batchApprovePlatformUnifiedOrders(tenantId: string, orderIds: string[]) {
|
||||
export interface UnifiedOrderBatchReviewItem {
|
||||
orderId: string
|
||||
orderVersion: number
|
||||
}
|
||||
|
||||
export interface UnifiedOrderBatchApprovalPreviewItem extends UnifiedOrderBatchReviewItem {
|
||||
inboundCode: string | null
|
||||
customerId: string | null
|
||||
customerName: string | null
|
||||
chineseGoodsNames: string[]
|
||||
channelCode: string | null
|
||||
channelName: string | null
|
||||
destinationWarehouseCode: string | null
|
||||
destinationWarehouseName: string | null
|
||||
canApprove: boolean
|
||||
blockReason: string | null
|
||||
}
|
||||
|
||||
export interface UnifiedOrderBatchApprovalPreview {
|
||||
total: number
|
||||
approvableCount: number
|
||||
items: UnifiedOrderBatchApprovalPreviewItem[]
|
||||
}
|
||||
|
||||
function normalizeBatchApprovalPreview(result: UnifiedOrderBatchApprovalPreview): UnifiedOrderBatchApprovalPreview {
|
||||
return {
|
||||
...result,
|
||||
total: integer(result.total, 0),
|
||||
approvableCount: integer(result.approvableCount, 0),
|
||||
items: (result.items || []).map((item) => ({
|
||||
...item,
|
||||
orderId: String(item.orderId),
|
||||
orderVersion: integer(item.orderVersion, 0),
|
||||
customerId: id(item.customerId),
|
||||
chineseGoodsNames: (item.chineseGoodsNames || []).map((name) => name.trim()).filter(Boolean),
|
||||
canApprove: Boolean(item.canApprove),
|
||||
})),
|
||||
}
|
||||
}
|
||||
|
||||
export async function getPlatformUnifiedOrderBatchApprovalPreview(tenantId: string, items: UnifiedOrderBatchReviewItem[]) {
|
||||
const response = await http.post<ApiEnvelope<UnifiedOrderBatchApprovalPreview>, ApiEnvelope<UnifiedOrderBatchApprovalPreview>>(
|
||||
'/platform/v1/orders/first-leg/batch-review-preview',
|
||||
{ items },
|
||||
{ params: { tenantId } },
|
||||
)
|
||||
return normalizeBatchApprovalPreview(unwrapApiResponse(response))
|
||||
}
|
||||
|
||||
export function batchApprovePlatformUnifiedOrders(tenantId: string, items: UnifiedOrderBatchReviewItem[]) {
|
||||
return http.post<ApiEnvelope<UnifiedOrderBatchApprovalResult>, ApiEnvelope<UnifiedOrderBatchApprovalResult>>(
|
||||
'/platform/v1/orders/first-leg/batch-approve',
|
||||
{ orderIds },
|
||||
{ items },
|
||||
{ params: { tenantId } },
|
||||
).then(unwrapApiResponse)
|
||||
}
|
||||
|
||||
@@ -18,7 +18,7 @@ import type {
|
||||
InboundFeeSupplierOption, SaveInboundFeeDetailRequest,
|
||||
} from '@/modules/unified-orders/api/inboundFeeDetails'
|
||||
|
||||
const props = defineProps<{ accountId: string; inboundId: string }>()
|
||||
const props = defineProps<{ accountId: string; inboundId: string; destinationType?: string | null }>()
|
||||
interface OtherFeeSummary { currency: string; approvedReceivable: number; approvedPayable: number }
|
||||
const emit = defineEmits<{ changed: []; summary: [value: OtherFeeSummary] }>()
|
||||
const access = useAccessPreviewStore()
|
||||
@@ -74,7 +74,11 @@ const directionOptions = computed(() => [
|
||||
{ label: '应收', value: 'RECEIVABLE' },
|
||||
{ label: '应付', value: 'PAYABLE', disabled: !canViewSuppliers.value },
|
||||
])
|
||||
const applicableItems = computed(() => feeItems.value.filter((item) => form.direction === 'RECEIVABLE' ? item.warehouseReceivable : item.warehousePayable))
|
||||
const privateDeliveryFeeCode = 'PRIVATE_LAST_MILE_DELIVERY'
|
||||
const applicableItems = computed(() => feeItems.value.filter((item) => {
|
||||
if (item.feeCode === privateDeliveryFeeCode && props.destinationType !== 'PRIVATE') return false
|
||||
return form.direction === 'RECEIVABLE' ? item.warehouseReceivable : item.warehousePayable
|
||||
}))
|
||||
const selectedFeeItem = computed(() => feeItems.value.find((item) => String(item.id) === String(form.feeItemId)))
|
||||
|
||||
function isManual(row: InboundFeeDetail) { return row.sourceType === 'MANUAL' }
|
||||
@@ -298,7 +302,7 @@ onMounted(() => void load())
|
||||
<el-table-column label="应收/应付" width="110"><template #default="{ row }">{{ directionLabel(row.direction) }}</template></el-table-column>
|
||||
<el-table-column label="结算方式" width="120"><template #default="{ row }">{{ settlementLabel(row as InboundFeeDetail) }}</template></el-table-column>
|
||||
<el-table-column label="已付摘要" min-width="290" show-overflow-tooltip><template #default="{ row }">{{ paidSummary(row as InboundFeeDetail) }}</template></el-table-column>
|
||||
<el-table-column prop="feeTypeNameSnapshot" label="费用类型" min-width="150" />
|
||||
<el-table-column label="费用类型" min-width="190" show-overflow-tooltip><template #default="{ row }"><span>{{ row.feeTypeNameSnapshot }}</span><el-tag v-if="row.feeTypeNameSnapshot === '私人仓尾程派送费'" class="private-delivery-tag" size="small" type="warning" effect="light">仅私人仓</el-tag></template></el-table-column>
|
||||
<el-table-column label="供应商/客户" min-width="170"><template #default="{ row }">{{ row.direction === 'PAYABLE' ? row.supplierName : row.customerName || '—' }}</template></el-table-column>
|
||||
<el-table-column prop="businessDate" label="业务发生日" width="130" />
|
||||
<el-table-column prop="currency" label="货币" width="90" />
|
||||
@@ -314,6 +318,7 @@ onMounted(() => void load())
|
||||
|
||||
<AppDialog v-model="editorOpen" :title="editorMode === 'create' ? '新增费用' : editorMode === 'adjust' ? '调整已审核费用' : '编辑费用'" width="min(680px, calc(100vw - 28px))" :confirm-loading="saving" confirm-text="保存" @confirm="save">
|
||||
<el-alert v-if="editorMode === 'adjust'" title="调整将生成新版本并重新进入待审核状态" type="warning" :closable="false" show-icon />
|
||||
<el-alert v-if="selectedFeeItem?.feeCode === privateDeliveryFeeCode" title="私人仓尾程派送费仅适用于目的仓类型为“私人仓”的订单,最终资格由服务端校验。" type="info" :closable="false" show-icon />
|
||||
<el-alert v-if="!canViewFeeItems" title="当前账号缺少费用项目查看权限,无法新增或修改费用" type="warning" :closable="false" show-icon />
|
||||
<el-alert v-if="!canViewSuppliers" title="当前账号缺少供应商查看权限,应付费用不可维护;应收费用不受影响" type="warning" :closable="false" show-icon />
|
||||
<el-alert v-if="feeItemsError" type="error" :closable="true" @close="feeItemsError = null"><template #title>{{ feeItemsError.message }}</template><ApiErrorMeta :details="feeItemsError" /></el-alert>
|
||||
@@ -360,6 +365,7 @@ onMounted(() => void load())
|
||||
.voucher-field { grid-column: 1 / -1; }.voucher-control { display: flex; align-items: center; flex-wrap: wrap; gap: 10px; width: 100%; }.voucher-picker { display: inline-flex; align-items: center; gap: 6px; padding: 7px 12px; border: 1px solid var(--cc-border); border-radius: 6px; color: var(--el-color-primary); cursor: pointer; }.voucher-picker.is-disabled { cursor: not-allowed; opacity: .6; }.voucher-picker input { position: absolute; width: 1px; height: 1px; opacity: 0; }.voucher-hint { color: var(--cc-muted); font-size: 12px; }.voucher-list { display: grid; width: 100%; gap: 6px; margin-top: 8px; }.voucher-list > span { display: flex; align-items: center; justify-content: space-between; gap: 8px; padding: 6px 9px; border-radius: 5px; background: var(--el-fill-color-light); }.voucher-list > span > span { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }.voucher-list button { display: inline-flex; padding: 2px; border: 0; background: transparent; color: var(--el-color-danger); cursor: pointer; }
|
||||
.fee-table-shell { min-width: 0; max-width: 100%; overflow: hidden; }
|
||||
.fee-table-shell :deep(.el-table) { width: 100%; max-width: 100%; }
|
||||
.private-delivery-tag { margin-left: 6px; vertical-align: middle; }
|
||||
@keyframes fee-refresh-spin { to { transform: rotate(360deg); } }
|
||||
@media (max-width: 720px) { .fee-toolbar { align-items: flex-start; flex-direction: column; } .fee-form { grid-template-columns: 1fr; } .fee-form :deep(.el-form-item:last-child) { grid-column: auto; } }
|
||||
</style>
|
||||
|
||||
@@ -108,6 +108,9 @@ describe('UnifiedOrdersView contract', () => {
|
||||
expect(source).not.toContain('批量审核接口待接入')
|
||||
expect(source).toContain('@selection-change="handleOrderSelectionChange"')
|
||||
expect(source).toContain('batchApprovePlatformUnifiedOrders')
|
||||
expect(source).toContain('getPlatformUnifiedOrderBatchApprovalPreview')
|
||||
expect(source).toContain('中文品名')
|
||||
expect(source).toContain('确认批量审核')
|
||||
expect(source).toContain('批量审核通过')
|
||||
expect(source).toContain('title="订单列表暂时无法加载"')
|
||||
expect(source).toContain('empty-text="暂无符合条件的订单"')
|
||||
|
||||
@@ -8,6 +8,7 @@ import {
|
||||
downloadPlatformProductImage,
|
||||
approvePlatformUnifiedOrder,
|
||||
batchApprovePlatformUnifiedOrders,
|
||||
getPlatformUnifiedOrderBatchApprovalPreview,
|
||||
addPlatformUnifiedOrderNote,
|
||||
listPlatformUnifiedOrders,
|
||||
updatePlatformUnifiedOrderPlanning,
|
||||
@@ -16,6 +17,8 @@ import {
|
||||
type UnifiedOrderCoLoadGroupSummary,
|
||||
type UnifiedOrderMainStatus,
|
||||
type UnifiedOrderResource,
|
||||
type UnifiedOrderBatchApprovalPreviewItem,
|
||||
type UnifiedOrderBatchReviewItem,
|
||||
} from '@/modules/unified-orders/api/unifiedOrders'
|
||||
import { cancelPlatformCoLoadGroup, createPlatformCoLoadGroup, getPlatformCoLoadGroupByInboundCode, type CoLoadBusinessSummary, type CoLoadGroup } from '@/modules/unified-orders/api/coLoadGroups'
|
||||
import OrderFulfillmentTreePanel from '@/modules/unified-orders/components/OrderFulfillmentTreePanel.vue'
|
||||
@@ -150,6 +153,12 @@ const approvalOpen = ref(false)
|
||||
const approvalLoadingId = ref('')
|
||||
const approvalSaving = ref(false)
|
||||
const batchApprovalSaving = ref(false)
|
||||
const batchApprovalLoading = ref(false)
|
||||
const batchApprovalOpen = ref(false)
|
||||
const batchApprovalError = ref<ApiErrorDetails | null>(null)
|
||||
const batchApprovalPreviewRows = ref<UnifiedOrderBatchApprovalPreviewItem[]>([])
|
||||
const batchApprovalSelectedRows = ref<UnifiedOrderBatchApprovalPreviewItem[]>([])
|
||||
const batchApprovalTableRef = ref<{ toggleRowSelection: (row: UnifiedOrderBatchApprovalPreviewItem, selected?: boolean) => void }>()
|
||||
const exportSubmitting = ref(false)
|
||||
const selectedApprovalOrders = ref<UnifiedOrderResource[]>([])
|
||||
const selectedOrders = ref<UnifiedOrderResource[]>([])
|
||||
@@ -1809,27 +1818,62 @@ async function cancelCoLoadGroup() {
|
||||
}
|
||||
}
|
||||
|
||||
async function batchApproveOrders() {
|
||||
function batchReviewItem(order: UnifiedOrderResource): UnifiedOrderBatchReviewItem {
|
||||
return { orderId: String(order.orderId), orderVersion: Number(order.orderVersion || 0) }
|
||||
}
|
||||
|
||||
function handleBatchApprovalSelection(rows: UnifiedOrderBatchApprovalPreviewItem[]) {
|
||||
batchApprovalSelectedRows.value = rows
|
||||
}
|
||||
|
||||
async function openBatchApproval() {
|
||||
const selected = [...selectedApprovalOrders.value]
|
||||
if (!selected.length || batchApprovalSaving.value) return
|
||||
batchApprovalSaving.value = true
|
||||
if (!selected.length || batchApprovalLoading.value || batchApprovalSaving.value) return
|
||||
batchApprovalOpen.value = true
|
||||
batchApprovalLoading.value = true
|
||||
batchApprovalError.value = null
|
||||
batchApprovalPreviewRows.value = []
|
||||
batchApprovalSelectedRows.value = []
|
||||
try {
|
||||
await ElMessageBox.confirm(
|
||||
`确认批量审核通过已勾选的 ${selected.length} 个订单吗?审核后订单将进入待测量。`,
|
||||
'批量审核订单',
|
||||
{ confirmButtonText: '确认批量审核', cancelButtonText: '取消', type: 'warning' },
|
||||
)
|
||||
const groups = new Map<string, UnifiedOrderResource[]>()
|
||||
selected.forEach((order) => {
|
||||
const tenantId = String(order.tenantId)
|
||||
groups.set(tenantId, [...(groups.get(tenantId) || []), order])
|
||||
})
|
||||
const previews = await Promise.all([...groups].map(([tenantId, orders]) => (
|
||||
getPlatformUnifiedOrderBatchApprovalPreview(tenantId, orders.map(batchReviewItem))
|
||||
)))
|
||||
batchApprovalPreviewRows.value = previews.flatMap((preview) => preview.items)
|
||||
await nextTick()
|
||||
batchApprovalPreviewRows.value.forEach((row) => {
|
||||
if (row.canApprove) batchApprovalTableRef.value?.toggleRowSelection(row, true)
|
||||
})
|
||||
} catch (error) {
|
||||
batchApprovalError.value = getApiErrorDetails(error, '批量审核预览加载失败,请刷新订单后重试')
|
||||
} finally {
|
||||
batchApprovalLoading.value = false
|
||||
}
|
||||
}
|
||||
|
||||
async function batchApproveOrders() {
|
||||
const selected = [...batchApprovalSelectedRows.value]
|
||||
if (!selected.length || batchApprovalSaving.value) return
|
||||
batchApprovalSaving.value = true
|
||||
try {
|
||||
const groups = new Map<string, UnifiedOrderBatchApprovalPreviewItem[]>()
|
||||
selected.forEach((order) => {
|
||||
const tenantId = String(order.customerId)
|
||||
groups.set(tenantId, [...(groups.get(tenantId) || []), order])
|
||||
})
|
||||
let successCount = 0
|
||||
let failureCount = 0
|
||||
const failures: string[] = []
|
||||
for (const [tenantId, orders] of groups) {
|
||||
try {
|
||||
const result = await batchApprovePlatformUnifiedOrders(tenantId, orders.map((order) => String(order.orderId)))
|
||||
const result = await batchApprovePlatformUnifiedOrders(tenantId, orders.map((order) => ({
|
||||
orderId: order.orderId,
|
||||
orderVersion: order.orderVersion,
|
||||
})))
|
||||
successCount += result.successCount
|
||||
failureCount += result.failureCount
|
||||
failures.push(...result.failedOrders.map((failure) => failure.message))
|
||||
@@ -1838,13 +1882,12 @@ async function batchApproveOrders() {
|
||||
failures.push(getApiErrorDetails(error, '该客户订单批量审核失败').message)
|
||||
}
|
||||
}
|
||||
batchApprovalOpen.value = false
|
||||
await loadOrders()
|
||||
const reason = [...new Set(failures.filter(Boolean))].slice(0, 3).join(';')
|
||||
if (!failureCount) ElMessage.success(`已批量审核通过 ${successCount} 个订单`)
|
||||
else if (successCount) ElMessage.warning(`批量审核完成:成功 ${successCount} 个,失败 ${failureCount} 个${reason ? `。${reason}` : ''}`)
|
||||
else ElMessage.error(`批量审核失败:${failureCount} 个订单未通过${reason ? `。${reason}` : ''}`)
|
||||
} catch (error) {
|
||||
if (error !== 'cancel' && error !== 'close') ElMessage.error(getApiErrorDetails(error, '批量审核失败').message)
|
||||
} finally {
|
||||
batchApprovalSaving.value = false
|
||||
}
|
||||
@@ -2243,6 +2286,7 @@ onBeforeUnmount(() => {
|
||||
<InboundFeeDetailManager
|
||||
:account-id="String(detail.summary.tenantId)"
|
||||
:inbound-id="normalizedInboundId"
|
||||
:destination-type="detail.summary.destinationType"
|
||||
@summary="otherFeeSummary = $event"
|
||||
@changed="loadDetail(true)"
|
||||
/>
|
||||
@@ -2464,7 +2508,7 @@ onBeforeUnmount(() => {
|
||||
<DataTable v-model:page="page" v-model:page-size="pageSize" :data="records" :columns="columns" preference-key="unified-orders-table-v2" :loading="loading" :total="total" :page-sizes="[20, 50, 100]" row-key="orderId" border stripe empty-text="暂无符合条件的订单" aria-label="统一订单列表" @selection-change="handleOrderSelectionChange">
|
||||
<template #toolbar-actions>
|
||||
<el-button v-if="can('platform:order:export') && can('platform:download:list')" :loading="exportSubmitting" :disabled="loading || exportSubmitting" @click="exportOrders"><Download :size="16" />导出<span v-if="selectedOrders.length">(已选 {{ selectedOrders.length }})</span></el-button>
|
||||
<el-button v-if="can('platform:order:approve')" type="success" :loading="batchApprovalSaving" :disabled="loading || !selectedApprovalOrders.length" @click="batchApproveOrders"><CircleCheck :size="16" />批量审核通过<span v-if="selectedApprovalOrders.length">({{ selectedApprovalOrders.length }})</span></el-button>
|
||||
<el-button v-if="can('platform:order:approve')" type="success" :loading="batchApprovalLoading || batchApprovalSaving" :disabled="loading || !selectedApprovalOrders.length" @click="openBatchApproval"><CircleCheck :size="16" />批量审核通过<span v-if="selectedApprovalOrders.length">({{ selectedApprovalOrders.length }})</span></el-button>
|
||||
<div v-if="can('platform:firstleg:smart-loading:assign')" class="coload-toolbar-action">
|
||||
<el-button type="primary" plain :loading="coLoadSaving" :disabled="loading || !canCreateCoLoadGroup" aria-label="合柜报关" @click="openCoLoadCreate"><Link2 :size="16" />合柜报关<span v-if="selectedOrders.length">({{ selectedOrders.length }})</span></el-button>
|
||||
</div>
|
||||
@@ -2554,6 +2598,22 @@ onBeforeUnmount(() => {
|
||||
</template>
|
||||
</ListPageLayout>
|
||||
<SmartLoadingDialog v-model="smartLoadingOpen" />
|
||||
<AppDialog v-model="batchApprovalOpen" title="批量审核订单" confirm-text="确认批量审核" confirm-type="success" width="min(1100px, calc(100vw - 28px))" :loading="batchApprovalLoading" :confirm-loading="batchApprovalSaving" :confirm-disabled="batchApprovalLoading || !batchApprovalSelectedRows.length" destroy-on-close @confirm="batchApproveOrders">
|
||||
<el-alert title="请逐票核对入仓码、客户、中文品名、渠道和目的仓;审核通过后订单进入待测量。" type="info" :closable="false" show-icon />
|
||||
<LoadErrorState v-if="batchApprovalError" compact title="批量审核预览加载失败" :message="batchApprovalError.message" :loading="batchApprovalLoading" @retry="openBatchApproval"><template #details><ApiErrorMeta :details="batchApprovalError" /></template></LoadErrorState>
|
||||
<template v-else>
|
||||
<div class="batch-approval-summary"><span>预览 {{ batchApprovalPreviewRows.length }} 票</span><strong>已勾选 {{ batchApprovalSelectedRows.length }} 票</strong></div>
|
||||
<el-table ref="batchApprovalTableRef" class="batch-approval-table" :data="batchApprovalPreviewRows" row-key="orderId" border stripe max-height="520" empty-text="暂无可审核订单" @selection-change="handleBatchApprovalSelection">
|
||||
<el-table-column type="selection" width="48" fixed="left" :selectable="(row: UnifiedOrderBatchApprovalPreviewItem) => row.canApprove" />
|
||||
<el-table-column label="入仓码" min-width="160" show-overflow-tooltip><template #default="{ row }"><strong>{{ row.inboundCode || '—' }}</strong></template></el-table-column>
|
||||
<el-table-column label="客户" min-width="150" show-overflow-tooltip><template #default="{ row }">{{ row.customerName || '—' }}</template></el-table-column>
|
||||
<el-table-column label="中文品名" min-width="220" show-overflow-tooltip><template #default="{ row }">{{ row.chineseGoodsNames.length ? row.chineseGoodsNames.join('、') : '—' }}</template></el-table-column>
|
||||
<el-table-column label="渠道" min-width="160" show-overflow-tooltip><template #default="{ row }">{{ row.channelName || row.channelCode || '—' }}</template></el-table-column>
|
||||
<el-table-column label="目的仓" min-width="180" show-overflow-tooltip><template #default="{ row }">{{ row.destinationWarehouseName || row.destinationWarehouseCode || '—' }}</template></el-table-column>
|
||||
<el-table-column label="校验结果" min-width="180" show-overflow-tooltip><template #default="{ row }"><el-tag :type="row.canApprove ? 'success' : 'danger'" effect="light">{{ row.canApprove ? '可审核' : row.blockReason || '不可审核' }}</el-tag></template></el-table-column>
|
||||
</el-table>
|
||||
</template>
|
||||
</AppDialog>
|
||||
<AppDialog v-model="coLoadCreateOpen" title="合柜报关" confirm-text="确认建组" :confirm-loading="coLoadSaving" :confirm-disabled="!canCreateCoLoadGroup" @confirm="createCoLoadGroup">
|
||||
<el-alert type="warning" :closable="false" show-icon :title="`所选 ${selectedOrders.length} 票须属于同一国内仓、同一渠道,并全量进入同一柜;目的仓或目的港可以不同。资格由服务端按完整入仓片段校验。`" />
|
||||
<div class="coload-selection"><span v-for="row in selectedOrders" :key="String(row.orderId)">{{ row.inboundCode || '待生成入仓码' }}</span></div>
|
||||
@@ -2675,6 +2735,9 @@ onBeforeUnmount(() => {
|
||||
.subsequent-fulfillment { min-height: 72px; margin-top: 16px; padding-top: 14px; border-top: 1px solid var(--cc-border); }
|
||||
.subsequent-fulfillment h3 { margin: 0 0 10px; font-size: 15px; }
|
||||
.fulfillment-facts { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); margin: 0 0 10px; border: 1px solid var(--cc-border); border-radius: 6px; overflow: hidden; }
|
||||
.batch-approval-summary { display: flex; align-items: center; justify-content: space-between; gap: 16px; margin: 12px 0 8px; color: var(--cc-muted); font-size: 13px; white-space: nowrap; }
|
||||
.batch-approval-summary strong { color: var(--cc-text); }
|
||||
.batch-approval-table :deep(.cell) { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
|
||||
.fulfillment-facts > div { min-width: 0; padding: 9px 10px; border-right: 1px solid var(--cc-border); background: #fff; }
|
||||
.fulfillment-facts > div.wide { grid-column: span 2; }
|
||||
.fulfillment-facts dt { color: var(--cc-muted); font-size: 12px; }
|
||||
|
||||
Reference in New Issue
Block a user