import { forwardRef, useImperativeHandle, useState, useRef } from 'react'; import { Form, Input, Select, App, Button, Tabs, Space } from 'antd'; import { useTranslation } from 'react-i18next'; import type { MCPToolItem, ToolItem } from '../types' import RbModal from '@/components/RbModal'; import Empty from '@/components/Empty'; import RequestHeaderModal from './RequestHeaderModal'; import Table from '@/components/Table'; import { addTool, updateTool, testConnection } from '@/api/tools' import type { McpServiceModalRef } from '../types' const FormItem = Form.Item; interface McpServiceModalProps { refresh: () => void; } export interface RequestHeader { key: string; value: string; [key: string]: string | undefined; } export interface RequestHeaderModalRef { handleOpen: (index?: number, data?: RequestHeader) => void; handleClose: () => void; } const authTypeList = ['none', 'api_key', 'basic_auth'] const tabKeys = ['auth', 'requestHeader', 'config'] const McpServiceModal = forwardRef(({ refresh }, ref) => { const { t } = useTranslation(); const { message } = App.useApp(); const [visible, setVisible] = useState(false); const [form] = Form.useForm(); const [loading, setLoading] = useState(false); const [editVo, setEditVo] = useState(null) const [activeTab, setActiveTab] = useState('auth'); const values = Form.useWatch([], form) const requestHeaderModalRef = useRef(null) const [requestHeaderList, setRequestHeaderList] = useState([]) const formatTabItems = () => { return tabKeys.map(key => ({ key, label: t(`tool.${key}`), })) } const handleChangeTab = (key: string) => { setActiveTab(key); } // 封装取消方法,添加关闭弹窗逻辑 const handleClose = () => { setVisible(false); form.resetFields(); setLoading(false); setEditVo(null) setActiveTab('auth') setRequestHeaderList([]) }; const handleOpen = (data?: ToolItem) => { if (data?.id) { const { config_data, name, description, icon } = data form.setFieldsValue({ name, description, icon, config: { ...config_data } }) if (config_data.connection_config.headers) { console.log(Object.keys(config_data.connection_config.headers).map(key => ({ key, value: config_data.connection_config.headers[key] }))) setRequestHeaderList(Object.keys(config_data.connection_config.headers).map(key => ({ key, value: config_data.connection_config.headers[key] }))) } setEditVo(data) } else { form.resetFields(); } setVisible(true); }; // 封装保存方法,添加提交逻辑 const handleSave = () => { form .validateFields() .then(() => { setLoading(true); // 创建新服务对象 const { config, ...rest } = values const newService: MCPToolItem = { ...rest, tool_type: 'mcp', config: { ...config, connection_config: { ...config.connection_config, headers: requestHeaderList.reduce((acc: Record, cur) => { acc[cur.key] = cur.value return acc }, {}) } } } const request = editVo?.id ? updateTool(editVo.id, newService) : addTool(newService) request.then((res: any) => { message.success(t('common.saveSuccess')); testConnection(res.tool_id || editVo?.id) .then(() => { handleClose(); refresh() }) .finally(() => { setLoading(false); }) }) .catch(() => { setLoading(false); }) }) .catch((err) => { console.log('表单验证失败:', err); setLoading(false); }); }; const handleEditRequestHeader = (index?: number, data?: RequestHeader) => { requestHeaderModalRef.current?.handleOpen(index, data) } const handleDeleteRequestHeader = (index: number) => { const list = requestHeaderList.filter((_item, idx) => idx !== index) setRequestHeaderList([...list]) } // 暴露给父组件的方法 useImperativeHandle(ref, () => ({ handleOpen, handleClose })); return (
{/* 服务端点 URL */} {/* 名称和图标 */} {/* */} {/* 描述 */} {/* 认证、请求头、配置 */} {/* 认证模块 */} <> {/* 认证方式 */} } {/* API Key: 认证方式 = bearer_token 展示 */} {values?.config?.connection_config?.auth_type === 'bearer_token' && } {/* API Key: 认证方式 = basic_auth 展示 */} {values?.config?.connection_config?.auth_type === 'basic_auth' && <> } {/* 请求头模块 */}
{t('tool.requestHeader')}
{t('tool.requestHeaderDesc')}
{requestHeaderList.length === 0 ? : ( ), }, ]} initialData={requestHeaderList} emptySize={88} /> } {/* 配置模块 */} <> ); }); export default McpServiceModal;