feat(admin-web): 新增履约渠道页,含待分类队列与渠道规则

- 待分类按 SKU 聚合,可直接指定渠道(含第三方卡券仅统计渠道)
- 渠道规则支持新增/删除,展示优先级与作用范围
- 问题队列按类型筛选,统一使用 PercentTable
This commit is contained in:
yml2213
2026-10-31 18:12:31 +08:00
parent 855f2efcff
commit 9b01443424
5 changed files with 544 additions and 0 deletions
@@ -0,0 +1,119 @@
import { apiDelete, apiGet, apiPost } from '@/lib/http'
/** 待分类队列(按 SKU 聚合)。 */
export type PendingChannelGroup = {
provider: string
shop_id: string
sku_code: string
sku_name: string
item_count: number
revenue_fen: number
first_seen_at: string
last_seen_at: string
}
export type PendingChannelGroupListResult = {
items: PendingChannelGroup[]
total: number
page: number
pageSize: number
}
/** 渠道规则(L1)。 */
export type ChannelRule = {
id: number
provider: string
shop_id: string
match_key_type: 'sku_code' | 'internal_sku' | 'sku_name'
match_key: string
channel: 'work_order' | 'affiliate_dash' | 'third_party_voucher' | 'manual'
priority: number
enabled: boolean
}
export type ChannelException = {
id: number
reason: string
status: string
scope_key: string
item_count: number
first_seen_at: string
last_seen_at: string
detail_json: unknown
}
export type ChannelExceptionListResult = {
items: ChannelException[]
total: number
page: number
pageSize: number
}
export type PipelineRunResult = Record<string, unknown>
export function fetchPendingChannelGroups(
params: {
page?: number
pageSize?: number
keyword?: string
} = {},
) {
return apiGet<PendingChannelGroupListResult>('/api/v1/admin/fulfillment/pending', params)
}
export function fetchChannelExceptions(
params: {
reason?: string
status?: string
page?: number
pageSize?: number
} = {},
) {
return apiGet<ChannelExceptionListResult>('/api/v1/admin/fulfillment/exceptions', params)
}
export function assignChannelBySku(payload: {
provider: string
shopId: string
skuCode: string
channel: string
note?: string
}) {
return apiPost<{ updated: number }>('/api/v1/admin/fulfillment/assign', payload)
}
export function assignChannelToItems(payload: {
orderItemIds: number[]
channel: string
note?: string
}) {
return apiPost<{ updated: number }>('/api/v1/admin/fulfillment/assign', payload)
}
export function fetchChannelRules(params: { channel?: string } = {}) {
return apiGet<ChannelRule[]>('/api/v1/admin/fulfillment/rules', params)
}
export function saveChannelRule(payload: {
id?: number
provider?: string
shopId?: string
matchKeyType: string
matchKey: string
channel: string
priority?: number
enabled?: boolean
note?: string
}) {
return apiPost<{ id: number }>('/api/v1/admin/fulfillment/rules', payload)
}
export function deleteChannelRule(ruleId: number) {
return apiDelete<{ deleted: boolean }>(`/api/v1/admin/fulfillment/rules/${ruleId}`)
}
export function runFinancePipeline(payload: { days?: number } = {}) {
return apiPost<PipelineRunResult>('/api/v1/admin/fulfillment/pipeline/run', payload, {
timeout: 300_000,
})
}
@@ -3,6 +3,7 @@ export * from './dashboard'
export * from './finance'
export * from './finance-ledger'
export * from './cost-center'
export * from './fulfillment-channel'
export * from './fund'
export * from './users'
export * from './audit-logs'