/** * 管理后台 API 客户端 - 统一走后端接口(MongoDB) * 前端仅通过此模块请求数据,不再直连 Dexie */ const BASE = "/api/admin" async function fetchJson(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 { const r = await fetchJson<{ data: DashboardData }>(`${BASE}/dashboard`) return r.success && r.data ? r.data : null } export async function getUsers(): Promise[]> { const r = await fetchJson<{ data: Record[] }>(`${BASE}/users`) return r.success && r.data ? r.data : [] } export async function updateUser(id: string, body: Record): Promise { const r = await fetchJson(`${BASE}/users/${id}`, { method: "PATCH", body: JSON.stringify(body) }) return r.success === true } export async function deleteUser(id: string): Promise { 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 enriched: UserDetailEnriched } | null> { const r = await fetchJson<{ data: { local: Record; enriched: UserDetailEnriched } }>( `${BASE}/users/${id}/detail` ) return r.success && r.data ? r.data : null } export async function getStreamers(): Promise[]> { const r = await fetchJson<{ data: Record[] }>(`${BASE}/streamers`) return r.success && r.data ? r.data : [] } /** 单条主播详情(含公会名、绑定统计,后端若已实现则返回) */ export async function getStreamer(id: string): Promise | null> { const r = await fetchJson<{ data: Record }>(`${BASE}/streamers/${id}`) return r.success && r.data ? r.data : null } export async function createStreamer(body: Record): 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): Promise { const r = await fetchJson(`${BASE}/streamers/${id}`, { method: "PATCH", body: JSON.stringify(body) }) return r.success === true } export async function deleteStreamer(id: string): Promise { const r = await fetchJson(`${BASE}/streamers/${id}`, { method: "DELETE" }) return r.success === true } export async function getProducts(): Promise[]> { const r = await fetchJson<{ data: Record[] }>(`${BASE}/products`) return r.success && r.data ? r.data : [] } export async function createProduct(body: Record): 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): Promise { const r = await fetchJson(`${BASE}/products/${id}`, { method: "PATCH", body: JSON.stringify(body) }) return r.success === true } export async function deleteProduct(id: string): Promise { const r = await fetchJson(`${BASE}/products/${id}`, { method: "DELETE" }) return r.success === true } export async function getPawns(): Promise[]> { const r = await fetchJson<{ data: Record[] }>(`${BASE}/pawns`) return r.success && r.data ? r.data : [] } export async function updatePawn(id: string, body: Record): Promise { 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 { 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 { const r = await fetchJson(`${BASE}/orders/status`, { method: "PATCH", body: JSON.stringify({ id, sourceTable, status }), }) return r.success === true }