feat(finance): 统一履约事实并改造人工账单分类

This commit is contained in:
yml2213
2026-10-23 13:35:48 +08:00
parent fb80cad695
commit 5d1ba11523
18 changed files with 764 additions and 123 deletions
@@ -32,7 +32,7 @@ import StatusTag from '@/components/admin/StatusTag'
import { fetchAdminOrderDetail, updateAdminOrderClaimStatus } from '@/services/admin'
import type { AdminOrderDetail, AdminTaskListItem } from '@/types/admin'
import { formatAdminDateTime } from '@/utils/admin-time'
import { resolveOrderFulfillmentMode } from '@/utils/admin-display'
import { resolveOrderFulfillmentMode, resolveVoucherStateLabel } from '@/utils/admin-display'
export default function AdminOrderDetailPage() {
const navigate = useNavigate()
@@ -185,9 +185,11 @@ export default function AdminOrderDetailPage() {
detail.order.payStatus === 'refunded' || detail.order.orderStatus === 'cancelled'
const canPauseOrClose = !isOrderFulfilled && !isOrderRefundedOrCancelled
const isAutoClaimOrder = Boolean(
detail.order.canClaimH5 || detail.order.fulfillmentType === 'auto_claim',
detail.order.fulfillmentMode === 'affiliate_dash' ||
(detail.order.fulfillmentMode === 'mixed' && detail.order.canClaimH5),
)
const fulfillmentMode = resolveOrderFulfillmentMode(detail.order)
const voucherLabel = resolveVoucherStateLabel(detail.order.voucherState)
return (
<section className="page-stack">
@@ -254,6 +256,15 @@ export default function AdminOrderDetailPage() {
{fulfillmentMode.label}
</Tag>
</Descriptions.Item>
<Descriptions.Item label="核销码">
{detail.order.hasVoucher && voucherLabel ? (
<Tag color="gold" style={{ margin: 0 }}>
🎫 {voucherLabel}
</Tag>
) : (
<span className="muted">无</span>
)}
</Descriptions.Item>
<Descriptions.Item label="订单状态">
<StatusTag value={detail.order.orderStatus} />
</Descriptions.Item>
@@ -32,7 +32,11 @@ import StatusTag from '@/components/admin/StatusTag'
import dayjs from '@/lib/dayjs'
import { fetchAdminOrders } from '@/services/admin'
import type { AdminOrderListItem } from '@/types/admin'
import { resolveOrderFulfillmentMode, resolveOrderPlatformBadge } from '@/utils/admin-display'
import {
resolveOrderFulfillmentMode,
resolveOrderPlatformBadge,
resolveVoucherStateLabel,
} from '@/utils/admin-display'
import {
adminOrderExecutorOptions,
adminOrderPlatformSegmentedOptions,
@@ -271,6 +275,7 @@ export default function AdminOrdersPage() {
minWidth: 230,
render: (_, row) => {
const fulfillmentMode = resolveOrderFulfillmentMode(row)
const voucherLabel = resolveVoucherStateLabel(row.voucherState)
return (
<div className="cell-stack" style={{ gap: 4 }}>
@@ -278,6 +283,11 @@ export default function AdminOrdersPage() {
<Tag color={fulfillmentMode.color} style={{ margin: 0, fontSize: 11 }}>
{fulfillmentMode.label}
</Tag>
{row.hasVoucher && voucherLabel ? (
<Tag color="gold" style={{ margin: 0, fontSize: 11 }}>
🎫 {voucherLabel}
</Tag>
) : null}
<StatusTag value={row.payStatus} kind="pay" />
<StatusTag value={row.resourceStatus} kind="resource" />
<StatusTag value={row.customerStatus} kind="customer" />
@@ -318,8 +328,7 @@ export default function AdminOrdersPage() {
render: (_, row) => {
const orderNo = row.platformOrderId || String(row.orderId)
const h5Url = `${window.location.origin}/h5/${encodeURIComponent(orderNo)}`
const isManualOrder =
row.fulfillmentType === 'manual' || (!row.canClaimH5 && !row.workOrderCount)
const isManualOrder = Number(row.manualItemCount || 0) > 0
return (
<Space size={6} wrap>
+23 -2
View File
@@ -8,11 +8,23 @@ export interface AdminOrderFulfillmentProgress {
customerStatus: string
}
export type AdminOrderItemFulfillmentMode =
| 'work_order'
| 'affiliate_dash'
| 'legacy_platform'
| 'manual'
| 'pending'
export type AdminOrderFulfillmentMode = AdminOrderItemFulfillmentMode | 'mixed'
export type AdminVoucherState = 'none' | 'unused' | 'consumed' | 'destroyed' | 'mixed'
export interface AdminOrderItemSummary {
itemTitle: string
skuNick: string
matchSku: string
quantity: number
fulfillmentMode: AdminOrderItemFulfillmentMode
}
export interface AdminOrderListItem {
@@ -48,7 +60,11 @@ export interface AdminOrderListItem {
claimStatus?: string
claimStatusReason?: string
claimStatusUpdatedAt?: string | null
fulfillmentType?: 'auto_claim' | 'worker_dispatch' | 'voucher_only' | 'manual'
fulfillmentMode: AdminOrderFulfillmentMode
manualItemCount: number
pendingItemCount: number
hasVoucher: boolean
voucherState: AdminVoucherState
workOrderCount?: number
canClaimH5?: boolean
}
@@ -66,7 +82,11 @@ export interface AdminOrderDetail {
claimStatus?: string
claimStatusReason?: string
claimStatusUpdatedAt?: string | null
fulfillmentType?: 'auto_claim' | 'worker_dispatch' | 'voucher_only' | 'manual'
fulfillmentMode: AdminOrderFulfillmentMode
manualItemCount: number
pendingItemCount: number
hasVoucher: boolean
voucherState: AdminVoucherState
workOrderCount?: number
canClaimH5?: boolean
buyerId: string
@@ -92,6 +112,7 @@ export interface AdminOrderDetail {
skuNick?: string
matchSku?: string
quantity: number
fulfillmentMode: AdminOrderItemFulfillmentMode
deliveryMode: string
spec: Record<string, unknown>
}>
+34 -28
View File
@@ -219,35 +219,41 @@ export function resolveOrderPlatformBadge(row: { platform?: string; provider?: s
}
export function resolveOrderFulfillmentMode(row: {
provider?: string
platform?: string
fulfillmentType?: 'auto_claim' | 'worker_dispatch' | 'voucher_only' | 'manual'
workOrderCount?: number
canClaimH5?: boolean
taskCount?: number
fulfillmentMode?:
| 'work_order'
| 'affiliate_dash'
| 'legacy_platform'
| 'manual'
| 'pending'
| 'mixed'
}): { label: string; color: string } {
const provider = String(row.provider || '').toLowerCase()
switch (row.fulfillmentMode) {
case 'affiliate_dash':
return { label: '⚡ 自动发货', color: 'blue' }
case 'work_order':
return { label: '👥 接单平台', color: 'purple' }
case 'legacy_platform':
return { label: '🗄 历史平台', color: 'default' }
case 'manual':
return { label: '🙋 人工履约', color: 'orange' }
case 'mixed':
return { label: '🔀 混合履约', color: 'geekblue' }
default:
return { label: '⏳ 待判定', color: 'default' }
}
}
if (row.canClaimH5 || row.fulfillmentType === 'auto_claim' || provider === 'douyin_mashida') {
return { label: '⚡ 自动直发', color: 'blue' }
export function resolveVoucherStateLabel(state?: string) {
switch (state) {
case 'unused':
return '核销码未用'
case 'consumed':
return '核销码已核销'
case 'destroyed':
return '核销码已销毁'
case 'mixed':
return '核销码混合状态'
default:
return ''
}
if (row.fulfillmentType === 'worker_dispatch' || Number(row.workOrderCount || 0) > 0) {
return { label: '👥 打手履约', color: 'purple' }
}
if (
provider === 'kuaishou_industry' ||
provider === '91kaquan' ||
provider === 'open_91' ||
row.fulfillmentType === 'voucher_only'
) {
return { label: '🎫 电子凭证', color: 'gold' }
}
if (provider === 'pdd') {
return { label: '📦 拼多多发货', color: 'red' }
}
return { label: '手动交付', color: 'default' }
}