Files
wzdj/lib/api/admin.ts

148 lines
5.6 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/**
* 管理后台 API 客户端 - 统一走后端接口MongoDB
* 前端仅通过此模块请求数据,不再直连 Dexie
*/
const BASE = "/api/admin"
async function fetchJson<T>(url: string, init?: RequestInit): Promise<{ success: boolean; data?: T; message?: string }> {
const res = await fetch(url, { ...init, headers: { "Content-Type": "application/json", ...init?.headers } })
const json = await res.json().catch(() => ({}))
if (!res.ok) return { success: false, message: json.message ?? res.statusText }
return json
}
export interface DashboardData {
stats: {
totalUsers: number
totalStreamers: number
totalOrders: number
totalRevenue: number
todayNewUsers: number
todayOrders: number
activeStreamers: number
pendingPawns: number
}
recentUsers: { id: string; name?: string; avatar?: string; phone?: string; createdAt?: string }[]
recentOrders: { orderNo: string; itemName: string; amount: number; createdAt: string }[]
}
export async function getDashboard(): Promise<DashboardData | null> {
const r = await fetchJson<{ data: DashboardData }>(`${BASE}/dashboard`)
return r.success && r.data ? r.data : null
}
export async function getUsers(): Promise<Record<string, unknown>[]> {
const r = await fetchJson<{ data: Record<string, unknown>[] }>(`${BASE}/users`)
return r.success && r.data ? r.data : []
}
export async function updateUser(id: string, body: Record<string, unknown>): Promise<boolean> {
const r = await fetchJson(`${BASE}/users/${id}`, { method: "PATCH", body: JSON.stringify(body) })
return r.success === true
}
export async function deleteUser(id: string): Promise<boolean> {
const r = await fetchJson(`${BASE}/users/${id}`, { method: "DELETE" })
return r.success === true
}
/** 用户详情(本库 + 用户资产 API 补充:消费记录、绑定主播),用于管理端点击查询 */
export interface UserDetailEnriched {
user: { user_id?: string; name?: string; gender?: string; phone?: string; created_at?: string; [k: string]: unknown } | null
consumption: { amount?: number; timestamp?: string; [k: string]: unknown }[]
boundStreamer: { streamer_id?: string; streamer_name?: string; [k: string]: unknown } | null
fromExternal: boolean
}
export async function getUserDetail(id: string): Promise<{
local: Record<string, unknown>
enriched: UserDetailEnriched
} | null> {
const r = await fetchJson<{ data: { local: Record<string, unknown>; enriched: UserDetailEnriched } }>(
`${BASE}/users/${id}/detail`
)
return r.success && r.data ? r.data : null
}
export async function getStreamers(): Promise<Record<string, unknown>[]> {
const r = await fetchJson<{ data: Record<string, unknown>[] }>(`${BASE}/streamers`)
return r.success && r.data ? r.data : []
}
/** 单条主播详情(含公会名、绑定统计,后端若已实现则返回) */
export async function getStreamer(id: string): Promise<Record<string, unknown> | null> {
const r = await fetchJson<{ data: Record<string, unknown> }>(`${BASE}/streamers/${id}`)
return r.success && r.data ? r.data : null
}
export async function createStreamer(body: Record<string, unknown>): Promise<{ id: string } | null> {
const r = await fetchJson<{ data: { id: string } }>(`${BASE}/streamers`, { method: "POST", body: JSON.stringify(body) })
return r.success && r.data ? r.data : null
}
export async function updateStreamer(id: string, body: Record<string, unknown>): Promise<boolean> {
const r = await fetchJson(`${BASE}/streamers/${id}`, { method: "PATCH", body: JSON.stringify(body) })
return r.success === true
}
export async function deleteStreamer(id: string): Promise<boolean> {
const r = await fetchJson(`${BASE}/streamers/${id}`, { method: "DELETE" })
return r.success === true
}
export async function getProducts(): Promise<Record<string, unknown>[]> {
const r = await fetchJson<{ data: Record<string, unknown>[] }>(`${BASE}/products`)
return r.success && r.data ? r.data : []
}
export async function createProduct(body: Record<string, unknown>): Promise<{ id: string } | null> {
const r = await fetchJson<{ data: { id: string } }>(`${BASE}/products`, { method: "POST", body: JSON.stringify(body) })
return r.success && r.data ? r.data : null
}
export async function updateProduct(id: string, body: Record<string, unknown>): Promise<boolean> {
const r = await fetchJson(`${BASE}/products/${id}`, { method: "PATCH", body: JSON.stringify(body) })
return r.success === true
}
export async function deleteProduct(id: string): Promise<boolean> {
const r = await fetchJson(`${BASE}/products/${id}`, { method: "DELETE" })
return r.success === true
}
export async function getPawns(): Promise<Record<string, unknown>[]> {
const r = await fetchJson<{ data: Record<string, unknown>[] }>(`${BASE}/pawns`)
return r.success && r.data ? r.data : []
}
export async function updatePawn(id: string, body: Record<string, unknown>): Promise<boolean> {
const r = await fetchJson(`${BASE}/pawns/${id}`, { method: "PATCH", body: JSON.stringify(body) })
return r.success === true
}
export interface AdminOrder {
id: string
orderNo: string
type: string
itemName: string
amount: number
status: string
userId?: string
createdAt: string
sourceTable: string
}
export async function getOrders(): Promise<AdminOrder[]> {
const r = await fetchJson<{ data: AdminOrder[] }>(`${BASE}/orders`)
return r.success && r.data ? r.data : []
}
export async function updateOrderStatus(id: string, sourceTable: string, status: string): Promise<boolean> {
const r = await fetchJson(`${BASE}/orders/status`, {
method: "PATCH",
body: JSON.stringify({ id, sourceTable, status }),
})
return r.success === true
}