feat(frontend-v2): #986 Token 驾驶舱真实数据页 (token/overview|rankings|logs|balance)
This commit is contained in:
1 parent
4a2920e637
commit
910394423d
4 files changed
+501
-35
No files matched your search
@@ -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'),
|
||||
};
|
||||
Reference in new issue
Block a user