- 用户侧 dto.User 移除 notes 字段,避免泄露管理员备注\n- 新增 dto.AdminUser 并调整 /admin/users 系列接口使用\n- 前端拆分 User/AdminUser,管理端用户页面使用 AdminUser\n- 更新契约测试:/api/v1/auth/me 响应不包含 notes
191 lines
4.5 KiB
TypeScript
191 lines
4.5 KiB
TypeScript
/**
|
|
* Admin Users API endpoints
|
|
* Handles user management for administrators
|
|
*/
|
|
|
|
import { apiClient } from '../client'
|
|
import type { AdminUser, UpdateUserRequest, PaginatedResponse } from '@/types'
|
|
|
|
/**
|
|
* List all users with pagination
|
|
* @param page - Page number (default: 1)
|
|
* @param pageSize - Items per page (default: 20)
|
|
* @param filters - Optional filters (status, role, search, attributes)
|
|
* @param options - Optional request options (signal)
|
|
* @returns Paginated list of users
|
|
*/
|
|
export async function list(
|
|
page: number = 1,
|
|
pageSize: number = 20,
|
|
filters?: {
|
|
status?: 'active' | 'disabled'
|
|
role?: 'admin' | 'user'
|
|
search?: string
|
|
attributes?: Record<number, string> // attributeId -> value
|
|
},
|
|
options?: {
|
|
signal?: AbortSignal
|
|
}
|
|
): Promise<PaginatedResponse<AdminUser>> {
|
|
// Build params with attribute filters in attr[id]=value format
|
|
const params: Record<string, any> = {
|
|
page,
|
|
page_size: pageSize,
|
|
status: filters?.status,
|
|
role: filters?.role,
|
|
search: filters?.search
|
|
}
|
|
|
|
// Add attribute filters as attr[id]=value
|
|
if (filters?.attributes) {
|
|
for (const [attrId, value] of Object.entries(filters.attributes)) {
|
|
if (value) {
|
|
params[`attr[${attrId}]`] = value
|
|
}
|
|
}
|
|
}
|
|
const { data } = await apiClient.get<PaginatedResponse<AdminUser>>('/admin/users', {
|
|
params,
|
|
signal: options?.signal
|
|
})
|
|
return data
|
|
}
|
|
|
|
/**
|
|
* Get user by ID
|
|
* @param id - User ID
|
|
* @returns User details
|
|
*/
|
|
export async function getById(id: number): Promise<AdminUser> {
|
|
const { data } = await apiClient.get<AdminUser>(`/admin/users/${id}`)
|
|
return data
|
|
}
|
|
|
|
/**
|
|
* Create new user
|
|
* @param userData - User data (email, password, etc.)
|
|
* @returns Created user
|
|
*/
|
|
export async function create(userData: {
|
|
email: string
|
|
password: string
|
|
balance?: number
|
|
concurrency?: number
|
|
allowed_groups?: number[] | null
|
|
}): Promise<AdminUser> {
|
|
const { data } = await apiClient.post<AdminUser>('/admin/users', userData)
|
|
return data
|
|
}
|
|
|
|
/**
|
|
* Update user
|
|
* @param id - User ID
|
|
* @param updates - Fields to update
|
|
* @returns Updated user
|
|
*/
|
|
export async function update(id: number, updates: UpdateUserRequest): Promise<AdminUser> {
|
|
const { data } = await apiClient.put<AdminUser>(`/admin/users/${id}`, updates)
|
|
return data
|
|
}
|
|
|
|
/**
|
|
* Delete user
|
|
* @param id - User ID
|
|
* @returns Success confirmation
|
|
*/
|
|
export async function deleteUser(id: number): Promise<{ message: string }> {
|
|
const { data } = await apiClient.delete<{ message: string }>(`/admin/users/${id}`)
|
|
return data
|
|
}
|
|
|
|
/**
|
|
* Update user balance
|
|
* @param id - User ID
|
|
* @param balance - New balance
|
|
* @param operation - Operation type ('set', 'add', 'subtract')
|
|
* @param notes - Optional notes for the balance adjustment
|
|
* @returns Updated user
|
|
*/
|
|
export async function updateBalance(
|
|
id: number,
|
|
balance: number,
|
|
operation: 'set' | 'add' | 'subtract' = 'set',
|
|
notes?: string
|
|
): Promise<AdminUser> {
|
|
const { data } = await apiClient.post<AdminUser>(`/admin/users/${id}/balance`, {
|
|
balance,
|
|
operation,
|
|
notes: notes || ''
|
|
})
|
|
return data
|
|
}
|
|
|
|
/**
|
|
* Update user concurrency
|
|
* @param id - User ID
|
|
* @param concurrency - New concurrency limit
|
|
* @returns Updated user
|
|
*/
|
|
export async function updateConcurrency(id: number, concurrency: number): Promise<AdminUser> {
|
|
return update(id, { concurrency })
|
|
}
|
|
|
|
/**
|
|
* Toggle user status
|
|
* @param id - User ID
|
|
* @param status - New status
|
|
* @returns Updated user
|
|
*/
|
|
export async function toggleStatus(id: number, status: 'active' | 'disabled'): Promise<AdminUser> {
|
|
return update(id, { status })
|
|
}
|
|
|
|
/**
|
|
* Get user's API keys
|
|
* @param id - User ID
|
|
* @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
|
|
}
|
|
|
|
/**
|
|
* Get user's usage statistics
|
|
* @param id - User ID
|
|
* @param period - Time period
|
|
* @returns User usage statistics
|
|
*/
|
|
export async function getUserUsageStats(
|
|
id: number,
|
|
period: string = 'month'
|
|
): Promise<{
|
|
total_requests: number
|
|
total_cost: number
|
|
total_tokens: number
|
|
}> {
|
|
const { data } = await apiClient.get<{
|
|
total_requests: number
|
|
total_cost: number
|
|
total_tokens: number
|
|
}>(`/admin/users/${id}/usage`, {
|
|
params: { period }
|
|
})
|
|
return data
|
|
}
|
|
|
|
export const usersAPI = {
|
|
list,
|
|
getById,
|
|
create,
|
|
update,
|
|
delete: deleteUser,
|
|
updateBalance,
|
|
updateConcurrency,
|
|
toggleStatus,
|
|
getUserApiKeys,
|
|
getUserUsageStats
|
|
}
|
|
|
|
export default usersAPI
|