528 lines
16 KiB
TypeScript
528 lines
16 KiB
TypeScript
import { useUserData } from "./useUserData";
|
||
import { useEffect, useState, useCallback } from "react";
|
||
import logger from "@/utils/logger";
|
||
import type { IUserInfo, ISystemStatus } from "@/interfaces/database/user-setting";
|
||
import userService from "@/services/user_service";
|
||
import { rsaPsw } from "../utils/encryption";
|
||
import type { IFactory, IMyLlmModel } from "@/interfaces/database/llm";
|
||
import type { LLMFactory } from "@/constants/llm";
|
||
import type { IMcpServer, IMcpServerListResponse } from "@/interfaces/database/mcp";
|
||
import type { IImportMcpServersRequestBody, ITestMcpRequestBody, ICreateMcpServerRequestBody } from "@/interfaces/request/mcp";
|
||
import type { IPaginationBody } from "@/interfaces/request/base";
|
||
import { LanguageAbbreviation, LanguageAbbreviationKeysMap, LanguageTranslationMap } from "@/constants/common";
|
||
|
||
/**
|
||
* 个人中心设置
|
||
*/
|
||
export function useProfileSetting() {
|
||
const { fetchUserInfo, userInfo } = useUserData();
|
||
|
||
useEffect(() => {
|
||
// 仅在已登录情况下才获取用户信息,避免登录页触发401导致重复跳转
|
||
const authorization = localStorage.getItem('Authorization');
|
||
if (authorization && authorization !== '') {
|
||
fetchUserInfo();
|
||
}
|
||
}, [fetchUserInfo]);
|
||
|
||
const updateUserInfo = async (newUserInfo: Partial<IUserInfo>) => {
|
||
try {
|
||
await userService.updateSetting(newUserInfo);
|
||
} catch (error) {
|
||
logger.error('更新用户信息失败:', error);
|
||
throw error;
|
||
}
|
||
};
|
||
|
||
const changeUserPassword = async (data: { password: string; new_password: string }) => {
|
||
try {
|
||
const newPassword = rsaPsw(data.new_password);
|
||
const oldPassword = rsaPsw(data.password);
|
||
const res = await userService.updatePassword({
|
||
password: oldPassword,
|
||
new_password: newPassword,
|
||
});
|
||
return res;
|
||
} catch (error) {
|
||
throw error;
|
||
}
|
||
};
|
||
|
||
return {
|
||
userInfo,
|
||
updateUserInfo,
|
||
changeUserPassword,
|
||
};
|
||
}
|
||
|
||
export function useLanguageSetting() {
|
||
const { userInfo, updateUserInfo } = useProfileSetting();
|
||
const [language, setLanguage] = useState(userInfo?.language || 'English');
|
||
|
||
const changeLanguage = async (language: LanguageAbbreviation) => {
|
||
try {
|
||
// LanguageAbbreviation to language
|
||
const translatedLanguage = LanguageAbbreviationKeysMap[language];
|
||
const authorization = localStorage.getItem('Authorization');
|
||
// 未登录时仅本地切换语言,不请求后端,避免401导致跳转
|
||
if (!authorization || authorization === '') {
|
||
setLanguage(translatedLanguage);
|
||
return;
|
||
}
|
||
await updateUserInfo({ language: translatedLanguage });
|
||
setLanguage(translatedLanguage);
|
||
} catch (error) {
|
||
logger.error('更新语言设置失败:', error);
|
||
throw error;
|
||
}
|
||
}
|
||
|
||
return {
|
||
language,
|
||
changeLanguage,
|
||
}
|
||
}
|
||
|
||
/**
|
||
* LLM 模型设置
|
||
*/
|
||
export function useLlmModelSetting() {
|
||
const [llmFactory, setLlmFactory] = useState<IFactory[]>([]);
|
||
const [myLlm, setMyLlm] = useState<Record<LLMFactory, IMyLlmModel>>();
|
||
|
||
const fetchLlmFactory = async () => {
|
||
try {
|
||
const res = await userService.llm_factories_list();
|
||
const arr = res.data.data || [];
|
||
setLlmFactory(arr);
|
||
} catch (error) {
|
||
logger.error('获取模型工厂失败:', error);
|
||
throw error;
|
||
}
|
||
}
|
||
|
||
const fetchMyLlm = async () => {
|
||
try {
|
||
const res = await userService.my_llm({include_details: true});
|
||
const llm_dic = res.data.data || {};
|
||
setMyLlm(llm_dic);
|
||
} catch (error) {
|
||
logger.error('获取我的模型失败:', error);
|
||
throw error;
|
||
}
|
||
}
|
||
useEffect(() => {
|
||
fetchLlmFactory();
|
||
fetchMyLlm();
|
||
}, []);
|
||
|
||
const refreshLlmModel = async () => {
|
||
await fetchMyLlm();
|
||
// await fetchLlmFactory();
|
||
logger.info('刷新我的模型成功');
|
||
}
|
||
|
||
return {
|
||
llmFactory,
|
||
myLlm,
|
||
refreshLlmModel,
|
||
}
|
||
}
|
||
|
||
/**
|
||
* 系统状态设置
|
||
*/
|
||
export function useSystemStatus() {
|
||
const [systemStatus, setSystemStatus] = useState<ISystemStatus | null>(null);
|
||
const [loading, setLoading] = useState(false);
|
||
const [error, setError] = useState<string | null>(null);
|
||
|
||
const fetchSystemStatus = useCallback(async () => {
|
||
try {
|
||
setLoading(true);
|
||
setError(null);
|
||
const res = await userService.system_status();
|
||
if (res.data.code === 0) {
|
||
setSystemStatus(res.data.data);
|
||
} else {
|
||
throw new Error(res.data.message || '获取系统状态失败');
|
||
}
|
||
} catch (error: any) {
|
||
const errorMessage = error.response?.data?.message || error.message || '获取系统状态失败';
|
||
setError(errorMessage);
|
||
logger.error('获取系统状态失败:', error);
|
||
} finally {
|
||
setLoading(false);
|
||
}
|
||
}, []);
|
||
|
||
return {
|
||
systemStatus,
|
||
loading,
|
||
error,
|
||
fetchSystemStatus,
|
||
};
|
||
}
|
||
|
||
/**
|
||
* 团队设置
|
||
*/
|
||
export function useTeamSetting() {
|
||
const { userInfo, tenantInfo, tenantList, refreshUserData } = useUserData();
|
||
const [tenantUsers, setTenantUsers] = useState<any[]>([]);
|
||
const [loading, setLoading] = useState(false);
|
||
const [error, setError] = useState<string | null>(null);
|
||
|
||
// 获取租户用户列表
|
||
const fetchTenantUsers = useCallback(async () => {
|
||
if (!tenantInfo?.tenant_id) return;
|
||
|
||
try {
|
||
const response = await userService.listTenantUser(tenantInfo.tenant_id);
|
||
if (response.data.code === 0) {
|
||
setTenantUsers(response.data.data || []);
|
||
}
|
||
} catch (error) {
|
||
logger.error('获取租户用户失败:', error);
|
||
}
|
||
}, [tenantInfo?.tenant_id]);
|
||
|
||
useEffect(() => {
|
||
if (tenantInfo?.tenant_id) {
|
||
fetchTenantUsers();
|
||
}
|
||
}, [fetchTenantUsers]);
|
||
|
||
const inviteUser = async (email: string) => {
|
||
if (!email.trim() || !tenantInfo?.tenant_id) return;
|
||
|
||
setLoading(true);
|
||
setError(null);
|
||
|
||
try {
|
||
const response = await userService.addTenantUser(tenantInfo.tenant_id, email.trim());
|
||
if (response.data.code === 0) {
|
||
await fetchTenantUsers();
|
||
await refreshUserData();
|
||
return { success: true };
|
||
} else {
|
||
const errorMsg = response.data.message || '邀请失败';
|
||
setError(errorMsg);
|
||
return { success: false, error: errorMsg };
|
||
}
|
||
} catch (error: any) {
|
||
const errorMsg = error.message || '邀请失败';
|
||
setError(errorMsg);
|
||
return { success: false, error: errorMsg };
|
||
} finally {
|
||
setLoading(false);
|
||
}
|
||
};
|
||
|
||
const deleteUser = async (userId: string) => {
|
||
if (!tenantInfo?.tenant_id) return;
|
||
|
||
try {
|
||
const response = await userService.deleteTenantUser({
|
||
tenantId: tenantInfo.tenant_id,
|
||
userId
|
||
});
|
||
if (response.data.code === 0) {
|
||
await fetchTenantUsers();
|
||
return { success: true };
|
||
}
|
||
return { success: false };
|
||
} catch (error) {
|
||
logger.error('删除用户失败:', error);
|
||
return { success: false };
|
||
}
|
||
};
|
||
|
||
const agreeTenant = async (tenantId: string) => {
|
||
try {
|
||
const response = await userService.agreeTenant(tenantId);
|
||
if (response.data.code === 0) {
|
||
await refreshUserData();
|
||
return { success: true };
|
||
}
|
||
return { success: false };
|
||
} catch (error) {
|
||
logger.error('同意加入失败:', error);
|
||
return { success: false };
|
||
}
|
||
};
|
||
|
||
const quitTenant = async (tenantId: string) => {
|
||
if (!userInfo?.id) return;
|
||
|
||
try {
|
||
const response = await userService.deleteTenantUser({
|
||
tenantId,
|
||
userId: userInfo.id
|
||
});
|
||
if (response.data.code === 0) {
|
||
await refreshUserData();
|
||
return { success: true };
|
||
}
|
||
return { success: false };
|
||
} catch (error) {
|
||
logger.error('退出租户失败:', error);
|
||
return { success: false };
|
||
}
|
||
};
|
||
|
||
return {
|
||
userInfo,
|
||
tenantInfo,
|
||
tenantList,
|
||
tenantUsers,
|
||
loading,
|
||
error,
|
||
inviteUser,
|
||
deleteUser,
|
||
agreeTenant,
|
||
quitTenant,
|
||
refreshUserData,
|
||
};
|
||
}
|
||
|
||
/**
|
||
* MCP 设置
|
||
*/
|
||
export function useMcpSetting({ refreshServer }: { refreshServer: (initial?: boolean) => Promise<void> }) {
|
||
const [mcpServers, setMcpServers] = useState<IMcpServer[]>([]);
|
||
const [loading, setLoading] = useState(false);
|
||
const [error, setError] = useState<string | null>(null);
|
||
const [total, setTotal] = useState(0);
|
||
|
||
// 获取 MCP 服务器列表
|
||
const fetchMcpServers = useCallback(async (params?: IPaginationBody & {
|
||
keyword?: string;
|
||
}) => {
|
||
try {
|
||
setLoading(true);
|
||
setError(null);
|
||
const res = await userService.listMcpServer({
|
||
page: params?.page || 1,
|
||
size: params?.size || 8,
|
||
keyword: params?.keyword,
|
||
});
|
||
if (res.data.code === 0) {
|
||
const data: IMcpServerListResponse = res.data.data;
|
||
setMcpServers(data.mcp_servers || []);
|
||
setTotal(data.total || 0);
|
||
} else {
|
||
throw new Error(res.data.message || '获取 MCP 服务器列表失败');
|
||
}
|
||
} catch (error: any) {
|
||
const errorMessage = error.response?.data?.message || error.message || '获取 MCP 服务器列表失败';
|
||
setError(errorMessage);
|
||
logger.error('获取 MCP 服务器列表失败:', error);
|
||
} finally {
|
||
setLoading(false);
|
||
}
|
||
}, []);
|
||
|
||
// 导入 MCP 服务器
|
||
const importMcpServers = useCallback(async (data: IImportMcpServersRequestBody) => {
|
||
try {
|
||
setLoading(true);
|
||
setError(null);
|
||
const res = await userService.importMcpServer(data);
|
||
if (res.data.code === 0) {
|
||
await refreshServer();
|
||
return { success: true };
|
||
} else {
|
||
throw new Error(res.data.message || '导入 MCP 服务器失败');
|
||
}
|
||
} catch (error: any) {
|
||
const errorMessage = error.response?.data?.message || error.message || '导入 MCP 服务器失败';
|
||
setError(errorMessage);
|
||
logger.error('导入 MCP 服务器失败:', error);
|
||
return { success: false, error: errorMessage };
|
||
} finally {
|
||
setLoading(false);
|
||
}
|
||
}, []);
|
||
|
||
// 导出 MCP 服务器
|
||
const exportMcpServers = useCallback(async (mcpIds: string[]) => {
|
||
try {
|
||
setLoading(true);
|
||
setError(null);
|
||
const res = await userService.exportMcpServer(mcpIds);
|
||
if (res.data.code === 0) {
|
||
// 处理导出数据,创建下载
|
||
const exportData = res.data.data;
|
||
const blob = new Blob([JSON.stringify(exportData, null, 2)], { type: 'application/json' });
|
||
const url = URL.createObjectURL(blob);
|
||
const a = document.createElement('a');
|
||
a.href = url;
|
||
a.download = 'mcp-servers.json';
|
||
a.click();
|
||
URL.revokeObjectURL(url);
|
||
return { success: true };
|
||
} else {
|
||
throw new Error(res.data.message || '导出 MCP 服务器失败');
|
||
}
|
||
} catch (error: any) {
|
||
const errorMessage = error.response?.data?.message || error.message || '导出 MCP 服务器失败';
|
||
setError(errorMessage);
|
||
logger.error('导出 MCP 服务器失败:', error);
|
||
return { success: false, error: errorMessage };
|
||
} finally {
|
||
setLoading(false);
|
||
}
|
||
}, []);
|
||
|
||
// 测试 MCP 服务器
|
||
const testMcpServer = useCallback(async (data: ITestMcpRequestBody) => {
|
||
try {
|
||
setLoading(true);
|
||
setError(null);
|
||
const res = await userService.testMcpServer(data);
|
||
if (res.data.code === 0) {
|
||
return { success: true, data: res.data.data };
|
||
} else {
|
||
throw new Error(res.data.message || '测试 MCP 服务器失败');
|
||
}
|
||
} catch (error: any) {
|
||
const errorMessage = error.response?.data?.message || error.message || '测试 MCP 服务器失败';
|
||
setError(errorMessage);
|
||
return { success: false, error: errorMessage };
|
||
} finally {
|
||
setLoading(false);
|
||
}
|
||
}, []);
|
||
|
||
// 获取 MCP 服务器详情
|
||
const getMcpServerDetail = useCallback(async (mcpId: string) => {
|
||
try {
|
||
setLoading(true);
|
||
setError(null);
|
||
const res = await userService.mcpDetail(mcpId);
|
||
if (res.data.code === 0) {
|
||
const detail: IMcpServer = res.data.data;
|
||
return { success: true, data: detail };
|
||
} else {
|
||
throw new Error(res.data.message || '获取 MCP 服务器详情失败');
|
||
}
|
||
} catch (error: any) {
|
||
const errorMessage = error.response?.data?.message || error.message || '获取 MCP 服务器详情失败';
|
||
setError(errorMessage);
|
||
logger.error('获取 MCP 服务器详情失败:', error);
|
||
return { success: false, error: errorMessage };
|
||
} finally {
|
||
setLoading(false);
|
||
}
|
||
}, []);
|
||
|
||
// 创建 MCP 服务器
|
||
const createMcpServer = useCallback(async (data: ICreateMcpServerRequestBody) => {
|
||
try {
|
||
setLoading(true);
|
||
setError(null);
|
||
const res = await userService.createMcpServer(data);
|
||
if (res.data.code === 0) {
|
||
await refreshServer(true); // 重新获取列表
|
||
return { success: true, data: res.data.data };
|
||
} else {
|
||
throw new Error(res.data.message || '创建 MCP 服务器失败');
|
||
}
|
||
} catch (error: any) {
|
||
const errorMessage = error.response?.data?.message || error.message || '创建 MCP 服务器失败';
|
||
setError(errorMessage);
|
||
logger.error('创建 MCP 服务器失败:', error);
|
||
return { success: false, error: errorMessage };
|
||
} finally {
|
||
setLoading(false);
|
||
}
|
||
}, []);
|
||
|
||
// 更新 MCP 服务器
|
||
const updateMcpServer = useCallback(async (data: ICreateMcpServerRequestBody & { mcp_id: string }) => {
|
||
try {
|
||
setLoading(true);
|
||
setError(null);
|
||
const res = await userService.updateMcpServer(data);
|
||
if (res.data.code === 0) {
|
||
await refreshServer(); // 刷新列表
|
||
return { success: true, data: res.data.data };
|
||
} else {
|
||
throw new Error(res.data.message || '更新 MCP 服务器失败');
|
||
}
|
||
} catch (error: any) {
|
||
const errorMessage = error.response?.data?.message || error.message || '更新 MCP 服务器失败';
|
||
setError(errorMessage);
|
||
logger.error('更新 MCP 服务器失败:', error);
|
||
return { success: false, error: errorMessage };
|
||
} finally {
|
||
setLoading(false);
|
||
}
|
||
}, []);
|
||
|
||
// 删除 MCP 服务器
|
||
const deleteMcpServer = useCallback(async (mcpId: string) => {
|
||
try {
|
||
setLoading(true);
|
||
setError(null);
|
||
const res = await userService.removeMcpServer([mcpId]);
|
||
if (res.data.code === 0) {
|
||
await refreshServer(); // 刷新列表
|
||
return { success: true };
|
||
} else {
|
||
throw new Error(res.data.message || '删除 MCP 服务器失败');
|
||
}
|
||
} catch (error: any) {
|
||
const errorMessage = error.response?.data?.message || error.message || '删除 MCP 服务器失败';
|
||
setError(errorMessage);
|
||
logger.error('删除 MCP 服务器失败:', error);
|
||
return { success: false, error: errorMessage };
|
||
} finally {
|
||
setLoading(false);
|
||
}
|
||
}, []);
|
||
|
||
// 批量删除 MCP 服务器
|
||
const batchDeleteMcpServers = useCallback(async (mcpIds: string[]) => {
|
||
try {
|
||
setLoading(true);
|
||
setError(null);
|
||
const res = await userService.removeMcpServer(mcpIds);
|
||
if (res.data.code === 0) {
|
||
await fetchMcpServers(); // 重新获取列表
|
||
return { success: true };
|
||
} else {
|
||
throw new Error(res.data.message || '批量删除 MCP 服务器失败');
|
||
}
|
||
} catch (error: any) {
|
||
const errorMessage = error.response?.data?.message || error.message || '批量删除 MCP 服务器失败';
|
||
setError(errorMessage);
|
||
logger.error('批量删除 MCP 服务器失败:', error);
|
||
return { success: false, error: errorMessage };
|
||
} finally {
|
||
setLoading(false);
|
||
}
|
||
}, []);
|
||
|
||
return {
|
||
// 状态
|
||
mcpServers,
|
||
loading,
|
||
error,
|
||
total,
|
||
|
||
// 方法
|
||
fetchMcpServers,
|
||
importMcpServers,
|
||
exportMcpServers,
|
||
testMcpServer,
|
||
getMcpServerDetail,
|
||
createMcpServer,
|
||
updateMcpServer,
|
||
deleteMcpServer,
|
||
batchDeleteMcpServers,
|
||
};
|
||
}
|
||
|