style(frontend): 统一 API 模块代码风格
- 移除所有语句末尾分号 - 统一对象属性尾随逗号格式 - 优化类型定义导入顺序 - 提升代码一致性和可读性
This commit is contained in:
@@ -12,7 +12,7 @@ import type {
|
||||
AccountUsageInfo,
|
||||
WindowStats,
|
||||
ClaudeModel,
|
||||
AccountUsageStatsResponse,
|
||||
AccountUsageStatsResponse
|
||||
} from '@/types'
|
||||
|
||||
/**
|
||||
@@ -36,8 +36,8 @@ export async function list(
|
||||
params: {
|
||||
page,
|
||||
page_size: pageSize,
|
||||
...filters,
|
||||
},
|
||||
...filters
|
||||
}
|
||||
})
|
||||
return data
|
||||
}
|
||||
@@ -129,7 +129,7 @@ export async function refreshCredentials(id: number): Promise<Account> {
|
||||
*/
|
||||
export async function getStats(id: number, days: number = 30): Promise<AccountUsageStatsResponse> {
|
||||
const { data } = await apiClient.get<AccountUsageStatsResponse>(`/admin/accounts/${id}/stats`, {
|
||||
params: { days },
|
||||
params: { days }
|
||||
})
|
||||
return data
|
||||
}
|
||||
@@ -254,7 +254,7 @@ export async function bulkUpdate(
|
||||
results: Array<{ account_id: number; success: boolean; error?: string }>
|
||||
}>('/admin/accounts/bulk-update', {
|
||||
account_ids: accountIds,
|
||||
...updates,
|
||||
...updates
|
||||
})
|
||||
return data
|
||||
}
|
||||
@@ -277,7 +277,7 @@ export async function getTodayStats(id: number): Promise<WindowStats> {
|
||||
*/
|
||||
export async function setSchedulable(id: number, schedulable: boolean): Promise<Account> {
|
||||
const { data } = await apiClient.post<Account>(`/admin/accounts/${id}/schedulable`, {
|
||||
schedulable,
|
||||
schedulable
|
||||
})
|
||||
return data
|
||||
}
|
||||
@@ -335,7 +335,7 @@ export const accountsAPI = {
|
||||
batchCreate,
|
||||
batchUpdateCredentials,
|
||||
bulkUpdate,
|
||||
syncFromCrs,
|
||||
syncFromCrs
|
||||
}
|
||||
|
||||
export default accountsAPI
|
||||
|
||||
@@ -3,16 +3,22 @@
|
||||
* Provides system-wide statistics and metrics
|
||||
*/
|
||||
|
||||
import { apiClient } from '../client';
|
||||
import type { DashboardStats, TrendDataPoint, ModelStat, ApiKeyUsageTrendPoint, UserUsageTrendPoint } from '@/types';
|
||||
import { apiClient } from '../client'
|
||||
import type {
|
||||
DashboardStats,
|
||||
TrendDataPoint,
|
||||
ModelStat,
|
||||
ApiKeyUsageTrendPoint,
|
||||
UserUsageTrendPoint
|
||||
} from '@/types'
|
||||
|
||||
/**
|
||||
* Get dashboard statistics
|
||||
* @returns Dashboard statistics including users, keys, accounts, and token usage
|
||||
*/
|
||||
export async function getStats(): Promise<DashboardStats> {
|
||||
const { data } = await apiClient.get<DashboardStats>('/admin/dashboard/stats');
|
||||
return data;
|
||||
const { data } = await apiClient.get<DashboardStats>('/admin/dashboard/stats')
|
||||
return data
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -20,33 +26,33 @@ export async function getStats(): Promise<DashboardStats> {
|
||||
* @returns Real-time system metrics
|
||||
*/
|
||||
export async function getRealtimeMetrics(): Promise<{
|
||||
active_requests: number;
|
||||
requests_per_minute: number;
|
||||
average_response_time: number;
|
||||
error_rate: number;
|
||||
active_requests: number
|
||||
requests_per_minute: number
|
||||
average_response_time: number
|
||||
error_rate: number
|
||||
}> {
|
||||
const { data } = await apiClient.get<{
|
||||
active_requests: number;
|
||||
requests_per_minute: number;
|
||||
average_response_time: number;
|
||||
error_rate: number;
|
||||
}>('/admin/dashboard/realtime');
|
||||
return data;
|
||||
active_requests: number
|
||||
requests_per_minute: number
|
||||
average_response_time: number
|
||||
error_rate: number
|
||||
}>('/admin/dashboard/realtime')
|
||||
return data
|
||||
}
|
||||
|
||||
export interface TrendParams {
|
||||
start_date?: string;
|
||||
end_date?: string;
|
||||
granularity?: 'day' | 'hour';
|
||||
user_id?: number;
|
||||
api_key_id?: number;
|
||||
start_date?: string
|
||||
end_date?: string
|
||||
granularity?: 'day' | 'hour'
|
||||
user_id?: number
|
||||
api_key_id?: number
|
||||
}
|
||||
|
||||
export interface TrendResponse {
|
||||
trend: TrendDataPoint[];
|
||||
start_date: string;
|
||||
end_date: string;
|
||||
granularity: string;
|
||||
trend: TrendDataPoint[]
|
||||
start_date: string
|
||||
end_date: string
|
||||
granularity: string
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -55,21 +61,21 @@ export interface TrendResponse {
|
||||
* @returns Usage trend data
|
||||
*/
|
||||
export async function getUsageTrend(params?: TrendParams): Promise<TrendResponse> {
|
||||
const { data } = await apiClient.get<TrendResponse>('/admin/dashboard/trend', { params });
|
||||
return data;
|
||||
const { data } = await apiClient.get<TrendResponse>('/admin/dashboard/trend', { params })
|
||||
return data
|
||||
}
|
||||
|
||||
export interface ModelStatsParams {
|
||||
start_date?: string;
|
||||
end_date?: string;
|
||||
user_id?: number;
|
||||
api_key_id?: number;
|
||||
start_date?: string
|
||||
end_date?: string
|
||||
user_id?: number
|
||||
api_key_id?: number
|
||||
}
|
||||
|
||||
export interface ModelStatsResponse {
|
||||
models: ModelStat[];
|
||||
start_date: string;
|
||||
end_date: string;
|
||||
models: ModelStat[]
|
||||
start_date: string
|
||||
end_date: string
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -78,19 +84,19 @@ export interface ModelStatsResponse {
|
||||
* @returns Model usage statistics
|
||||
*/
|
||||
export async function getModelStats(params?: ModelStatsParams): Promise<ModelStatsResponse> {
|
||||
const { data } = await apiClient.get<ModelStatsResponse>('/admin/dashboard/models', { params });
|
||||
return data;
|
||||
const { data } = await apiClient.get<ModelStatsResponse>('/admin/dashboard/models', { params })
|
||||
return data
|
||||
}
|
||||
|
||||
export interface ApiKeyTrendParams extends TrendParams {
|
||||
limit?: number;
|
||||
limit?: number
|
||||
}
|
||||
|
||||
export interface ApiKeyTrendResponse {
|
||||
trend: ApiKeyUsageTrendPoint[];
|
||||
start_date: string;
|
||||
end_date: string;
|
||||
granularity: string;
|
||||
trend: ApiKeyUsageTrendPoint[]
|
||||
start_date: string
|
||||
end_date: string
|
||||
granularity: string
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -98,20 +104,24 @@ export interface ApiKeyTrendResponse {
|
||||
* @param params - Query parameters for filtering
|
||||
* @returns API key usage trend data
|
||||
*/
|
||||
export async function getApiKeyUsageTrend(params?: ApiKeyTrendParams): Promise<ApiKeyTrendResponse> {
|
||||
const { data } = await apiClient.get<ApiKeyTrendResponse>('/admin/dashboard/api-keys-trend', { params });
|
||||
return data;
|
||||
export async function getApiKeyUsageTrend(
|
||||
params?: ApiKeyTrendParams
|
||||
): Promise<ApiKeyTrendResponse> {
|
||||
const { data } = await apiClient.get<ApiKeyTrendResponse>('/admin/dashboard/api-keys-trend', {
|
||||
params
|
||||
})
|
||||
return data
|
||||
}
|
||||
|
||||
export interface UserTrendParams extends TrendParams {
|
||||
limit?: number;
|
||||
limit?: number
|
||||
}
|
||||
|
||||
export interface UserTrendResponse {
|
||||
trend: UserUsageTrendPoint[];
|
||||
start_date: string;
|
||||
end_date: string;
|
||||
granularity: string;
|
||||
trend: UserUsageTrendPoint[]
|
||||
start_date: string
|
||||
end_date: string
|
||||
granularity: string
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -120,18 +130,20 @@ export interface UserTrendResponse {
|
||||
* @returns User usage trend data
|
||||
*/
|
||||
export async function getUserUsageTrend(params?: UserTrendParams): Promise<UserTrendResponse> {
|
||||
const { data } = await apiClient.get<UserTrendResponse>('/admin/dashboard/users-trend', { params });
|
||||
return data;
|
||||
const { data } = await apiClient.get<UserTrendResponse>('/admin/dashboard/users-trend', {
|
||||
params
|
||||
})
|
||||
return data
|
||||
}
|
||||
|
||||
export interface BatchUserUsageStats {
|
||||
user_id: number;
|
||||
today_actual_cost: number;
|
||||
total_actual_cost: number;
|
||||
user_id: number
|
||||
today_actual_cost: number
|
||||
total_actual_cost: number
|
||||
}
|
||||
|
||||
export interface BatchUsersUsageResponse {
|
||||
stats: Record<string, BatchUserUsageStats>;
|
||||
stats: Record<string, BatchUserUsageStats>
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -141,19 +153,19 @@ export interface BatchUsersUsageResponse {
|
||||
*/
|
||||
export async function getBatchUsersUsage(userIds: number[]): Promise<BatchUsersUsageResponse> {
|
||||
const { data } = await apiClient.post<BatchUsersUsageResponse>('/admin/dashboard/users-usage', {
|
||||
user_ids: userIds,
|
||||
});
|
||||
return data;
|
||||
user_ids: userIds
|
||||
})
|
||||
return data
|
||||
}
|
||||
|
||||
export interface BatchApiKeyUsageStats {
|
||||
api_key_id: number;
|
||||
today_actual_cost: number;
|
||||
total_actual_cost: number;
|
||||
api_key_id: number
|
||||
today_actual_cost: number
|
||||
total_actual_cost: number
|
||||
}
|
||||
|
||||
export interface BatchApiKeysUsageResponse {
|
||||
stats: Record<string, BatchApiKeyUsageStats>;
|
||||
stats: Record<string, BatchApiKeyUsageStats>
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -161,11 +173,16 @@ export interface BatchApiKeysUsageResponse {
|
||||
* @param apiKeyIds - Array of API key IDs
|
||||
* @returns Usage stats map keyed by API key ID
|
||||
*/
|
||||
export async function getBatchApiKeysUsage(apiKeyIds: number[]): Promise<BatchApiKeysUsageResponse> {
|
||||
const { data } = await apiClient.post<BatchApiKeysUsageResponse>('/admin/dashboard/api-keys-usage', {
|
||||
api_key_ids: apiKeyIds,
|
||||
});
|
||||
return data;
|
||||
export async function getBatchApiKeysUsage(
|
||||
apiKeyIds: number[]
|
||||
): Promise<BatchApiKeysUsageResponse> {
|
||||
const { data } = await apiClient.post<BatchApiKeysUsageResponse>(
|
||||
'/admin/dashboard/api-keys-usage',
|
||||
{
|
||||
api_key_ids: apiKeyIds
|
||||
}
|
||||
)
|
||||
return data
|
||||
}
|
||||
|
||||
export const dashboardAPI = {
|
||||
@@ -176,7 +193,7 @@ export const dashboardAPI = {
|
||||
getApiKeyUsageTrend,
|
||||
getUserUsageTrend,
|
||||
getBatchUsersUsage,
|
||||
getBatchApiKeysUsage,
|
||||
};
|
||||
getBatchApiKeysUsage
|
||||
}
|
||||
|
||||
export default dashboardAPI;
|
||||
export default dashboardAPI
|
||||
|
||||
@@ -3,14 +3,14 @@
|
||||
* Handles API key group management for administrators
|
||||
*/
|
||||
|
||||
import { apiClient } from '../client';
|
||||
import { apiClient } from '../client'
|
||||
import type {
|
||||
Group,
|
||||
GroupPlatform,
|
||||
CreateGroupRequest,
|
||||
UpdateGroupRequest,
|
||||
PaginatedResponse,
|
||||
} from '@/types';
|
||||
PaginatedResponse
|
||||
} from '@/types'
|
||||
|
||||
/**
|
||||
* List all groups with pagination
|
||||
@@ -23,19 +23,19 @@ export async function list(
|
||||
page: number = 1,
|
||||
pageSize: number = 20,
|
||||
filters?: {
|
||||
platform?: GroupPlatform;
|
||||
status?: 'active' | 'inactive';
|
||||
is_exclusive?: boolean;
|
||||
platform?: GroupPlatform
|
||||
status?: 'active' | 'inactive'
|
||||
is_exclusive?: boolean
|
||||
}
|
||||
): Promise<PaginatedResponse<Group>> {
|
||||
const { data } = await apiClient.get<PaginatedResponse<Group>>('/admin/groups', {
|
||||
params: {
|
||||
page,
|
||||
page_size: pageSize,
|
||||
...filters,
|
||||
},
|
||||
});
|
||||
return data;
|
||||
...filters
|
||||
}
|
||||
})
|
||||
return data
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -46,8 +46,8 @@ export async function list(
|
||||
export async function getAll(platform?: GroupPlatform): Promise<Group[]> {
|
||||
const { data } = await apiClient.get<Group[]>('/admin/groups/all', {
|
||||
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
|
||||
*/
|
||||
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
|
||||
*/
|
||||
export async function getById(id: number): Promise<Group> {
|
||||
const { data } = await apiClient.get<Group>(`/admin/groups/${id}`);
|
||||
return data;
|
||||
const { data } = await apiClient.get<Group>(`/admin/groups/${id}`)
|
||||
return data
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -75,8 +75,8 @@ export async function getById(id: number): Promise<Group> {
|
||||
* @returns Created group
|
||||
*/
|
||||
export async function create(groupData: CreateGroupRequest): Promise<Group> {
|
||||
const { data } = await apiClient.post<Group>('/admin/groups', groupData);
|
||||
return data;
|
||||
const { data } = await apiClient.post<Group>('/admin/groups', groupData)
|
||||
return data
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -86,8 +86,8 @@ export async function create(groupData: CreateGroupRequest): Promise<Group> {
|
||||
* @returns Updated group
|
||||
*/
|
||||
export async function update(id: number, updates: UpdateGroupRequest): Promise<Group> {
|
||||
const { data } = await apiClient.put<Group>(`/admin/groups/${id}`, updates);
|
||||
return data;
|
||||
const { data } = await apiClient.put<Group>(`/admin/groups/${id}`, updates)
|
||||
return data
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -96,8 +96,8 @@ export async function update(id: number, updates: UpdateGroupRequest): Promise<G
|
||||
* @returns Success confirmation
|
||||
*/
|
||||
export async function deleteGroup(id: number): Promise<{ message: string }> {
|
||||
const { data } = await apiClient.delete<{ message: string }>(`/admin/groups/${id}`);
|
||||
return data;
|
||||
const { data } = await apiClient.delete<{ message: string }>(`/admin/groups/${id}`)
|
||||
return data
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -106,11 +106,8 @@ export async function deleteGroup(id: number): Promise<{ message: string }> {
|
||||
* @param status - New status
|
||||
* @returns Updated group
|
||||
*/
|
||||
export async function toggleStatus(
|
||||
id: number,
|
||||
status: 'active' | 'inactive'
|
||||
): Promise<Group> {
|
||||
return update(id, { status });
|
||||
export async function toggleStatus(id: number, status: 'active' | 'inactive'): Promise<Group> {
|
||||
return update(id, { status })
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -119,18 +116,18 @@ export async function toggleStatus(
|
||||
* @returns Group usage statistics
|
||||
*/
|
||||
export async function getStats(id: number): Promise<{
|
||||
total_api_keys: number;
|
||||
active_api_keys: number;
|
||||
total_requests: number;
|
||||
total_cost: number;
|
||||
total_api_keys: number
|
||||
active_api_keys: number
|
||||
total_requests: number
|
||||
total_cost: number
|
||||
}> {
|
||||
const { data } = await apiClient.get<{
|
||||
total_api_keys: number;
|
||||
active_api_keys: number;
|
||||
total_requests: number;
|
||||
total_cost: number;
|
||||
}>(`/admin/groups/${id}/stats`);
|
||||
return data;
|
||||
total_api_keys: number
|
||||
active_api_keys: number
|
||||
total_requests: number
|
||||
total_cost: number
|
||||
}>(`/admin/groups/${id}/stats`)
|
||||
return data
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -145,13 +142,10 @@ export async function getGroupApiKeys(
|
||||
page: number = 1,
|
||||
pageSize: number = 20
|
||||
): Promise<PaginatedResponse<any>> {
|
||||
const { data } = await apiClient.get<PaginatedResponse<any>>(
|
||||
`/admin/groups/${id}/api-keys`,
|
||||
{
|
||||
params: { page, page_size: pageSize },
|
||||
}
|
||||
);
|
||||
return data;
|
||||
const { data } = await apiClient.get<PaginatedResponse<any>>(`/admin/groups/${id}/api-keys`, {
|
||||
params: { page, page_size: pageSize }
|
||||
})
|
||||
return data
|
||||
}
|
||||
|
||||
export const groupsAPI = {
|
||||
@@ -164,7 +158,7 @@ export const groupsAPI = {
|
||||
delete: deleteGroup,
|
||||
toggleStatus,
|
||||
getStats,
|
||||
getGroupApiKeys,
|
||||
};
|
||||
getGroupApiKeys
|
||||
}
|
||||
|
||||
export default groupsAPI;
|
||||
export default groupsAPI
|
||||
|
||||
@@ -3,16 +3,17 @@
|
||||
* Centralized exports for all admin API modules
|
||||
*/
|
||||
|
||||
import dashboardAPI from './dashboard';
|
||||
import usersAPI from './users';
|
||||
import groupsAPI from './groups';
|
||||
import accountsAPI from './accounts';
|
||||
import proxiesAPI from './proxies';
|
||||
import redeemAPI from './redeem';
|
||||
import settingsAPI from './settings';
|
||||
import systemAPI from './system';
|
||||
import subscriptionsAPI from './subscriptions';
|
||||
import usageAPI from './usage';
|
||||
import dashboardAPI from './dashboard'
|
||||
import usersAPI from './users'
|
||||
import groupsAPI from './groups'
|
||||
import accountsAPI from './accounts'
|
||||
import proxiesAPI from './proxies'
|
||||
import redeemAPI from './redeem'
|
||||
import settingsAPI from './settings'
|
||||
import systemAPI from './system'
|
||||
import subscriptionsAPI from './subscriptions'
|
||||
import usageAPI from './usage'
|
||||
import geminiAPI from './gemini'
|
||||
|
||||
/**
|
||||
* Unified admin API object for convenient access
|
||||
@@ -28,8 +29,21 @@ export const adminAPI = {
|
||||
system: systemAPI,
|
||||
subscriptions: subscriptionsAPI,
|
||||
usage: usageAPI,
|
||||
};
|
||||
gemini: geminiAPI
|
||||
}
|
||||
|
||||
export { dashboardAPI, usersAPI, groupsAPI, accountsAPI, proxiesAPI, redeemAPI, settingsAPI, systemAPI, subscriptionsAPI, usageAPI };
|
||||
export {
|
||||
dashboardAPI,
|
||||
usersAPI,
|
||||
groupsAPI,
|
||||
accountsAPI,
|
||||
proxiesAPI,
|
||||
redeemAPI,
|
||||
settingsAPI,
|
||||
systemAPI,
|
||||
subscriptionsAPI,
|
||||
usageAPI,
|
||||
geminiAPI
|
||||
}
|
||||
|
||||
export default adminAPI;
|
||||
export default adminAPI
|
||||
|
||||
@@ -3,13 +3,8 @@
|
||||
* Handles proxy server management for administrators
|
||||
*/
|
||||
|
||||
import { apiClient } from '../client';
|
||||
import type {
|
||||
Proxy,
|
||||
CreateProxyRequest,
|
||||
UpdateProxyRequest,
|
||||
PaginatedResponse,
|
||||
} from '@/types';
|
||||
import { apiClient } from '../client'
|
||||
import type { Proxy, CreateProxyRequest, UpdateProxyRequest, PaginatedResponse } from '@/types'
|
||||
|
||||
/**
|
||||
* List all proxies with pagination
|
||||
@@ -22,19 +17,19 @@ export async function list(
|
||||
page: number = 1,
|
||||
pageSize: number = 20,
|
||||
filters?: {
|
||||
protocol?: string;
|
||||
status?: 'active' | 'inactive';
|
||||
search?: string;
|
||||
protocol?: string
|
||||
status?: 'active' | 'inactive'
|
||||
search?: string
|
||||
}
|
||||
): Promise<PaginatedResponse<Proxy>> {
|
||||
const { data } = await apiClient.get<PaginatedResponse<Proxy>>('/admin/proxies', {
|
||||
params: {
|
||||
page,
|
||||
page_size: pageSize,
|
||||
...filters,
|
||||
},
|
||||
});
|
||||
return data;
|
||||
...filters
|
||||
}
|
||||
})
|
||||
return data
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -42,8 +37,8 @@ export async function list(
|
||||
* @returns List of all active proxies
|
||||
*/
|
||||
export async function getAll(): Promise<Proxy[]> {
|
||||
const { data } = await apiClient.get<Proxy[]>('/admin/proxies/all');
|
||||
return data;
|
||||
const { data } = await apiClient.get<Proxy[]>('/admin/proxies/all')
|
||||
return data
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -52,9 +47,9 @@ export async function getAll(): Promise<Proxy[]> {
|
||||
*/
|
||||
export async function getAllWithCount(): Promise<Proxy[]> {
|
||||
const { data } = await apiClient.get<Proxy[]>('/admin/proxies/all', {
|
||||
params: { with_count: 'true' },
|
||||
});
|
||||
return data;
|
||||
params: { with_count: 'true' }
|
||||
})
|
||||
return data
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -63,8 +58,8 @@ export async function getAllWithCount(): Promise<Proxy[]> {
|
||||
* @returns Proxy details
|
||||
*/
|
||||
export async function getById(id: number): Promise<Proxy> {
|
||||
const { data } = await apiClient.get<Proxy>(`/admin/proxies/${id}`);
|
||||
return data;
|
||||
const { data } = await apiClient.get<Proxy>(`/admin/proxies/${id}`)
|
||||
return data
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -73,8 +68,8 @@ export async function getById(id: number): Promise<Proxy> {
|
||||
* @returns Created proxy
|
||||
*/
|
||||
export async function create(proxyData: CreateProxyRequest): Promise<Proxy> {
|
||||
const { data } = await apiClient.post<Proxy>('/admin/proxies', proxyData);
|
||||
return data;
|
||||
const { data } = await apiClient.post<Proxy>('/admin/proxies', proxyData)
|
||||
return data
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -84,8 +79,8 @@ export async function create(proxyData: CreateProxyRequest): Promise<Proxy> {
|
||||
* @returns Updated proxy
|
||||
*/
|
||||
export async function update(id: number, updates: UpdateProxyRequest): Promise<Proxy> {
|
||||
const { data } = await apiClient.put<Proxy>(`/admin/proxies/${id}`, updates);
|
||||
return data;
|
||||
const { data } = await apiClient.put<Proxy>(`/admin/proxies/${id}`, updates)
|
||||
return data
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -94,8 +89,8 @@ export async function update(id: number, updates: UpdateProxyRequest): Promise<P
|
||||
* @returns Success confirmation
|
||||
*/
|
||||
export async function deleteProxy(id: number): Promise<{ message: string }> {
|
||||
const { data } = await apiClient.delete<{ message: string }>(`/admin/proxies/${id}`);
|
||||
return data;
|
||||
const { data } = await apiClient.delete<{ message: string }>(`/admin/proxies/${id}`)
|
||||
return data
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -104,11 +99,8 @@ export async function deleteProxy(id: number): Promise<{ message: string }> {
|
||||
* @param status - New status
|
||||
* @returns Updated proxy
|
||||
*/
|
||||
export async function toggleStatus(
|
||||
id: number,
|
||||
status: 'active' | 'inactive'
|
||||
): Promise<Proxy> {
|
||||
return update(id, { status });
|
||||
export async function toggleStatus(id: number, status: 'active' | 'inactive'): Promise<Proxy> {
|
||||
return update(id, { status })
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -117,24 +109,24 @@ export async function toggleStatus(
|
||||
* @returns Test result with IP info
|
||||
*/
|
||||
export async function testProxy(id: number): Promise<{
|
||||
success: boolean;
|
||||
message: string;
|
||||
latency_ms?: number;
|
||||
ip_address?: string;
|
||||
city?: string;
|
||||
region?: string;
|
||||
country?: string;
|
||||
success: boolean
|
||||
message: string
|
||||
latency_ms?: number
|
||||
ip_address?: string
|
||||
city?: string
|
||||
region?: string
|
||||
country?: string
|
||||
}> {
|
||||
const { data } = await apiClient.post<{
|
||||
success: boolean;
|
||||
message: string;
|
||||
latency_ms?: number;
|
||||
ip_address?: string;
|
||||
city?: string;
|
||||
region?: string;
|
||||
country?: string;
|
||||
}>(`/admin/proxies/${id}/test`);
|
||||
return data;
|
||||
success: boolean
|
||||
message: string
|
||||
latency_ms?: number
|
||||
ip_address?: string
|
||||
city?: string
|
||||
region?: string
|
||||
country?: string
|
||||
}>(`/admin/proxies/${id}/test`)
|
||||
return data
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -143,20 +135,20 @@ export async function testProxy(id: number): Promise<{
|
||||
* @returns Proxy usage statistics
|
||||
*/
|
||||
export async function getStats(id: number): Promise<{
|
||||
total_accounts: number;
|
||||
active_accounts: number;
|
||||
total_requests: number;
|
||||
success_rate: number;
|
||||
average_latency: number;
|
||||
total_accounts: number
|
||||
active_accounts: number
|
||||
total_requests: number
|
||||
success_rate: number
|
||||
average_latency: number
|
||||
}> {
|
||||
const { data } = await apiClient.get<{
|
||||
total_accounts: number;
|
||||
active_accounts: number;
|
||||
total_requests: number;
|
||||
success_rate: number;
|
||||
average_latency: number;
|
||||
}>(`/admin/proxies/${id}/stats`);
|
||||
return data;
|
||||
total_accounts: number
|
||||
active_accounts: number
|
||||
total_requests: number
|
||||
success_rate: number
|
||||
average_latency: number
|
||||
}>(`/admin/proxies/${id}/stats`)
|
||||
return data
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -165,10 +157,8 @@ export async function getStats(id: number): Promise<{
|
||||
* @returns List of accounts using the proxy
|
||||
*/
|
||||
export async function getProxyAccounts(id: number): Promise<PaginatedResponse<any>> {
|
||||
const { data } = await apiClient.get<PaginatedResponse<any>>(
|
||||
`/admin/proxies/${id}/accounts`
|
||||
);
|
||||
return data;
|
||||
const { data } = await apiClient.get<PaginatedResponse<any>>(`/admin/proxies/${id}/accounts`)
|
||||
return data
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -176,21 +166,23 @@ export async function getProxyAccounts(id: number): Promise<PaginatedResponse<an
|
||||
* @param proxies - Array of proxy data to create
|
||||
* @returns Creation result with count of created and skipped
|
||||
*/
|
||||
export async function batchCreate(proxies: Array<{
|
||||
protocol: string;
|
||||
host: string;
|
||||
port: number;
|
||||
username?: string;
|
||||
password?: string;
|
||||
}>): Promise<{
|
||||
created: number;
|
||||
skipped: number;
|
||||
export async function batchCreate(
|
||||
proxies: Array<{
|
||||
protocol: string
|
||||
host: string
|
||||
port: number
|
||||
username?: string
|
||||
password?: string
|
||||
}>
|
||||
): Promise<{
|
||||
created: number
|
||||
skipped: number
|
||||
}> {
|
||||
const { data } = await apiClient.post<{
|
||||
created: number;
|
||||
skipped: number;
|
||||
}>('/admin/proxies/batch', { proxies });
|
||||
return data;
|
||||
created: number
|
||||
skipped: number
|
||||
}>('/admin/proxies/batch', { proxies })
|
||||
return data
|
||||
}
|
||||
|
||||
export const proxiesAPI = {
|
||||
@@ -205,7 +197,7 @@ export const proxiesAPI = {
|
||||
testProxy,
|
||||
getStats,
|
||||
getProxyAccounts,
|
||||
batchCreate,
|
||||
};
|
||||
batchCreate
|
||||
}
|
||||
|
||||
export default proxiesAPI;
|
||||
export default proxiesAPI
|
||||
|
||||
@@ -3,13 +3,13 @@
|
||||
* Handles redeem code generation and management for administrators
|
||||
*/
|
||||
|
||||
import { apiClient } from '../client';
|
||||
import { apiClient } from '../client'
|
||||
import type {
|
||||
RedeemCode,
|
||||
GenerateRedeemCodesRequest,
|
||||
RedeemCodeType,
|
||||
PaginatedResponse,
|
||||
} from '@/types';
|
||||
PaginatedResponse
|
||||
} from '@/types'
|
||||
|
||||
/**
|
||||
* List all redeem codes with pagination
|
||||
@@ -22,19 +22,19 @@ export async function list(
|
||||
page: number = 1,
|
||||
pageSize: number = 20,
|
||||
filters?: {
|
||||
type?: RedeemCodeType;
|
||||
status?: 'active' | 'used' | 'expired' | 'unused';
|
||||
search?: string;
|
||||
type?: RedeemCodeType
|
||||
status?: 'active' | 'used' | 'expired' | 'unused'
|
||||
search?: string
|
||||
}
|
||||
): Promise<PaginatedResponse<RedeemCode>> {
|
||||
const { data } = await apiClient.get<PaginatedResponse<RedeemCode>>('/admin/redeem-codes', {
|
||||
params: {
|
||||
page,
|
||||
page_size: pageSize,
|
||||
...filters,
|
||||
},
|
||||
});
|
||||
return data;
|
||||
...filters
|
||||
}
|
||||
})
|
||||
return data
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -43,8 +43,8 @@ export async function list(
|
||||
* @returns Redeem code details
|
||||
*/
|
||||
export async function getById(id: number): Promise<RedeemCode> {
|
||||
const { data } = await apiClient.get<RedeemCode>(`/admin/redeem-codes/${id}`);
|
||||
return data;
|
||||
const { data } = await apiClient.get<RedeemCode>(`/admin/redeem-codes/${id}`)
|
||||
return data
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -66,19 +66,19 @@ export async function generate(
|
||||
const payload: GenerateRedeemCodesRequest = {
|
||||
count,
|
||||
type,
|
||||
value,
|
||||
};
|
||||
value
|
||||
}
|
||||
|
||||
// 订阅类型专用字段
|
||||
if (type === 'subscription') {
|
||||
payload.group_id = groupId;
|
||||
payload.group_id = groupId
|
||||
if (validityDays && validityDays > 0) {
|
||||
payload.validity_days = validityDays;
|
||||
payload.validity_days = validityDays
|
||||
}
|
||||
}
|
||||
|
||||
const { data } = await apiClient.post<RedeemCode[]>('/admin/redeem-codes/generate', payload);
|
||||
return data;
|
||||
const { data } = await apiClient.post<RedeemCode[]>('/admin/redeem-codes/generate', payload)
|
||||
return data
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -87,8 +87,8 @@ export async function generate(
|
||||
* @returns Success confirmation
|
||||
*/
|
||||
export async function deleteCode(id: number): Promise<{ message: string }> {
|
||||
const { data } = await apiClient.delete<{ message: string }>(`/admin/redeem-codes/${id}`);
|
||||
return data;
|
||||
const { data } = await apiClient.delete<{ message: string }>(`/admin/redeem-codes/${id}`)
|
||||
return data
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -97,14 +97,14 @@ export async function deleteCode(id: number): Promise<{ message: string }> {
|
||||
* @returns Success confirmation
|
||||
*/
|
||||
export async function batchDelete(ids: number[]): Promise<{
|
||||
deleted: number;
|
||||
message: string;
|
||||
deleted: number
|
||||
message: string
|
||||
}> {
|
||||
const { data } = await apiClient.post<{
|
||||
deleted: number;
|
||||
message: string;
|
||||
}>('/admin/redeem-codes/batch-delete', { ids });
|
||||
return data;
|
||||
deleted: number
|
||||
message: string
|
||||
}>('/admin/redeem-codes/batch-delete', { ids })
|
||||
return data
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -113,8 +113,8 @@ export async function batchDelete(ids: number[]): Promise<{
|
||||
* @returns Updated redeem code
|
||||
*/
|
||||
export async function expire(id: number): Promise<RedeemCode> {
|
||||
const { data } = await apiClient.post<RedeemCode>(`/admin/redeem-codes/${id}/expire`);
|
||||
return data;
|
||||
const { data } = await apiClient.post<RedeemCode>(`/admin/redeem-codes/${id}/expire`)
|
||||
return data
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -122,22 +122,22 @@ export async function expire(id: number): Promise<RedeemCode> {
|
||||
* @returns Statistics about redeem codes
|
||||
*/
|
||||
export async function getStats(): Promise<{
|
||||
total_codes: number;
|
||||
active_codes: number;
|
||||
used_codes: number;
|
||||
expired_codes: number;
|
||||
total_value_distributed: number;
|
||||
by_type: Record<RedeemCodeType, number>;
|
||||
total_codes: number
|
||||
active_codes: number
|
||||
used_codes: number
|
||||
expired_codes: number
|
||||
total_value_distributed: number
|
||||
by_type: Record<RedeemCodeType, number>
|
||||
}> {
|
||||
const { data } = await apiClient.get<{
|
||||
total_codes: number;
|
||||
active_codes: number;
|
||||
used_codes: number;
|
||||
expired_codes: number;
|
||||
total_value_distributed: number;
|
||||
by_type: Record<RedeemCodeType, number>;
|
||||
}>('/admin/redeem-codes/stats');
|
||||
return data;
|
||||
total_codes: number
|
||||
active_codes: number
|
||||
used_codes: number
|
||||
expired_codes: number
|
||||
total_value_distributed: number
|
||||
by_type: Record<RedeemCodeType, number>
|
||||
}>('/admin/redeem-codes/stats')
|
||||
return data
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -146,14 +146,14 @@ export async function getStats(): Promise<{
|
||||
* @returns CSV data as blob
|
||||
*/
|
||||
export async function exportCodes(filters?: {
|
||||
type?: RedeemCodeType;
|
||||
status?: 'active' | 'used' | 'expired';
|
||||
type?: RedeemCodeType
|
||||
status?: 'active' | 'used' | 'expired'
|
||||
}): Promise<Blob> {
|
||||
const response = await apiClient.get('/admin/redeem-codes/export', {
|
||||
params: filters,
|
||||
responseType: 'blob',
|
||||
});
|
||||
return response.data;
|
||||
responseType: 'blob'
|
||||
})
|
||||
return response.data
|
||||
}
|
||||
|
||||
export const redeemAPI = {
|
||||
@@ -164,7 +164,7 @@ export const redeemAPI = {
|
||||
batchDelete,
|
||||
expire,
|
||||
getStats,
|
||||
exportCodes,
|
||||
};
|
||||
exportCodes
|
||||
}
|
||||
|
||||
export default redeemAPI;
|
||||
export default redeemAPI
|
||||
|
||||
@@ -3,37 +3,37 @@
|
||||
* Handles system settings management for administrators
|
||||
*/
|
||||
|
||||
import { apiClient } from '../client';
|
||||
import { apiClient } from '../client'
|
||||
|
||||
/**
|
||||
* System settings interface
|
||||
*/
|
||||
export interface SystemSettings {
|
||||
// Registration settings
|
||||
registration_enabled: boolean;
|
||||
email_verify_enabled: boolean;
|
||||
registration_enabled: boolean
|
||||
email_verify_enabled: boolean
|
||||
// Default settings
|
||||
default_balance: number;
|
||||
default_concurrency: number;
|
||||
default_balance: number
|
||||
default_concurrency: number
|
||||
// OEM settings
|
||||
site_name: string;
|
||||
site_logo: string;
|
||||
site_subtitle: string;
|
||||
api_base_url: string;
|
||||
contact_info: string;
|
||||
doc_url: string;
|
||||
site_name: string
|
||||
site_logo: string
|
||||
site_subtitle: string
|
||||
api_base_url: string
|
||||
contact_info: string
|
||||
doc_url: string
|
||||
// SMTP settings
|
||||
smtp_host: string;
|
||||
smtp_port: number;
|
||||
smtp_username: string;
|
||||
smtp_password: string;
|
||||
smtp_from_email: string;
|
||||
smtp_from_name: string;
|
||||
smtp_use_tls: boolean;
|
||||
smtp_host: string
|
||||
smtp_port: number
|
||||
smtp_username: string
|
||||
smtp_password: string
|
||||
smtp_from_email: string
|
||||
smtp_from_name: string
|
||||
smtp_use_tls: boolean
|
||||
// Cloudflare Turnstile settings
|
||||
turnstile_enabled: boolean;
|
||||
turnstile_site_key: string;
|
||||
turnstile_secret_key: string;
|
||||
turnstile_enabled: boolean
|
||||
turnstile_site_key: string
|
||||
turnstile_secret_key: string
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -41,8 +41,8 @@ export interface SystemSettings {
|
||||
* @returns System settings
|
||||
*/
|
||||
export async function getSettings(): Promise<SystemSettings> {
|
||||
const { data } = await apiClient.get<SystemSettings>('/admin/settings');
|
||||
return data;
|
||||
const { data } = await apiClient.get<SystemSettings>('/admin/settings')
|
||||
return data
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -51,19 +51,19 @@ export async function getSettings(): Promise<SystemSettings> {
|
||||
* @returns Updated settings
|
||||
*/
|
||||
export async function updateSettings(settings: Partial<SystemSettings>): Promise<SystemSettings> {
|
||||
const { data } = await apiClient.put<SystemSettings>('/admin/settings', settings);
|
||||
return data;
|
||||
const { data } = await apiClient.put<SystemSettings>('/admin/settings', settings)
|
||||
return data
|
||||
}
|
||||
|
||||
/**
|
||||
* Test SMTP connection request
|
||||
*/
|
||||
export interface TestSmtpRequest {
|
||||
smtp_host: string;
|
||||
smtp_port: number;
|
||||
smtp_username: string;
|
||||
smtp_password: string;
|
||||
smtp_use_tls: boolean;
|
||||
smtp_host: string
|
||||
smtp_port: number
|
||||
smtp_username: string
|
||||
smtp_password: string
|
||||
smtp_use_tls: boolean
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -72,22 +72,22 @@ export interface TestSmtpRequest {
|
||||
* @returns Test result message
|
||||
*/
|
||||
export async function testSmtpConnection(config: TestSmtpRequest): Promise<{ message: string }> {
|
||||
const { data } = await apiClient.post<{ message: string }>('/admin/settings/test-smtp', config);
|
||||
return data;
|
||||
const { data } = await apiClient.post<{ message: string }>('/admin/settings/test-smtp', config)
|
||||
return data
|
||||
}
|
||||
|
||||
/**
|
||||
* Send test email request
|
||||
*/
|
||||
export interface SendTestEmailRequest {
|
||||
email: string;
|
||||
smtp_host: string;
|
||||
smtp_port: number;
|
||||
smtp_username: string;
|
||||
smtp_password: string;
|
||||
smtp_from_email: string;
|
||||
smtp_from_name: string;
|
||||
smtp_use_tls: boolean;
|
||||
email: string
|
||||
smtp_host: string
|
||||
smtp_port: number
|
||||
smtp_username: string
|
||||
smtp_password: string
|
||||
smtp_from_email: string
|
||||
smtp_from_name: string
|
||||
smtp_use_tls: boolean
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -96,16 +96,19 @@ export interface SendTestEmailRequest {
|
||||
* @returns Test result message
|
||||
*/
|
||||
export async function sendTestEmail(request: SendTestEmailRequest): Promise<{ message: string }> {
|
||||
const { data } = await apiClient.post<{ message: string }>('/admin/settings/send-test-email', request);
|
||||
return data;
|
||||
const { data } = await apiClient.post<{ message: string }>(
|
||||
'/admin/settings/send-test-email',
|
||||
request
|
||||
)
|
||||
return data
|
||||
}
|
||||
|
||||
/**
|
||||
* Admin API Key status response
|
||||
*/
|
||||
export interface AdminApiKeyStatus {
|
||||
exists: boolean;
|
||||
masked_key: string;
|
||||
exists: boolean
|
||||
masked_key: string
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -113,8 +116,8 @@ export interface AdminApiKeyStatus {
|
||||
* @returns Status indicating if key exists and masked version
|
||||
*/
|
||||
export async function getAdminApiKey(): Promise<AdminApiKeyStatus> {
|
||||
const { data } = await apiClient.get<AdminApiKeyStatus>('/admin/settings/admin-api-key');
|
||||
return data;
|
||||
const { data } = await apiClient.get<AdminApiKeyStatus>('/admin/settings/admin-api-key')
|
||||
return data
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -122,8 +125,8 @@ export async function getAdminApiKey(): Promise<AdminApiKeyStatus> {
|
||||
* @returns The new full API key (only shown once)
|
||||
*/
|
||||
export async function regenerateAdminApiKey(): Promise<{ key: string }> {
|
||||
const { data } = await apiClient.post<{ key: string }>('/admin/settings/admin-api-key/regenerate');
|
||||
return data;
|
||||
const { data } = await apiClient.post<{ key: string }>('/admin/settings/admin-api-key/regenerate')
|
||||
return data
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -131,8 +134,8 @@ export async function regenerateAdminApiKey(): Promise<{ key: string }> {
|
||||
* @returns Success message
|
||||
*/
|
||||
export async function deleteAdminApiKey(): Promise<{ message: string }> {
|
||||
const { data } = await apiClient.delete<{ message: string }>('/admin/settings/admin-api-key');
|
||||
return data;
|
||||
const { data } = await apiClient.delete<{ message: string }>('/admin/settings/admin-api-key')
|
||||
return data
|
||||
}
|
||||
|
||||
export const settingsAPI = {
|
||||
@@ -142,7 +145,7 @@ export const settingsAPI = {
|
||||
sendTestEmail,
|
||||
getAdminApiKey,
|
||||
regenerateAdminApiKey,
|
||||
deleteAdminApiKey,
|
||||
};
|
||||
deleteAdminApiKey
|
||||
}
|
||||
|
||||
export default settingsAPI;
|
||||
export default settingsAPI
|
||||
|
||||
@@ -3,15 +3,15 @@
|
||||
* Handles user subscription management for administrators
|
||||
*/
|
||||
|
||||
import { apiClient } from '../client';
|
||||
import { apiClient } from '../client'
|
||||
import type {
|
||||
UserSubscription,
|
||||
SubscriptionProgress,
|
||||
AssignSubscriptionRequest,
|
||||
BulkAssignSubscriptionRequest,
|
||||
ExtendSubscriptionRequest,
|
||||
PaginatedResponse,
|
||||
} from '@/types';
|
||||
PaginatedResponse
|
||||
} from '@/types'
|
||||
|
||||
/**
|
||||
* List all subscriptions with pagination
|
||||
@@ -24,19 +24,22 @@ export async function list(
|
||||
page: number = 1,
|
||||
pageSize: number = 20,
|
||||
filters?: {
|
||||
status?: 'active' | 'expired' | 'revoked';
|
||||
user_id?: number;
|
||||
group_id?: number;
|
||||
status?: 'active' | 'expired' | 'revoked'
|
||||
user_id?: number
|
||||
group_id?: number
|
||||
}
|
||||
): Promise<PaginatedResponse<UserSubscription>> {
|
||||
const { data } = await apiClient.get<PaginatedResponse<UserSubscription>>('/admin/subscriptions', {
|
||||
params: {
|
||||
page,
|
||||
page_size: pageSize,
|
||||
...filters,
|
||||
},
|
||||
});
|
||||
return data;
|
||||
const { data } = await apiClient.get<PaginatedResponse<UserSubscription>>(
|
||||
'/admin/subscriptions',
|
||||
{
|
||||
params: {
|
||||
page,
|
||||
page_size: pageSize,
|
||||
...filters
|
||||
}
|
||||
}
|
||||
)
|
||||
return data
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -45,8 +48,8 @@ export async function list(
|
||||
* @returns Subscription details
|
||||
*/
|
||||
export async function getById(id: number): Promise<UserSubscription> {
|
||||
const { data } = await apiClient.get<UserSubscription>(`/admin/subscriptions/${id}`);
|
||||
return data;
|
||||
const { data } = await apiClient.get<UserSubscription>(`/admin/subscriptions/${id}`)
|
||||
return data
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -55,8 +58,8 @@ export async function getById(id: number): Promise<UserSubscription> {
|
||||
* @returns Subscription progress with usage stats
|
||||
*/
|
||||
export async function getProgress(id: number): Promise<SubscriptionProgress> {
|
||||
const { data } = await apiClient.get<SubscriptionProgress>(`/admin/subscriptions/${id}/progress`);
|
||||
return data;
|
||||
const { data } = await apiClient.get<SubscriptionProgress>(`/admin/subscriptions/${id}/progress`)
|
||||
return data
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -65,8 +68,8 @@ export async function getProgress(id: number): Promise<SubscriptionProgress> {
|
||||
* @returns Created subscription
|
||||
*/
|
||||
export async function assign(request: AssignSubscriptionRequest): Promise<UserSubscription> {
|
||||
const { data } = await apiClient.post<UserSubscription>('/admin/subscriptions/assign', request);
|
||||
return data;
|
||||
const { data } = await apiClient.post<UserSubscription>('/admin/subscriptions/assign', request)
|
||||
return data
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -74,9 +77,14 @@ export async function assign(request: AssignSubscriptionRequest): Promise<UserSu
|
||||
* @param request - Bulk assignment request
|
||||
* @returns Created subscriptions
|
||||
*/
|
||||
export async function bulkAssign(request: BulkAssignSubscriptionRequest): Promise<UserSubscription[]> {
|
||||
const { data } = await apiClient.post<UserSubscription[]>('/admin/subscriptions/bulk-assign', request);
|
||||
return data;
|
||||
export async function bulkAssign(
|
||||
request: BulkAssignSubscriptionRequest
|
||||
): 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
|
||||
* @returns Updated subscription
|
||||
*/
|
||||
export async function extend(id: number, request: ExtendSubscriptionRequest): Promise<UserSubscription> {
|
||||
const { data } = await apiClient.post<UserSubscription>(`/admin/subscriptions/${id}/extend`, request);
|
||||
return data;
|
||||
export async function extend(
|
||||
id: number,
|
||||
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
|
||||
*/
|
||||
export async function revoke(id: number): Promise<{ message: string }> {
|
||||
const { data } = await apiClient.delete<{ message: string }>(`/admin/subscriptions/${id}`);
|
||||
return data;
|
||||
const { data } = await apiClient.delete<{ message: string }>(`/admin/subscriptions/${id}`)
|
||||
return data
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -115,10 +129,10 @@ export async function listByGroup(
|
||||
const { data } = await apiClient.get<PaginatedResponse<UserSubscription>>(
|
||||
`/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>>(
|
||||
`/admin/users/${userId}/subscriptions`,
|
||||
{
|
||||
params: { page, page_size: pageSize },
|
||||
params: { page, page_size: pageSize }
|
||||
}
|
||||
);
|
||||
return data;
|
||||
)
|
||||
return data
|
||||
}
|
||||
|
||||
export const subscriptionsAPI = {
|
||||
@@ -151,7 +165,7 @@ export const subscriptionsAPI = {
|
||||
extend,
|
||||
revoke,
|
||||
listByGroup,
|
||||
listByUser,
|
||||
};
|
||||
listByUser
|
||||
}
|
||||
|
||||
export default subscriptionsAPI;
|
||||
export default subscriptionsAPI
|
||||
|
||||
@@ -2,31 +2,31 @@
|
||||
* System API endpoints for admin operations
|
||||
*/
|
||||
|
||||
import { apiClient } from '../client';
|
||||
import { apiClient } from '../client'
|
||||
|
||||
export interface ReleaseInfo {
|
||||
name: string;
|
||||
body: string;
|
||||
published_at: string;
|
||||
html_url: string;
|
||||
name: string
|
||||
body: string
|
||||
published_at: string
|
||||
html_url: string
|
||||
}
|
||||
|
||||
export interface VersionInfo {
|
||||
current_version: string;
|
||||
latest_version: string;
|
||||
has_update: boolean;
|
||||
release_info?: ReleaseInfo;
|
||||
cached: boolean;
|
||||
warning?: string;
|
||||
build_type: string; // "source" for manual builds, "release" for CI builds
|
||||
current_version: string
|
||||
latest_version: string
|
||||
has_update: boolean
|
||||
release_info?: ReleaseInfo
|
||||
cached: boolean
|
||||
warning?: string
|
||||
build_type: string // "source" for manual builds, "release" for CI builds
|
||||
}
|
||||
|
||||
/**
|
||||
* Get current version
|
||||
*/
|
||||
export async function getVersion(): Promise<{ version: string }> {
|
||||
const { data } = await apiClient.get<{ version: string }>('/admin/system/version');
|
||||
return data;
|
||||
const { data } = await apiClient.get<{ version: string }>('/admin/system/version')
|
||||
return data
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -35,14 +35,14 @@ export async function getVersion(): Promise<{ version: string }> {
|
||||
*/
|
||||
export async function checkUpdates(force = false): Promise<VersionInfo> {
|
||||
const { data } = await apiClient.get<VersionInfo>('/admin/system/check-updates', {
|
||||
params: force ? { force: 'true' } : undefined,
|
||||
});
|
||||
return data;
|
||||
params: force ? { force: 'true' } : undefined
|
||||
})
|
||||
return data
|
||||
}
|
||||
|
||||
export interface UpdateResult {
|
||||
message: string;
|
||||
need_restart: boolean;
|
||||
message: string
|
||||
need_restart: boolean
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -50,24 +50,24 @@ export interface UpdateResult {
|
||||
* Downloads and applies the latest version
|
||||
*/
|
||||
export async function performUpdate(): Promise<UpdateResult> {
|
||||
const { data } = await apiClient.post<UpdateResult>('/admin/system/update');
|
||||
return data;
|
||||
const { data } = await apiClient.post<UpdateResult>('/admin/system/update')
|
||||
return data
|
||||
}
|
||||
|
||||
/**
|
||||
* Rollback to previous version
|
||||
*/
|
||||
export async function rollback(): Promise<UpdateResult> {
|
||||
const { data } = await apiClient.post<UpdateResult>('/admin/system/rollback');
|
||||
return data;
|
||||
const { data } = await apiClient.post<UpdateResult>('/admin/system/rollback')
|
||||
return data
|
||||
}
|
||||
|
||||
/**
|
||||
* Restart the service
|
||||
*/
|
||||
export async function restartService(): Promise<{ message: string }> {
|
||||
const { data } = await apiClient.post<{ message: string }>('/admin/system/restart');
|
||||
return data;
|
||||
const { data } = await apiClient.post<{ message: string }>('/admin/system/restart')
|
||||
return data
|
||||
}
|
||||
|
||||
export const systemAPI = {
|
||||
@@ -75,7 +75,7 @@ export const systemAPI = {
|
||||
checkUpdates,
|
||||
performUpdate,
|
||||
rollback,
|
||||
restartService,
|
||||
};
|
||||
restartService
|
||||
}
|
||||
|
||||
export default systemAPI;
|
||||
export default systemAPI
|
||||
|
||||
@@ -3,39 +3,35 @@
|
||||
* Handles admin-level usage logs and statistics retrieval
|
||||
*/
|
||||
|
||||
import { apiClient } from '../client';
|
||||
import type {
|
||||
UsageLog,
|
||||
UsageQueryParams,
|
||||
PaginatedResponse,
|
||||
} from '@/types';
|
||||
import { apiClient } from '../client'
|
||||
import type { UsageLog, UsageQueryParams, PaginatedResponse } from '@/types'
|
||||
|
||||
// ==================== Types ====================
|
||||
|
||||
export interface AdminUsageStatsResponse {
|
||||
total_requests: number;
|
||||
total_input_tokens: number;
|
||||
total_output_tokens: number;
|
||||
total_cache_tokens: number;
|
||||
total_tokens: number;
|
||||
total_cost: number;
|
||||
total_actual_cost: number;
|
||||
average_duration_ms: number;
|
||||
total_requests: number
|
||||
total_input_tokens: number
|
||||
total_output_tokens: number
|
||||
total_cache_tokens: number
|
||||
total_tokens: number
|
||||
total_cost: number
|
||||
total_actual_cost: number
|
||||
average_duration_ms: number
|
||||
}
|
||||
|
||||
export interface SimpleUser {
|
||||
id: number;
|
||||
email: string;
|
||||
id: number
|
||||
email: string
|
||||
}
|
||||
|
||||
export interface SimpleApiKey {
|
||||
id: number;
|
||||
name: string;
|
||||
user_id: number;
|
||||
id: number
|
||||
name: string
|
||||
user_id: number
|
||||
}
|
||||
|
||||
export interface AdminUsageQueryParams extends UsageQueryParams {
|
||||
user_id?: number;
|
||||
user_id?: number
|
||||
}
|
||||
|
||||
// ==================== API Functions ====================
|
||||
@@ -47,9 +43,9 @@ export interface AdminUsageQueryParams extends UsageQueryParams {
|
||||
*/
|
||||
export async function list(params: AdminUsageQueryParams): Promise<PaginatedResponse<UsageLog>> {
|
||||
const { data } = await apiClient.get<PaginatedResponse<UsageLog>>('/admin/usage', {
|
||||
params,
|
||||
});
|
||||
return data;
|
||||
params
|
||||
})
|
||||
return data
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -58,16 +54,16 @@ export async function list(params: AdminUsageQueryParams): Promise<PaginatedResp
|
||||
* @returns Usage statistics
|
||||
*/
|
||||
export async function getStats(params: {
|
||||
user_id?: number;
|
||||
api_key_id?: number;
|
||||
period?: string;
|
||||
start_date?: string;
|
||||
end_date?: string;
|
||||
user_id?: number
|
||||
api_key_id?: number
|
||||
period?: string
|
||||
start_date?: string
|
||||
end_date?: string
|
||||
}): Promise<AdminUsageStatsResponse> {
|
||||
const { data } = await apiClient.get<AdminUsageStatsResponse>('/admin/usage/stats', {
|
||||
params,
|
||||
});
|
||||
return data;
|
||||
params
|
||||
})
|
||||
return data
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -77,9 +73,9 @@ export async function getStats(params: {
|
||||
*/
|
||||
export async function searchUsers(keyword: string): Promise<SimpleUser[]> {
|
||||
const { data } = await apiClient.get<SimpleUser[]>('/admin/usage/search-users', {
|
||||
params: { q: keyword },
|
||||
});
|
||||
return data;
|
||||
params: { q: keyword }
|
||||
})
|
||||
return data
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -89,24 +85,24 @@ export async function searchUsers(keyword: string): Promise<SimpleUser[]> {
|
||||
* @returns List of matching API keys (max 30)
|
||||
*/
|
||||
export async function searchApiKeys(userId?: number, keyword?: string): Promise<SimpleApiKey[]> {
|
||||
const params: Record<string, unknown> = {};
|
||||
const params: Record<string, unknown> = {}
|
||||
if (userId !== undefined) {
|
||||
params.user_id = userId;
|
||||
params.user_id = userId
|
||||
}
|
||||
if (keyword) {
|
||||
params.q = keyword;
|
||||
params.q = keyword
|
||||
}
|
||||
const { data } = await apiClient.get<SimpleApiKey[]>('/admin/usage/search-api-keys', {
|
||||
params,
|
||||
});
|
||||
return data;
|
||||
params
|
||||
})
|
||||
return data
|
||||
}
|
||||
|
||||
export const adminUsageAPI = {
|
||||
list,
|
||||
getStats,
|
||||
searchUsers,
|
||||
searchApiKeys,
|
||||
};
|
||||
searchApiKeys
|
||||
}
|
||||
|
||||
export default adminUsageAPI;
|
||||
export default adminUsageAPI
|
||||
|
||||
@@ -3,8 +3,8 @@
|
||||
* Handles user management for administrators
|
||||
*/
|
||||
|
||||
import { apiClient } from '../client';
|
||||
import type { User, UpdateUserRequest, PaginatedResponse } from '@/types';
|
||||
import { apiClient } from '../client'
|
||||
import type { User, UpdateUserRequest, PaginatedResponse } from '@/types'
|
||||
|
||||
/**
|
||||
* List all users with pagination
|
||||
@@ -17,19 +17,19 @@ export async function list(
|
||||
page: number = 1,
|
||||
pageSize: number = 20,
|
||||
filters?: {
|
||||
status?: 'active' | 'disabled';
|
||||
role?: 'admin' | 'user';
|
||||
search?: string;
|
||||
status?: 'active' | 'disabled'
|
||||
role?: 'admin' | 'user'
|
||||
search?: string
|
||||
}
|
||||
): Promise<PaginatedResponse<User>> {
|
||||
const { data } = await apiClient.get<PaginatedResponse<User>>('/admin/users', {
|
||||
params: {
|
||||
page,
|
||||
page_size: pageSize,
|
||||
...filters,
|
||||
},
|
||||
});
|
||||
return data;
|
||||
...filters
|
||||
}
|
||||
})
|
||||
return data
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -38,8 +38,8 @@ export async function list(
|
||||
* @returns User details
|
||||
*/
|
||||
export async function getById(id: number): Promise<User> {
|
||||
const { data } = await apiClient.get<User>(`/admin/users/${id}`);
|
||||
return data;
|
||||
const { data } = await apiClient.get<User>(`/admin/users/${id}`)
|
||||
return data
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -48,14 +48,14 @@ export async function getById(id: number): Promise<User> {
|
||||
* @returns Created user
|
||||
*/
|
||||
export async function create(userData: {
|
||||
email: string;
|
||||
password: string;
|
||||
balance?: number;
|
||||
concurrency?: number;
|
||||
allowed_groups?: number[] | null;
|
||||
email: string
|
||||
password: string
|
||||
balance?: number
|
||||
concurrency?: number
|
||||
allowed_groups?: number[] | null
|
||||
}): Promise<User> {
|
||||
const { data } = await apiClient.post<User>('/admin/users', userData);
|
||||
return data;
|
||||
const { data } = await apiClient.post<User>('/admin/users', userData)
|
||||
return data
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -65,8 +65,8 @@ export async function create(userData: {
|
||||
* @returns Updated user
|
||||
*/
|
||||
export async function update(id: number, updates: UpdateUserRequest): Promise<User> {
|
||||
const { data } = await apiClient.put<User>(`/admin/users/${id}`, updates);
|
||||
return data;
|
||||
const { data } = await apiClient.put<User>(`/admin/users/${id}`, updates)
|
||||
return data
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -75,8 +75,8 @@ export async function update(id: number, updates: UpdateUserRequest): Promise<Us
|
||||
* @returns Success confirmation
|
||||
*/
|
||||
export async function deleteUser(id: number): Promise<{ message: string }> {
|
||||
const { data } = await apiClient.delete<{ message: string }>(`/admin/users/${id}`);
|
||||
return data;
|
||||
const { data } = await apiClient.delete<{ message: string }>(`/admin/users/${id}`)
|
||||
return data
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -96,9 +96,9 @@ export async function updateBalance(
|
||||
const { data } = await apiClient.post<User>(`/admin/users/${id}/balance`, {
|
||||
balance,
|
||||
operation,
|
||||
notes: notes || '',
|
||||
});
|
||||
return data;
|
||||
notes: notes || ''
|
||||
})
|
||||
return data
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -108,7 +108,7 @@ export async function updateBalance(
|
||||
* @returns Updated user
|
||||
*/
|
||||
export async function updateConcurrency(id: number, concurrency: number): Promise<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
|
||||
*/
|
||||
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
|
||||
*/
|
||||
export async function getUserApiKeys(id: number): Promise<PaginatedResponse<any>> {
|
||||
const { data } = await apiClient.get<PaginatedResponse<any>>(`/admin/users/${id}/api-keys`);
|
||||
return data;
|
||||
const { data } = await apiClient.get<PaginatedResponse<any>>(`/admin/users/${id}/api-keys`)
|
||||
return data
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -141,18 +141,18 @@ export async function getUserUsageStats(
|
||||
id: number,
|
||||
period: string = 'month'
|
||||
): Promise<{
|
||||
total_requests: number;
|
||||
total_cost: number;
|
||||
total_tokens: number;
|
||||
total_requests: number
|
||||
total_cost: number
|
||||
total_tokens: number
|
||||
}> {
|
||||
const { data } = await apiClient.get<{
|
||||
total_requests: number;
|
||||
total_cost: number;
|
||||
total_tokens: number;
|
||||
total_requests: number
|
||||
total_cost: number
|
||||
total_tokens: number
|
||||
}>(`/admin/users/${id}/usage`, {
|
||||
params: { period },
|
||||
});
|
||||
return data;
|
||||
params: { period }
|
||||
})
|
||||
return data
|
||||
}
|
||||
|
||||
export const usersAPI = {
|
||||
@@ -165,7 +165,7 @@ export const usersAPI = {
|
||||
updateConcurrency,
|
||||
toggleStatus,
|
||||
getUserApiKeys,
|
||||
getUserUsageStats,
|
||||
};
|
||||
getUserUsageStats
|
||||
}
|
||||
|
||||
export default usersAPI;
|
||||
export default usersAPI
|
||||
|
||||
@@ -3,29 +3,37 @@
|
||||
* Handles user login, registration, and logout operations
|
||||
*/
|
||||
|
||||
import { apiClient } from './client';
|
||||
import type { LoginRequest, RegisterRequest, AuthResponse, User, SendVerifyCodeRequest, SendVerifyCodeResponse, PublicSettings } from '@/types';
|
||||
import { apiClient } from './client'
|
||||
import type {
|
||||
LoginRequest,
|
||||
RegisterRequest,
|
||||
AuthResponse,
|
||||
User,
|
||||
SendVerifyCodeRequest,
|
||||
SendVerifyCodeResponse,
|
||||
PublicSettings
|
||||
} from '@/types'
|
||||
|
||||
/**
|
||||
* Store authentication token in localStorage
|
||||
*/
|
||||
export function setAuthToken(token: string): void {
|
||||
localStorage.setItem('auth_token', token);
|
||||
localStorage.setItem('auth_token', token)
|
||||
}
|
||||
|
||||
/**
|
||||
* Get authentication token from localStorage
|
||||
*/
|
||||
export function getAuthToken(): string | null {
|
||||
return localStorage.getItem('auth_token');
|
||||
return localStorage.getItem('auth_token')
|
||||
}
|
||||
|
||||
/**
|
||||
* Clear authentication token from localStorage
|
||||
*/
|
||||
export function clearAuthToken(): void {
|
||||
localStorage.removeItem('auth_token');
|
||||
localStorage.removeItem('auth_user');
|
||||
localStorage.removeItem('auth_token')
|
||||
localStorage.removeItem('auth_user')
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -34,13 +42,13 @@ export function clearAuthToken(): void {
|
||||
* @returns Authentication response with token and user data
|
||||
*/
|
||||
export async function login(credentials: LoginRequest): Promise<AuthResponse> {
|
||||
const { data } = await apiClient.post<AuthResponse>('/auth/login', credentials);
|
||||
const { data } = await apiClient.post<AuthResponse>('/auth/login', credentials)
|
||||
|
||||
// Store token and user data
|
||||
setAuthToken(data.access_token);
|
||||
localStorage.setItem('auth_user', JSON.stringify(data.user));
|
||||
setAuthToken(data.access_token)
|
||||
localStorage.setItem('auth_user', JSON.stringify(data.user))
|
||||
|
||||
return data;
|
||||
return data
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -49,13 +57,13 @@ export async function login(credentials: LoginRequest): Promise<AuthResponse> {
|
||||
* @returns Authentication response with token and user data
|
||||
*/
|
||||
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
|
||||
setAuthToken(data.access_token);
|
||||
localStorage.setItem('auth_user', JSON.stringify(data.user));
|
||||
setAuthToken(data.access_token)
|
||||
localStorage.setItem('auth_user', JSON.stringify(data.user))
|
||||
|
||||
return data;
|
||||
return data
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -63,8 +71,8 @@ export async function register(userData: RegisterRequest): Promise<AuthResponse>
|
||||
* @returns User profile data
|
||||
*/
|
||||
export async function getCurrentUser(): Promise<User> {
|
||||
const { data } = await apiClient.get<User>('/auth/me');
|
||||
return data;
|
||||
const { data } = await apiClient.get<User>('/auth/me')
|
||||
return data
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -72,7 +80,7 @@ export async function getCurrentUser(): Promise<User> {
|
||||
* Clears authentication token and user data from localStorage
|
||||
*/
|
||||
export function logout(): void {
|
||||
clearAuthToken();
|
||||
clearAuthToken()
|
||||
// Optionally redirect to login page
|
||||
// window.location.href = '/login';
|
||||
}
|
||||
@@ -82,7 +90,7 @@ export function logout(): void {
|
||||
* @returns True if user has valid token
|
||||
*/
|
||||
export function isAuthenticated(): boolean {
|
||||
return getAuthToken() !== null;
|
||||
return getAuthToken() !== null
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -90,8 +98,8 @@ export function isAuthenticated(): boolean {
|
||||
* @returns Public settings including registration and Turnstile config
|
||||
*/
|
||||
export async function getPublicSettings(): Promise<PublicSettings> {
|
||||
const { data } = await apiClient.get<PublicSettings>('/settings/public');
|
||||
return data;
|
||||
const { data } = await apiClient.get<PublicSettings>('/settings/public')
|
||||
return data
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -99,9 +107,11 @@ export async function getPublicSettings(): Promise<PublicSettings> {
|
||||
* @param request - Email and optional Turnstile token
|
||||
* @returns Response with countdown seconds
|
||||
*/
|
||||
export async function sendVerifyCode(request: SendVerifyCodeRequest): Promise<SendVerifyCodeResponse> {
|
||||
const { data } = await apiClient.post<SendVerifyCodeResponse>('/auth/send-verify-code', request);
|
||||
return data;
|
||||
export async function sendVerifyCode(
|
||||
request: SendVerifyCodeRequest
|
||||
): Promise<SendVerifyCodeResponse> {
|
||||
const { data } = await apiClient.post<SendVerifyCodeResponse>('/auth/send-verify-code', request)
|
||||
return data
|
||||
}
|
||||
|
||||
export const authAPI = {
|
||||
@@ -114,7 +124,7 @@ export const authAPI = {
|
||||
getAuthToken,
|
||||
clearAuthToken,
|
||||
getPublicSettings,
|
||||
sendVerifyCode,
|
||||
};
|
||||
sendVerifyCode
|
||||
}
|
||||
|
||||
export default authAPI;
|
||||
export default authAPI
|
||||
|
||||
@@ -3,70 +3,70 @@
|
||||
* Base client with interceptors for authentication and error handling
|
||||
*/
|
||||
|
||||
import axios, { AxiosInstance, AxiosError, InternalAxiosRequestConfig } from 'axios';
|
||||
import type { ApiResponse } from '@/types';
|
||||
import axios, { AxiosInstance, AxiosError, InternalAxiosRequestConfig } from 'axios'
|
||||
import type { ApiResponse } from '@/types'
|
||||
|
||||
// ==================== Axios Instance Configuration ====================
|
||||
|
||||
const API_BASE_URL = import.meta.env.VITE_API_BASE_URL || '/api/v1';
|
||||
const API_BASE_URL = import.meta.env.VITE_API_BASE_URL || '/api/v1'
|
||||
|
||||
export const apiClient: AxiosInstance = axios.create({
|
||||
baseURL: API_BASE_URL,
|
||||
timeout: 30000,
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
},
|
||||
});
|
||||
'Content-Type': 'application/json'
|
||||
}
|
||||
})
|
||||
|
||||
// ==================== Request Interceptor ====================
|
||||
|
||||
apiClient.interceptors.request.use(
|
||||
(config: InternalAxiosRequestConfig) => {
|
||||
// Attach token from localStorage
|
||||
const token = localStorage.getItem('auth_token');
|
||||
const token = localStorage.getItem('auth_token')
|
||||
if (token && config.headers) {
|
||||
config.headers.Authorization = `Bearer ${token}`;
|
||||
config.headers.Authorization = `Bearer ${token}`
|
||||
}
|
||||
return config;
|
||||
return config
|
||||
},
|
||||
(error) => {
|
||||
return Promise.reject(error);
|
||||
return Promise.reject(error)
|
||||
}
|
||||
);
|
||||
)
|
||||
|
||||
// ==================== Response Interceptor ====================
|
||||
|
||||
apiClient.interceptors.response.use(
|
||||
(response) => {
|
||||
// Unwrap standard API response format { code, message, data }
|
||||
const apiResponse = response.data as ApiResponse<unknown>;
|
||||
const apiResponse = response.data as ApiResponse<unknown>
|
||||
if (apiResponse && typeof apiResponse === 'object' && 'code' in apiResponse) {
|
||||
if (apiResponse.code === 0) {
|
||||
// Success - return the data portion
|
||||
response.data = apiResponse.data;
|
||||
response.data = apiResponse.data
|
||||
} else {
|
||||
// API error
|
||||
return Promise.reject({
|
||||
status: response.status,
|
||||
code: apiResponse.code,
|
||||
message: apiResponse.message || 'Unknown error',
|
||||
});
|
||||
message: apiResponse.message || 'Unknown error'
|
||||
})
|
||||
}
|
||||
}
|
||||
return response;
|
||||
return response
|
||||
},
|
||||
(error: AxiosError<ApiResponse<unknown>>) => {
|
||||
// Handle common errors
|
||||
if (error.response) {
|
||||
const { status, data } = error.response;
|
||||
const { status, data } = error.response
|
||||
|
||||
// 401: Unauthorized - clear token and redirect to login
|
||||
if (status === 401) {
|
||||
localStorage.removeItem('auth_token');
|
||||
localStorage.removeItem('auth_user');
|
||||
localStorage.removeItem('auth_token')
|
||||
localStorage.removeItem('auth_user')
|
||||
// Only redirect if not already on login page
|
||||
if (!window.location.pathname.includes('/login')) {
|
||||
window.location.href = '/login';
|
||||
window.location.href = '/login'
|
||||
}
|
||||
}
|
||||
|
||||
@@ -74,16 +74,16 @@ apiClient.interceptors.response.use(
|
||||
return Promise.reject({
|
||||
status,
|
||||
code: data?.code,
|
||||
message: data?.message || error.message,
|
||||
});
|
||||
message: data?.message || error.message
|
||||
})
|
||||
}
|
||||
|
||||
// Network error
|
||||
return Promise.reject({
|
||||
status: 0,
|
||||
message: 'Network error. Please check your connection.',
|
||||
});
|
||||
message: 'Network error. Please check your connection.'
|
||||
})
|
||||
}
|
||||
);
|
||||
)
|
||||
|
||||
export default apiClient;
|
||||
export default apiClient
|
||||
|
||||
@@ -3,8 +3,8 @@
|
||||
* Handles group-related operations for regular users
|
||||
*/
|
||||
|
||||
import { apiClient } from './client';
|
||||
import type { Group } from '@/types';
|
||||
import { apiClient } from './client'
|
||||
import type { Group } from '@/types'
|
||||
|
||||
/**
|
||||
* Get available groups that the current user can bind to API keys
|
||||
@@ -14,12 +14,12 @@ import type { Group } from '@/types';
|
||||
* @returns List of available groups
|
||||
*/
|
||||
export async function getAvailable(): Promise<Group[]> {
|
||||
const { data } = await apiClient.get<Group[]>('/groups/available');
|
||||
return data;
|
||||
const { data } = await apiClient.get<Group[]>('/groups/available')
|
||||
return data
|
||||
}
|
||||
|
||||
export const userGroupsAPI = {
|
||||
getAvailable,
|
||||
};
|
||||
getAvailable
|
||||
}
|
||||
|
||||
export default userGroupsAPI;
|
||||
export default userGroupsAPI
|
||||
|
||||
@@ -4,20 +4,20 @@
|
||||
*/
|
||||
|
||||
// Re-export the HTTP client
|
||||
export { apiClient } from './client';
|
||||
export { apiClient } from './client'
|
||||
|
||||
// Auth API
|
||||
export { authAPI } from './auth';
|
||||
export { authAPI } from './auth'
|
||||
|
||||
// User APIs
|
||||
export { keysAPI } from './keys';
|
||||
export { usageAPI } from './usage';
|
||||
export { userAPI } from './user';
|
||||
export { redeemAPI, type RedeemHistoryItem } from './redeem';
|
||||
export { userGroupsAPI } from './groups';
|
||||
export { keysAPI } from './keys'
|
||||
export { usageAPI } from './usage'
|
||||
export { userAPI } from './user'
|
||||
export { redeemAPI, type RedeemHistoryItem } from './redeem'
|
||||
export { userGroupsAPI } from './groups'
|
||||
|
||||
// Admin APIs
|
||||
export { adminAPI } from './admin';
|
||||
export { adminAPI } from './admin'
|
||||
|
||||
// Default export
|
||||
export { default } from './client';
|
||||
export { default } from './client'
|
||||
|
||||
@@ -3,13 +3,8 @@
|
||||
* Handles CRUD operations for user API keys
|
||||
*/
|
||||
|
||||
import { apiClient } from './client';
|
||||
import type {
|
||||
ApiKey,
|
||||
CreateApiKeyRequest,
|
||||
UpdateApiKeyRequest,
|
||||
PaginatedResponse,
|
||||
} from '@/types';
|
||||
import { apiClient } from './client'
|
||||
import type { ApiKey, CreateApiKeyRequest, UpdateApiKeyRequest, PaginatedResponse } from '@/types'
|
||||
|
||||
/**
|
||||
* List all API keys for current user
|
||||
@@ -17,11 +12,14 @@ import type {
|
||||
* @param pageSize - Items per page (default: 10)
|
||||
* @returns Paginated list of API keys
|
||||
*/
|
||||
export async function list(page: number = 1, pageSize: number = 10): Promise<PaginatedResponse<ApiKey>> {
|
||||
export async function list(
|
||||
page: number = 1,
|
||||
pageSize: number = 10
|
||||
): Promise<PaginatedResponse<ApiKey>> {
|
||||
const { data } = await apiClient.get<PaginatedResponse<ApiKey>>('/keys', {
|
||||
params: { page, page_size: pageSize },
|
||||
});
|
||||
return data;
|
||||
params: { page, page_size: pageSize }
|
||||
})
|
||||
return data
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -30,8 +28,8 @@ export async function list(page: number = 1, pageSize: number = 10): Promise<Pag
|
||||
* @returns API key details
|
||||
*/
|
||||
export async function getById(id: number): Promise<ApiKey> {
|
||||
const { data } = await apiClient.get<ApiKey>(`/keys/${id}`);
|
||||
return data;
|
||||
const { data } = await apiClient.get<ApiKey>(`/keys/${id}`)
|
||||
return data
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -41,17 +39,21 @@ export async function getById(id: number): Promise<ApiKey> {
|
||||
* @param customKey - Optional custom key value
|
||||
* @returns Created API key
|
||||
*/
|
||||
export async function create(name: string, groupId?: number | null, customKey?: string): Promise<ApiKey> {
|
||||
const payload: CreateApiKeyRequest = { name };
|
||||
export async function create(
|
||||
name: string,
|
||||
groupId?: number | null,
|
||||
customKey?: string
|
||||
): Promise<ApiKey> {
|
||||
const payload: CreateApiKeyRequest = { name }
|
||||
if (groupId !== undefined) {
|
||||
payload.group_id = groupId;
|
||||
payload.group_id = groupId
|
||||
}
|
||||
if (customKey) {
|
||||
payload.custom_key = customKey;
|
||||
payload.custom_key = customKey
|
||||
}
|
||||
|
||||
const { data } = await apiClient.post<ApiKey>('/keys', payload);
|
||||
return data;
|
||||
const { data } = await apiClient.post<ApiKey>('/keys', payload)
|
||||
return data
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -61,8 +63,8 @@ export async function create(name: string, groupId?: number | null, customKey?:
|
||||
* @returns Updated API key
|
||||
*/
|
||||
export async function update(id: number, updates: UpdateApiKeyRequest): Promise<ApiKey> {
|
||||
const { data } = await apiClient.put<ApiKey>(`/keys/${id}`, updates);
|
||||
return data;
|
||||
const { data } = await apiClient.put<ApiKey>(`/keys/${id}`, updates)
|
||||
return data
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -71,8 +73,8 @@ export async function update(id: number, updates: UpdateApiKeyRequest): Promise<
|
||||
* @returns Success confirmation
|
||||
*/
|
||||
export async function deleteKey(id: number): Promise<{ message: string }> {
|
||||
const { data } = await apiClient.delete<{ message: string }>(`/keys/${id}`);
|
||||
return data;
|
||||
const { data } = await apiClient.delete<{ message: string }>(`/keys/${id}`)
|
||||
return data
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -81,11 +83,8 @@ export async function deleteKey(id: number): Promise<{ message: string }> {
|
||||
* @param status - New status
|
||||
* @returns Updated API key
|
||||
*/
|
||||
export async function toggleStatus(
|
||||
id: number,
|
||||
status: 'active' | 'inactive'
|
||||
): Promise<ApiKey> {
|
||||
return update(id, { status });
|
||||
export async function toggleStatus(id: number, status: 'active' | 'inactive'): Promise<ApiKey> {
|
||||
return update(id, { status })
|
||||
}
|
||||
|
||||
export const keysAPI = {
|
||||
@@ -94,7 +93,7 @@ export const keysAPI = {
|
||||
create,
|
||||
update,
|
||||
delete: deleteKey,
|
||||
toggleStatus,
|
||||
};
|
||||
toggleStatus
|
||||
}
|
||||
|
||||
export default keysAPI;
|
||||
export default keysAPI
|
||||
|
||||
@@ -3,24 +3,24 @@
|
||||
* Handles redeem code redemption for users
|
||||
*/
|
||||
|
||||
import { apiClient } from './client';
|
||||
import type { RedeemCodeRequest } from '@/types';
|
||||
import { apiClient } from './client'
|
||||
import type { RedeemCodeRequest } from '@/types'
|
||||
|
||||
export interface RedeemHistoryItem {
|
||||
id: number;
|
||||
code: string;
|
||||
type: string;
|
||||
value: number;
|
||||
status: string;
|
||||
used_at: string;
|
||||
created_at: string;
|
||||
id: number
|
||||
code: string
|
||||
type: string
|
||||
value: number
|
||||
status: string
|
||||
used_at: string
|
||||
created_at: string
|
||||
// 订阅类型专用字段
|
||||
group_id?: number;
|
||||
validity_days?: number;
|
||||
group_id?: number
|
||||
validity_days?: number
|
||||
group?: {
|
||||
id: number;
|
||||
name: string;
|
||||
};
|
||||
id: number
|
||||
name: string
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -29,23 +29,23 @@ export interface RedeemHistoryItem {
|
||||
* @returns Redemption result with updated balance or concurrency
|
||||
*/
|
||||
export async function redeem(code: string): Promise<{
|
||||
message: string;
|
||||
type: string;
|
||||
value: number;
|
||||
new_balance?: number;
|
||||
new_concurrency?: number;
|
||||
message: string
|
||||
type: string
|
||||
value: number
|
||||
new_balance?: number
|
||||
new_concurrency?: number
|
||||
}> {
|
||||
const payload: RedeemCodeRequest = { code };
|
||||
const payload: RedeemCodeRequest = { code }
|
||||
|
||||
const { data } = await apiClient.post<{
|
||||
message: string;
|
||||
type: string;
|
||||
value: number;
|
||||
new_balance?: number;
|
||||
new_concurrency?: number;
|
||||
}>('/redeem', payload);
|
||||
message: string
|
||||
type: string
|
||||
value: number
|
||||
new_balance?: number
|
||||
new_concurrency?: number
|
||||
}>('/redeem', payload)
|
||||
|
||||
return data;
|
||||
return data
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -53,13 +53,13 @@ export async function redeem(code: string): Promise<{
|
||||
* @returns List of redeemed codes
|
||||
*/
|
||||
export async function getHistory(): Promise<RedeemHistoryItem[]> {
|
||||
const { data } = await apiClient.get<RedeemHistoryItem[]>('/redeem/history');
|
||||
return data;
|
||||
const { data } = await apiClient.get<RedeemHistoryItem[]>('/redeem/history')
|
||||
return data
|
||||
}
|
||||
|
||||
export const redeemAPI = {
|
||||
redeem,
|
||||
getHistory,
|
||||
};
|
||||
getHistory
|
||||
}
|
||||
|
||||
export default redeemAPI;
|
||||
export default redeemAPI
|
||||
|
||||
@@ -1,87 +1,87 @@
|
||||
/**
|
||||
* Setup API endpoints
|
||||
*/
|
||||
import axios from 'axios';
|
||||
import axios from 'axios'
|
||||
|
||||
// Create a separate client for setup endpoints (not under /api/v1)
|
||||
const setupClient = axios.create({
|
||||
baseURL: '',
|
||||
timeout: 30000,
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
},
|
||||
});
|
||||
'Content-Type': 'application/json'
|
||||
}
|
||||
})
|
||||
|
||||
export interface SetupStatus {
|
||||
needs_setup: boolean;
|
||||
step: string;
|
||||
needs_setup: boolean
|
||||
step: string
|
||||
}
|
||||
|
||||
export interface DatabaseConfig {
|
||||
host: string;
|
||||
port: number;
|
||||
user: string;
|
||||
password: string;
|
||||
dbname: string;
|
||||
sslmode: string;
|
||||
host: string
|
||||
port: number
|
||||
user: string
|
||||
password: string
|
||||
dbname: string
|
||||
sslmode: string
|
||||
}
|
||||
|
||||
export interface RedisConfig {
|
||||
host: string;
|
||||
port: number;
|
||||
password: string;
|
||||
db: number;
|
||||
host: string
|
||||
port: number
|
||||
password: string
|
||||
db: number
|
||||
}
|
||||
|
||||
export interface AdminConfig {
|
||||
email: string;
|
||||
password: string;
|
||||
email: string
|
||||
password: string
|
||||
}
|
||||
|
||||
export interface ServerConfig {
|
||||
host: string;
|
||||
port: number;
|
||||
mode: string;
|
||||
host: string
|
||||
port: number
|
||||
mode: string
|
||||
}
|
||||
|
||||
export interface InstallRequest {
|
||||
database: DatabaseConfig;
|
||||
redis: RedisConfig;
|
||||
admin: AdminConfig;
|
||||
server: ServerConfig;
|
||||
database: DatabaseConfig
|
||||
redis: RedisConfig
|
||||
admin: AdminConfig
|
||||
server: ServerConfig
|
||||
}
|
||||
|
||||
export interface InstallResponse {
|
||||
message: string;
|
||||
restart: boolean;
|
||||
message: string
|
||||
restart: boolean
|
||||
}
|
||||
|
||||
/**
|
||||
* Get setup status
|
||||
*/
|
||||
export async function getSetupStatus(): Promise<SetupStatus> {
|
||||
const response = await setupClient.get('/setup/status');
|
||||
return response.data.data;
|
||||
const response = await setupClient.get('/setup/status')
|
||||
return response.data.data
|
||||
}
|
||||
|
||||
/**
|
||||
* Test database connection
|
||||
*/
|
||||
export async function testDatabase(config: DatabaseConfig): Promise<void> {
|
||||
await setupClient.post('/setup/test-db', config);
|
||||
await setupClient.post('/setup/test-db', config)
|
||||
}
|
||||
|
||||
/**
|
||||
* Test Redis connection
|
||||
*/
|
||||
export async function testRedis(config: RedisConfig): Promise<void> {
|
||||
await setupClient.post('/setup/test-redis', config);
|
||||
await setupClient.post('/setup/test-redis', config)
|
||||
}
|
||||
|
||||
/**
|
||||
* Perform installation
|
||||
*/
|
||||
export async function install(config: InstallRequest): Promise<InstallResponse> {
|
||||
const response = await setupClient.post('/setup/install', config);
|
||||
return response.data.data;
|
||||
const response = await setupClient.post('/setup/install', config)
|
||||
return response.data.data
|
||||
}
|
||||
|
||||
@@ -3,64 +3,68 @@
|
||||
* API for regular users to view their own subscriptions and progress
|
||||
*/
|
||||
|
||||
import { apiClient } from './client';
|
||||
import type { UserSubscription, SubscriptionProgress } from '@/types';
|
||||
import { apiClient } from './client'
|
||||
import type { UserSubscription, SubscriptionProgress } from '@/types'
|
||||
|
||||
/**
|
||||
* Subscription summary for user dashboard
|
||||
*/
|
||||
export interface SubscriptionSummary {
|
||||
active_count: number;
|
||||
active_count: number
|
||||
subscriptions: Array<{
|
||||
id: number;
|
||||
group_name: string;
|
||||
status: string;
|
||||
daily_progress: number | null;
|
||||
weekly_progress: number | null;
|
||||
monthly_progress: number | null;
|
||||
expires_at: string | null;
|
||||
days_remaining: number | null;
|
||||
}>;
|
||||
id: number
|
||||
group_name: string
|
||||
status: string
|
||||
daily_progress: number | null
|
||||
weekly_progress: number | null
|
||||
monthly_progress: number | null
|
||||
expires_at: string | null
|
||||
days_remaining: number | null
|
||||
}>
|
||||
}
|
||||
|
||||
/**
|
||||
* Get list of current user's subscriptions
|
||||
*/
|
||||
export async function getMySubscriptions(): Promise<UserSubscription[]> {
|
||||
const response = await apiClient.get<UserSubscription[]>('/subscriptions');
|
||||
return response.data;
|
||||
const response = await apiClient.get<UserSubscription[]>('/subscriptions')
|
||||
return response.data
|
||||
}
|
||||
|
||||
/**
|
||||
* Get current user's active subscriptions
|
||||
*/
|
||||
export async function getActiveSubscriptions(): Promise<UserSubscription[]> {
|
||||
const response = await apiClient.get<UserSubscription[]>('/subscriptions/active');
|
||||
return response.data;
|
||||
const response = await apiClient.get<UserSubscription[]>('/subscriptions/active')
|
||||
return response.data
|
||||
}
|
||||
|
||||
/**
|
||||
* Get progress for all user's active subscriptions
|
||||
*/
|
||||
export async function getSubscriptionsProgress(): Promise<SubscriptionProgress[]> {
|
||||
const response = await apiClient.get<SubscriptionProgress[]>('/subscriptions/progress');
|
||||
return response.data;
|
||||
const response = await apiClient.get<SubscriptionProgress[]>('/subscriptions/progress')
|
||||
return response.data
|
||||
}
|
||||
|
||||
/**
|
||||
* Get subscription summary for dashboard display
|
||||
*/
|
||||
export async function getSubscriptionSummary(): Promise<SubscriptionSummary> {
|
||||
const response = await apiClient.get<SubscriptionSummary>('/subscriptions/summary');
|
||||
return response.data;
|
||||
const response = await apiClient.get<SubscriptionSummary>('/subscriptions/summary')
|
||||
return response.data
|
||||
}
|
||||
|
||||
/**
|
||||
* Get progress for a specific subscription
|
||||
*/
|
||||
export async function getSubscriptionProgress(subscriptionId: number): Promise<SubscriptionProgress> {
|
||||
const response = await apiClient.get<SubscriptionProgress>(`/subscriptions/${subscriptionId}/progress`);
|
||||
return response.data;
|
||||
export async function getSubscriptionProgress(
|
||||
subscriptionId: number
|
||||
): Promise<SubscriptionProgress> {
|
||||
const response = await apiClient.get<SubscriptionProgress>(
|
||||
`/subscriptions/${subscriptionId}/progress`
|
||||
)
|
||||
return response.data
|
||||
}
|
||||
|
||||
export default {
|
||||
@@ -68,5 +72,5 @@ export default {
|
||||
getActiveSubscriptions,
|
||||
getSubscriptionsProgress,
|
||||
getSubscriptionSummary,
|
||||
getSubscriptionProgress,
|
||||
};
|
||||
getSubscriptionProgress
|
||||
}
|
||||
|
||||
@@ -3,59 +3,59 @@
|
||||
* Handles usage logs and statistics retrieval
|
||||
*/
|
||||
|
||||
import { apiClient } from './client';
|
||||
import { apiClient } from './client'
|
||||
import type {
|
||||
UsageLog,
|
||||
UsageQueryParams,
|
||||
UsageStatsResponse,
|
||||
PaginatedResponse,
|
||||
TrendDataPoint,
|
||||
ModelStat,
|
||||
} from '@/types';
|
||||
ModelStat
|
||||
} from '@/types'
|
||||
|
||||
// ==================== Dashboard Types ====================
|
||||
|
||||
export interface UserDashboardStats {
|
||||
total_api_keys: number;
|
||||
active_api_keys: number;
|
||||
total_requests: number;
|
||||
total_input_tokens: number;
|
||||
total_output_tokens: number;
|
||||
total_cache_creation_tokens: number;
|
||||
total_cache_read_tokens: number;
|
||||
total_tokens: number;
|
||||
total_cost: number; // 标准计费
|
||||
total_actual_cost: number; // 实际扣除
|
||||
today_requests: number;
|
||||
today_input_tokens: number;
|
||||
today_output_tokens: number;
|
||||
today_cache_creation_tokens: number;
|
||||
today_cache_read_tokens: number;
|
||||
today_tokens: number;
|
||||
today_cost: number; // 今日标准计费
|
||||
today_actual_cost: number; // 今日实际扣除
|
||||
average_duration_ms: number;
|
||||
rpm: number; // 近5分钟平均每分钟请求数
|
||||
tpm: number; // 近5分钟平均每分钟Token数
|
||||
total_api_keys: number
|
||||
active_api_keys: number
|
||||
total_requests: number
|
||||
total_input_tokens: number
|
||||
total_output_tokens: number
|
||||
total_cache_creation_tokens: number
|
||||
total_cache_read_tokens: number
|
||||
total_tokens: number
|
||||
total_cost: number // 标准计费
|
||||
total_actual_cost: number // 实际扣除
|
||||
today_requests: number
|
||||
today_input_tokens: number
|
||||
today_output_tokens: number
|
||||
today_cache_creation_tokens: number
|
||||
today_cache_read_tokens: number
|
||||
today_tokens: number
|
||||
today_cost: number // 今日标准计费
|
||||
today_actual_cost: number // 今日实际扣除
|
||||
average_duration_ms: number
|
||||
rpm: number // 近5分钟平均每分钟请求数
|
||||
tpm: number // 近5分钟平均每分钟Token数
|
||||
}
|
||||
|
||||
export interface TrendParams {
|
||||
start_date?: string;
|
||||
end_date?: string;
|
||||
granularity?: 'day' | 'hour';
|
||||
start_date?: string
|
||||
end_date?: string
|
||||
granularity?: 'day' | 'hour'
|
||||
}
|
||||
|
||||
export interface TrendResponse {
|
||||
trend: TrendDataPoint[];
|
||||
start_date: string;
|
||||
end_date: string;
|
||||
granularity: string;
|
||||
trend: TrendDataPoint[]
|
||||
start_date: string
|
||||
end_date: string
|
||||
granularity: string
|
||||
}
|
||||
|
||||
export interface ModelStatsResponse {
|
||||
models: ModelStat[];
|
||||
start_date: string;
|
||||
end_date: string;
|
||||
models: ModelStat[]
|
||||
start_date: string
|
||||
end_date: string
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -72,17 +72,17 @@ export async function list(
|
||||
): Promise<PaginatedResponse<UsageLog>> {
|
||||
const params: UsageQueryParams = {
|
||||
page,
|
||||
page_size: pageSize,
|
||||
};
|
||||
page_size: pageSize
|
||||
}
|
||||
|
||||
if (apiKeyId !== undefined) {
|
||||
params.api_key_id = apiKeyId;
|
||||
params.api_key_id = apiKeyId
|
||||
}
|
||||
|
||||
const { data } = await apiClient.get<PaginatedResponse<UsageLog>>('/usage', {
|
||||
params,
|
||||
});
|
||||
return data;
|
||||
params
|
||||
})
|
||||
return data
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -92,9 +92,9 @@ export async function list(
|
||||
*/
|
||||
export async function query(params: UsageQueryParams): Promise<PaginatedResponse<UsageLog>> {
|
||||
const { data } = await apiClient.get<PaginatedResponse<UsageLog>>('/usage', {
|
||||
params,
|
||||
});
|
||||
return data;
|
||||
params
|
||||
})
|
||||
return data
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -107,16 +107,16 @@ export async function getStats(
|
||||
period: string = 'today',
|
||||
apiKeyId?: number
|
||||
): Promise<UsageStatsResponse> {
|
||||
const params: Record<string, unknown> = { period };
|
||||
const params: Record<string, unknown> = { period }
|
||||
|
||||
if (apiKeyId !== undefined) {
|
||||
params.api_key_id = apiKeyId;
|
||||
params.api_key_id = apiKeyId
|
||||
}
|
||||
|
||||
const { data } = await apiClient.get<UsageStatsResponse>('/usage/stats', {
|
||||
params,
|
||||
});
|
||||
return data;
|
||||
params
|
||||
})
|
||||
return data
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -133,17 +133,17 @@ export async function getStatsByDateRange(
|
||||
): Promise<UsageStatsResponse> {
|
||||
const params: Record<string, unknown> = {
|
||||
start_date: startDate,
|
||||
end_date: endDate,
|
||||
};
|
||||
end_date: endDate
|
||||
}
|
||||
|
||||
if (apiKeyId !== undefined) {
|
||||
params.api_key_id = apiKeyId;
|
||||
params.api_key_id = apiKeyId
|
||||
}
|
||||
|
||||
const { data } = await apiClient.get<UsageStatsResponse>('/usage/stats', {
|
||||
params,
|
||||
});
|
||||
return data;
|
||||
params
|
||||
})
|
||||
return data
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -162,17 +162,17 @@ export async function getByDateRange(
|
||||
start_date: startDate,
|
||||
end_date: endDate,
|
||||
page: 1,
|
||||
page_size: 100,
|
||||
};
|
||||
page_size: 100
|
||||
}
|
||||
|
||||
if (apiKeyId !== undefined) {
|
||||
params.api_key_id = apiKeyId;
|
||||
params.api_key_id = apiKeyId
|
||||
}
|
||||
|
||||
const { data } = await apiClient.get<PaginatedResponse<UsageLog>>('/usage', {
|
||||
params,
|
||||
});
|
||||
return data;
|
||||
params
|
||||
})
|
||||
return data
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -181,8 +181,8 @@ export async function getByDateRange(
|
||||
* @returns Usage log details
|
||||
*/
|
||||
export async function getById(id: number): Promise<UsageLog> {
|
||||
const { data } = await apiClient.get<UsageLog>(`/usage/${id}`);
|
||||
return data;
|
||||
const { data } = await apiClient.get<UsageLog>(`/usage/${id}`)
|
||||
return data
|
||||
}
|
||||
|
||||
// ==================== Dashboard API ====================
|
||||
@@ -192,8 +192,8 @@ export async function getById(id: number): Promise<UsageLog> {
|
||||
* @returns Dashboard statistics for current user
|
||||
*/
|
||||
export async function getDashboardStats(): Promise<UserDashboardStats> {
|
||||
const { data } = await apiClient.get<UserDashboardStats>('/usage/dashboard/stats');
|
||||
return data;
|
||||
const { data } = await apiClient.get<UserDashboardStats>('/usage/dashboard/stats')
|
||||
return data
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -202,8 +202,8 @@ export async function getDashboardStats(): Promise<UserDashboardStats> {
|
||||
* @returns Usage trend data for current user
|
||||
*/
|
||||
export async function getDashboardTrend(params?: TrendParams): Promise<TrendResponse> {
|
||||
const { data } = await apiClient.get<TrendResponse>('/usage/dashboard/trend', { params });
|
||||
return data;
|
||||
const { data } = await apiClient.get<TrendResponse>('/usage/dashboard/trend', { params })
|
||||
return data
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -211,19 +211,22 @@ export async function getDashboardTrend(params?: TrendParams): Promise<TrendResp
|
||||
* @param params - Query parameters for filtering
|
||||
* @returns Model usage statistics for current user
|
||||
*/
|
||||
export async function getDashboardModels(params?: { start_date?: string; end_date?: string }): Promise<ModelStatsResponse> {
|
||||
const { data } = await apiClient.get<ModelStatsResponse>('/usage/dashboard/models', { params });
|
||||
return data;
|
||||
export async function getDashboardModels(params?: {
|
||||
start_date?: string
|
||||
end_date?: string
|
||||
}): Promise<ModelStatsResponse> {
|
||||
const { data } = await apiClient.get<ModelStatsResponse>('/usage/dashboard/models', { params })
|
||||
return data
|
||||
}
|
||||
|
||||
export interface BatchApiKeyUsageStats {
|
||||
api_key_id: number;
|
||||
today_actual_cost: number;
|
||||
total_actual_cost: number;
|
||||
api_key_id: number
|
||||
today_actual_cost: number
|
||||
total_actual_cost: number
|
||||
}
|
||||
|
||||
export interface BatchApiKeysUsageResponse {
|
||||
stats: Record<string, BatchApiKeyUsageStats>;
|
||||
stats: Record<string, BatchApiKeyUsageStats>
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -231,11 +234,16 @@ export interface BatchApiKeysUsageResponse {
|
||||
* @param apiKeyIds - Array of API key IDs
|
||||
* @returns Usage stats map keyed by API key ID
|
||||
*/
|
||||
export async function getDashboardApiKeysUsage(apiKeyIds: number[]): Promise<BatchApiKeysUsageResponse> {
|
||||
const { data } = await apiClient.post<BatchApiKeysUsageResponse>('/usage/dashboard/api-keys-usage', {
|
||||
api_key_ids: apiKeyIds,
|
||||
});
|
||||
return data;
|
||||
export async function getDashboardApiKeysUsage(
|
||||
apiKeyIds: number[]
|
||||
): Promise<BatchApiKeysUsageResponse> {
|
||||
const { data } = await apiClient.post<BatchApiKeysUsageResponse>(
|
||||
'/usage/dashboard/api-keys-usage',
|
||||
{
|
||||
api_key_ids: apiKeyIds
|
||||
}
|
||||
)
|
||||
return data
|
||||
}
|
||||
|
||||
export const usageAPI = {
|
||||
@@ -249,7 +257,7 @@ export const usageAPI = {
|
||||
getDashboardStats,
|
||||
getDashboardTrend,
|
||||
getDashboardModels,
|
||||
getDashboardApiKeysUsage,
|
||||
};
|
||||
getDashboardApiKeysUsage
|
||||
}
|
||||
|
||||
export default usageAPI;
|
||||
export default usageAPI
|
||||
|
||||
@@ -3,16 +3,16 @@
|
||||
* Handles user profile management and password changes
|
||||
*/
|
||||
|
||||
import { apiClient } from './client';
|
||||
import type { User, ChangePasswordRequest } from '@/types';
|
||||
import { apiClient } from './client'
|
||||
import type { User, ChangePasswordRequest } from '@/types'
|
||||
|
||||
/**
|
||||
* Get current user profile
|
||||
* @returns User profile data
|
||||
*/
|
||||
export async function getProfile(): Promise<User> {
|
||||
const { data } = await apiClient.get<User>('/user/profile');
|
||||
return data;
|
||||
const { data } = await apiClient.get<User>('/user/profile')
|
||||
return data
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -21,11 +21,11 @@ export async function getProfile(): Promise<User> {
|
||||
* @returns Updated user profile data
|
||||
*/
|
||||
export async function updateProfile(profile: {
|
||||
username?: string;
|
||||
wechat?: string;
|
||||
username?: string
|
||||
wechat?: string
|
||||
}): Promise<User> {
|
||||
const { data } = await apiClient.put<User>('/user', profile);
|
||||
return data;
|
||||
const { data } = await apiClient.put<User>('/user', profile)
|
||||
return data
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -39,17 +39,17 @@ export async function changePassword(
|
||||
): Promise<{ message: string }> {
|
||||
const payload: ChangePasswordRequest = {
|
||||
old_password: oldPassword,
|
||||
new_password: newPassword,
|
||||
};
|
||||
new_password: newPassword
|
||||
}
|
||||
|
||||
const { data } = await apiClient.put<{ message: string }>('/user/password', payload);
|
||||
return data;
|
||||
const { data } = await apiClient.put<{ message: string }>('/user/password', payload)
|
||||
return data
|
||||
}
|
||||
|
||||
export const userAPI = {
|
||||
getProfile,
|
||||
updateProfile,
|
||||
changePassword,
|
||||
};
|
||||
changePassword
|
||||
}
|
||||
|
||||
export default userAPI;
|
||||
export default userAPI
|
||||
|
||||
Reference in New Issue
Block a user