diff --git a/frontend/src/api/admin/accounts.ts b/frontend/src/api/admin/accounts.ts index 99146bf2..cac50232 100644 --- a/frontend/src/api/admin/accounts.ts +++ b/frontend/src/api/admin/accounts.ts @@ -12,7 +12,7 @@ import type { AccountUsageInfo, WindowStats, ClaudeModel, - AccountUsageStatsResponse, + AccountUsageStatsResponse } from '@/types' /** @@ -36,8 +36,8 @@ export async function list( params: { page, page_size: pageSize, - ...filters, - }, + ...filters + } }) return data } @@ -129,7 +129,7 @@ export async function refreshCredentials(id: number): Promise { */ export async function getStats(id: number, days: number = 30): Promise { const { data } = await apiClient.get(`/admin/accounts/${id}/stats`, { - params: { days }, + params: { days } }) return data } @@ -254,7 +254,7 @@ export async function bulkUpdate( results: Array<{ account_id: number; success: boolean; error?: string }> }>('/admin/accounts/bulk-update', { account_ids: accountIds, - ...updates, + ...updates }) return data } @@ -277,7 +277,7 @@ export async function getTodayStats(id: number): Promise { */ export async function setSchedulable(id: number, schedulable: boolean): Promise { const { data } = await apiClient.post(`/admin/accounts/${id}/schedulable`, { - schedulable, + schedulable }) return data } @@ -335,7 +335,7 @@ export const accountsAPI = { batchCreate, batchUpdateCredentials, bulkUpdate, - syncFromCrs, + syncFromCrs } export default accountsAPI diff --git a/frontend/src/api/admin/dashboard.ts b/frontend/src/api/admin/dashboard.ts index 39253538..83e56c0e 100644 --- a/frontend/src/api/admin/dashboard.ts +++ b/frontend/src/api/admin/dashboard.ts @@ -3,16 +3,22 @@ * Provides system-wide statistics and metrics */ -import { apiClient } from '../client'; -import type { DashboardStats, TrendDataPoint, ModelStat, ApiKeyUsageTrendPoint, UserUsageTrendPoint } from '@/types'; +import { apiClient } from '../client' +import type { + DashboardStats, + TrendDataPoint, + ModelStat, + ApiKeyUsageTrendPoint, + UserUsageTrendPoint +} from '@/types' /** * Get dashboard statistics * @returns Dashboard statistics including users, keys, accounts, and token usage */ export async function getStats(): Promise { - const { data } = await apiClient.get('/admin/dashboard/stats'); - return data; + const { data } = await apiClient.get('/admin/dashboard/stats') + return data } /** @@ -20,33 +26,33 @@ export async function getStats(): Promise { * @returns Real-time system metrics */ export async function getRealtimeMetrics(): Promise<{ - active_requests: number; - requests_per_minute: number; - average_response_time: number; - error_rate: number; + active_requests: number + requests_per_minute: number + average_response_time: number + error_rate: number }> { const { data } = await apiClient.get<{ - active_requests: number; - requests_per_minute: number; - average_response_time: number; - error_rate: number; - }>('/admin/dashboard/realtime'); - return data; + active_requests: number + requests_per_minute: number + average_response_time: number + error_rate: number + }>('/admin/dashboard/realtime') + return data } export interface TrendParams { - start_date?: string; - end_date?: string; - granularity?: 'day' | 'hour'; - user_id?: number; - api_key_id?: number; + start_date?: string + end_date?: string + granularity?: 'day' | 'hour' + user_id?: number + api_key_id?: number } export interface TrendResponse { - trend: TrendDataPoint[]; - start_date: string; - end_date: string; - granularity: string; + trend: TrendDataPoint[] + start_date: string + end_date: string + granularity: string } /** @@ -55,21 +61,21 @@ export interface TrendResponse { * @returns Usage trend data */ export async function getUsageTrend(params?: TrendParams): Promise { - const { data } = await apiClient.get('/admin/dashboard/trend', { params }); - return data; + const { data } = await apiClient.get('/admin/dashboard/trend', { params }) + return data } export interface ModelStatsParams { - start_date?: string; - end_date?: string; - user_id?: number; - api_key_id?: number; + start_date?: string + end_date?: string + user_id?: number + api_key_id?: number } export interface ModelStatsResponse { - models: ModelStat[]; - start_date: string; - end_date: string; + models: ModelStat[] + start_date: string + end_date: string } /** @@ -78,19 +84,19 @@ export interface ModelStatsResponse { * @returns Model usage statistics */ export async function getModelStats(params?: ModelStatsParams): Promise { - const { data } = await apiClient.get('/admin/dashboard/models', { params }); - return data; + const { data } = await apiClient.get('/admin/dashboard/models', { params }) + return data } export interface ApiKeyTrendParams extends TrendParams { - limit?: number; + limit?: number } export interface ApiKeyTrendResponse { - trend: ApiKeyUsageTrendPoint[]; - start_date: string; - end_date: string; - granularity: string; + trend: ApiKeyUsageTrendPoint[] + start_date: string + end_date: string + granularity: string } /** @@ -98,20 +104,24 @@ export interface ApiKeyTrendResponse { * @param params - Query parameters for filtering * @returns API key usage trend data */ -export async function getApiKeyUsageTrend(params?: ApiKeyTrendParams): Promise { - const { data } = await apiClient.get('/admin/dashboard/api-keys-trend', { params }); - return data; +export async function getApiKeyUsageTrend( + params?: ApiKeyTrendParams +): Promise { + const { data } = await apiClient.get('/admin/dashboard/api-keys-trend', { + params + }) + return data } export interface UserTrendParams extends TrendParams { - limit?: number; + limit?: number } export interface UserTrendResponse { - trend: UserUsageTrendPoint[]; - start_date: string; - end_date: string; - granularity: string; + trend: UserUsageTrendPoint[] + start_date: string + end_date: string + granularity: string } /** @@ -120,18 +130,20 @@ export interface UserTrendResponse { * @returns User usage trend data */ export async function getUserUsageTrend(params?: UserTrendParams): Promise { - const { data } = await apiClient.get('/admin/dashboard/users-trend', { params }); - return data; + const { data } = await apiClient.get('/admin/dashboard/users-trend', { + params + }) + return data } export interface BatchUserUsageStats { - user_id: number; - today_actual_cost: number; - total_actual_cost: number; + user_id: number + today_actual_cost: number + total_actual_cost: number } export interface BatchUsersUsageResponse { - stats: Record; + stats: Record } /** @@ -141,19 +153,19 @@ export interface BatchUsersUsageResponse { */ export async function getBatchUsersUsage(userIds: number[]): Promise { const { data } = await apiClient.post('/admin/dashboard/users-usage', { - user_ids: userIds, - }); - return data; + user_ids: userIds + }) + return data } export interface BatchApiKeyUsageStats { - api_key_id: number; - today_actual_cost: number; - total_actual_cost: number; + api_key_id: number + today_actual_cost: number + total_actual_cost: number } export interface BatchApiKeysUsageResponse { - stats: Record; + stats: Record } /** @@ -161,11 +173,16 @@ export interface BatchApiKeysUsageResponse { * @param apiKeyIds - Array of API key IDs * @returns Usage stats map keyed by API key ID */ -export async function getBatchApiKeysUsage(apiKeyIds: number[]): Promise { - const { data } = await apiClient.post('/admin/dashboard/api-keys-usage', { - api_key_ids: apiKeyIds, - }); - return data; +export async function getBatchApiKeysUsage( + apiKeyIds: number[] +): Promise { + const { data } = await apiClient.post( + '/admin/dashboard/api-keys-usage', + { + api_key_ids: apiKeyIds + } + ) + return data } export const dashboardAPI = { @@ -176,7 +193,7 @@ export const dashboardAPI = { getApiKeyUsageTrend, getUserUsageTrend, getBatchUsersUsage, - getBatchApiKeysUsage, -}; + getBatchApiKeysUsage +} -export default dashboardAPI; +export default dashboardAPI diff --git a/frontend/src/api/admin/groups.ts b/frontend/src/api/admin/groups.ts index 1bc530ec..d48792e7 100644 --- a/frontend/src/api/admin/groups.ts +++ b/frontend/src/api/admin/groups.ts @@ -3,14 +3,14 @@ * Handles API key group management for administrators */ -import { apiClient } from '../client'; +import { apiClient } from '../client' import type { Group, GroupPlatform, CreateGroupRequest, UpdateGroupRequest, - PaginatedResponse, -} from '@/types'; + PaginatedResponse +} from '@/types' /** * List all groups with pagination @@ -23,19 +23,19 @@ export async function list( page: number = 1, pageSize: number = 20, filters?: { - platform?: GroupPlatform; - status?: 'active' | 'inactive'; - is_exclusive?: boolean; + platform?: GroupPlatform + status?: 'active' | 'inactive' + is_exclusive?: boolean } ): Promise> { const { data } = await apiClient.get>('/admin/groups', { params: { page, page_size: pageSize, - ...filters, - }, - }); - return data; + ...filters + } + }) + return data } /** @@ -46,8 +46,8 @@ export async function list( export async function getAll(platform?: GroupPlatform): Promise { const { data } = await apiClient.get('/admin/groups/all', { params: platform ? { platform } : undefined - }); - return data; + }) + return data } /** @@ -56,7 +56,7 @@ export async function getAll(platform?: GroupPlatform): Promise { * @returns List of groups for the specified platform */ export async function getByPlatform(platform: GroupPlatform): Promise { - return getAll(platform); + return getAll(platform) } /** @@ -65,8 +65,8 @@ export async function getByPlatform(platform: GroupPlatform): Promise { * @returns Group details */ export async function getById(id: number): Promise { - const { data } = await apiClient.get(`/admin/groups/${id}`); - return data; + const { data } = await apiClient.get(`/admin/groups/${id}`) + return data } /** @@ -75,8 +75,8 @@ export async function getById(id: number): Promise { * @returns Created group */ export async function create(groupData: CreateGroupRequest): Promise { - const { data } = await apiClient.post('/admin/groups', groupData); - return data; + const { data } = await apiClient.post('/admin/groups', groupData) + return data } /** @@ -86,8 +86,8 @@ export async function create(groupData: CreateGroupRequest): Promise { * @returns Updated group */ export async function update(id: number, updates: UpdateGroupRequest): Promise { - const { data } = await apiClient.put(`/admin/groups/${id}`, updates); - return data; + const { data } = await apiClient.put(`/admin/groups/${id}`, updates) + return data } /** @@ -96,8 +96,8 @@ export async function update(id: number, updates: UpdateGroupRequest): Promise { - const { data } = await apiClient.delete<{ message: string }>(`/admin/groups/${id}`); - return data; + const { data } = await apiClient.delete<{ message: string }>(`/admin/groups/${id}`) + return data } /** @@ -106,11 +106,8 @@ export async function deleteGroup(id: number): Promise<{ message: string }> { * @param status - New status * @returns Updated group */ -export async function toggleStatus( - id: number, - status: 'active' | 'inactive' -): Promise { - return update(id, { status }); +export async function toggleStatus(id: number, status: 'active' | 'inactive'): Promise { + return update(id, { status }) } /** @@ -119,18 +116,18 @@ export async function toggleStatus( * @returns Group usage statistics */ export async function getStats(id: number): Promise<{ - total_api_keys: number; - active_api_keys: number; - total_requests: number; - total_cost: number; + total_api_keys: number + active_api_keys: number + total_requests: number + total_cost: number }> { const { data } = await apiClient.get<{ - total_api_keys: number; - active_api_keys: number; - total_requests: number; - total_cost: number; - }>(`/admin/groups/${id}/stats`); - return data; + total_api_keys: number + active_api_keys: number + total_requests: number + total_cost: number + }>(`/admin/groups/${id}/stats`) + return data } /** @@ -145,13 +142,10 @@ export async function getGroupApiKeys( page: number = 1, pageSize: number = 20 ): Promise> { - const { data } = await apiClient.get>( - `/admin/groups/${id}/api-keys`, - { - params: { page, page_size: pageSize }, - } - ); - return data; + const { data } = await apiClient.get>(`/admin/groups/${id}/api-keys`, { + params: { page, page_size: pageSize } + }) + return data } export const groupsAPI = { @@ -164,7 +158,7 @@ export const groupsAPI = { delete: deleteGroup, toggleStatus, getStats, - getGroupApiKeys, -}; + getGroupApiKeys +} -export default groupsAPI; +export default groupsAPI diff --git a/frontend/src/api/admin/index.ts b/frontend/src/api/admin/index.ts index 4c2baea9..55477c87 100644 --- a/frontend/src/api/admin/index.ts +++ b/frontend/src/api/admin/index.ts @@ -3,16 +3,17 @@ * Centralized exports for all admin API modules */ -import dashboardAPI from './dashboard'; -import usersAPI from './users'; -import groupsAPI from './groups'; -import accountsAPI from './accounts'; -import proxiesAPI from './proxies'; -import redeemAPI from './redeem'; -import settingsAPI from './settings'; -import systemAPI from './system'; -import subscriptionsAPI from './subscriptions'; -import usageAPI from './usage'; +import dashboardAPI from './dashboard' +import usersAPI from './users' +import groupsAPI from './groups' +import accountsAPI from './accounts' +import proxiesAPI from './proxies' +import redeemAPI from './redeem' +import settingsAPI from './settings' +import systemAPI from './system' +import subscriptionsAPI from './subscriptions' +import usageAPI from './usage' +import geminiAPI from './gemini' /** * Unified admin API object for convenient access @@ -28,8 +29,21 @@ export const adminAPI = { system: systemAPI, subscriptions: subscriptionsAPI, usage: usageAPI, -}; + gemini: geminiAPI +} -export { dashboardAPI, usersAPI, groupsAPI, accountsAPI, proxiesAPI, redeemAPI, settingsAPI, systemAPI, subscriptionsAPI, usageAPI }; +export { + dashboardAPI, + usersAPI, + groupsAPI, + accountsAPI, + proxiesAPI, + redeemAPI, + settingsAPI, + systemAPI, + subscriptionsAPI, + usageAPI, + geminiAPI +} -export default adminAPI; +export default adminAPI diff --git a/frontend/src/api/admin/proxies.ts b/frontend/src/api/admin/proxies.ts index 0ec092a7..273e1f8a 100644 --- a/frontend/src/api/admin/proxies.ts +++ b/frontend/src/api/admin/proxies.ts @@ -3,13 +3,8 @@ * Handles proxy server management for administrators */ -import { apiClient } from '../client'; -import type { - Proxy, - CreateProxyRequest, - UpdateProxyRequest, - PaginatedResponse, -} from '@/types'; +import { apiClient } from '../client' +import type { Proxy, CreateProxyRequest, UpdateProxyRequest, PaginatedResponse } from '@/types' /** * List all proxies with pagination @@ -22,19 +17,19 @@ export async function list( page: number = 1, pageSize: number = 20, filters?: { - protocol?: string; - status?: 'active' | 'inactive'; - search?: string; + protocol?: string + status?: 'active' | 'inactive' + search?: string } ): Promise> { const { data } = await apiClient.get>('/admin/proxies', { params: { page, page_size: pageSize, - ...filters, - }, - }); - return data; + ...filters + } + }) + return data } /** @@ -42,8 +37,8 @@ export async function list( * @returns List of all active proxies */ export async function getAll(): Promise { - const { data } = await apiClient.get('/admin/proxies/all'); - return data; + const { data } = await apiClient.get('/admin/proxies/all') + return data } /** @@ -52,9 +47,9 @@ export async function getAll(): Promise { */ export async function getAllWithCount(): Promise { const { data } = await apiClient.get('/admin/proxies/all', { - params: { with_count: 'true' }, - }); - return data; + params: { with_count: 'true' } + }) + return data } /** @@ -63,8 +58,8 @@ export async function getAllWithCount(): Promise { * @returns Proxy details */ export async function getById(id: number): Promise { - const { data } = await apiClient.get(`/admin/proxies/${id}`); - return data; + const { data } = await apiClient.get(`/admin/proxies/${id}`) + return data } /** @@ -73,8 +68,8 @@ export async function getById(id: number): Promise { * @returns Created proxy */ export async function create(proxyData: CreateProxyRequest): Promise { - const { data } = await apiClient.post('/admin/proxies', proxyData); - return data; + const { data } = await apiClient.post('/admin/proxies', proxyData) + return data } /** @@ -84,8 +79,8 @@ export async function create(proxyData: CreateProxyRequest): Promise { * @returns Updated proxy */ export async function update(id: number, updates: UpdateProxyRequest): Promise { - const { data } = await apiClient.put(`/admin/proxies/${id}`, updates); - return data; + const { data } = await apiClient.put(`/admin/proxies/${id}`, updates) + return data } /** @@ -94,8 +89,8 @@ export async function update(id: number, updates: UpdateProxyRequest): Promise

{ - const { data } = await apiClient.delete<{ message: string }>(`/admin/proxies/${id}`); - return data; + const { data } = await apiClient.delete<{ message: string }>(`/admin/proxies/${id}`) + return data } /** @@ -104,11 +99,8 @@ export async function deleteProxy(id: number): Promise<{ message: string }> { * @param status - New status * @returns Updated proxy */ -export async function toggleStatus( - id: number, - status: 'active' | 'inactive' -): Promise { - return update(id, { status }); +export async function toggleStatus(id: number, status: 'active' | 'inactive'): Promise { + return update(id, { status }) } /** @@ -117,24 +109,24 @@ export async function toggleStatus( * @returns Test result with IP info */ export async function testProxy(id: number): Promise<{ - success: boolean; - message: string; - latency_ms?: number; - ip_address?: string; - city?: string; - region?: string; - country?: string; + success: boolean + message: string + latency_ms?: number + ip_address?: string + city?: string + region?: string + country?: string }> { const { data } = await apiClient.post<{ - success: boolean; - message: string; - latency_ms?: number; - ip_address?: string; - city?: string; - region?: string; - country?: string; - }>(`/admin/proxies/${id}/test`); - return data; + success: boolean + message: string + latency_ms?: number + ip_address?: string + city?: string + region?: string + country?: string + }>(`/admin/proxies/${id}/test`) + return data } /** @@ -143,20 +135,20 @@ export async function testProxy(id: number): Promise<{ * @returns Proxy usage statistics */ export async function getStats(id: number): Promise<{ - total_accounts: number; - active_accounts: number; - total_requests: number; - success_rate: number; - average_latency: number; + total_accounts: number + active_accounts: number + total_requests: number + success_rate: number + average_latency: number }> { const { data } = await apiClient.get<{ - total_accounts: number; - active_accounts: number; - total_requests: number; - success_rate: number; - average_latency: number; - }>(`/admin/proxies/${id}/stats`); - return data; + total_accounts: number + active_accounts: number + total_requests: number + success_rate: number + average_latency: number + }>(`/admin/proxies/${id}/stats`) + return data } /** @@ -165,10 +157,8 @@ export async function getStats(id: number): Promise<{ * @returns List of accounts using the proxy */ export async function getProxyAccounts(id: number): Promise> { - const { data } = await apiClient.get>( - `/admin/proxies/${id}/accounts` - ); - return data; + const { data } = await apiClient.get>(`/admin/proxies/${id}/accounts`) + return data } /** @@ -176,21 +166,23 @@ export async function getProxyAccounts(id: number): Promise): Promise<{ - created: number; - skipped: number; +export async function batchCreate( + proxies: Array<{ + protocol: string + host: string + port: number + username?: string + password?: string + }> +): Promise<{ + created: number + skipped: number }> { const { data } = await apiClient.post<{ - created: number; - skipped: number; - }>('/admin/proxies/batch', { proxies }); - return data; + created: number + skipped: number + }>('/admin/proxies/batch', { proxies }) + return data } export const proxiesAPI = { @@ -205,7 +197,7 @@ export const proxiesAPI = { testProxy, getStats, getProxyAccounts, - batchCreate, -}; + batchCreate +} -export default proxiesAPI; +export default proxiesAPI diff --git a/frontend/src/api/admin/redeem.ts b/frontend/src/api/admin/redeem.ts index d5af176b..738b1519 100644 --- a/frontend/src/api/admin/redeem.ts +++ b/frontend/src/api/admin/redeem.ts @@ -3,13 +3,13 @@ * Handles redeem code generation and management for administrators */ -import { apiClient } from '../client'; +import { apiClient } from '../client' import type { RedeemCode, GenerateRedeemCodesRequest, RedeemCodeType, - PaginatedResponse, -} from '@/types'; + PaginatedResponse +} from '@/types' /** * List all redeem codes with pagination @@ -22,19 +22,19 @@ export async function list( page: number = 1, pageSize: number = 20, filters?: { - type?: RedeemCodeType; - status?: 'active' | 'used' | 'expired' | 'unused'; - search?: string; + type?: RedeemCodeType + status?: 'active' | 'used' | 'expired' | 'unused' + search?: string } ): Promise> { const { data } = await apiClient.get>('/admin/redeem-codes', { params: { page, page_size: pageSize, - ...filters, - }, - }); - return data; + ...filters + } + }) + return data } /** @@ -43,8 +43,8 @@ export async function list( * @returns Redeem code details */ export async function getById(id: number): Promise { - const { data } = await apiClient.get(`/admin/redeem-codes/${id}`); - return data; + const { data } = await apiClient.get(`/admin/redeem-codes/${id}`) + return data } /** @@ -66,19 +66,19 @@ export async function generate( const payload: GenerateRedeemCodesRequest = { count, type, - value, - }; + value + } // 订阅类型专用字段 if (type === 'subscription') { - payload.group_id = groupId; + payload.group_id = groupId if (validityDays && validityDays > 0) { - payload.validity_days = validityDays; + payload.validity_days = validityDays } } - const { data } = await apiClient.post('/admin/redeem-codes/generate', payload); - return data; + const { data } = await apiClient.post('/admin/redeem-codes/generate', payload) + return data } /** @@ -87,8 +87,8 @@ export async function generate( * @returns Success confirmation */ export async function deleteCode(id: number): Promise<{ message: string }> { - const { data } = await apiClient.delete<{ message: string }>(`/admin/redeem-codes/${id}`); - return data; + const { data } = await apiClient.delete<{ message: string }>(`/admin/redeem-codes/${id}`) + return data } /** @@ -97,14 +97,14 @@ export async function deleteCode(id: number): Promise<{ message: string }> { * @returns Success confirmation */ export async function batchDelete(ids: number[]): Promise<{ - deleted: number; - message: string; + deleted: number + message: string }> { const { data } = await apiClient.post<{ - deleted: number; - message: string; - }>('/admin/redeem-codes/batch-delete', { ids }); - return data; + deleted: number + message: string + }>('/admin/redeem-codes/batch-delete', { ids }) + return data } /** @@ -113,8 +113,8 @@ export async function batchDelete(ids: number[]): Promise<{ * @returns Updated redeem code */ export async function expire(id: number): Promise { - const { data } = await apiClient.post(`/admin/redeem-codes/${id}/expire`); - return data; + const { data } = await apiClient.post(`/admin/redeem-codes/${id}/expire`) + return data } /** @@ -122,22 +122,22 @@ export async function expire(id: number): Promise { * @returns Statistics about redeem codes */ export async function getStats(): Promise<{ - total_codes: number; - active_codes: number; - used_codes: number; - expired_codes: number; - total_value_distributed: number; - by_type: Record; + total_codes: number + active_codes: number + used_codes: number + expired_codes: number + total_value_distributed: number + by_type: Record }> { const { data } = await apiClient.get<{ - total_codes: number; - active_codes: number; - used_codes: number; - expired_codes: number; - total_value_distributed: number; - by_type: Record; - }>('/admin/redeem-codes/stats'); - return data; + total_codes: number + active_codes: number + used_codes: number + expired_codes: number + total_value_distributed: number + by_type: Record + }>('/admin/redeem-codes/stats') + return data } /** @@ -146,14 +146,14 @@ export async function getStats(): Promise<{ * @returns CSV data as blob */ export async function exportCodes(filters?: { - type?: RedeemCodeType; - status?: 'active' | 'used' | 'expired'; + type?: RedeemCodeType + status?: 'active' | 'used' | 'expired' }): Promise { const response = await apiClient.get('/admin/redeem-codes/export', { params: filters, - responseType: 'blob', - }); - return response.data; + responseType: 'blob' + }) + return response.data } export const redeemAPI = { @@ -164,7 +164,7 @@ export const redeemAPI = { batchDelete, expire, getStats, - exportCodes, -}; + exportCodes +} -export default redeemAPI; +export default redeemAPI diff --git a/frontend/src/api/admin/settings.ts b/frontend/src/api/admin/settings.ts index 56a74ccc..cf5cba6d 100644 --- a/frontend/src/api/admin/settings.ts +++ b/frontend/src/api/admin/settings.ts @@ -3,37 +3,37 @@ * Handles system settings management for administrators */ -import { apiClient } from '../client'; +import { apiClient } from '../client' /** * System settings interface */ export interface SystemSettings { // Registration settings - registration_enabled: boolean; - email_verify_enabled: boolean; + registration_enabled: boolean + email_verify_enabled: boolean // Default settings - default_balance: number; - default_concurrency: number; + default_balance: number + default_concurrency: number // OEM settings - site_name: string; - site_logo: string; - site_subtitle: string; - api_base_url: string; - contact_info: string; - doc_url: string; + site_name: string + site_logo: string + site_subtitle: string + api_base_url: string + contact_info: string + doc_url: string // SMTP settings - smtp_host: string; - smtp_port: number; - smtp_username: string; - smtp_password: string; - smtp_from_email: string; - smtp_from_name: string; - smtp_use_tls: boolean; + smtp_host: string + smtp_port: number + smtp_username: string + smtp_password: string + smtp_from_email: string + smtp_from_name: string + smtp_use_tls: boolean // Cloudflare Turnstile settings - turnstile_enabled: boolean; - turnstile_site_key: string; - turnstile_secret_key: string; + turnstile_enabled: boolean + turnstile_site_key: string + turnstile_secret_key: string } /** @@ -41,8 +41,8 @@ export interface SystemSettings { * @returns System settings */ export async function getSettings(): Promise { - const { data } = await apiClient.get('/admin/settings'); - return data; + const { data } = await apiClient.get('/admin/settings') + return data } /** @@ -51,19 +51,19 @@ export async function getSettings(): Promise { * @returns Updated settings */ export async function updateSettings(settings: Partial): Promise { - const { data } = await apiClient.put('/admin/settings', settings); - return data; + const { data } = await apiClient.put('/admin/settings', settings) + return data } /** * Test SMTP connection request */ export interface TestSmtpRequest { - smtp_host: string; - smtp_port: number; - smtp_username: string; - smtp_password: string; - smtp_use_tls: boolean; + smtp_host: string + smtp_port: number + smtp_username: string + smtp_password: string + smtp_use_tls: boolean } /** @@ -72,22 +72,22 @@ export interface TestSmtpRequest { * @returns Test result message */ export async function testSmtpConnection(config: TestSmtpRequest): Promise<{ message: string }> { - const { data } = await apiClient.post<{ message: string }>('/admin/settings/test-smtp', config); - return data; + const { data } = await apiClient.post<{ message: string }>('/admin/settings/test-smtp', config) + return data } /** * Send test email request */ export interface SendTestEmailRequest { - email: string; - smtp_host: string; - smtp_port: number; - smtp_username: string; - smtp_password: string; - smtp_from_email: string; - smtp_from_name: string; - smtp_use_tls: boolean; + email: string + smtp_host: string + smtp_port: number + smtp_username: string + smtp_password: string + smtp_from_email: string + smtp_from_name: string + smtp_use_tls: boolean } /** @@ -96,16 +96,19 @@ export interface SendTestEmailRequest { * @returns Test result message */ export async function sendTestEmail(request: SendTestEmailRequest): Promise<{ message: string }> { - const { data } = await apiClient.post<{ message: string }>('/admin/settings/send-test-email', request); - return data; + const { data } = await apiClient.post<{ message: string }>( + '/admin/settings/send-test-email', + request + ) + return data } /** * Admin API Key status response */ export interface AdminApiKeyStatus { - exists: boolean; - masked_key: string; + exists: boolean + masked_key: string } /** @@ -113,8 +116,8 @@ export interface AdminApiKeyStatus { * @returns Status indicating if key exists and masked version */ export async function getAdminApiKey(): Promise { - const { data } = await apiClient.get('/admin/settings/admin-api-key'); - return data; + const { data } = await apiClient.get('/admin/settings/admin-api-key') + return data } /** @@ -122,8 +125,8 @@ export async function getAdminApiKey(): Promise { * @returns The new full API key (only shown once) */ export async function regenerateAdminApiKey(): Promise<{ key: string }> { - const { data } = await apiClient.post<{ key: string }>('/admin/settings/admin-api-key/regenerate'); - return data; + const { data } = await apiClient.post<{ key: string }>('/admin/settings/admin-api-key/regenerate') + return data } /** @@ -131,8 +134,8 @@ export async function regenerateAdminApiKey(): Promise<{ key: string }> { * @returns Success message */ export async function deleteAdminApiKey(): Promise<{ message: string }> { - const { data } = await apiClient.delete<{ message: string }>('/admin/settings/admin-api-key'); - return data; + const { data } = await apiClient.delete<{ message: string }>('/admin/settings/admin-api-key') + return data } export const settingsAPI = { @@ -142,7 +145,7 @@ export const settingsAPI = { sendTestEmail, getAdminApiKey, regenerateAdminApiKey, - deleteAdminApiKey, -}; + deleteAdminApiKey +} -export default settingsAPI; +export default settingsAPI diff --git a/frontend/src/api/admin/subscriptions.ts b/frontend/src/api/admin/subscriptions.ts index 5d000b9a..ceabd4ee 100644 --- a/frontend/src/api/admin/subscriptions.ts +++ b/frontend/src/api/admin/subscriptions.ts @@ -3,15 +3,15 @@ * Handles user subscription management for administrators */ -import { apiClient } from '../client'; +import { apiClient } from '../client' import type { UserSubscription, SubscriptionProgress, AssignSubscriptionRequest, BulkAssignSubscriptionRequest, ExtendSubscriptionRequest, - PaginatedResponse, -} from '@/types'; + PaginatedResponse +} from '@/types' /** * List all subscriptions with pagination @@ -24,19 +24,22 @@ export async function list( page: number = 1, pageSize: number = 20, filters?: { - status?: 'active' | 'expired' | 'revoked'; - user_id?: number; - group_id?: number; + status?: 'active' | 'expired' | 'revoked' + user_id?: number + group_id?: number } ): Promise> { - const { data } = await apiClient.get>('/admin/subscriptions', { - params: { - page, - page_size: pageSize, - ...filters, - }, - }); - return data; + const { data } = await apiClient.get>( + '/admin/subscriptions', + { + params: { + page, + page_size: pageSize, + ...filters + } + } + ) + return data } /** @@ -45,8 +48,8 @@ export async function list( * @returns Subscription details */ export async function getById(id: number): Promise { - const { data } = await apiClient.get(`/admin/subscriptions/${id}`); - return data; + const { data } = await apiClient.get(`/admin/subscriptions/${id}`) + return data } /** @@ -55,8 +58,8 @@ export async function getById(id: number): Promise { * @returns Subscription progress with usage stats */ export async function getProgress(id: number): Promise { - const { data } = await apiClient.get(`/admin/subscriptions/${id}/progress`); - return data; + const { data } = await apiClient.get(`/admin/subscriptions/${id}/progress`) + return data } /** @@ -65,8 +68,8 @@ export async function getProgress(id: number): Promise { * @returns Created subscription */ export async function assign(request: AssignSubscriptionRequest): Promise { - const { data } = await apiClient.post('/admin/subscriptions/assign', request); - return data; + const { data } = await apiClient.post('/admin/subscriptions/assign', request) + return data } /** @@ -74,9 +77,14 @@ export async function assign(request: AssignSubscriptionRequest): Promise { - const { data } = await apiClient.post('/admin/subscriptions/bulk-assign', request); - return data; +export async function bulkAssign( + request: BulkAssignSubscriptionRequest +): Promise { + const { data } = await apiClient.post( + '/admin/subscriptions/bulk-assign', + request + ) + return data } /** @@ -85,9 +93,15 @@ export async function bulkAssign(request: BulkAssignSubscriptionRequest): Promis * @param request - Extension request with days * @returns Updated subscription */ -export async function extend(id: number, request: ExtendSubscriptionRequest): Promise { - const { data } = await apiClient.post(`/admin/subscriptions/${id}/extend`, request); - return data; +export async function extend( + id: number, + request: ExtendSubscriptionRequest +): Promise { + const { data } = await apiClient.post( + `/admin/subscriptions/${id}/extend`, + request + ) + return data } /** @@ -96,8 +110,8 @@ export async function extend(id: number, request: ExtendSubscriptionRequest): Pr * @returns Success confirmation */ export async function revoke(id: number): Promise<{ message: string }> { - const { data } = await apiClient.delete<{ message: string }>(`/admin/subscriptions/${id}`); - return data; + const { data } = await apiClient.delete<{ message: string }>(`/admin/subscriptions/${id}`) + return data } /** @@ -115,10 +129,10 @@ export async function listByGroup( const { data } = await apiClient.get>( `/admin/groups/${groupId}/subscriptions`, { - params: { page, page_size: pageSize }, + params: { page, page_size: pageSize } } - ); - return data; + ) + return data } /** @@ -136,10 +150,10 @@ export async function listByUser( const { data } = await apiClient.get>( `/admin/users/${userId}/subscriptions`, { - params: { page, page_size: pageSize }, + params: { page, page_size: pageSize } } - ); - return data; + ) + return data } export const subscriptionsAPI = { @@ -151,7 +165,7 @@ export const subscriptionsAPI = { extend, revoke, listByGroup, - listByUser, -}; + listByUser +} -export default subscriptionsAPI; +export default subscriptionsAPI diff --git a/frontend/src/api/admin/system.ts b/frontend/src/api/admin/system.ts index cb3e39a5..9ea312d5 100644 --- a/frontend/src/api/admin/system.ts +++ b/frontend/src/api/admin/system.ts @@ -2,31 +2,31 @@ * System API endpoints for admin operations */ -import { apiClient } from '../client'; +import { apiClient } from '../client' export interface ReleaseInfo { - name: string; - body: string; - published_at: string; - html_url: string; + name: string + body: string + published_at: string + html_url: string } export interface VersionInfo { - current_version: string; - latest_version: string; - has_update: boolean; - release_info?: ReleaseInfo; - cached: boolean; - warning?: string; - build_type: string; // "source" for manual builds, "release" for CI builds + current_version: string + latest_version: string + has_update: boolean + release_info?: ReleaseInfo + cached: boolean + warning?: string + build_type: string // "source" for manual builds, "release" for CI builds } /** * Get current version */ export async function getVersion(): Promise<{ version: string }> { - const { data } = await apiClient.get<{ version: string }>('/admin/system/version'); - return data; + const { data } = await apiClient.get<{ version: string }>('/admin/system/version') + return data } /** @@ -35,14 +35,14 @@ export async function getVersion(): Promise<{ version: string }> { */ export async function checkUpdates(force = false): Promise { const { data } = await apiClient.get('/admin/system/check-updates', { - params: force ? { force: 'true' } : undefined, - }); - return data; + params: force ? { force: 'true' } : undefined + }) + return data } export interface UpdateResult { - message: string; - need_restart: boolean; + message: string + need_restart: boolean } /** @@ -50,24 +50,24 @@ export interface UpdateResult { * Downloads and applies the latest version */ export async function performUpdate(): Promise { - const { data } = await apiClient.post('/admin/system/update'); - return data; + const { data } = await apiClient.post('/admin/system/update') + return data } /** * Rollback to previous version */ export async function rollback(): Promise { - const { data } = await apiClient.post('/admin/system/rollback'); - return data; + const { data } = await apiClient.post('/admin/system/rollback') + return data } /** * Restart the service */ export async function restartService(): Promise<{ message: string }> { - const { data } = await apiClient.post<{ message: string }>('/admin/system/restart'); - return data; + const { data } = await apiClient.post<{ message: string }>('/admin/system/restart') + return data } export const systemAPI = { @@ -75,7 +75,7 @@ export const systemAPI = { checkUpdates, performUpdate, rollback, - restartService, -}; + restartService +} -export default systemAPI; +export default systemAPI diff --git a/frontend/src/api/admin/usage.ts b/frontend/src/api/admin/usage.ts index 2c5e800e..5d4896d3 100644 --- a/frontend/src/api/admin/usage.ts +++ b/frontend/src/api/admin/usage.ts @@ -3,39 +3,35 @@ * Handles admin-level usage logs and statistics retrieval */ -import { apiClient } from '../client'; -import type { - UsageLog, - UsageQueryParams, - PaginatedResponse, -} from '@/types'; +import { apiClient } from '../client' +import type { UsageLog, UsageQueryParams, PaginatedResponse } from '@/types' // ==================== Types ==================== export interface AdminUsageStatsResponse { - total_requests: number; - total_input_tokens: number; - total_output_tokens: number; - total_cache_tokens: number; - total_tokens: number; - total_cost: number; - total_actual_cost: number; - average_duration_ms: number; + total_requests: number + total_input_tokens: number + total_output_tokens: number + total_cache_tokens: number + total_tokens: number + total_cost: number + total_actual_cost: number + average_duration_ms: number } export interface SimpleUser { - id: number; - email: string; + id: number + email: string } export interface SimpleApiKey { - id: number; - name: string; - user_id: number; + id: number + name: string + user_id: number } export interface AdminUsageQueryParams extends UsageQueryParams { - user_id?: number; + user_id?: number } // ==================== API Functions ==================== @@ -47,9 +43,9 @@ export interface AdminUsageQueryParams extends UsageQueryParams { */ export async function list(params: AdminUsageQueryParams): Promise> { const { data } = await apiClient.get>('/admin/usage', { - params, - }); - return data; + params + }) + return data } /** @@ -58,16 +54,16 @@ export async function list(params: AdminUsageQueryParams): Promise { const { data } = await apiClient.get('/admin/usage/stats', { - params, - }); - return data; + params + }) + return data } /** @@ -77,9 +73,9 @@ export async function getStats(params: { */ export async function searchUsers(keyword: string): Promise { const { data } = await apiClient.get('/admin/usage/search-users', { - params: { q: keyword }, - }); - return data; + params: { q: keyword } + }) + return data } /** @@ -89,24 +85,24 @@ export async function searchUsers(keyword: string): Promise { * @returns List of matching API keys (max 30) */ export async function searchApiKeys(userId?: number, keyword?: string): Promise { - const params: Record = {}; + const params: Record = {} if (userId !== undefined) { - params.user_id = userId; + params.user_id = userId } if (keyword) { - params.q = keyword; + params.q = keyword } const { data } = await apiClient.get('/admin/usage/search-api-keys', { - params, - }); - return data; + params + }) + return data } export const adminUsageAPI = { list, getStats, searchUsers, - searchApiKeys, -}; + searchApiKeys +} -export default adminUsageAPI; +export default adminUsageAPI diff --git a/frontend/src/api/admin/users.ts b/frontend/src/api/admin/users.ts index 8aa81775..9ba58e8b 100644 --- a/frontend/src/api/admin/users.ts +++ b/frontend/src/api/admin/users.ts @@ -3,8 +3,8 @@ * Handles user management for administrators */ -import { apiClient } from '../client'; -import type { User, UpdateUserRequest, PaginatedResponse } from '@/types'; +import { apiClient } from '../client' +import type { User, UpdateUserRequest, PaginatedResponse } from '@/types' /** * List all users with pagination @@ -17,19 +17,19 @@ export async function list( page: number = 1, pageSize: number = 20, filters?: { - status?: 'active' | 'disabled'; - role?: 'admin' | 'user'; - search?: string; + status?: 'active' | 'disabled' + role?: 'admin' | 'user' + search?: string } ): Promise> { const { data } = await apiClient.get>('/admin/users', { params: { page, page_size: pageSize, - ...filters, - }, - }); - return data; + ...filters + } + }) + return data } /** @@ -38,8 +38,8 @@ export async function list( * @returns User details */ export async function getById(id: number): Promise { - const { data } = await apiClient.get(`/admin/users/${id}`); - return data; + const { data } = await apiClient.get(`/admin/users/${id}`) + return data } /** @@ -48,14 +48,14 @@ export async function getById(id: number): Promise { * @returns Created user */ export async function create(userData: { - email: string; - password: string; - balance?: number; - concurrency?: number; - allowed_groups?: number[] | null; + email: string + password: string + balance?: number + concurrency?: number + allowed_groups?: number[] | null }): Promise { - const { data } = await apiClient.post('/admin/users', userData); - return data; + const { data } = await apiClient.post('/admin/users', userData) + return data } /** @@ -65,8 +65,8 @@ export async function create(userData: { * @returns Updated user */ export async function update(id: number, updates: UpdateUserRequest): Promise { - const { data } = await apiClient.put(`/admin/users/${id}`, updates); - return data; + const { data } = await apiClient.put(`/admin/users/${id}`, updates) + return data } /** @@ -75,8 +75,8 @@ export async function update(id: number, updates: UpdateUserRequest): Promise { - const { data } = await apiClient.delete<{ message: string }>(`/admin/users/${id}`); - return data; + const { data } = await apiClient.delete<{ message: string }>(`/admin/users/${id}`) + return data } /** @@ -96,9 +96,9 @@ export async function updateBalance( const { data } = await apiClient.post(`/admin/users/${id}/balance`, { balance, operation, - notes: notes || '', - }); - return data; + notes: notes || '' + }) + return data } /** @@ -108,7 +108,7 @@ export async function updateBalance( * @returns Updated user */ export async function updateConcurrency(id: number, concurrency: number): Promise { - return update(id, { concurrency }); + return update(id, { concurrency }) } /** @@ -118,7 +118,7 @@ export async function updateConcurrency(id: number, concurrency: number): Promis * @returns Updated user */ export async function toggleStatus(id: number, status: 'active' | 'disabled'): Promise { - return update(id, { status }); + return update(id, { status }) } /** @@ -127,8 +127,8 @@ export async function toggleStatus(id: number, status: 'active' | 'disabled'): P * @returns List of user's API keys */ export async function getUserApiKeys(id: number): Promise> { - const { data } = await apiClient.get>(`/admin/users/${id}/api-keys`); - return data; + const { data } = await apiClient.get>(`/admin/users/${id}/api-keys`) + return data } /** @@ -141,18 +141,18 @@ export async function getUserUsageStats( id: number, period: string = 'month' ): Promise<{ - total_requests: number; - total_cost: number; - total_tokens: number; + total_requests: number + total_cost: number + total_tokens: number }> { const { data } = await apiClient.get<{ - total_requests: number; - total_cost: number; - total_tokens: number; + total_requests: number + total_cost: number + total_tokens: number }>(`/admin/users/${id}/usage`, { - params: { period }, - }); - return data; + params: { period } + }) + return data } export const usersAPI = { @@ -165,7 +165,7 @@ export const usersAPI = { updateConcurrency, toggleStatus, getUserApiKeys, - getUserUsageStats, -}; + getUserUsageStats +} -export default usersAPI; +export default usersAPI diff --git a/frontend/src/api/auth.ts b/frontend/src/api/auth.ts index 9d8c1597..ccac8a77 100644 --- a/frontend/src/api/auth.ts +++ b/frontend/src/api/auth.ts @@ -3,29 +3,37 @@ * Handles user login, registration, and logout operations */ -import { apiClient } from './client'; -import type { LoginRequest, RegisterRequest, AuthResponse, User, SendVerifyCodeRequest, SendVerifyCodeResponse, PublicSettings } from '@/types'; +import { apiClient } from './client' +import type { + LoginRequest, + RegisterRequest, + AuthResponse, + User, + SendVerifyCodeRequest, + SendVerifyCodeResponse, + PublicSettings +} from '@/types' /** * Store authentication token in localStorage */ export function setAuthToken(token: string): void { - localStorage.setItem('auth_token', token); + localStorage.setItem('auth_token', token) } /** * Get authentication token from localStorage */ export function getAuthToken(): string | null { - return localStorage.getItem('auth_token'); + return localStorage.getItem('auth_token') } /** * Clear authentication token from localStorage */ export function clearAuthToken(): void { - localStorage.removeItem('auth_token'); - localStorage.removeItem('auth_user'); + localStorage.removeItem('auth_token') + localStorage.removeItem('auth_user') } /** @@ -34,13 +42,13 @@ export function clearAuthToken(): void { * @returns Authentication response with token and user data */ export async function login(credentials: LoginRequest): Promise { - const { data } = await apiClient.post('/auth/login', credentials); + const { data } = await apiClient.post('/auth/login', credentials) // Store token and user data - setAuthToken(data.access_token); - localStorage.setItem('auth_user', JSON.stringify(data.user)); + setAuthToken(data.access_token) + localStorage.setItem('auth_user', JSON.stringify(data.user)) - return data; + return data } /** @@ -49,13 +57,13 @@ export async function login(credentials: LoginRequest): Promise { * @returns Authentication response with token and user data */ export async function register(userData: RegisterRequest): Promise { - const { data } = await apiClient.post('/auth/register', userData); + const { data } = await apiClient.post('/auth/register', userData) // Store token and user data - setAuthToken(data.access_token); - localStorage.setItem('auth_user', JSON.stringify(data.user)); + setAuthToken(data.access_token) + localStorage.setItem('auth_user', JSON.stringify(data.user)) - return data; + return data } /** @@ -63,8 +71,8 @@ export async function register(userData: RegisterRequest): Promise * @returns User profile data */ export async function getCurrentUser(): Promise { - const { data } = await apiClient.get('/auth/me'); - return data; + const { data } = await apiClient.get('/auth/me') + return data } /** @@ -72,7 +80,7 @@ export async function getCurrentUser(): Promise { * Clears authentication token and user data from localStorage */ export function logout(): void { - clearAuthToken(); + clearAuthToken() // Optionally redirect to login page // window.location.href = '/login'; } @@ -82,7 +90,7 @@ export function logout(): void { * @returns True if user has valid token */ export function isAuthenticated(): boolean { - return getAuthToken() !== null; + return getAuthToken() !== null } /** @@ -90,8 +98,8 @@ export function isAuthenticated(): boolean { * @returns Public settings including registration and Turnstile config */ export async function getPublicSettings(): Promise { - const { data } = await apiClient.get('/settings/public'); - return data; + const { data } = await apiClient.get('/settings/public') + return data } /** @@ -99,9 +107,11 @@ export async function getPublicSettings(): Promise { * @param request - Email and optional Turnstile token * @returns Response with countdown seconds */ -export async function sendVerifyCode(request: SendVerifyCodeRequest): Promise { - const { data } = await apiClient.post('/auth/send-verify-code', request); - return data; +export async function sendVerifyCode( + request: SendVerifyCodeRequest +): Promise { + const { data } = await apiClient.post('/auth/send-verify-code', request) + return data } export const authAPI = { @@ -114,7 +124,7 @@ export const authAPI = { getAuthToken, clearAuthToken, getPublicSettings, - sendVerifyCode, -}; + sendVerifyCode +} -export default authAPI; +export default authAPI diff --git a/frontend/src/api/client.ts b/frontend/src/api/client.ts index 4847b22a..3aac41a6 100644 --- a/frontend/src/api/client.ts +++ b/frontend/src/api/client.ts @@ -3,70 +3,70 @@ * Base client with interceptors for authentication and error handling */ -import axios, { AxiosInstance, AxiosError, InternalAxiosRequestConfig } from 'axios'; -import type { ApiResponse } from '@/types'; +import axios, { AxiosInstance, AxiosError, InternalAxiosRequestConfig } from 'axios' +import type { ApiResponse } from '@/types' // ==================== Axios Instance Configuration ==================== -const API_BASE_URL = import.meta.env.VITE_API_BASE_URL || '/api/v1'; +const API_BASE_URL = import.meta.env.VITE_API_BASE_URL || '/api/v1' export const apiClient: AxiosInstance = axios.create({ baseURL: API_BASE_URL, timeout: 30000, headers: { - 'Content-Type': 'application/json', - }, -}); + 'Content-Type': 'application/json' + } +}) // ==================== Request Interceptor ==================== apiClient.interceptors.request.use( (config: InternalAxiosRequestConfig) => { // Attach token from localStorage - const token = localStorage.getItem('auth_token'); + const token = localStorage.getItem('auth_token') if (token && config.headers) { - config.headers.Authorization = `Bearer ${token}`; + config.headers.Authorization = `Bearer ${token}` } - return config; + return config }, (error) => { - return Promise.reject(error); + return Promise.reject(error) } -); +) // ==================== Response Interceptor ==================== apiClient.interceptors.response.use( (response) => { // Unwrap standard API response format { code, message, data } - const apiResponse = response.data as ApiResponse; + const apiResponse = response.data as ApiResponse if (apiResponse && typeof apiResponse === 'object' && 'code' in apiResponse) { if (apiResponse.code === 0) { // Success - return the data portion - response.data = apiResponse.data; + response.data = apiResponse.data } else { // API error return Promise.reject({ status: response.status, code: apiResponse.code, - message: apiResponse.message || 'Unknown error', - }); + message: apiResponse.message || 'Unknown error' + }) } } - return response; + return response }, (error: AxiosError>) => { // Handle common errors if (error.response) { - const { status, data } = error.response; + const { status, data } = error.response // 401: Unauthorized - clear token and redirect to login if (status === 401) { - localStorage.removeItem('auth_token'); - localStorage.removeItem('auth_user'); + localStorage.removeItem('auth_token') + localStorage.removeItem('auth_user') // Only redirect if not already on login page if (!window.location.pathname.includes('/login')) { - window.location.href = '/login'; + window.location.href = '/login' } } @@ -74,16 +74,16 @@ apiClient.interceptors.response.use( return Promise.reject({ status, code: data?.code, - message: data?.message || error.message, - }); + message: data?.message || error.message + }) } // Network error return Promise.reject({ status: 0, - message: 'Network error. Please check your connection.', - }); + message: 'Network error. Please check your connection.' + }) } -); +) -export default apiClient; +export default apiClient diff --git a/frontend/src/api/groups.ts b/frontend/src/api/groups.ts index 490c03cd..0f366d51 100644 --- a/frontend/src/api/groups.ts +++ b/frontend/src/api/groups.ts @@ -3,8 +3,8 @@ * Handles group-related operations for regular users */ -import { apiClient } from './client'; -import type { Group } from '@/types'; +import { apiClient } from './client' +import type { Group } from '@/types' /** * Get available groups that the current user can bind to API keys @@ -14,12 +14,12 @@ import type { Group } from '@/types'; * @returns List of available groups */ export async function getAvailable(): Promise { - const { data } = await apiClient.get('/groups/available'); - return data; + const { data } = await apiClient.get('/groups/available') + return data } export const userGroupsAPI = { - getAvailable, -}; + getAvailable +} -export default userGroupsAPI; +export default userGroupsAPI diff --git a/frontend/src/api/index.ts b/frontend/src/api/index.ts index fd3bc414..50b14c4c 100644 --- a/frontend/src/api/index.ts +++ b/frontend/src/api/index.ts @@ -4,20 +4,20 @@ */ // Re-export the HTTP client -export { apiClient } from './client'; +export { apiClient } from './client' // Auth API -export { authAPI } from './auth'; +export { authAPI } from './auth' // User APIs -export { keysAPI } from './keys'; -export { usageAPI } from './usage'; -export { userAPI } from './user'; -export { redeemAPI, type RedeemHistoryItem } from './redeem'; -export { userGroupsAPI } from './groups'; +export { keysAPI } from './keys' +export { usageAPI } from './usage' +export { userAPI } from './user' +export { redeemAPI, type RedeemHistoryItem } from './redeem' +export { userGroupsAPI } from './groups' // Admin APIs -export { adminAPI } from './admin'; +export { adminAPI } from './admin' // Default export -export { default } from './client'; +export { default } from './client' diff --git a/frontend/src/api/keys.ts b/frontend/src/api/keys.ts index 754c06a0..5bedbf2c 100644 --- a/frontend/src/api/keys.ts +++ b/frontend/src/api/keys.ts @@ -3,13 +3,8 @@ * Handles CRUD operations for user API keys */ -import { apiClient } from './client'; -import type { - ApiKey, - CreateApiKeyRequest, - UpdateApiKeyRequest, - PaginatedResponse, -} from '@/types'; +import { apiClient } from './client' +import type { ApiKey, CreateApiKeyRequest, UpdateApiKeyRequest, PaginatedResponse } from '@/types' /** * List all API keys for current user @@ -17,11 +12,14 @@ import type { * @param pageSize - Items per page (default: 10) * @returns Paginated list of API keys */ -export async function list(page: number = 1, pageSize: number = 10): Promise> { +export async function list( + page: number = 1, + pageSize: number = 10 +): Promise> { const { data } = await apiClient.get>('/keys', { - params: { page, page_size: pageSize }, - }); - return data; + params: { page, page_size: pageSize } + }) + return data } /** @@ -30,8 +28,8 @@ export async function list(page: number = 1, pageSize: number = 10): Promise { - const { data } = await apiClient.get(`/keys/${id}`); - return data; + const { data } = await apiClient.get(`/keys/${id}`) + return data } /** @@ -41,17 +39,21 @@ export async function getById(id: number): Promise { * @param customKey - Optional custom key value * @returns Created API key */ -export async function create(name: string, groupId?: number | null, customKey?: string): Promise { - const payload: CreateApiKeyRequest = { name }; +export async function create( + name: string, + groupId?: number | null, + customKey?: string +): Promise { + const payload: CreateApiKeyRequest = { name } if (groupId !== undefined) { - payload.group_id = groupId; + payload.group_id = groupId } if (customKey) { - payload.custom_key = customKey; + payload.custom_key = customKey } - const { data } = await apiClient.post('/keys', payload); - return data; + const { data } = await apiClient.post('/keys', payload) + return data } /** @@ -61,8 +63,8 @@ export async function create(name: string, groupId?: number | null, customKey?: * @returns Updated API key */ export async function update(id: number, updates: UpdateApiKeyRequest): Promise { - const { data } = await apiClient.put(`/keys/${id}`, updates); - return data; + const { data } = await apiClient.put(`/keys/${id}`, updates) + return data } /** @@ -71,8 +73,8 @@ export async function update(id: number, updates: UpdateApiKeyRequest): Promise< * @returns Success confirmation */ export async function deleteKey(id: number): Promise<{ message: string }> { - const { data } = await apiClient.delete<{ message: string }>(`/keys/${id}`); - return data; + const { data } = await apiClient.delete<{ message: string }>(`/keys/${id}`) + return data } /** @@ -81,11 +83,8 @@ export async function deleteKey(id: number): Promise<{ message: string }> { * @param status - New status * @returns Updated API key */ -export async function toggleStatus( - id: number, - status: 'active' | 'inactive' -): Promise { - return update(id, { status }); +export async function toggleStatus(id: number, status: 'active' | 'inactive'): Promise { + return update(id, { status }) } export const keysAPI = { @@ -94,7 +93,7 @@ export const keysAPI = { create, update, delete: deleteKey, - toggleStatus, -}; + toggleStatus +} -export default keysAPI; +export default keysAPI diff --git a/frontend/src/api/redeem.ts b/frontend/src/api/redeem.ts index 2b127f1e..9e1c7d94 100644 --- a/frontend/src/api/redeem.ts +++ b/frontend/src/api/redeem.ts @@ -3,24 +3,24 @@ * Handles redeem code redemption for users */ -import { apiClient } from './client'; -import type { RedeemCodeRequest } from '@/types'; +import { apiClient } from './client' +import type { RedeemCodeRequest } from '@/types' export interface RedeemHistoryItem { - id: number; - code: string; - type: string; - value: number; - status: string; - used_at: string; - created_at: string; + id: number + code: string + type: string + value: number + status: string + used_at: string + created_at: string // 订阅类型专用字段 - group_id?: number; - validity_days?: number; + group_id?: number + validity_days?: number group?: { - id: number; - name: string; - }; + id: number + name: string + } } /** @@ -29,23 +29,23 @@ export interface RedeemHistoryItem { * @returns Redemption result with updated balance or concurrency */ export async function redeem(code: string): Promise<{ - message: string; - type: string; - value: number; - new_balance?: number; - new_concurrency?: number; + message: string + type: string + value: number + new_balance?: number + new_concurrency?: number }> { - const payload: RedeemCodeRequest = { code }; + const payload: RedeemCodeRequest = { code } const { data } = await apiClient.post<{ - message: string; - type: string; - value: number; - new_balance?: number; - new_concurrency?: number; - }>('/redeem', payload); + message: string + type: string + value: number + new_balance?: number + new_concurrency?: number + }>('/redeem', payload) - return data; + return data } /** @@ -53,13 +53,13 @@ export async function redeem(code: string): Promise<{ * @returns List of redeemed codes */ export async function getHistory(): Promise { - const { data } = await apiClient.get('/redeem/history'); - return data; + const { data } = await apiClient.get('/redeem/history') + return data } export const redeemAPI = { redeem, - getHistory, -}; + getHistory +} -export default redeemAPI; +export default redeemAPI diff --git a/frontend/src/api/setup.ts b/frontend/src/api/setup.ts index ecf7a84f..8b744590 100644 --- a/frontend/src/api/setup.ts +++ b/frontend/src/api/setup.ts @@ -1,87 +1,87 @@ /** * Setup API endpoints */ -import axios from 'axios'; +import axios from 'axios' // Create a separate client for setup endpoints (not under /api/v1) const setupClient = axios.create({ baseURL: '', timeout: 30000, headers: { - 'Content-Type': 'application/json', - }, -}); + 'Content-Type': 'application/json' + } +}) export interface SetupStatus { - needs_setup: boolean; - step: string; + needs_setup: boolean + step: string } export interface DatabaseConfig { - host: string; - port: number; - user: string; - password: string; - dbname: string; - sslmode: string; + host: string + port: number + user: string + password: string + dbname: string + sslmode: string } export interface RedisConfig { - host: string; - port: number; - password: string; - db: number; + host: string + port: number + password: string + db: number } export interface AdminConfig { - email: string; - password: string; + email: string + password: string } export interface ServerConfig { - host: string; - port: number; - mode: string; + host: string + port: number + mode: string } export interface InstallRequest { - database: DatabaseConfig; - redis: RedisConfig; - admin: AdminConfig; - server: ServerConfig; + database: DatabaseConfig + redis: RedisConfig + admin: AdminConfig + server: ServerConfig } export interface InstallResponse { - message: string; - restart: boolean; + message: string + restart: boolean } /** * Get setup status */ export async function getSetupStatus(): Promise { - const response = await setupClient.get('/setup/status'); - return response.data.data; + const response = await setupClient.get('/setup/status') + return response.data.data } /** * Test database connection */ export async function testDatabase(config: DatabaseConfig): Promise { - await setupClient.post('/setup/test-db', config); + await setupClient.post('/setup/test-db', config) } /** * Test Redis connection */ export async function testRedis(config: RedisConfig): Promise { - await setupClient.post('/setup/test-redis', config); + await setupClient.post('/setup/test-redis', config) } /** * Perform installation */ export async function install(config: InstallRequest): Promise { - const response = await setupClient.post('/setup/install', config); - return response.data.data; + const response = await setupClient.post('/setup/install', config) + return response.data.data } diff --git a/frontend/src/api/subscriptions.ts b/frontend/src/api/subscriptions.ts index 3725aa7a..a614a425 100644 --- a/frontend/src/api/subscriptions.ts +++ b/frontend/src/api/subscriptions.ts @@ -3,64 +3,68 @@ * API for regular users to view their own subscriptions and progress */ -import { apiClient } from './client'; -import type { UserSubscription, SubscriptionProgress } from '@/types'; +import { apiClient } from './client' +import type { UserSubscription, SubscriptionProgress } from '@/types' /** * Subscription summary for user dashboard */ export interface SubscriptionSummary { - active_count: number; + active_count: number subscriptions: Array<{ - id: number; - group_name: string; - status: string; - daily_progress: number | null; - weekly_progress: number | null; - monthly_progress: number | null; - expires_at: string | null; - days_remaining: number | null; - }>; + id: number + group_name: string + status: string + daily_progress: number | null + weekly_progress: number | null + monthly_progress: number | null + expires_at: string | null + days_remaining: number | null + }> } /** * Get list of current user's subscriptions */ export async function getMySubscriptions(): Promise { - const response = await apiClient.get('/subscriptions'); - return response.data; + const response = await apiClient.get('/subscriptions') + return response.data } /** * Get current user's active subscriptions */ export async function getActiveSubscriptions(): Promise { - const response = await apiClient.get('/subscriptions/active'); - return response.data; + const response = await apiClient.get('/subscriptions/active') + return response.data } /** * Get progress for all user's active subscriptions */ export async function getSubscriptionsProgress(): Promise { - const response = await apiClient.get('/subscriptions/progress'); - return response.data; + const response = await apiClient.get('/subscriptions/progress') + return response.data } /** * Get subscription summary for dashboard display */ export async function getSubscriptionSummary(): Promise { - const response = await apiClient.get('/subscriptions/summary'); - return response.data; + const response = await apiClient.get('/subscriptions/summary') + return response.data } /** * Get progress for a specific subscription */ -export async function getSubscriptionProgress(subscriptionId: number): Promise { - const response = await apiClient.get(`/subscriptions/${subscriptionId}/progress`); - return response.data; +export async function getSubscriptionProgress( + subscriptionId: number +): Promise { + const response = await apiClient.get( + `/subscriptions/${subscriptionId}/progress` + ) + return response.data } export default { @@ -68,5 +72,5 @@ export default { getActiveSubscriptions, getSubscriptionsProgress, getSubscriptionSummary, - getSubscriptionProgress, -}; + getSubscriptionProgress +} diff --git a/frontend/src/api/usage.ts b/frontend/src/api/usage.ts index 409c3565..20581603 100644 --- a/frontend/src/api/usage.ts +++ b/frontend/src/api/usage.ts @@ -3,59 +3,59 @@ * Handles usage logs and statistics retrieval */ -import { apiClient } from './client'; +import { apiClient } from './client' import type { UsageLog, UsageQueryParams, UsageStatsResponse, PaginatedResponse, TrendDataPoint, - ModelStat, -} from '@/types'; + ModelStat +} from '@/types' // ==================== Dashboard Types ==================== export interface UserDashboardStats { - total_api_keys: number; - active_api_keys: number; - total_requests: number; - total_input_tokens: number; - total_output_tokens: number; - total_cache_creation_tokens: number; - total_cache_read_tokens: number; - total_tokens: number; - total_cost: number; // 标准计费 - total_actual_cost: number; // 实际扣除 - today_requests: number; - today_input_tokens: number; - today_output_tokens: number; - today_cache_creation_tokens: number; - today_cache_read_tokens: number; - today_tokens: number; - today_cost: number; // 今日标准计费 - today_actual_cost: number; // 今日实际扣除 - average_duration_ms: number; - rpm: number; // 近5分钟平均每分钟请求数 - tpm: number; // 近5分钟平均每分钟Token数 + total_api_keys: number + active_api_keys: number + total_requests: number + total_input_tokens: number + total_output_tokens: number + total_cache_creation_tokens: number + total_cache_read_tokens: number + total_tokens: number + total_cost: number // 标准计费 + total_actual_cost: number // 实际扣除 + today_requests: number + today_input_tokens: number + today_output_tokens: number + today_cache_creation_tokens: number + today_cache_read_tokens: number + today_tokens: number + today_cost: number // 今日标准计费 + today_actual_cost: number // 今日实际扣除 + average_duration_ms: number + rpm: number // 近5分钟平均每分钟请求数 + tpm: number // 近5分钟平均每分钟Token数 } export interface TrendParams { - start_date?: string; - end_date?: string; - granularity?: 'day' | 'hour'; + start_date?: string + end_date?: string + granularity?: 'day' | 'hour' } export interface TrendResponse { - trend: TrendDataPoint[]; - start_date: string; - end_date: string; - granularity: string; + trend: TrendDataPoint[] + start_date: string + end_date: string + granularity: string } export interface ModelStatsResponse { - models: ModelStat[]; - start_date: string; - end_date: string; + models: ModelStat[] + start_date: string + end_date: string } /** @@ -72,17 +72,17 @@ export async function list( ): Promise> { const params: UsageQueryParams = { page, - page_size: pageSize, - }; + page_size: pageSize + } if (apiKeyId !== undefined) { - params.api_key_id = apiKeyId; + params.api_key_id = apiKeyId } const { data } = await apiClient.get>('/usage', { - params, - }); - return data; + params + }) + return data } /** @@ -92,9 +92,9 @@ export async function list( */ export async function query(params: UsageQueryParams): Promise> { const { data } = await apiClient.get>('/usage', { - params, - }); - return data; + params + }) + return data } /** @@ -107,16 +107,16 @@ export async function getStats( period: string = 'today', apiKeyId?: number ): Promise { - const params: Record = { period }; + const params: Record = { period } if (apiKeyId !== undefined) { - params.api_key_id = apiKeyId; + params.api_key_id = apiKeyId } const { data } = await apiClient.get('/usage/stats', { - params, - }); - return data; + params + }) + return data } /** @@ -133,17 +133,17 @@ export async function getStatsByDateRange( ): Promise { const params: Record = { start_date: startDate, - end_date: endDate, - }; + end_date: endDate + } if (apiKeyId !== undefined) { - params.api_key_id = apiKeyId; + params.api_key_id = apiKeyId } const { data } = await apiClient.get('/usage/stats', { - params, - }); - return data; + params + }) + return data } /** @@ -162,17 +162,17 @@ export async function getByDateRange( start_date: startDate, end_date: endDate, page: 1, - page_size: 100, - }; + page_size: 100 + } if (apiKeyId !== undefined) { - params.api_key_id = apiKeyId; + params.api_key_id = apiKeyId } const { data } = await apiClient.get>('/usage', { - params, - }); - return data; + params + }) + return data } /** @@ -181,8 +181,8 @@ export async function getByDateRange( * @returns Usage log details */ export async function getById(id: number): Promise { - const { data } = await apiClient.get(`/usage/${id}`); - return data; + const { data } = await apiClient.get(`/usage/${id}`) + return data } // ==================== Dashboard API ==================== @@ -192,8 +192,8 @@ export async function getById(id: number): Promise { * @returns Dashboard statistics for current user */ export async function getDashboardStats(): Promise { - const { data } = await apiClient.get('/usage/dashboard/stats'); - return data; + const { data } = await apiClient.get('/usage/dashboard/stats') + return data } /** @@ -202,8 +202,8 @@ export async function getDashboardStats(): Promise { * @returns Usage trend data for current user */ export async function getDashboardTrend(params?: TrendParams): Promise { - const { data } = await apiClient.get('/usage/dashboard/trend', { params }); - return data; + const { data } = await apiClient.get('/usage/dashboard/trend', { params }) + return data } /** @@ -211,19 +211,22 @@ export async function getDashboardTrend(params?: TrendParams): Promise { - const { data } = await apiClient.get('/usage/dashboard/models', { params }); - return data; +export async function getDashboardModels(params?: { + start_date?: string + end_date?: string +}): Promise { + const { data } = await apiClient.get('/usage/dashboard/models', { params }) + return data } export interface BatchApiKeyUsageStats { - api_key_id: number; - today_actual_cost: number; - total_actual_cost: number; + api_key_id: number + today_actual_cost: number + total_actual_cost: number } export interface BatchApiKeysUsageResponse { - stats: Record; + stats: Record } /** @@ -231,11 +234,16 @@ export interface BatchApiKeysUsageResponse { * @param apiKeyIds - Array of API key IDs * @returns Usage stats map keyed by API key ID */ -export async function getDashboardApiKeysUsage(apiKeyIds: number[]): Promise { - const { data } = await apiClient.post('/usage/dashboard/api-keys-usage', { - api_key_ids: apiKeyIds, - }); - return data; +export async function getDashboardApiKeysUsage( + apiKeyIds: number[] +): Promise { + const { data } = await apiClient.post( + '/usage/dashboard/api-keys-usage', + { + api_key_ids: apiKeyIds + } + ) + return data } export const usageAPI = { @@ -249,7 +257,7 @@ export const usageAPI = { getDashboardStats, getDashboardTrend, getDashboardModels, - getDashboardApiKeysUsage, -}; + getDashboardApiKeysUsage +} -export default usageAPI; +export default usageAPI diff --git a/frontend/src/api/user.ts b/frontend/src/api/user.ts index db994e73..d34ce20e 100644 --- a/frontend/src/api/user.ts +++ b/frontend/src/api/user.ts @@ -3,16 +3,16 @@ * Handles user profile management and password changes */ -import { apiClient } from './client'; -import type { User, ChangePasswordRequest } from '@/types'; +import { apiClient } from './client' +import type { User, ChangePasswordRequest } from '@/types' /** * Get current user profile * @returns User profile data */ export async function getProfile(): Promise { - const { data } = await apiClient.get('/user/profile'); - return data; + const { data } = await apiClient.get('/user/profile') + return data } /** @@ -21,11 +21,11 @@ export async function getProfile(): Promise { * @returns Updated user profile data */ export async function updateProfile(profile: { - username?: string; - wechat?: string; + username?: string + wechat?: string }): Promise { - const { data } = await apiClient.put('/user', profile); - return data; + const { data } = await apiClient.put('/user', profile) + return data } /** @@ -39,17 +39,17 @@ export async function changePassword( ): Promise<{ message: string }> { const payload: ChangePasswordRequest = { old_password: oldPassword, - new_password: newPassword, - }; + new_password: newPassword + } - const { data } = await apiClient.put<{ message: string }>('/user/password', payload); - return data; + const { data } = await apiClient.put<{ message: string }>('/user/password', payload) + return data } export const userAPI = { getProfile, updateProfile, - changePassword, -}; + changePassword +} -export default userAPI; +export default userAPI