feat(distribution): 独立分销后台账号体系、多租户隔离与主站后台分销管理GUI
- 独立账号鉴权:分销后台支持独立登录页面、Bearer+Cookie 双模鉴权与租户资料接口 - 多租户隔离:分销商成员强制锁定自身站点数据范围,防止横向越权;平台超管享有全局视界 - 一键开通分销商:平台端支持一键录入站点、管理员账号、分配角色并原子化初始化佣金规则 - 主后台分销分组:在主站后台增加「分销管理」导航分组,提供站点管理、规则配置、订单监控与结算管理 GUI - 门禁与联调:补充完整单测,全量代码门禁 check.sh 100% 通过,dev.sh 支持前后端与分销后台一键同启
This commit is contained in:
@@ -0,0 +1,246 @@
|
||||
import { apiClient } from '@/shared/api/client'
|
||||
import type { ApiResponse } from '@/shared/types/types'
|
||||
|
||||
export interface DistributionSite {
|
||||
id: number
|
||||
site_code: string
|
||||
site_name: string
|
||||
domain: string
|
||||
status: string
|
||||
display_account_enabled: boolean
|
||||
tax_enabled: boolean
|
||||
tax_rate_bps: number
|
||||
created_at: string
|
||||
}
|
||||
|
||||
export interface DistributionRule {
|
||||
id: number
|
||||
site_id?: number
|
||||
mode: string
|
||||
version: number
|
||||
status: string
|
||||
platform_receive_ratio: number
|
||||
platform_sell_ratio: number
|
||||
distributor_receive_ratio: number
|
||||
distributor_sell_ratio: number
|
||||
distributor_a_ratio: number
|
||||
distributor_b_ratio: number
|
||||
service_fee_value: number
|
||||
service_fee_unit: string
|
||||
payment_fee_bps: number
|
||||
tax_enabled: boolean
|
||||
tax_rate_bps: number
|
||||
effective_from: string
|
||||
effective_to?: string
|
||||
}
|
||||
|
||||
export interface DistributionOrder {
|
||||
order_id: number
|
||||
order_no: string
|
||||
site_id: number
|
||||
status: string
|
||||
refund_status: string
|
||||
settlement_status: string
|
||||
distribution_mode: string
|
||||
net_paid_amount_cent: number
|
||||
payment_fee_cent: number
|
||||
service_fee_cent: number
|
||||
markup_amount_cent: number
|
||||
tax_amount_cent: number
|
||||
split_base_amount_cent: number
|
||||
rounding_adjustment_cent: number
|
||||
created_at: string
|
||||
}
|
||||
|
||||
export interface DistributionOrderPage {
|
||||
items: DistributionOrder[]
|
||||
total: number
|
||||
page: number
|
||||
page_size: number
|
||||
}
|
||||
|
||||
export interface DistributionSettlementBatch {
|
||||
id: number
|
||||
site_id: number
|
||||
batch_no: string
|
||||
period_start: string
|
||||
period_end: string
|
||||
total_amount_cent: number
|
||||
status: string
|
||||
}
|
||||
|
||||
export interface DistributionSettlementItem {
|
||||
id: number
|
||||
order_id: number
|
||||
party_role: string
|
||||
amount_cent: number
|
||||
status: string
|
||||
}
|
||||
|
||||
export interface OnboardDistributionSitePayload {
|
||||
site_code: string
|
||||
site_name: string
|
||||
domain: string
|
||||
admin_username: string
|
||||
admin_password: string
|
||||
admin_nickname?: string
|
||||
member_type?: string
|
||||
display_account_enabled?: boolean
|
||||
tax_enabled?: boolean
|
||||
tax_rate_bps?: number
|
||||
distributor_receive_ratio?: number
|
||||
platform_sell_ratio?: number
|
||||
service_fee_value?: number
|
||||
}
|
||||
|
||||
export interface OnboardDistributionSiteResult {
|
||||
site: DistributionSite
|
||||
rule: DistributionRule
|
||||
member: {
|
||||
admin_id: number
|
||||
username: string
|
||||
nickname: string
|
||||
is_superadmin: boolean
|
||||
site_id?: number
|
||||
site_code?: string
|
||||
site_name?: string
|
||||
domain?: string
|
||||
member_type?: string
|
||||
}
|
||||
}
|
||||
|
||||
export async function fetchDistributionSites() {
|
||||
const { data } = await apiClient.get<ApiResponse<{ items: DistributionSite[] }>>(
|
||||
'/admin/distribution/sites'
|
||||
)
|
||||
return data.data.items ?? []
|
||||
}
|
||||
|
||||
export async function onboardDistributionSite(payload: OnboardDistributionSitePayload) {
|
||||
const { data } = await apiClient.post<ApiResponse<OnboardDistributionSiteResult>>(
|
||||
'/admin/distribution/sites/onboard',
|
||||
payload
|
||||
)
|
||||
return data.data
|
||||
}
|
||||
|
||||
export async function updateDistributionSite(
|
||||
id: number,
|
||||
payload: Partial<
|
||||
Pick<
|
||||
DistributionSite,
|
||||
'site_name' | 'domain' | 'status' | 'display_account_enabled' | 'tax_enabled' | 'tax_rate_bps'
|
||||
>
|
||||
>
|
||||
) {
|
||||
const { data } = await apiClient.put<ApiResponse<DistributionSite>>(
|
||||
`/admin/distribution/sites/${id}`,
|
||||
payload
|
||||
)
|
||||
return data.data
|
||||
}
|
||||
|
||||
export async function fetchDistributionRules(siteId?: number, mode?: string) {
|
||||
const { data } = await apiClient.get<ApiResponse<{ items: DistributionRule[] }>>(
|
||||
'/admin/distribution/rules',
|
||||
{
|
||||
params: { site_id: siteId || undefined, mode: mode || undefined },
|
||||
}
|
||||
)
|
||||
return data.data.items ?? []
|
||||
}
|
||||
|
||||
export interface CreateRulePayload {
|
||||
site_id?: number
|
||||
mode: string
|
||||
distributor_receive_ratio?: number
|
||||
platform_sell_ratio?: number
|
||||
distributor_sell_ratio?: number
|
||||
platform_receive_ratio?: number
|
||||
distributor_a_ratio?: number
|
||||
distributor_b_ratio?: number
|
||||
service_fee_value: number
|
||||
service_fee_unit: string
|
||||
payment_fee_bps: number
|
||||
tax_enabled: boolean
|
||||
tax_rate_bps: number
|
||||
effective_from?: string
|
||||
}
|
||||
|
||||
export async function createDistributionRule(payload: CreateRulePayload) {
|
||||
const { data } = await apiClient.post<ApiResponse<DistributionRule>>(
|
||||
'/admin/distribution/rules',
|
||||
payload
|
||||
)
|
||||
return data.data
|
||||
}
|
||||
|
||||
export async function updateDistributionRuleStatus(id: number, status: string) {
|
||||
const { data } = await apiClient.put<ApiResponse<DistributionRule>>(
|
||||
`/admin/distribution/rules/${id}/status`,
|
||||
{ status }
|
||||
)
|
||||
return data.data
|
||||
}
|
||||
|
||||
export async function fetchDistributionOrders(params: {
|
||||
kind?: string
|
||||
status?: string
|
||||
siteID?: number
|
||||
page?: number
|
||||
pageSize?: number
|
||||
}) {
|
||||
const { data } = await apiClient.get<ApiResponse<DistributionOrderPage>>(
|
||||
'/admin/distribution/orders',
|
||||
{
|
||||
params: {
|
||||
kind: params.kind || undefined,
|
||||
status: params.status || undefined,
|
||||
site_id: params.siteID || undefined,
|
||||
page: params.page || 1,
|
||||
page_size: params.pageSize || 20,
|
||||
},
|
||||
}
|
||||
)
|
||||
return data.data
|
||||
}
|
||||
|
||||
export async function fetchDistributionSettlementBatches(siteId: number) {
|
||||
const { data } = await apiClient.get<ApiResponse<{ items: DistributionSettlementBatch[] }>>(
|
||||
'/admin/distribution/settlement-batches',
|
||||
{
|
||||
params: { site_id: siteId },
|
||||
}
|
||||
)
|
||||
return data.data.items ?? []
|
||||
}
|
||||
|
||||
export async function createDistributionSettlementBatch(
|
||||
siteId: number,
|
||||
periodStart: string,
|
||||
periodEnd: string
|
||||
) {
|
||||
const { data } = await apiClient.post<ApiResponse<DistributionSettlementBatch>>(
|
||||
'/admin/distribution/settlement-batches',
|
||||
{
|
||||
site_id: siteId,
|
||||
period_start: periodStart,
|
||||
period_end: periodEnd,
|
||||
}
|
||||
)
|
||||
return data.data
|
||||
}
|
||||
|
||||
export async function settleDistributionBatch(id: number) {
|
||||
const { data } = await apiClient.post<ApiResponse<DistributionSettlementBatch>>(
|
||||
`/admin/distribution/settlement-batches/${id}/settle`
|
||||
)
|
||||
return data.data
|
||||
}
|
||||
|
||||
export async function fetchDistributionSettlementItems(batchId: number) {
|
||||
const { data } = await apiClient.get<ApiResponse<{ items: DistributionSettlementItem[] }>>(
|
||||
`/admin/distribution/settlement-batches/${batchId}/items`
|
||||
)
|
||||
return data.data.items ?? []
|
||||
}
|
||||
Reference in New Issue
Block a user