feat(frontend-v2): #986 Token 驾驶舱真实数据页 (token/overview|rankings|logs|balance)

This commit is contained in:
QihuAI Design committed 2026-08-23 12:02:37 +08:00
1 parent 4a2920e637
commit 910394423d
4 files changed
+501 -35

No files matched your search

+79 -13
View File
@@ -24,6 +24,13 @@ async function request<T>(path: string, options: RequestInit = {}): Promise<T> {
return res.json();
}
// Backend responses use a unified envelope `{code, data, message}`.
// `request<T>()` returns the raw envelope; `data<T>()` unwraps `.data`.
async function data<T>(path: string, options: RequestInit = {}): Promise<T> {
const env = await request<{ code: number; data: T; message: string }>(path, options);
return env.data;
}
// ─── Auth ───────────────────────────────────────────────────────────────────────
export const authApi = {
@@ -229,19 +236,78 @@ export const profileApi = {
getBalance: () => request<{ balance: number; total_used: number }>('/profile/balance'),
};
// ─── Dashboard / Stats ──────────────────────────────────────────────────────────
// ─── Token 驾驶舱 ────────────────────────────────────────────────────────────────
export const dashboardApi = {
getStats: () =>
request<{
active_users: number;
today_conversations: number;
skill_count: number;
revenue: number;
user_change: string;
conv_change: string;
}>('/token/usage'),
export interface TokenOverview {
total_used: number;
balance: number;
today_apps: number;
server_time: string;
}
getHotSkills: () =>
request<{ name: string; downloads: string }[]>('/market/apps'),
export interface ModelRanking {
model_id: string;
model_name: string;
total_tokens: number;
usage_count: number;
}
export interface TopApp {
conversation_id: string;
total_tokens: number;
}
export interface TokenRankings {
model_rankings: ModelRanking[];
top_apps: TopApp[];
}
export interface TokenLogItem {
id: string;
model_id: string;
model_name: string;
prompt_tokens: number;
completion_tokens: number;
total_tokens: number;
conversation_id: string;
created_at: string | null;
}
export interface TokenLogPage {
total: number;
page: number;
page_size: number;
items: TokenLogItem[];
}
export interface TokenBalance {
balance: number;
updated_at: string | null;
}
export const tokenApi = {
getOverview: () => data<TokenOverview>('/token/overview'),
getRankings: () => data<TokenRankings>('/token/rankings'),
getLogs: (params: {
start_date?: string;
end_date?: string;
model_id?: string;
app_type?: string;
page?: number;
page_size?: number;
} = {}) => {
const qs = new URLSearchParams();
if (params.start_date) qs.set('start_date', params.start_date);
if (params.end_date) qs.set('end_date', params.end_date);
if (params.model_id) qs.set('model_id', params.model_id);
if (params.app_type) qs.set('app_type', params.app_type);
if (params.page) qs.set('page', String(params.page));
if (params.page_size) qs.set('page_size', String(params.page_size));
const q = qs.toString();
return data<TokenLogPage>(`/token/logs${q ? `?${q}` : ''}`);
},
getBalance: () => data<TokenBalance>('/token/balance'),
};