后端改进: - 新增 GetStatsWithFilters 方法支持完整筛选条件 - Stats 端点支持 account_id, group_id, model, stream, billing_type 参数 - 统一使用 filters 结构体,移除冗余的分支逻辑 前端改进: - 统计卡片添加"所选范围内"文字提示 - 优化总消费显示格式,清晰展示实际费用和标准计费 - Token 和费用列添加问号图标 tooltip 显示详细信息 - API Key 搜索框体验优化:点击即显示下拉选项 - 选择用户后自动加载该用户的所有 API Key
119 lines
2.8 KiB
TypeScript
119 lines
2.8 KiB
TypeScript
/**
|
|
* Admin Usage API endpoints
|
|
* Handles admin-level usage logs and statistics retrieval
|
|
*/
|
|
|
|
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
|
|
}
|
|
|
|
export interface SimpleUser {
|
|
id: number
|
|
email: string
|
|
}
|
|
|
|
export interface SimpleApiKey {
|
|
id: number
|
|
name: string
|
|
user_id: number
|
|
}
|
|
|
|
export interface AdminUsageQueryParams extends UsageQueryParams {
|
|
user_id?: number
|
|
}
|
|
|
|
// ==================== API Functions ====================
|
|
|
|
/**
|
|
* List all usage logs with optional filters (admin only)
|
|
* @param params - Query parameters for filtering and pagination
|
|
* @returns Paginated list of usage logs
|
|
*/
|
|
export async function list(
|
|
params: AdminUsageQueryParams,
|
|
options?: { signal?: AbortSignal }
|
|
): Promise<PaginatedResponse<UsageLog>> {
|
|
const { data } = await apiClient.get<PaginatedResponse<UsageLog>>('/admin/usage', {
|
|
params,
|
|
signal: options?.signal
|
|
})
|
|
return data
|
|
}
|
|
|
|
/**
|
|
* Get usage statistics with optional filters (admin only)
|
|
* @param params - Query parameters for filtering
|
|
* @returns Usage statistics
|
|
*/
|
|
export async function getStats(params: {
|
|
user_id?: number
|
|
api_key_id?: number
|
|
account_id?: number
|
|
group_id?: number
|
|
model?: string
|
|
stream?: boolean
|
|
billing_type?: number
|
|
period?: string
|
|
start_date?: string
|
|
end_date?: string
|
|
timezone?: string
|
|
}): Promise<AdminUsageStatsResponse> {
|
|
const { data } = await apiClient.get<AdminUsageStatsResponse>('/admin/usage/stats', {
|
|
params
|
|
})
|
|
return data
|
|
}
|
|
|
|
/**
|
|
* Search users by email keyword (admin only)
|
|
* @param keyword - Email keyword to search
|
|
* @returns List of matching users (max 30)
|
|
*/
|
|
export async function searchUsers(keyword: string): Promise<SimpleUser[]> {
|
|
const { data } = await apiClient.get<SimpleUser[]>('/admin/usage/search-users', {
|
|
params: { q: keyword }
|
|
})
|
|
return data
|
|
}
|
|
|
|
/**
|
|
* Search API keys by user ID and/or keyword (admin only)
|
|
* @param userId - Optional user ID to filter by
|
|
* @param keyword - Optional keyword to search in key name
|
|
* @returns List of matching API keys (max 30)
|
|
*/
|
|
export async function searchApiKeys(userId?: number, keyword?: string): Promise<SimpleApiKey[]> {
|
|
const params: Record<string, unknown> = {}
|
|
if (userId !== undefined) {
|
|
params.user_id = userId
|
|
}
|
|
if (keyword) {
|
|
params.q = keyword
|
|
}
|
|
const { data } = await apiClient.get<SimpleApiKey[]>('/admin/usage/search-api-keys', {
|
|
params
|
|
})
|
|
return data
|
|
}
|
|
|
|
export const adminUsageAPI = {
|
|
list,
|
|
getStats,
|
|
searchUsers,
|
|
searchApiKeys
|
|
}
|
|
|
|
export default adminUsageAPI
|