| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174 |
- /**
- * 开放平台API服务
- *
- * 提供API Key管理、调用统计和日志查询功能
- * 需求: 7, 11, 12
- */
- import { authService } from './authService';
- const RAW_API_BASE = import.meta.env.VITE_API_BASE_URL || '';
- const DEFAULT_API_PATH = import.meta.env.VITE_API_BASE_PATH || '/api/v1';
- export const API_BASE = RAW_API_BASE;
- // API_BASE_FULL: 如果 RAW_API_BASE 已包含 /api/... 则直接使用,否则追加默认的路径
- export const API_BASE_FULL = (() => {
- if (!RAW_API_BASE) return DEFAULT_API_PATH;
- if (/\/api(\/|$)/.test(RAW_API_BASE)) return RAW_API_BASE;
- return RAW_API_BASE.replace(/\/+$/g, '') + DEFAULT_API_PATH;
- })();
- export interface ApiKey {
- id: number;
- api_key_prefix: string;
- name: string | null;
- status: 'active' | 'disabled';
- key_type: 'public' | 'local';
- last_used_at: string | null;
- created_at: string;
- }
- export interface ApiKeyCreateResponse {
- id: number;
- api_key: string;
- api_key_prefix: string;
- name: string | null;
- key_type: 'public' | 'local';
- created_at: string;
- }
- export interface TrendItem {
- date: string;
- count: number;
- cost: string;
- }
- export interface ModelDistItem {
- model_name: string;
- count: number;
- percentage: number;
- }
- export interface Stats {
- today_calls: number;
- month_calls: number;
- total_calls: number;
- today_cost: string;
- month_cost: string;
- trend_data: TrendItem[];
- model_distribution: ModelDistItem[];
- }
- export interface CallLog {
- id: number;
- model_name: string;
- is_local: boolean;
- input_tokens: number;
- output_tokens: number;
- bill: string;
- status: string;
- api_key_prefix: string;
- created_at: string;
- input_price: string | null;
- output_price: string | null;
- }
- export interface CallLogQuery {
- start_date?: string;
- end_date?: string;
- model_id?: number;
- api_key_id?: number;
- page?: number;
- page_size?: number;
- }
- export interface PaginatedResponse<T> {
- items: T[];
- total: number;
- page: number;
- page_size: number;
- total_pages: number;
- }
- interface ApiResponse<T> {
- code: number;
- message: string;
- data: T;
- }
- async function request<T>(url: string, options: RequestInit = {}): Promise<ApiResponse<T>> {
- const token = authService.getToken();
- const headers: HeadersInit = {
- 'Content-Type': 'application/json',
- ...(token ? { Authorization: `Bearer ${token}` } : {}),
- ...options.headers,
- };
- const response = await fetch(`${API_BASE}${url}`, {
- ...options,
- headers,
- });
- if (!response.ok) {
- const error = await response.json().catch(() => ({ message: '请求失败' }));
- throw new Error(error.detail || error.message || '请求失败');
- }
- return response.json();
- }
- export const platformApi = {
- // API Key 管理
- async getApiKeys(): Promise<ApiKey[]> {
- const res = await request<ApiKey[]>('/api/platform/api-keys');
- return res.data;
- },
- async createApiKey(name?: string, keyType: 'public' | 'local' = 'public'): Promise<ApiKeyCreateResponse> {
- const res = await request<ApiKeyCreateResponse>('/api/platform/api-keys', {
- method: 'POST',
- body: JSON.stringify({ name, key_type: keyType }),
- });
- return res.data;
- },
- async updateApiKeyStatus(id: number, status: 'active' | 'disabled'): Promise<ApiKey> {
- const res = await request<ApiKey>(`/api/platform/api-keys/${id}`, {
- method: 'PUT',
- body: JSON.stringify({ status }),
- });
- return res.data;
- },
- async deleteApiKey(id: number): Promise<void> {
- await request<{ success: boolean }>(`/api/platform/api-keys/${id}`, {
- method: 'DELETE',
- });
- },
- // 统计
- async getStats(trendDays: number = 7, keyType?: 'public' | 'local'): Promise<Stats> {
- let url = `/api/platform/stats?trend_days=${trendDays}`;
- if (keyType) {
- url += `&key_type=${keyType}`;
- }
- const res = await request<Stats>(url);
- return res.data;
- },
- // 调用日志
- async getCallLogs(query: CallLogQuery & { key_type?: 'public' | 'local' } = {}): Promise<PaginatedResponse<CallLog>> {
- const params = new URLSearchParams();
- if (query.start_date) params.append('start_date', query.start_date);
- if (query.end_date) params.append('end_date', query.end_date);
- if (query.model_id) params.append('model_id', String(query.model_id));
- if (query.api_key_id) params.append('api_key_id', String(query.api_key_id));
- if (query.key_type) params.append('key_type', query.key_type);
- if (query.page) params.append('page', String(query.page));
- if (query.page_size) params.append('page_size', String(query.page_size));
- const url = `/api/platform/call-logs${params.toString() ? '?' + params.toString() : ''}`;
- const res = await request<PaginatedResponse<CallLog>>(url);
- return res.data;
- },
- };
|