style(frontend): 统一 API 模块代码风格

- 移除所有语句末尾分号
- 统一对象属性尾随逗号格式
- 优化类型定义导入顺序
- 提升代码一致性和可读性
This commit is contained in:
ianshaw
2025-12-25 08:41:30 -08:00
parent 34183b527b
commit f79b0f0fad
21 changed files with 802 additions and 751 deletions

View File

@@ -12,7 +12,7 @@ import type {
AccountUsageInfo, AccountUsageInfo,
WindowStats, WindowStats,
ClaudeModel, ClaudeModel,
AccountUsageStatsResponse, AccountUsageStatsResponse
} from '@/types' } from '@/types'
/** /**
@@ -36,8 +36,8 @@ export async function list(
params: { params: {
page, page,
page_size: pageSize, page_size: pageSize,
...filters, ...filters
}, }
}) })
return data return data
} }
@@ -129,7 +129,7 @@ export async function refreshCredentials(id: number): Promise<Account> {
*/ */
export async function getStats(id: number, days: number = 30): Promise<AccountUsageStatsResponse> { export async function getStats(id: number, days: number = 30): Promise<AccountUsageStatsResponse> {
const { data } = await apiClient.get<AccountUsageStatsResponse>(`/admin/accounts/${id}/stats`, { const { data } = await apiClient.get<AccountUsageStatsResponse>(`/admin/accounts/${id}/stats`, {
params: { days }, params: { days }
}) })
return data return data
} }
@@ -254,7 +254,7 @@ export async function bulkUpdate(
results: Array<{ account_id: number; success: boolean; error?: string }> results: Array<{ account_id: number; success: boolean; error?: string }>
}>('/admin/accounts/bulk-update', { }>('/admin/accounts/bulk-update', {
account_ids: accountIds, account_ids: accountIds,
...updates, ...updates
}) })
return data return data
} }
@@ -277,7 +277,7 @@ export async function getTodayStats(id: number): Promise<WindowStats> {
*/ */
export async function setSchedulable(id: number, schedulable: boolean): Promise<Account> { export async function setSchedulable(id: number, schedulable: boolean): Promise<Account> {
const { data } = await apiClient.post<Account>(`/admin/accounts/${id}/schedulable`, { const { data } = await apiClient.post<Account>(`/admin/accounts/${id}/schedulable`, {
schedulable, schedulable
}) })
return data return data
} }
@@ -335,7 +335,7 @@ export const accountsAPI = {
batchCreate, batchCreate,
batchUpdateCredentials, batchUpdateCredentials,
bulkUpdate, bulkUpdate,
syncFromCrs, syncFromCrs
} }
export default accountsAPI export default accountsAPI

View File

