98 lines
3.0 KiB
TypeScript
98 lines
3.0 KiB
TypeScript
/**
|
||
* 用户资产 API 客户端(仅服务端调用)
|
||
* 用于管理端用户详情:查询、消费记录、绑定主播
|
||
* 配置:USER_ASSET_API_BASE_URL、USER_ASSET_API_KEY、USER_ASSET_API_SECRET
|
||
*/
|
||
|
||
const BASE = process.env.USER_ASSET_API_BASE_URL || ""
|
||
const API_KEY = process.env.USER_ASSET_API_KEY || ""
|
||
const API_SECRET = process.env.USER_ASSET_API_SECRET || ""
|
||
|
||
function headers(): Record<string, string> {
|
||
const h: Record<string, string> = { "Content-Type": "application/json" }
|
||
if (API_KEY) h["X-API-Key"] = API_KEY
|
||
if (API_SECRET) h["X-API-Secret"] = API_SECRET
|
||
return h
|
||
}
|
||
|
||
export function isConfigured(): boolean {
|
||
return Boolean(BASE && API_KEY)
|
||
}
|
||
|
||
export interface UserAssetQueryResult {
|
||
user_id?: string
|
||
name?: string
|
||
gender?: string
|
||
phone?: string
|
||
created_at?: string
|
||
[k: string]: unknown
|
||
}
|
||
|
||
export interface ConsumptionRecord {
|
||
amount?: number
|
||
timestamp?: string
|
||
[k: string]: unknown
|
||
}
|
||
|
||
export interface BoundStreamer {
|
||
streamer_id?: string
|
||
streamer_name?: string
|
||
[k: string]: unknown
|
||
}
|
||
|
||
/** 查询单个用户 */
|
||
export async function queryUser(userId: string): Promise<UserAssetQueryResult | null> {
|
||
if (!BASE || !API_KEY) return null
|
||
try {
|
||
const res = await fetch(`${BASE}/api/user/query?user_id=${encodeURIComponent(userId)}`, { headers: headers() })
|
||
const data = await res.json().catch(() => ({}))
|
||
if (!res.ok) return null
|
||
return (data.data ?? data) as UserAssetQueryResult
|
||
} catch {
|
||
return null
|
||
}
|
||
}
|
||
|
||
/** 用户消费记录 */
|
||
export async function getUserConsumption(userId: string): Promise<ConsumptionRecord[]> {
|
||
if (!BASE || !API_KEY) return []
|
||
try {
|
||
const res = await fetch(`${BASE}/api/user/consumption?user_id=${encodeURIComponent(userId)}`, { headers: headers() })
|
||
const data = await res.json().catch(() => ({}))
|
||
if (!res.ok) return []
|
||
const list = data.data ?? data.list ?? data.records ?? []
|
||
return Array.isArray(list) ? list : []
|
||
} catch {
|
||
return []
|
||
}
|
||
}
|
||
|
||
/** 查询用户绑定的主播 */
|
||
export async function queryBoundStreamer(userId: string): Promise<BoundStreamer | null> {
|
||
if (!BASE || !API_KEY) return null
|
||
try {
|
||
const res = await fetch(`${BASE}/api/user/query_bound_streamer?user_id=${encodeURIComponent(userId)}`, {
|
||
headers: headers(),
|
||
})
|
||
const data = await res.json().catch(() => ({}))
|
||
if (!res.ok) return null
|
||
return (data.data ?? data) as BoundStreamer
|
||
} catch {
|
||
return null
|
||
}
|
||
}
|
||
|
||
/** 聚合:用户详情 + 消费记录 + 绑定主播(供管理端详情页一次拉取) */
|
||
export async function getUserDetailEnriched(userId: string): Promise<{
|
||
user: UserAssetQueryResult | null
|
||
consumption: ConsumptionRecord[]
|
||
boundStreamer: BoundStreamer | null
|
||
fromExternal: boolean
|
||
}> {
|
||
const fromExternal = isConfigured()
|
||
const [user, consumption, boundStreamer] = fromExternal
|
||
? await Promise.all([queryUser(userId), getUserConsumption(userId), queryBoundStreamer(userId)])
|
||
: [null, [], null]
|
||
return { user: user ?? null, consumption: consumption ?? [], boundStreamer: boundStreamer ?? null, fromExternal }
|
||
}
|