import { useMutation, useQuery, useQueryClient } from '@tanstack/react-query';
import { apiClient } from '../client';
import { logger } from '@/lib/logger';
* 分组项信息
*/
export interface GroupItem {
id?: number;
group_id?: number;
channel_id: number;
model_name: string;
priority: number;
weight: number;
}
* 分组模式
*/
export enum GroupMode {
RoundRobin = 1,
Random = 2,
Failover = 3,
Weighted = 4,
}
* 分组信息
*/
export interface Group {
id?: number;
name: string;
mode: GroupMode;
match_regex: string;
first_token_time_out?: number;
session_keep_time?: number;
items?: GroupItem[];
}
* 新增 item 请求
*/
export interface GroupItemAddRequest {
channel_id: number;
model_name: string;
priority: number;
weight: number;
}
* 更新 item 请求 (仅 priority)
*/
export interface GroupItemUpdateRequest {
id: number;
priority: number;
weight: number;
}
* 分组更新请求 - 仅包含变更的数据
*/
export interface GroupUpdateRequest {
id: number;
name?: string;
mode?: GroupMode;
match_regex?: string;
first_token_time_out?: number;
session_keep_time?: number;
items_to_add?: GroupItemAddRequest[];
items_to_update?: GroupItemUpdateRequest[];
items_to_delete?: number[];
}
* 获取分组列表 Hook
*
* @example
* const { data: groups, isLoading, error } = useGroupList();
*
* if (isLoading) return <Loading />;
* if (error) return <Error message={error.message} />;
*
* groups?.forEach(group => console.log(group.name, group.items));
*/
export function useGroupList() {
return useQuery({
queryKey: ['groups', 'list'],
queryFn: async () => {
return apiClient.get<Group[]>('/api/v1/group/list');
},
refetchInterval: 30000,
refetchOnMount: 'always',
});
}
* 创建分组 Hook
*
* @example
* const createGroup = useCreateGroup();
*
* createGroup.mutate({
* name: 'my-group',
* items: [
* { channel_id: 1, model_name: 'gpt-4', priority: 1 },
* ],
* });
*/
export function useCreateGroup() {
const queryClient = useQueryClient();
return useMutation({
mutationFn: async (data: Group) => {
return apiClient.post<Group>('/api/v1/group/create', data);
},
onSuccess: (data) => {
logger.log('分组创建成功:', data);
queryClient.invalidateQueries({ queryKey: ['groups', 'list'] });
},
onError: (error) => {
logger.error('分组创建失败:', error);
},
});
}
* 更新分组 Hook - 仅发送变更的数据
*
* @example
* const updateGroup = useUpdateGroup();
*
* updateGroup.mutate({
* id: 1,
* name: 'updated-group', // 可选,仅在名称变更时发送
* items_to_add: [{ channel_id: 1, model_name: 'gpt-4', priority: 1 }],
* items_to_update: [{ id: 1, priority: 2 }],
* items_to_delete: [2, 3],
* });
*/
export function useUpdateGroup() {
const queryClient = useQueryClient();
return useMutation({
mutationFn: async (data: GroupUpdateRequest) => {
return apiClient.post<Group>('/api/v1/group/update', data);
},
onSuccess: (data) => {
logger.log('分组更新成功:', data);
queryClient.invalidateQueries({ queryKey: ['groups', 'list'] });
},
onError: (error) => {
logger.error('分组更新失败:', error);
},
});
}
* 删除分组 Hook
*
* @example
* const deleteGroup = useDeleteGroup();
*
* deleteGroup.mutate(1); // 删除 ID 为 1 的分组
*/
export function useDeleteGroup() {
const queryClient = useQueryClient();
return useMutation({
mutationFn: async (id: number) => {
return apiClient.delete<null>(`/api/v1/group/delete/${id}`);
},
onSuccess: () => {
logger.log('分组删除成功');
queryClient.invalidateQueries({ queryKey: ['groups', 'list'] });
},
onError: (error) => {
logger.error('分组删除失败:', error);
},
});
}
* 自动添加分组 item Hook
*
* 后端路由: POST /api/v1/group/auto-add-item
* Body: { id: number }
*
* @example
* const autoAdd = useAutoAddGroupItem();
* autoAdd.mutate(1); // 为 groupId=1 自动添加匹配的 items
*/