- 后端支持补录/修改第三方单号接口 PUT /api/v1/admin/pickups/:id/third-party-order-no,记录流转事件与审计日志 - 前端线下提号主列表在第三方单号列后展示提号备注列 - 前端列表操作列及提号详情页增加补录/修改第三方单号操作入口与弹窗 - 通过 scripts/check.sh 全量门禁校验
416 lines
11 KiB
TypeScript
416 lines
11 KiB
TypeScript
import { apiClient } from '@/shared/api/client'
|
|
import type { ApiResponse, PaginatedResult } from '@/shared/types/types'
|
|
|
|
export type PickupAccountSource = 'internal' | 'external_platform_managed'
|
|
export type PickupSettlementMode = 'owner_wallet' | 'platform_managed'
|
|
export type PickupOfflineSettlementStatus = 'none' | 'pending' | 'settled'
|
|
export type PickupFinancialAdjustmentStatus = 'settled' | 'pending' | 'recovery_pending'
|
|
export type AvailableListingSourceType = '' | 'external' | 'internal'
|
|
|
|
export interface AdminPickup {
|
|
id: number
|
|
pickup_no: string
|
|
listing_id: number
|
|
listing_no: string
|
|
account_id: number
|
|
account_title: string
|
|
server_region: string
|
|
login_platform: string
|
|
owner_id: number
|
|
owner_phone: string
|
|
admin_id: number
|
|
operator: string
|
|
platform: string
|
|
third_party_order_no: string
|
|
shop_name: string
|
|
raw_shop_name?: string
|
|
account_source: PickupAccountSource
|
|
source_channel: string
|
|
settlement_mode: PickupSettlementMode
|
|
listing_price_cent: number
|
|
order_amount_cent: number
|
|
deposit_amount_cent: number
|
|
owner_price_cent: number
|
|
website_profit_cent: number
|
|
profit_amount_cent: number
|
|
profit_adjustment_cent: number
|
|
effective_profit_amount_cent: number
|
|
seller_ratio: number
|
|
buyer_ratio: number
|
|
account_snapshot?: Record<string, unknown>
|
|
settle_amount_cent: number
|
|
settle_adjustment_cent: number
|
|
effective_settle_amount_cent: number
|
|
status: string
|
|
offline_settlement_status: PickupOfflineSettlementStatus
|
|
offline_settlement_remark: string
|
|
offline_settled_by?: number
|
|
offline_settled_at?: string
|
|
remark: string
|
|
complete_remark: string
|
|
created_at: string
|
|
completed_at?: string
|
|
cancelled_at?: string
|
|
}
|
|
|
|
export interface AdminPickupFinancialAdjustment {
|
|
id: number
|
|
pickup_id: number
|
|
profit_delta_cent: number
|
|
settle_delta_cent: number
|
|
settlement_mode: PickupSettlementMode
|
|
status: PickupFinancialAdjustmentStatus
|
|
reason: string
|
|
created_by: number
|
|
settled_by?: number
|
|
settled_at?: string
|
|
settlement_remark: string
|
|
created_at: string
|
|
}
|
|
|
|
export interface AdminPickupProcessEvent {
|
|
id: number
|
|
stage: string
|
|
action: string
|
|
actor_type: string
|
|
actor_id: number
|
|
actor_name: string
|
|
target_type: string
|
|
target_id?: number
|
|
target_name: string
|
|
content: string
|
|
reason: string
|
|
payload: Record<string, unknown>
|
|
attachment_urls: string[]
|
|
state_before: Record<string, unknown>
|
|
state_after: Record<string, unknown>
|
|
created_at: string
|
|
}
|
|
|
|
export interface AvailableListing {
|
|
id: number
|
|
listing_no: string
|
|
account_id: number
|
|
account_title: string
|
|
server_region: string
|
|
login_platform: string
|
|
owner_id: number
|
|
owner_phone: string
|
|
listing_price_cent: number
|
|
owner_price_cent: number
|
|
owner_pure_price_cent: number
|
|
owner_extra_item_price_cent: number
|
|
owner_total_price_cent: number
|
|
website_profit_cent: number
|
|
seller_ratio: number
|
|
buyer_ratio: number
|
|
account_source: PickupAccountSource
|
|
is_external_upload: boolean
|
|
source_channel: string
|
|
handoff_mode: string
|
|
settlement_mode: string
|
|
}
|
|
|
|
export interface AdminPickupCreateRequest {
|
|
listing_id: number
|
|
operator?: string
|
|
platform?: string
|
|
third_party_order_no?: string
|
|
shop_name?: string
|
|
order_amount_cent?: number
|
|
deposit_amount_cent?: number
|
|
profit_amount_cent?: number
|
|
remark?: string
|
|
}
|
|
|
|
export interface AdminPickupCompleteRequest {
|
|
settle_amount_cent: number
|
|
profit_amount_cent?: number
|
|
complete_remark?: string
|
|
}
|
|
|
|
export interface AdminPickupProfitUpdateRequest {
|
|
profit_amount_cent: number
|
|
reason?: string
|
|
}
|
|
|
|
export interface AdminPickupThirdPartyOrderNoUpdateRequest {
|
|
third_party_order_no: string
|
|
}
|
|
|
|
export interface AdminPickupOfflineSettlementRequest {
|
|
remark?: string
|
|
}
|
|
|
|
export interface AdminPickupFinancialAdjustmentRequest {
|
|
profit_amount_cent?: number
|
|
settle_amount_cent?: number
|
|
reason: string
|
|
}
|
|
|
|
export interface AdminPickupFinancialAdjustmentSettlementRequest {
|
|
remark?: string
|
|
}
|
|
|
|
export interface AdminPickupListQuery {
|
|
page?: number
|
|
page_size?: number
|
|
keyword?: string
|
|
status?: string
|
|
shop_name?: string
|
|
account_source?: PickupAccountSource | ''
|
|
offline_settlement_status?: PickupOfflineSettlementStatus | ''
|
|
operator?: string
|
|
third_party_order_no?: string
|
|
start_time?: string
|
|
end_time?: string
|
|
}
|
|
|
|
export interface PickupShop {
|
|
id: number
|
|
name: string
|
|
platform: string
|
|
status: 'active' | 'disabled'
|
|
sort_order: number
|
|
remark: string
|
|
created_at: string
|
|
updated_at: string
|
|
}
|
|
|
|
export interface PickupShopCreateRequest {
|
|
name: string
|
|
platform?: string
|
|
status?: 'active' | 'disabled'
|
|
sort_order?: number
|
|
remark?: string
|
|
}
|
|
|
|
export interface PickupShopUpdateRequest {
|
|
name: string
|
|
platform?: string
|
|
status: 'active' | 'disabled'
|
|
sort_order?: number
|
|
remark?: string
|
|
}
|
|
|
|
export interface PickupShopQuery {
|
|
keyword?: string
|
|
platform?: string
|
|
status?: string
|
|
}
|
|
|
|
export type PickupShopMappingStatus = 'standard' | 'mapped' | 'unmapped'
|
|
|
|
export interface PickupShopHistoricalItem {
|
|
source_name: string
|
|
count: number
|
|
mapping_status: PickupShopMappingStatus
|
|
target_shop_id?: number
|
|
target_shop_name?: string
|
|
remark?: string
|
|
}
|
|
|
|
export interface PickupShopHistoricalStats {
|
|
items: PickupShopHistoricalItem[]
|
|
total_pickups: number
|
|
total_shops: number
|
|
standard_count: number
|
|
mapped_count: number
|
|
unmapped_count: number
|
|
}
|
|
|
|
export interface MapHistoricalShopsRequest {
|
|
from_shop_names: string[]
|
|
target_shop_name: string
|
|
create_target_missing?: boolean
|
|
target_platform?: string
|
|
remark?: string
|
|
}
|
|
|
|
export interface MapHistoricalShopsResult {
|
|
updated_pickups_count: number
|
|
target_shop_name: string
|
|
target_shop_id: number
|
|
created_standard_shop: boolean
|
|
}
|
|
|
|
function cleanParams(query: object) {
|
|
return Object.fromEntries(
|
|
Object.entries(query).filter(([, value]) => value !== '' && value !== undefined)
|
|
)
|
|
}
|
|
|
|
export async function fetchAdminPickups(query: AdminPickupListQuery = {}) {
|
|
const { data } = await apiClient.get<ApiResponse<PaginatedResult<AdminPickup>>>(
|
|
'/admin/pickups',
|
|
{ params: cleanParams(query) }
|
|
)
|
|
const result = data.data
|
|
return {
|
|
items: Array.isArray(result?.items) ? result.items : [],
|
|
total: Number(result?.total ?? 0),
|
|
page: Number(result?.page ?? query.page ?? 1),
|
|
page_size: Number(result?.page_size ?? query.page_size ?? 20),
|
|
}
|
|
}
|
|
|
|
export async function fetchAdminPickup(id: string | number) {
|
|
const { data } = await apiClient.get<ApiResponse<AdminPickup>>(`/admin/pickups/${id}`)
|
|
return data.data
|
|
}
|
|
|
|
export async function fetchAdminPickupShopOptions(platform = '') {
|
|
const { data } = await apiClient.get<ApiResponse<string[]>>('/admin/pickups/shop-options', {
|
|
params: cleanParams({ platform }),
|
|
})
|
|
return Array.isArray(data.data) ? data.data : []
|
|
}
|
|
|
|
export async function fetchAvailableListings(
|
|
keyword = '',
|
|
page = 1,
|
|
page_size = 20,
|
|
source_type: AvailableListingSourceType = ''
|
|
) {
|
|
const { data } = await apiClient.get<ApiResponse<PaginatedResult<AvailableListing>>>(
|
|
'/admin/pickups/available-listings',
|
|
{ params: cleanParams({ keyword, page, page_size, source_type }) }
|
|
)
|
|
const result = data.data
|
|
return {
|
|
items: Array.isArray(result?.items) ? result.items : [],
|
|
total: Number(result?.total ?? 0),
|
|
}
|
|
}
|
|
|
|
export async function createAdminPickup(req: AdminPickupCreateRequest) {
|
|
const { data } = await apiClient.post<ApiResponse<AdminPickup>>('/admin/pickups', req)
|
|
return data.data
|
|
}
|
|
|
|
export async function completeAdminPickup(id: number, req: AdminPickupCompleteRequest) {
|
|
const { data } = await apiClient.post<ApiResponse<AdminPickup>>(
|
|
`/admin/pickups/${id}/complete`,
|
|
req
|
|
)
|
|
return data.data
|
|
}
|
|
|
|
export async function confirmAdminPickupOfflineSettlement(
|
|
id: number,
|
|
req: AdminPickupOfflineSettlementRequest = {}
|
|
) {
|
|
const { data } = await apiClient.post<ApiResponse<AdminPickup>>(
|
|
`/admin/pickups/${id}/offline-settlement`,
|
|
req
|
|
)
|
|
return data.data
|
|
}
|
|
|
|
export async function updateAdminPickupProfit(id: number, req: AdminPickupProfitUpdateRequest) {
|
|
const { data } = await apiClient.put<ApiResponse<AdminPickup>>(`/admin/pickups/${id}/profit`, req)
|
|
return data.data
|
|
}
|
|
|
|
export async function updateAdminPickupThirdPartyOrderNo(
|
|
id: number,
|
|
req: AdminPickupThirdPartyOrderNoUpdateRequest
|
|
) {
|
|
const { data } = await apiClient.put<ApiResponse<AdminPickup>>(
|
|
`/admin/pickups/${id}/third-party-order-no`,
|
|
req
|
|
)
|
|
return data.data
|
|
}
|
|
|
|
export async function createAdminPickupFinancialAdjustment(
|
|
id: number,
|
|
req: AdminPickupFinancialAdjustmentRequest
|
|
) {
|
|
const { data } = await apiClient.post<ApiResponse<AdminPickup>>(
|
|
`/admin/pickups/${id}/financial-adjustments`,
|
|
req
|
|
)
|
|
return data.data
|
|
}
|
|
|
|
export async function fetchAdminPickupFinancialAdjustments(id: string | number) {
|
|
const { data } = await apiClient.get<ApiResponse<AdminPickupFinancialAdjustment[]>>(
|
|
`/admin/pickups/${id}/financial-adjustments`
|
|
)
|
|
return Array.isArray(data.data) ? data.data : []
|
|
}
|
|
|
|
export async function fetchAdminPickupProcessEvents(id: string | number) {
|
|
const { data } = await apiClient.get<ApiResponse<{ items: AdminPickupProcessEvent[] }>>(
|
|
`/admin/pickups/${id}/process-events`
|
|
)
|
|
return Array.isArray(data.data?.items) ? data.data.items : []
|
|
}
|
|
|
|
export async function settleAdminPickupFinancialAdjustment(
|
|
id: number,
|
|
req: AdminPickupFinancialAdjustmentSettlementRequest = {}
|
|
) {
|
|
const { data } = await apiClient.post<ApiResponse<{ settled: boolean }>>(
|
|
`/admin/pickup-financial-adjustments/${id}/settle`,
|
|
req
|
|
)
|
|
return data.data
|
|
}
|
|
|
|
export async function cancelAdminPickup(id: number, reason: string) {
|
|
const { data } = await apiClient.post<ApiResponse<{ cancelled: boolean }>>(
|
|
`/admin/pickups/${id}/cancel`,
|
|
{ reason }
|
|
)
|
|
return data.data
|
|
}
|
|
|
|
export async function fetchPickupShops(query: PickupShopQuery = {}) {
|
|
const { data } = await apiClient.get<ApiResponse<PickupShop[]>>('/admin/pickups/shops', {
|
|
params: cleanParams(query),
|
|
})
|
|
return Array.isArray(data.data) ? data.data : []
|
|
}
|
|
|
|
export async function createPickupShop(req: PickupShopCreateRequest) {
|
|
const { data } = await apiClient.post<ApiResponse<PickupShop>>('/admin/pickups/shops', req)
|
|
return data.data
|
|
}
|
|
|
|
export async function updatePickupShop(id: number, req: PickupShopUpdateRequest) {
|
|
const { data } = await apiClient.put<ApiResponse<PickupShop>>(`/admin/pickups/shops/${id}`, req)
|
|
return data.data
|
|
}
|
|
|
|
export async function deletePickupShop(id: number) {
|
|
const { data } = await apiClient.delete<ApiResponse<{ deleted: boolean }>>(
|
|
`/admin/pickups/shops/${id}`
|
|
)
|
|
return data.data
|
|
}
|
|
|
|
export async function fetchHistoricalShopStats() {
|
|
const { data } = await apiClient.get<ApiResponse<PickupShopHistoricalStats>>(
|
|
'/admin/pickups/shops/historical-stats'
|
|
)
|
|
return data.data
|
|
}
|
|
|
|
export async function mapHistoricalShops(req: MapHistoricalShopsRequest) {
|
|
const { data } = await apiClient.post<ApiResponse<MapHistoricalShopsResult>>(
|
|
'/admin/pickups/shops/map-historical',
|
|
req
|
|
)
|
|
return data.data
|
|
}
|
|
|
|
export async function deleteShopMapping(sourceName: string) {
|
|
const { data } = await apiClient.delete<ApiResponse<{ deleted: boolean }>>(
|
|
'/admin/pickups/shops/mappings',
|
|
{ params: { source_name: sourceName } }
|
|
)
|
|
return data.data
|
|
}
|