From 166eebabff6329f63326445f4c629efee7a4245c Mon Sep 17 00:00:00 2001 From: WangCham <651122857@qq.com> Date: Tue, 28 Oct 2025 13:11:09 +0800 Subject: [PATCH] fix: delete mcp market --- .../MCPServerComponent.tsx} | 2 +- .../MCPServerCardComponent.tsx} | 2 +- .../mcp-market-card/MCPServerCardVO.ts} | 0 web/src/app/home/plugins/page.tsx | 119 +++++++++--------- 4 files changed, 64 insertions(+), 59 deletions(-) rename web/src/app/home/plugins/{mcp-market/MCPMarketComponent.tsx => mcp-server/MCPServerComponent.tsx} (99%) rename web/src/app/home/plugins/{mcp-market/mcp-market-card/MCPMarketCardComponent.tsx => mcp-server/mcp-market-card/MCPServerCardComponent.tsx} (98%) rename web/src/app/home/plugins/{mcp-market/mcp-market-card/MCPMarketCardVO.ts => mcp-server/mcp-market-card/MCPServerCardVO.ts} (100%) diff --git a/web/src/app/home/plugins/mcp-market/MCPMarketComponent.tsx b/web/src/app/home/plugins/mcp-server/MCPServerComponent.tsx similarity index 99% rename from web/src/app/home/plugins/mcp-market/MCPMarketComponent.tsx rename to web/src/app/home/plugins/mcp-server/MCPServerComponent.tsx index 28f6ff86..83fc0851 100644 --- a/web/src/app/home/plugins/mcp-market/MCPMarketComponent.tsx +++ b/web/src/app/home/plugins/mcp-server/MCPServerComponent.tsx @@ -168,7 +168,7 @@ export default function MCPMarketComponent({ ) : installedServers.length === 0 ? (
- {t('mcp.noInstalledServers')} + {t('mcp.noServerInstalled')}
) : ( installedServers.map((server, index) => ( diff --git a/web/src/app/home/plugins/mcp-market/mcp-market-card/MCPMarketCardComponent.tsx b/web/src/app/home/plugins/mcp-server/mcp-market-card/MCPServerCardComponent.tsx similarity index 98% rename from web/src/app/home/plugins/mcp-market/mcp-market-card/MCPMarketCardComponent.tsx rename to web/src/app/home/plugins/mcp-server/mcp-market-card/MCPServerCardComponent.tsx index 330fe228..2190147f 100644 --- a/web/src/app/home/plugins/mcp-market/mcp-market-card/MCPMarketCardComponent.tsx +++ b/web/src/app/home/plugins/mcp-server/mcp-market-card/MCPServerCardComponent.tsx @@ -1,4 +1,4 @@ -import { MCPMarketCardVO } from '@/app/home/plugins/mcp-market/mcp-market-card/MCPMarketCardVO'; +import { MCPMarketCardVO } from '@/app/home/plugins/mcp-server/mcp-market-card/MCPServerCardVO'; import { Button } from '@/components/ui/button'; import { useTranslation } from 'react-i18next'; diff --git a/web/src/app/home/plugins/mcp-market/mcp-market-card/MCPMarketCardVO.ts b/web/src/app/home/plugins/mcp-server/mcp-market-card/MCPServerCardVO.ts similarity index 100% rename from web/src/app/home/plugins/mcp-market/mcp-market-card/MCPMarketCardVO.ts rename to web/src/app/home/plugins/mcp-server/mcp-market-card/MCPServerCardVO.ts diff --git a/web/src/app/home/plugins/page.tsx b/web/src/app/home/plugins/page.tsx index 6d02627c..8793daa3 100644 --- a/web/src/app/home/plugins/page.tsx +++ b/web/src/app/home/plugins/page.tsx @@ -7,7 +7,7 @@ import MarketPage from '@/app/home/plugins/plugin-market/PluginMarketComponent'; import MCPComponent, { MCPComponentRef, } from '@/app/home/plugins/mcp/MCPComponent'; -import MCPMarketComponent from '@/app/home/plugins/mcp-market/MCPMarketComponent'; +import MCPServerComponent from '@/app/home/plugins/mcp-server/MCPServerComponent'; import styles from './plugins.module.css'; import { Tabs, TabsContent, TabsList, TabsTrigger } from '@/components/ui/tabs'; import { Button } from '@/components/ui/button'; @@ -48,7 +48,7 @@ import { SelectItem, } from "@/components/ui/select" -import { useForm } from 'react-hook-form'; +import { Resolver, useForm } from 'react-hook-form'; import { zodResolver } from '@hookform/resolvers/zod'; import { z } from 'zod'; import { DialogDescription } from '@radix-ui/react-dialog'; @@ -121,26 +121,48 @@ export default function PluginConfigPage() { form.setValue('extra_args', newArgs); }; const getFormSchema = (t: (key: string) => string) => - z.object({ - name: z.string().min(1, { message: t('mcp.nameRequired') }), - timeout: z.number().min(30, { message: t('mcp.timeoutMin30') }), - ssereadtimeout: z - .number() - .min(300, { message: t('mcp.sseTimeoutMin300') }), - url: z.string().min(1, { message: t('mcp.requestURLRequired') }), - extra_args: z.array(getExtraArgSchema(t)).optional(), - }); - const formSchema = getFormSchema(t); - const form = useForm>({ - resolver: zodResolver(formSchema), - defaultValues: { - name: '', - url: '', - timeout: 30, - ssereadtimeout: 300, - extra_args: [], - }, + z.object({ + name: z.string({ required_error: t('mcp.nameRequired') }), + timeout: z + .number({ invalid_type_error: t('mcp.timeoutMustBeNumber') }) + .nonnegative({ message: t('mcp.timeoutNonNegative') }) + .default(30), + ssereadtimeout: z + .number({ invalid_type_error: t('mcp.sseTimeoutMustBeNumber') }) + .nonnegative({ message: t('mcp.sseTimeoutNonNegative') }) + .default(300), + url: z.string({ required_error: t('models.requestURLRequired') }), + extra_args: z + .array( + z.object({ + key: z.string(), + type: z.enum(['string', 'number', 'boolean']), + value: z.string(), + }) + ) + .optional(), }); + +const formSchema = getFormSchema(t); + + +type FormValues = z.infer & { + timeout: number; + ssereadtimeout: number; +}; + +const form = useForm({ + resolver: zodResolver(formSchema) as unknown as Resolver, + defaultValues: { + name: '', + url: '', + timeout: 30, + ssereadtimeout: 300, + extra_args: [], + }, +}); + + const [extraArgs, setExtraArgs] = useState< { key: string; type: 'string' | 'number' | 'boolean'; value: string }[] >([]); @@ -274,24 +296,12 @@ export default function PluginConfigPage() { }); if (!mcpSSEModalOpen && !modalOpen && !showDeleteConfirmModal) { - console.log( - '[Dialog Debug] All dialogs closed, cleaning up body styles...', - ); - console.log( - '[Dialog Debug] Before cleanup - body.style.pointerEvents:', - document.body.style.pointerEvents, - ); - console.log( - '[Dialog Debug] Before cleanup - body.style.overflow:', - document.body.style.overflow, - ); - const cleanup = () => { - // 强制移除 body 上可能残留的样式 + document.body.style.removeProperty('pointer-events'); document.body.style.removeProperty('overflow'); - // 如果 removeProperty 不起作用,强制设置为空字符串 + if (document.body.style.pointerEvents === 'none') { document.body.style.pointerEvents = ''; } @@ -334,7 +344,7 @@ export default function PluginConfigPage() { } }, [mcpSSEModalOpen, modalOpen, showDeleteConfirmModal]); - // 额外的全局清理:定期检查并清理 + useEffect(() => { const interval = setInterval(() => { if (!mcpSSEModalOpen && !modalOpen && !showDeleteConfirmModal) { @@ -454,16 +464,16 @@ export default function PluginConfigPage() { async function loadServerForEdit(serverName: string) { try { const resp = await httpClient.getMCPServer(serverName); - const server = resp.server ?? resp; // 有的接口包了一层,有的直接返回对象 + const server = resp.server ?? resp; console.log('Loaded server for edit:', server); - // 填充表单数据 + form.setValue('name', server.name); form.setValue('url', server.extra_args?.url || ''); form.setValue('timeout', server.extra_args?.timeout || 30); form.setValue('ssereadtimeout', server.extra_args?.ssereadtimeout || 300); - // 填充 headers + if (server.extra_args?.headers) { const headers = Object.entries(server.extra_args.headers).map( ([key, value]) => ({ @@ -476,23 +486,23 @@ export default function PluginConfigPage() { form.setValue('extra_args', headers); } - // 重置测试状态 + setMcpTestStatus('testing'); setMcpToolNames([]); setMcpTestError(''); - // 打开对话框 + setEditingServerName(serverName); setIsEditMode(true); setMcpSSEModalOpen(true); - // 在这里测试工具连接状态 + try { const res = await httpClient.testMCPServer(server.name); if (res.task_id) { const taskId = res.task_id; - // 监听任务完成 + const interval = setInterval(() => { httpClient.getAsyncTask(taskId).then((taskResp) => { console.log('Task response:', taskResp); @@ -505,13 +515,13 @@ export default function PluginConfigPage() { console.log('Exception:', taskResp.runtime.exception); if (taskResp.runtime.exception) { - // 测试失败 + console.log('Test failed with exception'); setMcpTestStatus('failed'); setMcpToolNames([]); setMcpTestError(taskResp.runtime.exception || '未知错误'); } else if (taskResp.runtime.result) { - // 测试成功 - 后端可能返回字符串或对象 + try { let result: { status?: string; @@ -520,7 +530,7 @@ export default function PluginConfigPage() { error?: string; }; - // 如果result是字符串,需要先解析 + const rawResult: any = taskResp.runtime.result; if (typeof rawResult === 'string') { console.log('Result is string, parsing...'); @@ -614,25 +624,21 @@ export default function PluginConfigPage() { }; if (isEditMode && editingServerName) { - // 编辑模式:更新服务器 + await httpClient.updateMCPServer(editingServerName, serverConfig); toast.success(t('mcp.updateSuccess')); } else { - // 创建模式:新建服务器 await httpClient.createMCPServer(serverConfig); toast.success(t('mcp.createSuccess')); } - // 只有在异步操作成功后才关闭对话框 setMcpSSEModalOpen(false); - // 重置表单和状态 form.reset(); setExtraArgs([]); setEditingServerName(null); setIsEditMode(false); - // 刷新服务器列表 setRefreshKey((prev) => prev + 1); } catch (error) { console.error('Failed to save MCP server:', error); @@ -706,7 +712,7 @@ export default function PluginConfigPage() { if (file) { uploadPluginFile(file); } - // 清空input值,以便可以重复选择同一个文件 + event.target.value = ''; }, [uploadPluginFile], @@ -748,7 +754,7 @@ export default function PluginConfigPage() { [uploadPluginFile, isPluginSystemReady, t], ); - // 插件系统未启用的状态显示 + const renderPluginDisabledState = () => (
@@ -761,7 +767,7 @@ export default function PluginConfigPage() {
); - // 插件系统连接异常的状态显示 + const renderPluginConnectionErrorState = () => (
); - // 加载状态显示 const renderLoadingState = () => (

@@ -792,7 +797,6 @@ export default function PluginConfigPage() {

); - // 根据状态返回不同的内容 if (statusLoading) { return renderLoadingState(); } @@ -930,7 +934,7 @@ export default function PluginConfigPage() { - { loadServerForEdit(serverName); @@ -1221,6 +1225,7 @@ export default function PluginConfigPage() { )} /> + {t('models.extraParameters')}