拆分客户/员工工作台,落地登录关怀、待办统计、公告双栏布局;同步接口映射 AI、H5 订单与相关页面优化。 Co-authored-by: Cursor <cursoragent@cursor.com>
184 lines
5.7 KiB
TypeScript
184 lines
5.7 KiB
TypeScript
import { axiosInstance } from '@/api/rbac'
|
|
import { resolveAdminApiPath } from '@/utils/adminApi'
|
|
|
|
function orderUrl(path: string): string {
|
|
return resolveAdminApiPath(path)
|
|
}
|
|
|
|
function assertBusinessOk(body: unknown) {
|
|
if (body == null) throw new Error('空响应')
|
|
const payload = body as Record<string, unknown>
|
|
const code = payload.code ?? payload.Code
|
|
const ok =
|
|
code === undefined ||
|
|
code === null ||
|
|
code === 0 ||
|
|
code === 200 ||
|
|
code === '0' ||
|
|
code === '200' ||
|
|
payload.success === true ||
|
|
payload.Success === true
|
|
if (!ok) {
|
|
throw new Error(
|
|
String(payload.msg ?? payload.Msg ?? payload.message ?? payload.Message ?? '请求失败'),
|
|
)
|
|
}
|
|
}
|
|
|
|
function unwrapData<T>(body: unknown): T {
|
|
assertBusinessOk(body)
|
|
const payload = body as Record<string, unknown>
|
|
return (payload.data ?? payload.Data ?? body) as T
|
|
}
|
|
|
|
export interface OrderWorkplaceStats {
|
|
total: number
|
|
counts: Record<string, number>
|
|
todayCreated: number
|
|
yesterdayCreated: number
|
|
dayOverDayGrowthPercent: number | null
|
|
pendingShip: number
|
|
shipped: number
|
|
pendingPayment: number
|
|
problematic: number
|
|
claimed: number
|
|
storeCount: number
|
|
storeOrderPending: number
|
|
}
|
|
|
|
export interface OrderWorkplaceTrendPoint {
|
|
label: string
|
|
forecastCount: number
|
|
shippedCount: number
|
|
}
|
|
|
|
export interface OrderWorkplaceTrend {
|
|
dimension: string
|
|
points: OrderWorkplaceTrendPoint[]
|
|
}
|
|
|
|
export interface OrderWorkplaceSpendTrendPoint {
|
|
label: string
|
|
orderCount: number
|
|
spendAmount: number
|
|
avgAmount: number
|
|
}
|
|
|
|
export interface OrderWorkplaceSpendTrend {
|
|
dimension: string
|
|
totalSpend: number
|
|
totalOrders: number
|
|
avgAmount: number
|
|
points: OrderWorkplaceSpendTrendPoint[]
|
|
}
|
|
|
|
function normalizeStats(raw: Record<string, unknown>): OrderWorkplaceStats {
|
|
const countsRaw = raw.counts ?? raw.Counts
|
|
const counts =
|
|
typeof countsRaw === 'object' && countsRaw != null
|
|
? (countsRaw as Record<string, number>)
|
|
: {}
|
|
const countOf = (...keys: string[]) => {
|
|
for (const key of keys) {
|
|
const v = counts[key]
|
|
if (v != null && Number.isFinite(Number(v))) return Number(v) || 0
|
|
}
|
|
return 0
|
|
}
|
|
return {
|
|
total: Number(raw.total ?? raw.Total ?? 0) || 0,
|
|
counts,
|
|
todayCreated: Number(raw.todayCreated ?? raw.TodayCreated ?? 0) || 0,
|
|
yesterdayCreated: Number(raw.yesterdayCreated ?? raw.YesterdayCreated ?? 0) || 0,
|
|
dayOverDayGrowthPercent:
|
|
raw.dayOverDayGrowthPercent ?? raw.DayOverDayGrowthPercent ?? null,
|
|
pendingShip: Number(raw.pendingShip ?? raw.PendingShip ?? 0) || 0,
|
|
shipped: Number(raw.shipped ?? raw.Shipped ?? 0) || 0,
|
|
pendingPayment: Number(raw.pendingPayment ?? raw.PendingPayment ?? 0) || 0,
|
|
problematic: Number(raw.problematic ?? raw.Problematic ?? 0) || 0,
|
|
claimed:
|
|
Number(raw.claimed ?? raw.Claimed ?? countOf('claimed', 'Claimed') ?? 0) || 0,
|
|
storeCount: Number(raw.storeCount ?? raw.StoreCount ?? 0) || 0,
|
|
storeOrderPending: Number(raw.storeOrderPending ?? raw.StoreOrderPending ?? 0) || 0,
|
|
}
|
|
}
|
|
|
|
function normalizeTrend(raw: Record<string, unknown>): OrderWorkplaceTrend {
|
|
const pointsRaw = raw.points ?? raw.Points
|
|
const points = Array.isArray(pointsRaw)
|
|
? pointsRaw.map((item) => {
|
|
const row = item as Record<string, unknown>
|
|
return {
|
|
label: String(row.label ?? row.Label ?? ''),
|
|
forecastCount: Number(row.forecastCount ?? row.ForecastCount ?? 0) || 0,
|
|
shippedCount: Number(row.shippedCount ?? row.ShippedCount ?? 0) || 0,
|
|
}
|
|
})
|
|
: []
|
|
|
|
return {
|
|
dimension: String(raw.dimension ?? raw.Dimension ?? 'day'),
|
|
points,
|
|
}
|
|
}
|
|
|
|
function normalizeSpendTrend(raw: Record<string, unknown>): OrderWorkplaceSpendTrend {
|
|
const pointsRaw = raw.points ?? raw.Points
|
|
const points = Array.isArray(pointsRaw)
|
|
? pointsRaw.map((item) => {
|
|
const row = item as Record<string, unknown>
|
|
return {
|
|
label: String(row.label ?? row.Label ?? ''),
|
|
orderCount: Number(row.orderCount ?? row.OrderCount ?? 0) || 0,
|
|
spendAmount: Number(row.spendAmount ?? row.SpendAmount ?? 0) || 0,
|
|
avgAmount: Number(row.avgAmount ?? row.AvgAmount ?? 0) || 0,
|
|
}
|
|
})
|
|
: []
|
|
|
|
return {
|
|
dimension: String(raw.dimension ?? raw.Dimension ?? 'day'),
|
|
totalSpend: Number(raw.totalSpend ?? raw.TotalSpend ?? 0) || 0,
|
|
totalOrders: Number(raw.totalOrders ?? raw.TotalOrders ?? 0) || 0,
|
|
avgAmount: Number(raw.avgAmount ?? raw.AvgAmount ?? 0) || 0,
|
|
points,
|
|
}
|
|
}
|
|
|
|
/** 工作台订单统计 GET /order/workplace-stats */
|
|
export async function getOrderWorkplaceStats(): Promise<OrderWorkplaceStats> {
|
|
const res = await axiosInstance.get(orderUrl('/order/workplace-stats'))
|
|
const data = unwrapData<Record<string, unknown>>(res.data)
|
|
return normalizeStats(data)
|
|
}
|
|
|
|
/** 工作台订单趋势 GET /order/workplace-trend */
|
|
export async function getOrderWorkplaceTrend(params: {
|
|
dimension: 'day' | 'week' | 'month'
|
|
count?: number
|
|
}): Promise<OrderWorkplaceTrend> {
|
|
const res = await axiosInstance.get(orderUrl('/order/workplace-trend'), {
|
|
params: {
|
|
dimension: params.dimension,
|
|
count: params.count,
|
|
},
|
|
})
|
|
const data = unwrapData<Record<string, unknown>>(res.data)
|
|
return normalizeTrend(data)
|
|
}
|
|
|
|
/** 工作台费用趋势 GET /order/workplace-spend-trend */
|
|
export async function getOrderWorkplaceSpendTrend(params: {
|
|
dimension: 'day' | 'week' | 'month'
|
|
count?: number
|
|
}): Promise<OrderWorkplaceSpendTrend> {
|
|
const res = await axiosInstance.get(orderUrl('/order/workplace-spend-trend'), {
|
|
params: {
|
|
dimension: params.dimension,
|
|
count: params.count,
|
|
},
|
|
})
|
|
const data = unwrapData<Record<string, unknown>>(res.data)
|
|
return normalizeSpendTrend(data)
|
|
}
|