@@ -3,16 +3,22 @@
* Provides system-wide statistics and metrics * Provides system-wide statistics and metrics
*/ */
import { apiClient } from '../client'; import { apiClient } from '../client'
import type { DashboardStats, TrendDataPoint, ModelStat, ApiKeyUsageTrendPoint, UserUsageTrendPoint } from '@/types'; import type {
DashboardStats,
TrendDataPoint,
ModelStat,
ApiKeyUsageTrendPoint,
UserUsageTrendPoint
} from '@/types'
/** /**
* Get dashboard statistics * Get dashboard statistics
* @returns Dashboard statistics including users, keys, accounts, and token usage * @returns Dashboard statistics including users, keys, accounts, and token usage
*/ */
export async function getStats(): Promise<DashboardStats> { export async function getStats(): Promise<DashboardStats> {
const { data } = await apiClient.get<DashboardStats>('/admin/dashboard/stats'); const { data } = await apiClient.get<DashboardStats>('/admin/dashboard/stats')
return data; return data
} }
/** /**
@@ -20,33 +26,33 @@ export async function getStats(): Promise<DashboardStats> {
* @returns Real-time system metrics * @returns Real-time system metrics
*/ */
export async function getRealtimeMetrics(): Promise<{ export async function getRealtimeMetrics(): Promise<{
active_requests: number; active_requests: number
requests_per_minute: number; requests_per_minute: number
average_response_time: number; average_response_time: number
error_rate: number; error_rate: number
}> { }> {
const { data } = await apiClient.get<{ const { data } = await apiClient.get<{
active_requests: number; active_requests: number
requests_per_minute: number; requests_per_minute: number
average_response_time: number; average_response_time: number
error_rate: number; error_rate: number
}>('/admin/dashboard/realtime'); }>('/admin/dashboard/realtime')
return data; return data
} }
export interface TrendParams { export interface TrendParams {
start_date?: string; start_date?: string
end_date?: string; end_date?: string
granularity?: 'day' | 'hour'; granularity?: 'day' | 'hour'
user_id?: number; user_id?: number
api_key_id?: number; api_key_id?: number
} }
export interface TrendResponse { export interface TrendResponse {
trend: TrendDataPoint[]; trend: TrendDataPoint[]
start_date: string; start_date: string
end_date: string; end_date: string
granularity: string; granularity: string
} }
/** /**
@@ -55,21 +61,21 @@ export interface TrendResponse {
* @returns Usage trend data * @returns Usage trend data
*/ */
export async function getUsageTrend(params?: TrendParams): Promise<TrendResponse> { export async function getUsageTrend(params?: TrendParams): Promise<TrendResponse> {
const { data } = await apiClient.get<TrendResponse>('/admin/dashboard/trend', { params }); const { data } = await apiClient.get<TrendResponse>('/admin/dashboard/trend', { params })
return data; return data
} }
export interface ModelStatsParams { export interface ModelStatsParams {
start_date?: string; start_date?: string
end_date?: string; end_date?: string
user_id?: number; user_id?: number
api_key_id?: number; api_key_id?: number
} }
export interface ModelStatsResponse { export interface ModelStatsResponse {
models: ModelStat[]; models: ModelStat[]
start_date: string; start_date: string
end_date: string; end_date: string
} }
/** /**
@@ -78,19 +84,19 @@ export interface ModelStatsResponse {
* @returns Model usage statistics * @returns Model usage statistics
*/ */
export async function getModelStats(params?: ModelStatsParams): Promise<ModelStatsResponse> { export async function getModelStats(params?: ModelStatsParams): Promise<ModelStatsResponse> {
const { data } = await apiClient.get<ModelStatsResponse>('/admin/dashboard/models', { params }); const { data } = await apiClient.get<ModelStatsResponse>('/admin/dashboard/models', { params })
return data; return data
} }
export interface ApiKeyTrendParams extends TrendParams { export interface ApiKeyTrendParams extends TrendParams {
limit?: number; limit?: number
} }
export interface ApiKeyTrendResponse { export interface ApiKeyTrendResponse {
trend: ApiKeyUsageTrendPoint[]; trend: ApiKeyUsageTrendPoint[]
start_date: string; start_date: string
end_date: string; end_date: string
granularity: string; granularity: string
} }
/** /**
@@ -98,20 +104,24 @@ export interface ApiKeyTrendResponse {
* @param params - Query parameters for filtering * @param params - Query parameters for filtering
* @returns API key usage trend data * @returns API key usage trend data
*/ */
export async function getApiKeyUsageTrend(params?: ApiKeyTrendParams): Promise<ApiKeyTrendResponse> { export async function getApiKeyUsageTrend(
const { data } = await apiClient.get<ApiKeyTrendResponse>('/admin/dashboard/api-keys-trend', { params }); params?: ApiKeyTrendParams
return data; ): Promise<ApiKeyTrendResponse> {
const { data } = await apiClient.get<ApiKeyTrendResponse>('/admin/dashboard/api-keys-trend', {
params
})
return data
} }
export interface UserTrendParams extends TrendParams { export interface UserTrendParams extends TrendParams {
limit?: number; limit?: number
} }
export interface UserTrendResponse { export interface UserTrendResponse {
trend: UserUsageTrendPoint[]; trend: UserUsageTrendPoint[]
start_date: string; start_date: string
end_date: string; end_date: string
granularity: string; granularity: string
} }
/** /**
@@ -120,18 +130,20 @@ export interface UserTrendResponse {
* @returns User usage trend data * @returns User usage trend data
*/ */
export async function getUserUsageTrend(params?: UserTrendParams): Promise<UserTrendResponse> { export async function getUserUsageTrend(params?: UserTrendParams): Promise<UserTrendResponse> {
const { data } = await apiClient.get<UserTrendResponse>('/admin/dashboard/users-trend', { params }); const { data } = await apiClient.get<UserTrendResponse>('/admin/dashboard/users-trend', {
return data; params
})
return data
} }
export interface BatchUserUsageStats { export interface BatchUserUsageStats {
user_id: number; user_id: number
today_actual_cost: number; today_actual_cost: number
total_actual_cost: number; total_actual_cost: number
} }
export interface BatchUsersUsageResponse { export interface BatchUsersUsageResponse {
stats: Record<string, BatchUserUsageStats>; stats: Record<string, BatchUserUsageStats>
} }
/** /**
@@ -141,19 +153,19 @@ export interface BatchUsersUsageResponse {
*/ */
export async function getBatchUsersUsage(userIds: number[]): Promise<BatchUsersUsageResponse> { export async function getBatchUsersUsage(userIds: number[]): Promise<BatchUsersUsageResponse> {
const { data } = await apiClient.post<BatchUsersUsageResponse>('/admin/dashboard/users-usage', { const { data } = await apiClient.post<BatchUsersUsageResponse>('/admin/dashboard/users-usage', {
user_ids: userIds, user_ids: userIds
}); })
return data; return data
} }
export interface BatchApiKeyUsageStats { export interface BatchApiKeyUsageStats {
api_key_id: number; api_key_id: number
today_actual_cost: number; today_actual_cost: number
total_actual_cost: number; total_actual_cost: number
} }
export interface BatchApiKeysUsageResponse { export interface BatchApiKeysUsageResponse {
stats: Record<string, BatchApiKeyUsageStats>; stats: Record<string, BatchApiKeyUsageStats>
} }
/** /**
@@ -161,11 +173,16 @@ export interface BatchApiKeysUsageResponse {
* @param apiKeyIds - Array of API key IDs * @param apiKeyIds - Array of API key IDs
* @returns Usage stats map keyed by API key ID * @returns Usage stats map keyed by API key ID
*/ */
export async function getBatchApiKeysUsage(apiKeyIds: number[]): Promise<BatchApiKeysUsageResponse> { export async function getBatchApiKeysUsage(
const { data } = await apiClient.post<BatchApiKeysUsageResponse>('/admin/dashboard/api-keys-usage', { apiKeyIds: number[]
api_key_ids: apiKeyIds, ): Promise<BatchApiKeysUsageResponse> {
}); const { data } = await apiClient.post<BatchApiKeysUsageResponse>(
return data; '/admin/dashboard/api-keys-usage',
{
api_key_ids: apiKeyIds
}
)
return data
} }
export const dashboardAPI = { export const dashboardAPI = {
@@ -176,7 +193,7 @@ export const dashboardAPI = {
getApiKeyUsageTrend, getApiKeyUsageTrend,
getUserUsageTrend, getUserUsageTrend,
getBatchUsersUsage, getBatchUsersUsage,
getBatchApiKeysUsage, getBatchApiKeysUsage
}; }
export default dashboardAPI; export default dashboardAPI

View File

@@ -3,14 +3,14 @@
* Handles API key group management for administrators * Handles API key group management for administrators
*/ */
import { apiClient } from '../client'; import { apiClient } from '../client'
import type { import type {
Group, Group,
GroupPlatform, GroupPlatform,
CreateGroupRequest, CreateGroupRequest,
UpdateGroupRequest, UpdateGroupRequest,
PaginatedResponse, PaginatedResponse
} from '@/types'; } from '@/types'
/** /**
* List all groups with pagination * List all groups with pagination
@@ -23,19 +23,19 @@ export async function list(
page: number = 1, page: number = 1,
pageSize: number = 20, pageSize: number = 20,
filters?: { filters?: {
platform?: GroupPlatform; platform?: GroupPlatform
status?: 'active' | 'inactive'; status?: 'active' | 'inactive'
is_exclusive?: boolean; is_exclusive?: boolean
} }
): Promise<PaginatedResponse<Group>> { ): Promise<PaginatedResponse<Group>> {
const { data } = await apiClient.get<PaginatedResponse<Group>>('/admin/groups', { const { data } = await apiClient.get<PaginatedResponse<Group>>('/admin/groups', {
params: { params: {
page, page,
page_size: pageSize, page_size: pageSize,
...filters, ...filters
}, }
}); })
return data; return data
} }
/** /**
@@ -46,8 +46,8 @@ export async function list(
export async function getAll(platform?: GroupPlatform): Promise<Group[]> { export async function getAll(platform?: GroupPlatform): Promise<Group[]> {
const { data } = await apiClient.get<Group[]>('/admin/groups/all', { const { data } = await apiClient.get<Group[]>('/admin/groups/all', {
params: platform ? { platform } : undefined params: platform ? { platform } : undefined
}); })
return data; return data
} }
/** /**
@@ -56,7 +56,7 @@ export async function getAll(platform?: GroupPlatform): Promise<Group[]> {
* @returns List of groups for the specified platform * @returns List of groups for the specified platform
*/ */
export async function getByPlatform(platform: GroupPlatform): Promise<Group[]> { export async function getByPlatform(platform: GroupPlatform): Promise<Group[]> {
return getAll(platform); return getAll(platform)
} }
/** /**
@@ -65,8 +65,8 @@ export async function getByPlatform(platform: GroupPlatform): Promise<Group[]> {
* @returns Group details * @returns Group details
*/ */
export async function getById(id: number): Promise<Group> { export async function getById(id: number): Promise<Group> {
const { data } = await apiClient.get<Group>(`/admin/groups/${id}`); const { data } = await apiClient.get<Group>(`/admin/groups/${id}`)
return data; return data
} }
/** /**
@@ -75,8 +75,8 @@ export async function getById(id: number): Promise<Group> {
* @returns Created group * @returns Created group
*/ */
export async function create(groupData: CreateGroupRequest): Promise<Group> { export async function create(groupData: CreateGroupRequest): Promise<Group> {
const { data } = await apiClient.post<Group>('/admin/groups', groupData); const { data } = await apiClient.post<Group>('/admin/groups', groupData)
return data; return data
} }
/** /**
@@ -86,8 +86,8 @@ export async function create(groupData: CreateGroupRequest): Promise<Group> {
* @returns Updated group * @returns Updated group
*/ */
export async function update(id: number, updates: UpdateGroupRequest): Promise<Group> { export async function update(id: number, updates: UpdateGroupRequest): Promise<Group> {
const { data } = await apiClient.put<Group>(`/admin/groups/${id}`, updates); const { data } = await apiClient.put<Group>(`/admin/groups/${id}`, updates)
return data; return data
} }
/** /**
@@ -96,8 +96,8 @@ export async function update(id: number, updates: UpdateGroupRequest): Promise<G
* @returns Success confirmation * @returns Success confirmation
*/ */
export async function deleteGroup(id: number): Promise<{ message: string }> { export async function deleteGroup(id: number): Promise<{ message: string }> {
const { data } = await apiClient.delete<{ message: string }>(`/admin/groups/${id}`); const { data } = await apiClient.delete<{ message: string }>(`/admin/groups/${id}`)
return data; return data
} }
/** /**
@@ -106,11 +106,8 @@ export async function deleteGroup(id: number): Promise<{ message: string }> {
* @param status - New status * @param status - New status
* @returns Updated group * @returns Updated group
*/ */
export async function toggleStatus( export async function toggleStatus(id: number, status: 'active' | 'inactive'): Promise<Group> {
id: number, return update(id, { status })
status: 'active' | 'inactive'
): Promise<Group> {
return update(id, { status });
} }
/** /**
@@ -119,18 +116,18 @@ export async function toggleStatus(
* @returns Group usage statistics * @returns Group usage statistics
*/ */
export async function getStats(id: number): Promise<{ export async function getStats(id: number): Promise<{
total_api_keys: number; total_api_keys: number
active_api_keys: number; active_api_keys: number
total_requests: number; total_requests: number
total_cost: number; total_cost: number
}> { }> {
const { data } = await apiClient.get<{ const { data } = await apiClient.get<{
total_api_keys: number; total_api_keys: number
active_api_keys: number; active_api_keys: number
total_requests: number; total_requests: number
total_cost: number; total_cost: number
}>(`/admin/groups/${id}/stats`); }>(`/admin/groups/${id}/stats`)
return data; return data
} }
/** /**
@@ -145,13 +142,10 @@ export async function getGroupApiKeys(
page: number = 1, page: number = 1,
pageSize: number = 20 pageSize: number = 20
): Promise<PaginatedResponse<any>> { ): Promise<PaginatedResponse<any>> {
const { data } = await apiClient.get<PaginatedResponse<any>>( const { data } = await apiClient.get<PaginatedResponse<any>>(`/admin/groups/${id}/api-keys`, {
`/admin/groups/${id}/api-keys`, params: { page, page_size: pageSize }
{ })
params: { page, page_size: pageSize }, return data
}
);
return data;
} }
export const groupsAPI = { export const groupsAPI = {
@@ -164,7 +158,7 @@ export const groupsAPI = {
delete: deleteGroup, delete: deleteGroup,
toggleStatus, toggleStatus,
getStats, getStats,
getGroupApiKeys, getGroupApiKeys
}; }
export default groupsAPI; export default groupsAPI

View File

@@ -3,16 +3,17 @@
* Centralized exports for all admin API modules * Centralized exports for all admin API modules
*/ */
import dashboardAPI from './dashboard'; import dashboardAPI from './dashboard'
import usersAPI from './users'; import usersAPI from './users'
import groupsAPI from './groups'; import groupsAPI from './groups'
import accountsAPI from './accounts'; import accountsAPI from './accounts'
import proxiesAPI from './proxies'; import proxiesAPI from './proxies'
import redeemAPI from './redeem'; import redeemAPI from './redeem'
import settingsAPI from './settings'; import settingsAPI from './settings'
import systemAPI from './system'; import systemAPI from './system'
import subscriptionsAPI from './subscriptions'; import subscriptionsAPI from './subscriptions'
import usageAPI from './usage'; import usageAPI from './usage'
import geminiAPI from './gemini'
/** /**
* Unified admin API object for convenient access * Unified admin API object for convenient access
@@ -28,8 +29,21 @@ export const adminAPI = {
system: systemAPI, system: systemAPI,
subscriptions: subscriptionsAPI, subscriptions: subscriptionsAPI,
usage: usageAPI, 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

View File

@@ -3,13 +3,8 @@
* Handles proxy server management for administrators * Handles proxy server management for administrators
*/ */
import { apiClient } from '../client'; import { apiClient } from '../client'
import type { import type { Proxy, CreateProxyRequest, UpdateProxyRequest, PaginatedResponse } from '@/types'
Proxy,
CreateProxyRequest,
UpdateProxyRequest,
PaginatedResponse,
} from '@/types';
/** /**
* List all proxies with pagination * List all proxies with pagination
@@ -22,19 +17,19 @@ export async function list(
page: number = 1, page: number = 1,
pageSize: number = 20, pageSize: number = 20,
filters?: { filters?: {
protocol?: string; protocol?: string
status?: 'active' | 'inactive'; status?: 'active' | 'inactive'
search?: string; search?: string
} }
): Promise<PaginatedResponse<Proxy>> { ): Promise<PaginatedResponse<Proxy>> {
const { data } = await apiClient.get<PaginatedResponse<Proxy>>('/admin/proxies', { const { data } = await apiClient.get<PaginatedResponse<Proxy>>('/admin/proxies', {
params: { params: {
page, page,
page_size: pageSize, page_size: pageSize,
...filters, ...filters
}, }
}); })
return data; return data
} }
/** /**
@@ -42,8 +37,8 @@ export async function list(
* @returns List of all active proxies * @returns List of all active proxies
*/ */
export async function getAll(): Promise<Proxy[]> { export async function getAll(): Promise<Proxy[]> {
const { data } = await apiClient.get<Proxy[]>('/admin/proxies/all'); const { data } = await apiClient.get<Proxy[]>('/admin/proxies/all')
return data; return data
} }
/** /**
@@ -52,9 +47,9 @@ export async function getAll(): Promise<Proxy[]> {
*/ */
export async function getAllWithCount(): Promise<Proxy[]> { export async function getAllWithCount(): Promise<Proxy[]> {
const { data } = await apiClient.get<Proxy[]>('/admin/proxies/all', { const { data } = await apiClient.get<Proxy[]>('/admin/proxies/all', {
params: { with_count: 'true' }, params: { with_count: 'true' }
}); })
return data; return data
} }
/** /**
@@ -63,8 +58,8 @@ export async function getAllWithCount(): Promise<Proxy[]> {
* @returns Proxy details * @returns Proxy details
*/ */
export async function getById(id: number): Promise<Proxy> { export async function getById(id: number): Promise<Proxy> {
const { data } = await apiClient.get<Proxy>(`/admin/proxies/${id}`); const { data } = await apiClient.get<Proxy>(`/admin/proxies/${id}`)
return data; return data
} }
/** /**
@@ -73,8 +68,8 @@ export async function getById(id: number): Promise<Proxy> {
* @returns Created proxy * @returns Created proxy
*/ */
export async function create(proxyData: CreateProxyRequest): Promise<Proxy> { export async function create(proxyData: CreateProxyRequest): Promise<Proxy> {
const { data } = await apiClient.post<Proxy>('/admin/proxies', proxyData); const { data } = await apiClient.post<Proxy>('/admin/proxies', proxyData)
return data; return data
} }
/** /**
@@ -84,8 +79,8 @@ export async function create(proxyData: CreateProxyRequest): Promise<Proxy> {
* @returns Updated proxy * @returns Updated proxy
*/ */
export async function update(id: number, updates: UpdateProxyRequest): Promise<Proxy> { export async function update(id: number, updates: UpdateProxyRequest): Promise<Proxy> {
const { data } = await apiClient.put<Proxy>(`/admin/proxies/${id}`, updates); const { data } = await apiClient.put<Proxy>(`/admin/proxies/${id}`, updates)
return data; return data
} }
/** /**
@@ -94,8 +89,8 @@ export async function update(id: number, updates: UpdateProxyRequest): Promise<P
* @returns Success confirmation * @returns Success confirmation
*/ */
export async function deleteProxy(id: number): Promise<{ message: string }> { export async function deleteProxy(id: number): Promise<{ message: string }> {
const { data } = await apiClient.delete<{ message: string }>(`/admin/proxies/${id}`); const { data } = await apiClient.delete<{ message: string }>(`/admin/proxies/${id}`)
return data; return data
} }
/** /**
@@ -104,11 +99,8 @@ export async function deleteProxy(id: number): Promise<{ message: string }> {
* @param status - New status * @param status - New status
* @returns Updated proxy * @returns Updated proxy
*/ */
export async function toggleStatus( export async function toggleStatus(id: number, status: 'active' | 'inactive'): Promise<Proxy> {
id: number, return update(id, { status })
status: 'active' | 'inactive'
): Promise<Proxy> {
return update(id, { status });
} }
/** /**
@@ -117,24 +109,24 @@ export async function toggleStatus(
* @returns Test result with IP info * @returns Test result with IP info
*/ */
export async function testProxy(id: number): Promise<{ export async function testProxy(id: number): Promise<{
success: boolean; success: boolean
message: string; message: string
latency_ms?: number; latency_ms?: number
ip_address?: string; ip_address?: string
city?: string; city?: string
region?: string; region?: string
country?: string; country?: string
}> { }> {
const { data } = await apiClient.post<{ const { data } = await apiClient.post<{
success: boolean; success: boolean
message: string; message: string
latency_ms?: number; latency_ms?: number
ip_address?: string; ip_address?: string
city?: string; city?: string
region?: string; region?: string
country?: string; country?: string
}>(`/admin/proxies/${id}/test`); }>(`/admin/proxies/${id}/test`)
return data; return data
} }
/** /**
@@ -143,20 +135,20 @@ export async function testProxy(id: number): Promise<{
* @returns Proxy usage statistics * @returns Proxy usage statistics
*/ */
export async function getStats(id: number): Promise<{ export async function getStats(id: number): Promise<{
total_accounts: number; total_accounts: number
active_accounts: number; active_accounts: number
total_requests: number; total_requests: number
success_rate: number; success_rate: number
average_latency: number; average_latency: number
}> { }> {
const { data } = await apiClient.get<{ const { data } = await apiClient.get<{
total_accounts: number; total_accounts: number
active_accounts: number; active_accounts: number
total_requests: number; total_requests: number
success_rate: number; success_rate: number
average_latency: number; average_latency: number
}>(`/admin/proxies/${id}/stats`); }>(`/admin/proxies/${id}/stats`)
return data; return data
} }
/** /**
@@ -165,10 +157,8 @@ export async function getStats(id: number): Promise<{
* @returns List of accounts using the proxy * @returns List of accounts using the proxy
*/ */
export async function getProxyAccounts(id: number): Promise<PaginatedResponse<any>> { export async function getProxyAccounts(id: number): Promise<PaginatedResponse<any>> {
const { data } = await apiClient.get<PaginatedResponse<any>>( const { data } = await apiClient.get<PaginatedResponse<any>>(`/admin/proxies/${id}/accounts`)
`/admin/proxies/${id}/accounts` return data
);
return data;
} }
/** /**
@@ -176,21 +166,23 @@ export async function getProxyAccounts(id: number): Promise<PaginatedResponse<an
* @param proxies - Array of proxy data to create * @param proxies - Array of proxy data to create
* @returns Creation result with count of created and skipped * @returns Creation result with count of created and skipped
*/ */
export async function batchCreate(proxies: Array<{ export async function batchCreate(
protocol: string; proxies: Array<{
host: string; protocol: string
port: number; host: string
username?: string; port: number
password?: string; username?: string
}>): Promise<{ password?: string
created: number; }>
skipped: number; ): Promise<{
created: number
skipped: number
}> { }> {
const { data } = await apiClient.post<{ const { data } = await apiClient.post<{
created: number; created: number
skipped: number; skipped: number
}>('/admin/proxies/batch', { proxies }); }>('/admin/proxies/batch', { proxies })
return data; return data
} }
export const proxiesAPI = { export const proxiesAPI = {
@@ -205,7 +197,7 @@ export const proxiesAPI = {
testProxy, testProxy,
getStats, getStats,
getProxyAccounts, getProxyAccounts,
batchCreate, batchCreate
}; }
export default proxiesAPI; export default proxiesAPI

View File

@@ -3,13 +3,13 @@
* Handles redeem code generation and management for administrators * Handles redeem code generation and management for administrators
*/ */
import { apiClient } from '../client'; import { apiClient } from '../client'
import type { import type {
RedeemCode, RedeemCode,
GenerateRedeemCodesRequest, GenerateRedeemCodesRequest,
RedeemCodeType, RedeemCodeType,
PaginatedResponse, PaginatedResponse
} from '@/types'; } from '@/types'
/** /**
* List all redeem codes with pagination * List all redeem codes with pagination
@@ -22,19 +22,19 @@ export async function list(
page: number = 1, page: number = 1,
pageSize: number = 20, pageSize: number = 20,
filters?: { filters?: {
type?: RedeemCodeType; type?: RedeemCodeType
status?: 'active' | 'used' | 'expired' | 'unused'; status?: 'active' | 'used' | 'expired' | 'unused'
search?: string; search?: string
} }
): Promise<PaginatedResponse<RedeemCode>> { ): Promise<PaginatedResponse<RedeemCode>> {
const { data } = await apiClient.get<PaginatedResponse<RedeemCode>>('/admin/redeem-codes', { const { data } = await apiClient.get<PaginatedResponse<RedeemCode>>('/admin/redeem-codes', {
params: { params: {
page, page,
page_size: pageSize, page_size: pageSize,
...filters, ...filters
}, }
}); })
return data; return data
} }
/** /**
@@ -43,8 +43,8 @@ export async function list(
* @returns Redeem code details * @returns Redeem code details
*/ */
export async function getById(id: number): Promise<RedeemCode> { export async function getById(id: number): Promise<RedeemCode> {
const { data } = await apiClient.get<RedeemCode>(`/admin/redeem-codes/${id}`); const { data } = await apiClient.get<RedeemCode>(`/admin/redeem-codes/${id}`)
return data; return data
} }
/** /**
@@ -66,19 +66,19 @@ export async function generate(
const payload: GenerateRedeemCodesRequest = { const payload: GenerateRedeemCodesRequest = {
count, count,
type, type,
value, value
}; }
// 订阅类型专用字段 // 订阅类型专用字段
if (type === 'subscription') { if (type === 'subscription') {
payload.group_id = groupId; payload.group_id = groupId
if (validityDays && validityDays > 0) { if (validityDays && validityDays > 0) {
payload.validity_days = validityDays; payload.validity_days = validityDays
} }
} }
const { data } = await apiClient.post<RedeemCode[]>('/admin/redeem-codes/generate', payload); const { data } = await apiClient.post<RedeemCode[]>('/admin/redeem-codes/generate', payload)
return data; return data
} }
/** /**
@@ -87,8 +87,8 @@ export async function generate(
* @returns Success confirmation * @returns Success confirmation
*/ */
export async function deleteCode(id: number): Promise<{ message: string }> { export async function deleteCode(id: number): Promise<{ message: string }> {
const { data } = await apiClient.delete<{ message: string }>(`/admin/redeem-codes/${id}`); const { data } = await apiClient.delete<{ message: string }>(`/admin/redeem-codes/${id}`)
return data; return data
} }
/** /**
@@ -97,14 +97,14 @@ export async function deleteCode(id: number): Promise<{ message: string }> {
* @returns Success confirmation * @returns Success confirmation
*/ */
export async function batchDelete(ids: number[]): Promise<{ export async function batchDelete(ids: number[]): Promise<{
deleted: number; deleted: number
message: string; message: string
}> { }> {
const { data } = await apiClient.post<{ const { data } = await apiClient.post<{
deleted: number; deleted: number
message: string; message: string
}>('/admin/redeem-codes/batch-delete', { ids }); }>('/admin/redeem-codes/batch-delete', { ids })
return data; return data
} }
/** /**
@@ -113,8 +113,8 @@ export async function batchDelete(ids: number[]): Promise<{
* @returns Updated redeem code * @returns Updated redeem code
*/ */
export async function expire(id: number): Promise<RedeemCode> { export async function expire(id: number): Promise<RedeemCode> {
const { data } = await apiClient.post<RedeemCode>(`/admin/redeem-codes/${id}/expire`); const { data } = await apiClient.post<RedeemCode>(`/admin/redeem-codes/${id}/expire`)
return data; return data
} }
/** /**
@@ -122,22 +122,22 @@ export async function expire(id: number): Promise<RedeemCode> {
* @returns Statistics about redeem codes * @returns Statistics about redeem codes
*/ */
export async function getStats(): Promise<{ export async function getStats(): Promise<{
total_codes: number; total_codes: number
active_codes: number; active_codes: number
used_codes: number; used_codes: number
expired_codes: number; expired_codes: number
total_value_distributed: number; total_value_distributed: number
by_type: Record<RedeemCodeType, number>; by_type: Record<RedeemCodeType, number>
}> { }> {
const { data } = await apiClient.get<{ const { data } = await apiClient.get<{
total_codes: number; total_codes: number
active_codes: number; active_codes: number
used_codes: number; used_codes: number
expired_codes: number; expired_codes: number
total_value_distributed: number; total_value_distributed: number
by_type: Record<RedeemCodeType, number>; by_type: Record<RedeemCodeType, number>
}>('/admin/redeem-codes/stats'); }>('/admin/redeem-codes/stats')
return data; return data
} }
/** /**
@@ -146,14 +146,14 @@ export async function getStats(): Promise<{
* @returns CSV data as blob * @returns CSV data as blob
*/ */
export async function exportCodes(filters?: { export async function exportCodes(filters?: {
type?: RedeemCodeType; type?: RedeemCodeType
status?: 'active' | 'used' | 'expired'; status?: 'active' | 'used' | 'expired'
}): Promise<Blob> { }): Promise<Blob> {
const response = await apiClient.get('/admin/redeem-codes/export', { const response = await apiClient.get('/admin/redeem-codes/export', {
params: filters, params: filters,
responseType: 'blob', responseType: 'blob'
}); })
return response.data; return response.data
} }
export const redeemAPI = { export const redeemAPI = {
@@ -164,7 +164,7 @@ export const redeemAPI = {
batchDelete, batchDelete,
expire, expire,
getStats, getStats,
exportCodes, exportCodes
}; }
export default redeemAPI; export default redeemAPI

View File

@@ -3,37 +3,37 @@
* Handles system settings management for administrators * Handles system settings management for administrators
*/ */
import { apiClient } from '../client'; import { apiClient } from '../client'
/** /**
* System settings interface * System settings interface
*/ */
export interface SystemSettings { export interface SystemSettings {
// Registration settings // Registration settings
registration_enabled: boolean; registration_enabled: boolean
email_verify_enabled: boolean; email_verify_enabled: boolean
// Default settings // Default settings
default_balance: number; default_balance: number
default_concurrency: number; default_concurrency: number
// OEM settings // OEM settings
site_name: string; site_name: string
site_logo: string; site_logo: string
site_subtitle: string; site_subtitle: string
api_base_url: string; api_base_url: string
contact_info: string; contact_info: string
doc_url: string; doc_url: string
// SMTP settings // SMTP settings
smtp_host: string; smtp_host: string
smtp_port: number; smtp_port: number
smtp_username: string; smtp_username: string
smtp_password: string; smtp_password: string
smtp_from_email: string; smtp_from_email: string
smtp_from_name: string; smtp_from_name: string
smtp_use_tls: boolean; smtp_use_tls: boolean
// Cloudflare Turnstile settings // Cloudflare Turnstile settings
turnstile_enabled: boolean; turnstile_enabled: boolean
turnstile_site_key: string; turnstile_site_key: string
turnstile_secret_key: string; turnstile_secret_key: string
} }
/** /**
@@ -41,8 +41,8 @@ export interface SystemSettings {
* @returns System settings * @returns System settings
*/ */
export async function getSettings(): Promise<SystemSettings> { export async function getSettings(): Promise<SystemSettings> {
const { data } = await apiClient.get<SystemSettings>('/admin/settings'); const { data } = await apiClient.get<SystemSettings>('/admin/settings')
return data; return data
} }
/** /**
@@ -51,19 +51,19 @@ export async function getSettings(): Promise<SystemSettings> {
* @returns Updated settings * @returns Updated settings
*/ */
export async function updateSettings(settings: Partial<SystemSettings>): Promise<SystemSettings> { export async function updateSettings(settings: Partial<SystemSettings>): Promise<SystemSettings> {
const { data } = await apiClient.put<SystemSettings>('/admin/settings', settings); const { data } = await apiClient.put<SystemSettings>('/admin/settings', settings)
return data; return data
} }
/** /**
* Test SMTP connection request * Test SMTP connection request
*/ */
export interface TestSmtpRequest { export interface TestSmtpRequest {
smtp_host: string; smtp_host: string
smtp_port: number; smtp_port: number
smtp_username: string; smtp_username: string
smtp_password: string; smtp_password: string
smtp_use_tls: boolean; smtp_use_tls: boolean
} }
/** /**
@@ -72,22 +72,22 @@ export interface TestSmtpRequest {
* @returns Test result message * @returns Test result message
*/ */
export async function testSmtpConnection(config: TestSmtpRequest): Promise<{ message: string }> { export async function testSmtpConnection(config: TestSmtpRequest): Promise<{ message: string }> {
const { data } = await apiClient.post<{ message: string }>('/admin/settings/test-smtp', config); const { data } = await apiClient.post<{ message: string }>('/admin/settings/test-smtp', config)
return data; return data
} }
/** /**
* Send test email request * Send test email request
*/ */
export interface SendTestEmailRequest { export interface SendTestEmailRequest {
email: string; email: string
smtp_host: string; smtp_host: string
smtp_port: number; smtp_port: number
smtp_username: string; smtp_username: string
smtp_password: string; smtp_password: string
smtp_from_email: string; smtp_from_email: string
smtp_from_name: string; smtp_from_name: string
smtp_use_tls: boolean; smtp_use_tls: boolean
} }
/** /**
@@ -96,16 +96,19 @@ export interface SendTestEmailRequest {
* @returns Test result message * @returns Test result message
*/ */
export async function sendTestEmail(request: SendTestEmailRequest): Promise<{ message: string }> { export async function sendTestEmail(request: SendTestEmailRequest): Promise<{ message: string }> {
const { data } = await apiClient.post<{ message: string }>('/admin/settings/send-test-email', request); const { data } = await apiClient.post<{ message: string }>(
return data; '/admin/settings/send-test-email',
request
)
return data
} }
/** /**
* Admin API Key status response * Admin API Key status response
*/ */
export interface AdminApiKeyStatus { export interface AdminApiKeyStatus {
exists: boolean; exists: boolean
masked_key: string; masked_key: string
} }
/** /**
@@ -113,8 +116,8 @@ export interface AdminApiKeyStatus {
* @returns Status indicating if key exists and masked version * @returns Status indicating if key exists and masked version
*/ */
export async function getAdminApiKey(): Promise<AdminApiKeyStatus> { export async function getAdminApiKey(): Promise<AdminApiKeyStatus> {
const { data } = await apiClient.get<AdminApiKeyStatus>('/admin/settings/admin-api-key'); const { data } = await apiClient.get<AdminApiKeyStatus>('/admin/settings/admin-api-key')
return data; return data
} }
/** /**
@@ -122,8 +125,8 @@ export async function getAdminApiKey(): Promise<AdminApiKeyStatus> {
* @returns The new full API key (only shown once) * @returns The new full API key (only shown once)
*/ */
export async function regenerateAdminApiKey(): Promise<{ key: string }> { export async function regenerateAdminApiKey(): Promise<{ key: string }> {
const { data } = await apiClient.post<{ key: string }>('/admin/settings/admin-api-key/regenerate'); const { data } = await apiClient.post<{ key: string }>('/admin/settings/admin-api-key/regenerate')
return data; return data
} }
/** /**
@@ -131,8 +134,8 @@ export async function regenerateAdminApiKey(): Promise<{ key: string }> {
* @returns Success message * @returns Success message
*/ */
export async function deleteAdminApiKey(): Promise<{ message: string }> { export async function deleteAdminApiKey(): Promise<{ message: string }> {
const { data } = await apiClient.delete<{ message: string }>('/admin/settings/admin-api-key'); const { data } = await apiClient.delete<{ message: string }>('/admin/settings/admin-api-key')
return data; return data
} }
export const settingsAPI = { export const settingsAPI = {
@@ -142,7 +145,7 @@ export const settingsAPI = {
sendTestEmail, sendTestEmail,
getAdminApiKey, getAdminApiKey,
regenerateAdminApiKey, regenerateAdminApiKey,
deleteAdminApiKey, deleteAdminApiKey
}; }
export default settingsAPI; export default settingsAPI

View File

@@ -3,15 +3,15 @@
* Handles user subscription management for administrators * Handles user subscription management for administrators
*/ */
import { apiClient } from '../client'; import { apiClient } from '../client'
import type { import type {
UserSubscription, UserSubscription,
SubscriptionProgress, SubscriptionProgress,
AssignSubscriptionRequest, AssignSubscriptionRequest,
BulkAssignSubscriptionRequest, BulkAssignSubscriptionRequest,
ExtendSubscriptionRequest, ExtendSubscriptionRequest,
PaginatedResponse, PaginatedResponse
} from '@/types'; } from '@/types'
/** /**
* List all subscriptions with pagination * List all subscriptions with pagination
@@ -24,19 +24,22 @@ export async function list(
page: number = 1, page: number = 1,
pageSize: number = 20, pageSize: number = 20,
filters?: { filters?: {
status?: 'active' | 'expired' | 'revoked'; status?: 'active' | 'expired' | 'revoked'
user_id?: number; user_id?: number
group_id?: number; group_id?: number
} }
): Promise<PaginatedResponse<UserSubscription>> { ): Promise<PaginatedResponse<UserSubscription>> {
const { data } = await apiClient.get<PaginatedResponse<UserSubscription>>('/admin/subscriptions', { const { data } = await apiClient.get<PaginatedResponse<UserSubscription>>(
params: { '/admin/subscriptions',
page, {
page_size: pageSize, params: {
...filters, page,
}, page_size: pageSize,
}); ...filters
return data; }
}
)
return data
} }
/** /**
@@ -45,8 +48,8 @@ export async function list(
* @returns Subscription details * @returns Subscription details
*/ */
export async function getById(id: number): Promise<UserSubscription> { export async function getById(id: number): Promise<UserSubscription> {
const { data } = await apiClient.get<UserSubscription>(`/admin/subscriptions/${id}`); const { data } = await apiClient.get<UserSubscription>(`/admin/subscriptions/${id}`)
return data; return data
} }
/** /**
@@ -55,8 +58,8 @@ export async function getById(id: number): Promise<UserSubscription> {
* @returns Subscription progress with usage stats * @returns Subscription progress with usage stats
*/ */
export async function getProgress(id: number): Promise<SubscriptionProgress> { export async function getProgress(id: number): Promise<SubscriptionProgress> {
const { data } = await apiClient.get<SubscriptionProgress>(`/admin/subscriptions/${id}/progress`); const { data } = await apiClient.get<SubscriptionProgress>(`/admin/subscriptions/${id}/progress`)
return data; return data
} }
/** /**
@@ -65,8 +68,8 @@ export async function getProgress(id: number): Promise<SubscriptionProgress> {
* @returns Created subscription * @returns Created subscription
*/ */
export async function assign(request: AssignSubscriptionRequest): Promise<UserSubscription> { export async function assign(request: AssignSubscriptionRequest): Promise<UserSubscription> {
const { data } = await apiClient.post<UserSubscription>('/admin/subscriptions/assign', request); const { data } = await apiClient.post<UserSubscription>('/admin/subscriptions/assign', request)
return data; return data
} }
/** /**
@@ -74,9 +77,14 @@ export async function assign(request: AssignSubscriptionRequest): Promise<UserSu
* @param request - Bulk assignment request * @param request - Bulk assignment request
* @returns Created subscriptions * @returns Created subscriptions
*/ */
export async function bulkAssign(request: BulkAssignSubscriptionRequest): Promise<UserSubscription[]> { export async function bulkAssign(
const { data } = await apiClient.post<UserSubscription[]>('/admin/subscriptions/bulk-assign', request); request: BulkAssignSubscriptionRequest
return data; ): Promise<UserSubscription[]> {
const { data } = await apiClient.post<UserSubscription[]>(
'/admin/subscriptions/bulk-assign',
request
)
return data
} }
/** /**
@@ -85,9 +93,15 @@ export async function bulkAssign(request: BulkAssignSubscriptionRequest): Promis
* @param request - Extension request with days * @param request - Extension request with days
* @returns Updated subscription * @returns Updated subscription
*/ */
export async function extend(id: number, request: ExtendSubscriptionRequest): Promise<UserSubscription> { export async function extend(
const { data } = await apiClient.post<UserSubscription>(`/admin/subscriptions/${id}/extend`, request); id: number,
return data; request: ExtendSubscriptionRequest
): Promise<UserSubscription> {
const { data } = await apiClient.post<UserSubscription>(
`/admin/subscriptions/${id}/extend`,
request
)
return data
} }
/** /**
@@ -96,8 +110,8 @@ export async function extend(id: number, request: ExtendSubscriptionRequest): Pr
* @returns Success confirmation * @returns Success confirmation
*/ */
export async function revoke(id: number): Promise<{ message: string }> { export async function revoke(id: number): Promise<{ message: string }> {
const { data } = await apiClient.delete<{ message: string }>(`/admin/subscriptions/${id}`); const { data } = await apiClient.delete<{ message: string }>(`/admin/subscriptions/${id}`)
return data; return data
} }
/** /**
@@ -115,10 +129,10 @@ export async function listByGroup(
const { data } = await apiClient.get<PaginatedResponse<UserSubscription>>( const { data } = await apiClient.get<PaginatedResponse<UserSubscription>>(
`/admin/groups/${groupId}/subscriptions`, `/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<PaginatedResponse<UserSubscription>>( const { data } = await apiClient.get<PaginatedResponse<UserSubscription>>(
`/admin/users/${userId}/subscriptions`, `/admin/users/${userId}/subscriptions`,
{ {
params: { page, page_size: pageSize }, params: { page, page_size: pageSize }
} }
); )
return data; return data
} }
export const subscriptionsAPI = { export const subscriptionsAPI = {
@@ -151,7 +165,7 @@ export const subscriptionsAPI = {
extend, extend,
revoke, revoke,
listByGroup, listByGroup,
listByUser, listByUser
}; }
export default subscriptionsAPI; export default subscriptionsAPI

View File

@@ -2,31 +2,31 @@
* System API endpoints for admin operations * System API endpoints for admin operations
*/ */
import { apiClient } from '../client'; import { apiClient } from '../client'
export interface ReleaseInfo { export interface ReleaseInfo {
name: string; name: string
body: string; body: string
published_at: string; published_at: string
html_url: string; html_url: string
} }
export interface VersionInfo { export interface VersionInfo {
current_version: string; current_version: string
latest_version: string; latest_version: string
has_update: boolean; has_update: boolean
release_info?: ReleaseInfo; release_info?: ReleaseInfo
cached: boolean; cached: boolean
warning?: string; warning?: string
build_type: string; // "source" for manual builds, "release" for CI builds build_type: string // "source" for manual builds, "release" for CI builds
} }
/** /**
* Get current version * Get current version
*/ */
export async function getVersion(): Promise<{ version: string }> { export async function getVersion(): Promise<{ version: string }> {
const { data } = await apiClient.get<{ version: string }>('/admin/system/version'); const { data } = await apiClient.get<{ version: string }>('/admin/system/version')
return data; return data
} }
/** /**
@@ -35,14 +35,14 @@ export async function getVersion(): Promise<{ version: string }> {
*/ */
export async function checkUpdates(force = false): Promise<VersionInfo> { export async function checkUpdates(force = false): Promise<VersionInfo> {
const { data } = await apiClient.get<VersionInfo>('/admin/system/check-updates', { const { data } = await apiClient.get<VersionInfo>('/admin/system/check-updates', {
params: force ? { force: 'true' } : undefined, params: force ? { force: 'true' } : undefined
}); })
return data; return data
} }
export interface UpdateResult { export interface UpdateResult {
message: string; message: string
need_restart: boolean; need_restart: boolean
} }
/** /**
@@ -50,24 +50,24 @@ export interface UpdateResult {
* Downloads and applies the latest version * Downloads and applies the latest version
*/ */
export async function performUpdate(): Promise<UpdateResult> { export async function performUpdate(): Promise<UpdateResult> {
const { data } = await apiClient.post<UpdateResult>('/admin/system/update'); const { data } = await apiClient.post<UpdateResult>('/admin/system/update')
return data; return data
} }
/** /**
* Rollback to previous version * Rollback to previous version
*/ */
export async function rollback(): Promise<UpdateResult> { export async function rollback(): Promise<UpdateResult> {
const { data } = await apiClient.post<UpdateResult>('/admin/system/rollback'); const { data } = await apiClient.post<UpdateResult>('/admin/system/rollback')
return data; return data
} }
/** /**
* Restart the service * Restart the service
*/ */
export async function restartService(): Promise<{ message: string }> { export async function restartService(): Promise<{ message: string }> {
const { data } = await apiClient.post<{ message: string }>('/admin/system/restart'); const { data } = await apiClient.post<{ message: string }>('/admin/system/restart')
return data; return data
} }
export const systemAPI = { export const systemAPI = {
@@ -75,7 +75,7 @@ export const systemAPI = {
checkUpdates, checkUpdates,
performUpdate, performUpdate,
rollback, rollback,
restartService, restartService
}; }
export default systemAPI; export default systemAPI

View File

@@ -3,39 +3,35 @@
* Handles admin-level usage logs and statistics retrieval * Handles admin-level usage logs and statistics retrieval
*/ */
import { apiClient } from '../client'; import { apiClient } from '../client'
import type { import type { UsageLog, UsageQueryParams, PaginatedResponse } from '@/types'
UsageLog,
UsageQueryParams,
PaginatedResponse,
} from '@/types';
// ==================== Types ==================== // ==================== Types ====================
export interface AdminUsageStatsResponse { export interface AdminUsageStatsResponse {
total_requests: number; total_requests: number
total_input_tokens: number; total_input_tokens: number
total_output_tokens: number; total_output_tokens: number
total_cache_tokens: number; total_cache_tokens: number
total_tokens: number; total_tokens: number
total_cost: number; total_cost: number
total_actual_cost: number; total_actual_cost: number
average_duration_ms: number; average_duration_ms: number
} }
export interface SimpleUser { export interface SimpleUser {
id: number; id: number
email: string; email: string
} }
export interface SimpleApiKey { export interface SimpleApiKey {
id: number; id: number
name: string; name: string
user_id: number; user_id: number
} }
export interface AdminUsageQueryParams extends UsageQueryParams { export interface AdminUsageQueryParams extends UsageQueryParams {
user_id?: number; user_id?: number
} }
// ==================== API Functions ==================== // ==================== API Functions ====================
@@ -47,9 +43,9 @@ export interface AdminUsageQueryParams extends UsageQueryParams {
*/ */
export async function list(params: AdminUsageQueryParams): Promise<PaginatedResponse<UsageLog>> { export async function list(params: AdminUsageQueryParams): Promise<PaginatedResponse<UsageLog>> {
const { data } = await apiClient.get<PaginatedResponse<UsageLog>>('/admin/usage', { const { data } = await apiClient.get<PaginatedResponse<UsageLog>>('/admin/usage', {
params, params
}); })
return data; return data
} }
/** /**
@@ -58,16 +54,16 @@ export async function list(params: AdminUsageQueryParams): Promise<PaginatedResp
* @returns Usage statistics * @returns Usage statistics
*/ */
export async function getStats(params: { export async function getStats(params: {
user_id?: number; user_id?: number
api_key_id?: number; api_key_id?: number
period?: string; period?: string
start_date?: string; start_date?: string
end_date?: string; end_date?: string
}): Promise<AdminUsageStatsResponse> { }): Promise<AdminUsageStatsResponse> {
const { data } = await apiClient.get<AdminUsageStatsResponse>('/admin/usage/stats', { const { data } = await apiClient.get<AdminUsageStatsResponse>('/admin/usage/stats', {
params, params
}); })
return data; return data
} }
/** /**
@@ -77,9 +73,9 @@ export async function getStats(params: {
*/ */
export async function searchUsers(keyword: string): Promise<SimpleUser[]> { export async function searchUsers(keyword: string): Promise<SimpleUser[]> {
const { data } = await apiClient.get<SimpleUser[]>('/admin/usage/search-users', { const { data } = await apiClient.get<SimpleUser[]>('/admin/usage/search-users', {
params: { q: keyword }, params: { q: keyword }
}); })
return data; return data
} }
/** /**
@@ -89,24 +85,24 @@ export async function searchUsers(keyword: string): Promise<SimpleUser[]> {
* @returns List of matching API keys (max 30) * @returns List of matching API keys (max 30)
*/ */
export async function searchApiKeys(userId?: number, keyword?: string): Promise<SimpleApiKey[]> { export async function searchApiKeys(userId?: number, keyword?: string): Promise<SimpleApiKey[]> {
const params: Record<string, unknown> = {}; const params: Record<string, unknown> = {}
if (userId !== undefined) { if (userId !== undefined) {
params.user_id = userId; params.user_id = userId
} }
if (keyword) { if (keyword) {
params.q = keyword; params.q = keyword
} }
const { data } = await apiClient.get<SimpleApiKey[]>('/admin/usage/search-api-keys', { const { data } = await apiClient.get<SimpleApiKey[]>('/admin/usage/search-api-keys', {
params, params
}); })
return data; return data
} }
export const adminUsageAPI = { export const adminUsageAPI = {
list, list,
getStats, getStats,
searchUsers, searchUsers,
searchApiKeys, searchApiKeys
}; }
export default adminUsageAPI; export default adminUsageAPI

View File

@@ -3,8 +3,8 @@
* Handles user management for administrators * Handles user management for administrators
*/ */
import { apiClient } from '../client'; import { apiClient } from '../client'
import type { User, UpdateUserRequest, PaginatedResponse } from '@/types'; import type { User, UpdateUserRequest, PaginatedResponse } from '@/types'
/** /**
* List all users with pagination * List all users with pagination
@@ -17,19 +17,19 @@ export async function list(
page: number = 1, page: number = 1,
pageSize: number = 20, pageSize: number = 20,
filters?: { filters?: {
status?: 'active' | 'disabled'; status?: 'active' | 'disabled'
role?: 'admin' | 'user'; role?: 'admin' | 'user'
search?: string; search?: string
} }
): Promise<PaginatedResponse<User>> { ): Promise<PaginatedResponse<User>> {
const { data } = await apiClient.get<PaginatedResponse<User>>('/admin/users', { const { data } = await apiClient.get<PaginatedResponse<User>>('/admin/users', {
params: { params: {
page, page,
page_size: pageSize, page_size: pageSize,
...filters, ...filters
}, }
}); })
return data; return data
} }
/** /**
@@ -38,8 +38,8 @@ export async function list(
* @returns User details * @returns User details
*/ */
export async function getById(id: number): Promise<User> { export async function getById(id: number): Promise<User> {
const { data } = await apiClient.get<User>(`/admin/users/${id}`); const { data } = await apiClient.get<User>(`/admin/users/${id}`)
return data; return data
} }
/** /**
@@ -48,14 +48,14 @@ export async function getById(id: number): Promise<User> {
* @returns Created user * @returns Created user
*/ */
export async function create(userData: { export async function create(userData: {
email: string; email: string
password: string; password: string
balance?: number; balance?: number
concurrency?: number; concurrency?: number
allowed_groups?: number[] | null; allowed_groups?: number[] | null
}): Promise<User> { }): Promise<User> {
const { data } = await apiClient.post<User>('/admin/users', userData); const { data } = await apiClient.post<User>('/admin/users', userData)
return data; return data
} }
/** /**
@@ -65,8 +65,8 @@ export async function create(userData: {
* @returns Updated user * @returns Updated user
*/ */
export async function update(id: number, updates: UpdateUserRequest): Promise<User> { export async function update(id: number, updates: UpdateUserRequest): Promise<User> {
const { data } = await apiClient.put<User>(`/admin/users/${id}`, updates); const { data } = await apiClient.put<User>(`/admin/users/${id}`, updates)
return data; return data
} }
/** /**
@@ -75,8 +75,8 @@ export async function update(id: number, updates: UpdateUserRequest): Promise<Us
* @returns Success confirmation * @returns Success confirmation
*/ */
export async function deleteUser(id: number): Promise<{ message: string }> { export async function deleteUser(id: number): Promise<{ message: string }> {
const { data } = await apiClient.delete<{ message: string }>(`/admin/users/${id}`); const { data } = await apiClient.delete<{ message: string }>(`/admin/users/${id}`)
return data; return data
} }
/** /**
@@ -96,9 +96,9 @@ export async function updateBalance(
const { data } = await apiClient.post<User>(`/admin/users/${id}/balance`, { const { data } = await apiClient.post<User>(`/admin/users/${id}/balance`, {
balance, balance,
operation, operation,
notes: notes || '', notes: notes || ''
}); })
return data; return data
} }
/** /**
@@ -108,7 +108,7 @@ export async function updateBalance(
* @returns Updated user * @returns Updated user
*/ */
export async function updateConcurrency(id: number, concurrency: number): Promise<User> { export async function updateConcurrency(id: number, concurrency: number): Promise<User> {
return update(id, { concurrency }); return update(id, { concurrency })
} }
/** /**
@@ -118,7 +118,7 @@ export async function updateConcurrency(id: number, concurrency: number): Promis
* @returns Updated user * @returns Updated user
*/ */
export async function toggleStatus(id: number, status: 'active' | 'disabled'): Promise<User> { export async function toggleStatus(id: number, status: 'active' | 'disabled'): Promise<User> {
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 * @returns List of user's API keys
*/ */
export async function getUserApiKeys(id: number): Promise<PaginatedResponse<any>> { export async function getUserApiKeys(id: number): Promise<PaginatedResponse<any>> {
const { data } = await apiClient.get<PaginatedResponse<any>>(`/admin/users/${id}/api-keys`); const { data } = await apiClient.get<PaginatedResponse<any>>(`/admin/users/${id}/api-keys`)
return data; return data
} }
/** /**
@@ -141,18 +141,18 @@ export async function getUserUsageStats(
id: number, id: number,
period: string = 'month' period: string = 'month'
): Promise<{ ): Promise<{
total_requests: number; total_requests: number
total_cost: number; total_cost: number
total_tokens: number; total_tokens: number
}> { }> {
const { data } = await apiClient.get<{ const { data } = await apiClient.get<{
total_requests: number; total_requests: number
total_cost: number; total_cost: number
total_tokens: number; total_tokens: number
}>(`/admin/users/${id}/usage`, { }>(`/admin/users/${id}/usage`, {
params: { period }, params: { period }
}); })
return data; return data
} }
export const usersAPI = { export const usersAPI = {
@@ -165,7 +165,7 @@ export const usersAPI = {
updateConcurrency, updateConcurrency,
toggleStatus, toggleStatus,
getUserApiKeys, getUserApiKeys,
getUserUsageStats, getUserUsageStats
}; }
export default usersAPI; export default usersAPI

View File

@@ -3,29 +3,37 @@
* Handles user login, registration, and logout operations * Handles user login, registration, and logout operations
*/ */
import { apiClient } from './client'; import { apiClient } from './client'
import type { LoginRequest, RegisterRequest, AuthResponse, User, SendVerifyCodeRequest, SendVerifyCodeResponse, PublicSettings } from '@/types'; import type {
LoginRequest,
RegisterRequest,
AuthResponse,
User,
SendVerifyCodeRequest,
SendVerifyCodeResponse,
PublicSettings
} from '@/types'
/** /**
* Store authentication token in localStorage * Store authentication token in localStorage
*/ */
export function setAuthToken(token: string): void { export function setAuthToken(token: string): void {
localStorage.setItem('auth_token', token); localStorage.setItem('auth_token', token)
} }
/** /**
* Get authentication token from localStorage * Get authentication token from localStorage
*/ */
export function getAuthToken(): string | null { export function getAuthToken(): string | null {
return localStorage.getItem('auth_token'); return localStorage.getItem('auth_token')
} }
/** /**
* Clear authentication token from localStorage * Clear authentication token from localStorage
*/ */
export function clearAuthToken(): void { export function clearAuthToken(): void {
localStorage.removeItem('auth_token'); localStorage.removeItem('auth_token')
localStorage.removeItem('auth_user'); localStorage.removeItem('auth_user')
} }
/** /**
@@ -34,13 +42,13 @@ export function clearAuthToken(): void {
* @returns Authentication response with token and user data * @returns Authentication response with token and user data
*/ */
export async function login(credentials: LoginRequest): Promise<AuthResponse> { export async function login(credentials: LoginRequest): Promise<AuthResponse> {
const { data } = await apiClient.post<AuthResponse>('/auth/login', credentials); const { data } = await apiClient.post<AuthResponse>('/auth/login', credentials)
// Store token and user data // Store token and user data
setAuthToken(data.access_token); setAuthToken(data.access_token)
localStorage.setItem('auth_user', JSON.stringify(data.user)); localStorage.setItem('auth_user', JSON.stringify(data.user))
return data; return data
} }
/** /**
@@ -49,13 +57,13 @@ export async function login(credentials: LoginRequest): Promise<AuthResponse> {
* @returns Authentication response with token and user data * @returns Authentication response with token and user data
*/ */
export async function register(userData: RegisterRequest): Promise<AuthResponse> { export async function register(userData: RegisterRequest): Promise<AuthResponse> {
const { data } = await apiClient.post<AuthResponse>('/auth/register', userData); const { data } = await apiClient.post<AuthResponse>('/auth/register', userData)
// Store token and user data // Store token and user data
setAuthToken(data.access_token); setAuthToken(data.access_token)
localStorage.setItem('auth_user', JSON.stringify(data.user)); localStorage.setItem('auth_user', JSON.stringify(data.user))
return data; return data
} }
/** /**
@@ -63,8 +71,8 @@ export async function register(userData: RegisterRequest): Promise<AuthResponse>
* @returns User profile data * @returns User profile data
*/ */
export async function getCurrentUser(): Promise<User> { export async function getCurrentUser(): Promise<User> {
const { data } = await apiClient.get<User>('/auth/me'); const { data } = await apiClient.get<User>('/auth/me')
return data; return data
} }
/** /**
@@ -72,7 +80,7 @@ export async function getCurrentUser(): Promise<User> {
* Clears authentication token and user data from localStorage * Clears authentication token and user data from localStorage
*/ */
export function logout(): void { export function logout(): void {
clearAuthToken(); clearAuthToken()
// Optionally redirect to login page // Optionally redirect to login page
// window.location.href = '/login'; // window.location.href = '/login';
} }
@@ -82,7 +90,7 @@ export function logout(): void {
* @returns True if user has valid token * @returns True if user has valid token
*/ */
export function isAuthenticated(): boolean { 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 * @returns Public settings including registration and Turnstile config
*/ */
export async function getPublicSettings(): Promise<PublicSettings> { export async function getPublicSettings(): Promise<PublicSettings> {
const { data } = await apiClient.get<PublicSettings>('/settings/public'); const { data } = await apiClient.get<PublicSettings>('/settings/public')
return data; return data
} }
/** /**
@@ -99,9 +107,11 @@ export async function getPublicSettings(): Promise<PublicSettings> {
* @param request - Email and optional Turnstile token * @param request - Email and optional Turnstile token
* @returns Response with countdown seconds * @returns Response with countdown seconds
*/ */
export async function sendVerifyCode(request: SendVerifyCodeRequest): Promise<SendVerifyCodeResponse> { export async function sendVerifyCode(
const { data } = await apiClient.post<SendVerifyCodeResponse>('/auth/send-verify-code', request); request: SendVerifyCodeRequest
return data; ): Promise<SendVerifyCodeResponse> {
const { data } = await apiClient.post<SendVerifyCodeResponse>('/auth/send-verify-code', request)
return data
} }
export const authAPI = { export const authAPI = {
@@ -114,7 +124,7 @@ export const authAPI = {
getAuthToken, getAuthToken,
clearAuthToken, clearAuthToken,
getPublicSettings, getPublicSettings,
sendVerifyCode, sendVerifyCode
}; }
export default authAPI; export default authAPI

View File

@@ -3,70 +3,70 @@
* Base client with interceptors for authentication and error handling * Base client with interceptors for authentication and error handling
*/ */
import axios, { AxiosInstance, AxiosError, InternalAxiosRequestConfig } from 'axios'; import axios, { AxiosInstance, AxiosError, InternalAxiosRequestConfig } from 'axios'
import type { ApiResponse } from '@/types'; import type { ApiResponse } from '@/types'
// ==================== Axios Instance Configuration ==================== // ==================== 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({ export const apiClient: AxiosInstance = axios.create({
baseURL: API_BASE_URL, baseURL: API_BASE_URL,
timeout: 30000, timeout: 30000,
headers: { headers: {
'Content-Type': 'application/json', 'Content-Type': 'application/json'
}, }
}); })
// ==================== Request Interceptor ==================== // ==================== Request Interceptor ====================
apiClient.interceptors.request.use( apiClient.interceptors.request.use(
(config: InternalAxiosRequestConfig) => { (config: InternalAxiosRequestConfig) => {
// Attach token from localStorage // Attach token from localStorage
const token = localStorage.getItem('auth_token'); const token = localStorage.getItem('auth_token')
if (token && config.headers) { if (token && config.headers) {
config.headers.Authorization = `Bearer ${token}`; config.headers.Authorization = `Bearer ${token}`
} }
return config; return config
}, },
(error) => { (error) => {
return Promise.reject(error); return Promise.reject(error)
} }
); )
// ==================== Response Interceptor ==================== // ==================== Response Interceptor ====================
apiClient.interceptors.response.use( apiClient.interceptors.response.use(
(response) => { (response) => {
// Unwrap standard API response format { code, message, data } // Unwrap standard API response format { code, message, data }
const apiResponse = response.data as ApiResponse<unknown>; const apiResponse = response.data as ApiResponse<unknown>
if (apiResponse && typeof apiResponse === 'object' && 'code' in apiResponse) { if (apiResponse && typeof apiResponse === 'object' && 'code' in apiResponse) {
if (apiResponse.code === 0) { if (apiResponse.code === 0) {
// Success - return the data portion // Success - return the data portion
response.data = apiResponse.data; response.data = apiResponse.data
} else { } else {
// API error // API error
return Promise.reject({ return Promise.reject({
status: response.status, status: response.status,
code: apiResponse.code, code: apiResponse.code,
message: apiResponse.message || 'Unknown error', message: apiResponse.message || 'Unknown error'
}); })
} }
} }
return response; return response
}, },
(error: AxiosError<ApiResponse<unknown>>) => { (error: AxiosError<ApiResponse<unknown>>) => {
// Handle common errors // Handle common errors
if (error.response) { if (error.response) {
const { status, data } = error.response; const { status, data } = error.response
// 401: Unauthorized - clear token and redirect to login // 401: Unauthorized - clear token and redirect to login
if (status === 401) { if (status === 401) {
localStorage.removeItem('auth_token'); localStorage.removeItem('auth_token')
localStorage.removeItem('auth_user'); localStorage.removeItem('auth_user')
// Only redirect if not already on login page // Only redirect if not already on login page
if (!window.location.pathname.includes('/login')) { 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({ return Promise.reject({
status, status,
code: data?.code, code: data?.code,
message: data?.message || error.message, message: data?.message || error.message
}); })
} }
// Network error // Network error
return Promise.reject({ return Promise.reject({
status: 0, status: 0,
message: 'Network error. Please check your connection.', message: 'Network error. Please check your connection.'
}); })
} }
); )
export default apiClient; export default apiClient

View File

@@ -3,8 +3,8 @@
* Handles group-related operations for regular users * Handles group-related operations for regular users
*/ */
import { apiClient } from './client'; import { apiClient } from './client'
import type { Group } from '@/types'; import type { Group } from '@/types'
/** /**
* Get available groups that the current user can bind to API keys * 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 * @returns List of available groups
*/ */
export async function getAvailable(): Promise<Group[]> { export async function getAvailable(): Promise<Group[]> {
const { data } = await apiClient.get<Group[]>('/groups/available'); const { data } = await apiClient.get<Group[]>('/groups/available')
return data; return data
} }
export const userGroupsAPI = { export const userGroupsAPI = {
getAvailable, getAvailable
}; }
export default userGroupsAPI; export default userGroupsAPI

View File

@@ -4,20 +4,20 @@
*/ */
// Re-export the HTTP client // Re-export the HTTP client
export { apiClient } from './client'; export { apiClient } from './client'
// Auth API // Auth API
export { authAPI } from './auth'; export { authAPI } from './auth'
// User APIs // User APIs
export { keysAPI } from './keys'; export { keysAPI } from './keys'
export { usageAPI } from './usage'; export { usageAPI } from './usage'
export { userAPI } from './user'; export { userAPI } from './user'
export { redeemAPI, type RedeemHistoryItem } from './redeem'; export { redeemAPI, type RedeemHistoryItem } from './redeem'
export { userGroupsAPI } from './groups'; export { userGroupsAPI } from './groups'
// Admin APIs // Admin APIs
export { adminAPI } from './admin'; export { adminAPI } from './admin'
// Default export // Default export
export { default } from './client'; export { default } from './client'

View File

@@ -3,13 +3,8 @@
* Handles CRUD operations for user API keys * Handles CRUD operations for user API keys
*/ */
import { apiClient } from './client'; import { apiClient } from './client'
import type { import type { ApiKey, CreateApiKeyRequest, UpdateApiKeyRequest, PaginatedResponse } from '@/types'
ApiKey,
CreateApiKeyRequest,
UpdateApiKeyRequest,
PaginatedResponse,
} from '@/types';
/** /**
* List all API keys for current user * List all API keys for current user
@@ -17,11 +12,14 @@ import type {
* @param pageSize - Items per page (default: 10) * @param pageSize - Items per page (default: 10)
* @returns Paginated list of API keys * @returns Paginated list of API keys
*/ */
export async function list(page: number = 1, pageSize: number = 10): Promise<PaginatedResponse<ApiKey>> { export async function list(
page: number = 1,
pageSize: number = 10
): Promise<PaginatedResponse<ApiKey>> {
const { data } = await apiClient.get<PaginatedResponse<ApiKey>>('/keys', { const { data } = await apiClient.get<PaginatedResponse<ApiKey>>('/keys', {
params: { page, page_size: pageSize }, params: { page, page_size: pageSize }
}); })
return data; return data
} }
/** /**
@@ -30,8 +28,8 @@ export async function list(page: number = 1, pageSize: number = 10): Promise<Pag
* @returns API key details * @returns API key details
*/ */
export async function getById(id: number): Promise<ApiKey> { export async function getById(id: number): Promise<ApiKey> {
const { data } = await apiClient.get<ApiKey>(`/keys/${id}`); const { data } = await apiClient.get<ApiKey>(`/keys/${id}`)
return data; return data
} }
/** /**
@@ -41,17 +39,21 @@ export async function getById(id: number): Promise<ApiKey> {
* @param customKey - Optional custom key value * @param customKey - Optional custom key value
* @returns Created API key * @returns Created API key
*/ */
export async function create(name: string, groupId?: number | null, customKey?: string): Promise<ApiKey> { export async function create(
const payload: CreateApiKeyRequest = { name }; name: string,
groupId?: number | null,
customKey?: string
): Promise<ApiKey> {
const payload: CreateApiKeyRequest = { name }
if (groupId !== undefined) { if (groupId !== undefined) {
payload.group_id = groupId; payload.group_id = groupId
} }
if (customKey) { if (customKey) {
payload.custom_key = customKey; payload.custom_key = customKey
} }
const { data } = await apiClient.post<ApiKey>('/keys', payload); const { data } = await apiClient.post<ApiKey>('/keys', payload)
return data; return data
} }
/** /**
@@ -61,8 +63,8 @@ export async function create(name: string, groupId?: number | null, customKey?:
* @returns Updated API key * @returns Updated API key
*/ */
export async function update(id: number, updates: UpdateApiKeyRequest): Promise<ApiKey> { export async function update(id: number, updates: UpdateApiKeyRequest): Promise<ApiKey> {
const { data } = await apiClient.put<ApiKey>(`/keys/${id}`, updates); const { data } = await apiClient.put<ApiKey>(`/keys/${id}`, updates)
return data; return data
} }
/** /**
@@ -71,8 +73,8 @@ export async function update(id: number, updates: UpdateApiKeyRequest): Promise<
* @returns Success confirmation * @returns Success confirmation
*/ */
export async function deleteKey(id: number): Promise<{ message: string }> { export async function deleteKey(id: number): Promise<{ message: string }> {
const { data } = await apiClient.delete<{ message: string }>(`/keys/${id}`); const { data } = await apiClient.delete<{ message: string }>(`/keys/${id}`)
return data; return data
} }
/** /**
@@ -81,11 +83,8 @@ export async function deleteKey(id: number): Promise<{ message: string }> {
* @param status - New status * @param status - New status
* @returns Updated API key * @returns Updated API key
*/ */
export async function toggleStatus( export async function toggleStatus(id: number, status: 'active' | 'inactive'): Promise<ApiKey> {
id: number, return update(id, { status })
status: 'active' | 'inactive'
): Promise<ApiKey> {
return update(id, { status });
} }
export const keysAPI = { export const keysAPI = {
@@ -94,7 +93,7 @@ export const keysAPI = {
create, create,
update, update,
delete: deleteKey, delete: deleteKey,
toggleStatus, toggleStatus
}; }
export default keysAPI; export default keysAPI

View File

@@ -3,24 +3,24 @@
* Handles redeem code redemption for users * Handles redeem code redemption for users
*/ */
import { apiClient } from './client'; import { apiClient } from './client'
import type { RedeemCodeRequest } from '@/types'; import type { RedeemCodeRequest } from '@/types'
export interface RedeemHistoryItem { export interface RedeemHistoryItem {
id: number; id: number
code: string; code: string
type: string; type: string
value: number; value: number
status: string; status: string
used_at: string; used_at: string
created_at: string; created_at: string
// 订阅类型专用字段 // 订阅类型专用字段
group_id?: number; group_id?: number
validity_days?: number; validity_days?: number
group?: { group?: {
id: number; id: number
name: string; name: string
}; }
} }
/** /**
@@ -29,23 +29,23 @@ export interface RedeemHistoryItem {
* @returns Redemption result with updated balance or concurrency * @returns Redemption result with updated balance or concurrency
*/ */
export async function redeem(code: string): Promise<{ export async function redeem(code: string): Promise<{
message: string; message: string
type: string; type: string
value: number; value: number
new_balance?: number; new_balance?: number
new_concurrency?: number; new_concurrency?: number
}> { }> {
const payload: RedeemCodeRequest = { code }; const payload: RedeemCodeRequest = { code }
const { data } = await apiClient.post<{ const { data } = await apiClient.post<{
message: string; message: string
type: string; type: string
value: number; value: number
new_balance?: number; new_balance?: number
new_concurrency?: number; new_concurrency?: number
}>('/redeem', payload); }>('/redeem', payload)
return data; return data
} }
/** /**
@@ -53,13 +53,13 @@ export async function redeem(code: string): Promise<{
* @returns List of redeemed codes * @returns List of redeemed codes
*/ */
export async function getHistory(): Promise<RedeemHistoryItem[]> { export async function getHistory(): Promise<RedeemHistoryItem[]> {
const { data } = await apiClient.get<RedeemHistoryItem[]>('/redeem/history'); const { data } = await apiClient.get<RedeemHistoryItem[]>('/redeem/history')
return data; return data
} }
export const redeemAPI = { export const redeemAPI = {
redeem, redeem,
getHistory, getHistory
}; }
export default redeemAPI; export default redeemAPI

View File

@@ -1,87 +1,87 @@
/** /**
* Setup API endpoints * Setup API endpoints
*/ */
import axios from 'axios'; import axios from 'axios'
// Create a separate client for setup endpoints (not under /api/v1) // Create a separate client for setup endpoints (not under /api/v1)
const setupClient = axios.create({ const setupClient = axios.create({
baseURL: '', baseURL: '',
timeout: 30000, timeout: 30000,
headers: { headers: {
'Content-Type': 'application/json', 'Content-Type': 'application/json'
}, }
}); })
export interface SetupStatus { export interface SetupStatus {
needs_setup: boolean; needs_setup: boolean
step: string; step: string
} }
export interface DatabaseConfig { export interface DatabaseConfig {
host: string; host: string
port: number; port: number
user: string; user: string
password: string; password: string
dbname: string; dbname: string
sslmode: string; sslmode: string
} }
export interface RedisConfig { export interface RedisConfig {
host: string; host: string
port: number; port: number
password: string; password: string
db: number; db: number
} }
export interface AdminConfig { export interface AdminConfig {
email: string; email: string
password: string; password: string
} }
export interface ServerConfig { export interface ServerConfig {
host: string; host: string
port: number; port: number
mode: string; mode: string
} }
export interface InstallRequest { export interface InstallRequest {
database: DatabaseConfig; database: DatabaseConfig
redis: RedisConfig; redis: RedisConfig
admin: AdminConfig; admin: AdminConfig
server: ServerConfig; server: ServerConfig
} }
export interface InstallResponse { export interface InstallResponse {
message: string; message: string
restart: boolean; restart: boolean
} }
/** /**
* Get setup status * Get setup status
*/ */
export async function getSetupStatus(): Promise<SetupStatus> { export async function getSetupStatus(): Promise<SetupStatus> {
const response = await setupClient.get('/setup/status'); const response = await setupClient.get('/setup/status')
return response.data.data; return response.data.data
} }
/** /**
* Test database connection * Test database connection
*/ */
export async function testDatabase(config: DatabaseConfig): Promise<void> { export async function testDatabase(config: DatabaseConfig): Promise<void> {
await setupClient.post('/setup/test-db', config); await setupClient.post('/setup/test-db', config)
} }
/** /**
* Test Redis connection * Test Redis connection
*/ */
export async function testRedis(config: RedisConfig): Promise<void> { export async function testRedis(config: RedisConfig): Promise<void> {
await setupClient.post('/setup/test-redis', config); await setupClient.post('/setup/test-redis', config)
} }
/** /**
* Perform installation * Perform installation
*/ */
export async function install(config: InstallRequest): Promise<InstallResponse> { export async function install(config: InstallRequest): Promise<InstallResponse> {
const response = await setupClient.post('/setup/install', config); const response = await setupClient.post('/setup/install', config)
return response.data.data; return response.data.data
} }

View File

@@ -3,64 +3,68 @@
* API for regular users to view their own subscriptions and progress * API for regular users to view their own subscriptions and progress
*/ */
import { apiClient } from './client'; import { apiClient } from './client'
import type { UserSubscription, SubscriptionProgress } from '@/types'; import type { UserSubscription, SubscriptionProgress } from '@/types'
/** /**
* Subscription summary for user dashboard * Subscription summary for user dashboard
*/ */
export interface SubscriptionSummary { export interface SubscriptionSummary {
active_count: number; active_count: number
subscriptions: Array<{ subscriptions: Array<{
id: number; id: number
group_name: string; group_name: string
status: string; status: string
daily_progress: number | null; daily_progress: number | null
weekly_progress: number | null; weekly_progress: number | null
monthly_progress: number | null; monthly_progress: number | null
expires_at: string | null; expires_at: string | null
days_remaining: number | null; days_remaining: number | null
}>; }>
} }
/** /**
* Get list of current user's subscriptions * Get list of current user's subscriptions
*/ */
export async function getMySubscriptions(): Promise<UserSubscription[]> { export async function getMySubscriptions(): Promise<UserSubscription[]> {
const response = await apiClient.get<UserSubscription[]>('/subscriptions'); const response = await apiClient.get<UserSubscription[]>('/subscriptions')
return response.data; return response.data
} }
/** /**
* Get current user's active subscriptions * Get current user's active subscriptions
*/ */
export async function getActiveSubscriptions(): Promise<UserSubscription[]> { export async function getActiveSubscriptions(): Promise<UserSubscription[]> {
const response = await apiClient.get<UserSubscription[]>('/subscriptions/active'); const response = await apiClient.get<UserSubscription[]>('/subscriptions/active')
return response.data; return response.data
} }
/** /**
* Get progress for all user's active subscriptions * Get progress for all user's active subscriptions
*/ */
export async function getSubscriptionsProgress(): Promise<SubscriptionProgress[]> { export async function getSubscriptionsProgress(): Promise<SubscriptionProgress[]> {
const response = await apiClient.get<SubscriptionProgress[]>('/subscriptions/progress'); const response = await apiClient.get<SubscriptionProgress[]>('/subscriptions/progress')
return response.data; return response.data
} }
/** /**
* Get subscription summary for dashboard display * Get subscription summary for dashboard display
*/ */
export async function getSubscriptionSummary(): Promise<SubscriptionSummary> { export async function getSubscriptionSummary(): Promise<SubscriptionSummary> {
const response = await apiClient.get<SubscriptionSummary>('/subscriptions/summary'); const response = await apiClient.get<SubscriptionSummary>('/subscriptions/summary')
return response.data; return response.data
} }
/** /**
* Get progress for a specific subscription * Get progress for a specific subscription
*/ */
export async function getSubscriptionProgress(subscriptionId: number): Promise<SubscriptionProgress> { export async function getSubscriptionProgress(
const response = await apiClient.get<SubscriptionProgress>(`/subscriptions/${subscriptionId}/progress`); subscriptionId: number
return response.data; ): Promise<SubscriptionProgress> {
const response = await apiClient.get<SubscriptionProgress>(
`/subscriptions/${subscriptionId}/progress`
)
return response.data
} }
export default { export default {
@@ -68,5 +72,5 @@ export default {
getActiveSubscriptions, getActiveSubscriptions,
getSubscriptionsProgress, getSubscriptionsProgress,
getSubscriptionSummary, getSubscriptionSummary,
getSubscriptionProgress, getSubscriptionProgress
}; }

View File

@@ -3,59 +3,59 @@
* Handles usage logs and statistics retrieval * Handles usage logs and statistics retrieval
*/ */
import { apiClient } from './client'; import { apiClient } from './client'
import type { import type {
UsageLog, UsageLog,
UsageQueryParams, UsageQueryParams,
UsageStatsResponse, UsageStatsResponse,
PaginatedResponse, PaginatedResponse,
TrendDataPoint, TrendDataPoint,
ModelStat, ModelStat
} from '@/types'; } from '@/types'
// ==================== Dashboard Types ==================== // ==================== Dashboard Types ====================
export interface UserDashboardStats { export interface UserDashboardStats {
total_api_keys: number; total_api_keys: number
active_api_keys: number; active_api_keys: number
total_requests: number; total_requests: number
total_input_tokens: number; total_input_tokens: number
total_output_tokens: number; total_output_tokens: number
total_cache_creation_tokens: number; total_cache_creation_tokens: number
total_cache_read_tokens: number; total_cache_read_tokens: number
total_tokens: number; total_tokens: number
total_cost: number; // 标准计费 total_cost: number // 标准计费
total_actual_cost: number; // 实际扣除 total_actual_cost: number // 实际扣除
today_requests: number; today_requests: number
today_input_tokens: number; today_input_tokens: number
today_output_tokens: number; today_output_tokens: number
today_cache_creation_tokens: number; today_cache_creation_tokens: number
today_cache_read_tokens: number; today_cache_read_tokens: number
today_tokens: number; today_tokens: number
today_cost: number; // 今日标准计费 today_cost: number // 今日标准计费
today_actual_cost: number; // 今日实际扣除 today_actual_cost: number // 今日实际扣除
average_duration_ms: number; average_duration_ms: number
rpm: number; // 近5分钟平均每分钟请求数 rpm: number // 近5分钟平均每分钟请求数
tpm: number; // 近5分钟平均每分钟Token数 tpm: number // 近5分钟平均每分钟Token数
} }
export interface TrendParams { export interface TrendParams {
start_date?: string; start_date?: string
end_date?: string; end_date?: string
granularity?: 'day' | 'hour'; granularity?: 'day' | 'hour'
} }
export interface TrendResponse { export interface TrendResponse {
trend: TrendDataPoint[]; trend: TrendDataPoint[]
start_date: string; start_date: string
end_date: string; end_date: string
granularity: string; granularity: string
} }
export interface ModelStatsResponse { export interface ModelStatsResponse {
models: ModelStat[]; models: ModelStat[]
start_date: string; start_date: string
end_date: string; end_date: string
} }
/** /**
@@ -72,17 +72,17 @@ export async function list(
): Promise<PaginatedResponse<UsageLog>> { ): Promise<PaginatedResponse<UsageLog>> {
const params: UsageQueryParams = { const params: UsageQueryParams = {
page, page,
page_size: pageSize, page_size: pageSize
}; }
if (apiKeyId !== undefined) { if (apiKeyId !== undefined) {
params.api_key_id = apiKeyId; params.api_key_id = apiKeyId
} }
const { data } = await apiClient.get<PaginatedResponse<UsageLog>>('/usage', { const { data } = await apiClient.get<PaginatedResponse<UsageLog>>('/usage', {
params, params
}); })
return data; return data
} }
/** /**
@@ -92,9 +92,9 @@ export async function list(
*/ */
export async function query(params: UsageQueryParams): Promise<PaginatedResponse<UsageLog>> { export async function query(params: UsageQueryParams): Promise<PaginatedResponse<UsageLog>> {
const { data } = await apiClient.get<PaginatedResponse<UsageLog>>('/usage', { const { data } = await apiClient.get<PaginatedResponse<UsageLog>>('/usage', {
params, params
}); })
return data; return data
} }
/** /**
@@ -107,16 +107,16 @@ export async function getStats(
period: string = 'today', period: string = 'today',
apiKeyId?: number apiKeyId?: number
): Promise<UsageStatsResponse> { ): Promise<UsageStatsResponse> {
const params: Record<string, unknown> = { period }; const params: Record<string, unknown> = { period }
if (apiKeyId !== undefined) { if (apiKeyId !== undefined) {
params.api_key_id = apiKeyId; params.api_key_id = apiKeyId
} }
const { data } = await apiClient.get<UsageStatsResponse>('/usage/stats', { const { data } = await apiClient.get<UsageStatsResponse>('/usage/stats', {
params, params
}); })
return data; return data
} }
/** /**
@@ -133,17 +133,17 @@ export async function getStatsByDateRange(
): Promise<UsageStatsResponse> { ): Promise<UsageStatsResponse> {
const params: Record<string, unknown> = { const params: Record<string, unknown> = {
start_date: startDate, start_date: startDate,
end_date: endDate, end_date: endDate
}; }
if (apiKeyId !== undefined) { if (apiKeyId !== undefined) {
params.api_key_id = apiKeyId; params.api_key_id = apiKeyId
} }
const { data } = await apiClient.get<UsageStatsResponse>('/usage/stats', { const { data } = await apiClient.get<UsageStatsResponse>('/usage/stats', {
params, params
}); })
return data; return data
} }
/** /**
@@ -162,17 +162,17 @@ export async function getByDateRange(
start_date: startDate, start_date: startDate,
end_date: endDate, end_date: endDate,
page: 1, page: 1,
page_size: 100, page_size: 100
}; }
if (apiKeyId !== undefined) { if (apiKeyId !== undefined) {
params.api_key_id = apiKeyId; params.api_key_id = apiKeyId
} }
const { data } = await apiClient.get<PaginatedResponse<UsageLog>>('/usage', { const { data } = await apiClient.get<PaginatedResponse<UsageLog>>('/usage', {
params, params
}); })
return data; return data
} }
/** /**
@@ -181,8 +181,8 @@ export async function getByDateRange(
* @returns Usage log details * @returns Usage log details
*/ */
export async function getById(id: number): Promise<UsageLog> { export async function getById(id: number): Promise<UsageLog> {
const { data } = await apiClient.get<UsageLog>(`/usage/${id}`); const { data } = await apiClient.get<UsageLog>(`/usage/${id}`)
return data; return data
} }
// ==================== Dashboard API ==================== // ==================== Dashboard API ====================
@@ -192,8 +192,8 @@ export async function getById(id: number): Promise<UsageLog> {
* @returns Dashboard statistics for current user * @returns Dashboard statistics for current user
*/ */
export async function getDashboardStats(): Promise<UserDashboardStats> { export async function getDashboardStats(): Promise<UserDashboardStats> {
const { data } = await apiClient.get<UserDashboardStats>('/usage/dashboard/stats'); const { data } = await apiClient.get<UserDashboardStats>('/usage/dashboard/stats')
return data; return data
} }
/** /**
@@ -202,8 +202,8 @@ export async function getDashboardStats(): Promise<UserDashboardStats> {
* @returns Usage trend data for current user * @returns Usage trend data for current user
*/ */
export async function getDashboardTrend(params?: TrendParams): Promise<TrendResponse> { export async function getDashboardTrend(params?: TrendParams): Promise<TrendResponse> {
const { data } = await apiClient.get<TrendResponse>('/usage/dashboard/trend', { params }); const { data } = await apiClient.get<TrendResponse>('/usage/dashboard/trend', { params })
return data; return data
} }
/** /**
@@ -211,19 +211,22 @@ export async function getDashboardTrend(params?: TrendParams): Promise<TrendResp
* @param params - Query parameters for filtering * @param params - Query parameters for filtering
* @returns Model usage statistics for current user * @returns Model usage statistics for current user
*/ */
export async function getDashboardModels(params?: { start_date?: string; end_date?: string }): Promise<ModelStatsResponse> { export async function getDashboardModels(params?: {
const { data } = await apiClient.get<ModelStatsResponse>('/usage/dashboard/models', { params }); start_date?: string
return data; end_date?: string
}): Promise<ModelStatsResponse> {
const { data } = await apiClient.get<ModelStatsResponse>('/usage/dashboard/models', { params })
return data
} }
export interface BatchApiKeyUsageStats { export interface BatchApiKeyUsageStats {
api_key_id: number; api_key_id: number
today_actual_cost: number; today_actual_cost: number
total_actual_cost: number; total_actual_cost: number
} }
export interface BatchApiKeysUsageResponse { export interface BatchApiKeysUsageResponse {
stats: Record<string, BatchApiKeyUsageStats>; stats: Record<string, BatchApiKeyUsageStats>
} }
/** /**
@@ -231,11 +234,16 @@ export interface BatchApiKeysUsageResponse {
* @param apiKeyIds - Array of API key IDs * @param apiKeyIds - Array of API key IDs
* @returns Usage stats map keyed by API key ID * @returns Usage stats map keyed by API key ID
*/ */
export async function getDashboardApiKeysUsage(apiKeyIds: number[]): Promise<BatchApiKeysUsageResponse> { export async function getDashboardApiKeysUsage(
const { data } = await apiClient.post<BatchApiKeysUsageResponse>('/usage/dashboard/api-keys-usage', { apiKeyIds: number[]
api_key_ids: apiKeyIds, ): Promise<BatchApiKeysUsageResponse> {
}); const { data } = await apiClient.post<BatchApiKeysUsageResponse>(
return data; '/usage/dashboard/api-keys-usage',
{
api_key_ids: apiKeyIds
}
)
return data
} }
export const usageAPI = { export const usageAPI = {
@@ -249,7 +257,7 @@ export const usageAPI = {
getDashboardStats, getDashboardStats,
getDashboardTrend, getDashboardTrend,
getDashboardModels, getDashboardModels,
getDashboardApiKeysUsage, getDashboardApiKeysUsage
}; }
export default usageAPI; export default usageAPI

View File

@@ -3,16 +3,16 @@
* Handles user profile management and password changes * Handles user profile management and password changes
*/ */
import { apiClient } from './client'; import { apiClient } from './client'
import type { User, ChangePasswordRequest } from '@/types'; import type { User, ChangePasswordRequest } from '@/types'
/** /**
* Get current user profile * Get current user profile
* @returns User profile data * @returns User profile data
*/ */
export async function getProfile(): Promise<User> { export async function getProfile(): Promise<User> {
const { data } = await apiClient.get<User>('/user/profile'); const { data } = await apiClient.get<User>('/user/profile')
return data; return data
} }
/** /**
@@ -21,11 +21,11 @@ export async function getProfile(): Promise<User> {
* @returns Updated user profile data * @returns Updated user profile data
*/ */
export async function updateProfile(profile: { export async function updateProfile(profile: {
username?: string; username?: string
wechat?: string; wechat?: string
}): Promise<User> { }): Promise<User> {
const { data } = await apiClient.put<User>('/user', profile); const { data } = await apiClient.put<User>('/user', profile)
return data; return data
} }
/** /**
@@ -39,17 +39,17 @@ export async function changePassword(
): Promise<{ message: string }> { ): Promise<{ message: string }> {
const payload: ChangePasswordRequest = { const payload: ChangePasswordRequest = {
old_password: oldPassword, old_password: oldPassword,
new_password: newPassword, new_password: newPassword
}; }
const { data } = await apiClient.put<{ message: string }>('/user/password', payload); const { data } = await apiClient.put<{ message: string }>('/user/password', payload)
return data; return data
} }
export const userAPI = { export const userAPI = {
getProfile, getProfile,
updateProfile, updateProfile,
changePassword, changePassword
}; }
export default userAPI; export default userAPI