import React, { useEffect, useState, useRef } from 'react'; import { PageContainer } from '@ant-design/pro-components'; import { Row, Col, Menu, Tabs, Card, Button, message } from 'antd'; import { BetaSchemaForm, ProForm, ProFormGroup, ProFormText, ProFormTextArea } from '@ant-design/pro-form'; import type { NodeDesignData } from './types'; import * as service from './service'; import { useLocation } from 'react-router-dom'; // Tab 配置 const TAB_CONFIG = [ { key: 'panel', label: '属性(预览)', schemaKey: 'panelVariablesSchema', readonly: true }, { key: 'local', label: '环境变量(预览)', schemaKey: 'localVariablesSchema', readonly: true }, { key: 'form', label: '表单(预览)', schemaKey: 'formVariablesSchema', readonly: true }, { key: 'ui', label: 'UI配置', schemaKey: 'uiVariables', readonly: false } ]; const NodeDesignForm: React.FC = () => { const location = useLocation(); const nodeData = location.state?.nodeData; // 缓存节点定义数据 const [nodeDefinitions, setNodeDefinitions] = useState([]); const [loading, setLoading] = useState(false); // 当前选中的节点 const [selectedNode, setSelectedNode] = useState(null); // 当前选中的 tab const [activeTab, setActiveTab] = useState('panel'); const formRef = useRef(); const uiFormRef = useRef(); // 添加 UI 配置表单的 ref // 加载节点定义数据 useEffect(() => { const loadNodeDefinitions = async () => { try { setLoading(true); const data = await service.getNodeDefinitionsDefined(); setNodeDefinitions(data); // 如果是修改模式,设置当前节点为选中状态 if (nodeData) { setSelectedNode(nodeData); } else if (data.length > 0) { setSelectedNode(data[0]); } } catch (error) { console.error('加载节点定义失败:', error); } finally { setLoading(false); } }; loadNodeDefinitions(); }, [nodeData]); // 获取当前节点可用的 Tab 列表 const getAvailableTabs = (node: NodeDesignData | null) => { if (!node) return []; // 如果是修改模式,从nodeDefinitions中找到对应的节点定义 if (nodeData) { const nodeDefinition = nodeDefinitions.find(def => def.nodeCode === nodeData.nodeType); if (nodeDefinition) { return TAB_CONFIG.filter(tab => { // 使用节点定义中的schema const value = nodeDefinition[tab.schemaKey as keyof NodeDesignData]; return value !== null && value !== undefined; }); } } // 新建模式 return TAB_CONFIG.filter(tab => { const value = node[tab.schemaKey as keyof NodeDesignData]; return value !== null && value !== undefined; }); }; // 处理节点选择 const handleNodeSelect = (nodeCode: string) => { // 如果是修改模式,不允许选择其他节点 if (nodeData) return; const node = nodeDefinitions.find(n => n.nodeCode === nodeCode); if (node) { setSelectedNode(node); // 获取可用的 tab 列表 const availableTabs = getAvailableTabs(node); // 如果当前选中的 tab 不在可用列表中,则选择第一个可用的 tab if (availableTabs.length > 0 && !availableTabs.find(tab => tab.key === activeTab)) { setActiveTab(availableTabs[0].key); } } }; // 处理 Tab 切换 const handleTabChange = (newTab: string) => { setActiveTab(newTab); }; // 处理表单提交 const handleFormSubmit = async (values: any) => { console.log('表单提交:', values); // TODO: 调用接口保存数据 }; // 递归获取默认值 const getDefaultValues = (schema: any) => { console.log('Current Schema:', schema); if (!schema || !schema.properties) return {}; const result = Object.entries(schema.properties).reduce((acc, [key, value]: [string, any]) => { console.log(`Processing key: ${key}, value:`, value); if (value.type === 'object') { const nestedDefaults = getDefaultValues(value); console.log(`Nested defaults for ${key}:`, nestedDefaults); acc[key] = nestedDefaults; } else if (value.type === 'array' && value.items) { acc[key] = value.default || []; } else { acc[key] = value.default; } return acc; }, {}); console.log('Result for schema:', result); return result; }; // 将 JSON Schema 转换为 ProForm Schema const convertToProFormSchema = (schema: any, parentKey = '', level = 0) => { if (!schema || !schema.properties) return []; return Object.entries(schema.properties).map(([key, value]: [string, any]) => { const fullKey = parentKey ? `${parentKey}.${key}` : key; console.log('Converting schema key:', fullKey, 'value:', value); // 基础字段配置 const baseField = { title: value.title, dataIndex: fullKey, tooltip: value.description, initialValue: value.default }; // 处理不同类型的字段 if (value.type === 'object') { return { ...baseField, dataIndex: fullKey, valueType: 'group', columns: convertToProFormSchema(value, fullKey, level + 1), fieldProps: { title: value.title, style: { padding: level === 0 ? '16px' : '8px', marginBottom: '16px', border: '1px solid #f0f0f0', borderRadius: '4px', background: level === 0 ? '#fafafa' : 'transparent' } } }; } // 处理枚举类型 if (value.enum) { return { ...baseField, valueType: 'select', valueEnum: value.enum.reduce((acc: any, item: string, index: number) => { acc[item] = { text: value.enumNames?.[index] || item }; return acc; }, {}), placeholder: `请选择${value.title}` }; } // 处理数组类型 if (value.type === 'array') { const itemColumns = value.items ? convertToProFormSchema( { properties: { item: value.items } }, `${fullKey}.item`, level + 1 ) : []; return { ...baseField, valueType: 'formList', columns: itemColumns, placeholder: `请添加${value.title}` }; } // 处理基础类型 const typeMap: Record = { 'string': 'text', 'integer': 'digit', 'number': 'digit', 'boolean': 'switch' }; // 判断是否是颜色字段 const isColorField = value.type === 'string' && (value.title?.includes('颜色') || value.description?.includes('颜色')); if (isColorField) { return { ...baseField, valueType: 'color', placeholder: `请选择${value.title}`, fieldProps: { showText: true, format: 'hex' } }; } return { ...baseField, valueType: typeMap[value.type] || 'text', placeholder: `请输入${value.title}` }; }); }; // 渲染 Tab 内容 const renderTabContent = (schemaKey: string) => { if (!selectedNode) return null; // 获取schema和初始值 let schema; let initialValues = {}; if (nodeData) { // 编辑模式 const nodeDefinition = nodeDefinitions.find(def => def.nodeCode === nodeData.nodeType); if (!nodeDefinition) return null; if (schemaKey === 'uiVariables') { // UI配置:使用nodeDefinitions中的schema定义,使用nodeData中的实际数据作为初始值 schema = nodeDefinition.uiVariables; initialValues = nodeData.uiVariables || {}; } else { // 其他配置:使用schema中的定义 schema = nodeDefinition[schemaKey as keyof NodeDesignData]; // 只在非UI配置时使用默认值 initialValues = getDefaultValues(schema); } } else { // 新建模式 schema = selectedNode[schemaKey as keyof NodeDesignData]; initialValues = getDefaultValues(schema); } if (!schema) return null; console.log(`Rendering ${schemaKey}:`, { schema, initialValues }); const formColumns = convertToProFormSchema(schema); return ( ); }; // 将扁平的对象转换为嵌套对象 const flatToNested = (obj: Record) => { const result: Record = {}; Object.keys(obj).forEach(key => { const parts = key.split('.'); let current = result; parts.forEach((part, index) => { if (index === parts.length - 1) { current[part] = obj[key]; } else { current[part] = current[part] || {}; current = current[part]; } }); }); return result; }; const handleSave = async () => { if (!selectedNode) return; try { const formValues = await formRef.current?.validateFields(); const uiValues = await uiFormRef.current?.validateFields(); const saveData = { nodeType: formValues.nodeType, nodeCode: formValues.nodeCode, nodeName: formValues.nodeName, category: formValues.category, description: formValues.description, uiVariables: flatToNested(uiValues), // 将扁平结构转换为嵌套结构 localVariablesSchema: selectedNode.localVariablesSchema, panelVariablesSchema: selectedNode.panelVariablesSchema, formVariablesSchema: selectedNode.formVariablesSchema }; await service.saveNodeDefinition(saveData); message.success('保存成功'); } catch (error) { console.error('Save failed:', error); message.error('保存失败'); } }; const renderBasicForm = () => { if (!selectedNode) return null; return ( ); }; return ( 保存 ]} >
节点类型
({ key: node.nodeCode, label: `${node.nodeName}(${node.nodeCode})`, disabled: nodeData ? node.nodeCode !== nodeData.nodeCode : false // 只在修改模式下禁用不匹配的节点 }))} onClick={({ key }) => handleNodeSelect(key)} style={{ border: 'none', padding: '0 16px' }} />
{renderBasicForm()} ({ key: tab.schemaKey, label: tab.label, children: renderTabContent(tab.schemaKey) }))} />
); }; export default NodeDesignForm;