import { type FC, useEffect, useState, useRef } from "react"; import { useTranslation } from 'react-i18next' import { Graph, Node } from '@antv/x6'; import { Form, Input, Button, Select, InputNumber, Slider, Space, Divider, App } from 'antd' import type { NodeConfig, NodeProperties, StartVariableItem, VariableEditModalRef } from '../../types' import Empty from '@/components/Empty'; import emptyIcon from '@/assets/images/workflow/empty.png' import CustomSelect from "@/components/CustomSelect"; import VariableEditModal from './VariableEditModal'; import MessageEditor from './MessageEditor' interface PropertiesProps { selectedNode?: Node | null; setSelectedNode: (node: Node | null) => void; graphRef: React.MutableRefObject; blankClick: () => void; deleteEvent: () => void; copyEvent: () => void; parseEvent: () => void; } const Properties: FC = ({ selectedNode, graphRef, }) => { const { t } = useTranslation() const { modal } = App.useApp() const [form] = Form.useForm(); const [configs, setConfigs] = useState>({} as Record) const values = Form.useWatch([], form); const variableModalRef = useRef(null) const [editIndex, setEditIndex] = useState(null) useEffect(() => { form.resetFields() if (selectedNode && form) { const { type = 'default', name = '', config } = selectedNode.getData() || {} const initialValue: Record = {} Object.keys(config || {}).forEach(key => { if (config && config[key] && 'defaultValue' in config[key]) { initialValue[key] = config[key].defaultValue } }) form.setFieldsValue({ type, id: selectedNode.id, name, ...initialValue, }) setConfigs(config || {}) } }, [selectedNode, form]) const updateNodeLabel = (newLabel: string) => { if (selectedNode && form) { const nodeData = selectedNode.data as NodeProperties; selectedNode.setAttrByPath('text/text', `${nodeData.icon} ${newLabel}`); selectedNode.setData({ ...selectedNode.data, name: newLabel }); } }; useEffect(() => { console.log('values', values) if (values && selectedNode) { const { id, ...rest } = values Object.keys(values).forEach(key => { if (selectedNode.data?.config[key]) { selectedNode.data.config[key].defaultValue = values[key] } }) selectedNode?.setData({ ...selectedNode.data, ...rest }) } }, [values, selectedNode]) const handleAddVariable = () => { variableModalRef.current?.handleOpen() } const handleEditVariable = (index: number, vo: StartVariableItem) => { variableModalRef.current?.handleOpen(vo) setEditIndex(index) } const handleRefreshVariable = (value: StartVariableItem) => { if (!selectedNode) return if (editIndex !== null) { const defaultValue = selectedNode.data.config.variables.defaultValue ?? [] defaultValue[editIndex] = value selectedNode.data.config.variables.defaultValue = [...defaultValue] } else { const defaultValue = selectedNode.data.config.variables.defaultValue ?? [] selectedNode.data.config.variables.defaultValue = [...defaultValue, value] } selectedNode?.setData({ ...selectedNode.data}) setConfigs({ ...selectedNode.data.config}) } const handleDeleteVariable = (index: number, vo: StartVariableItem) => { if (!selectedNode) return modal.confirm({ title: t('common.confirmDeleteDesc', { name: vo.name }), okText: t('common.delete'), okType: 'danger', onOk: () => { const defaultValue = selectedNode.data.config.variables.defaultValue ?? [] defaultValue.splice(index, 1) selectedNode.data.config.variables.defaultValue = [...defaultValue] selectedNode?.setData({ ...selectedNode.data }) setConfigs({ ...selectedNode.data.config }) } }) } return (
{t('workflow.nodeProperties')}
{!selectedNode ? :
{ updateNodeLabel(e.target.value); }} /> {configs && Object.keys(configs).length > 0 && Object.keys(configs).map((key) => { const config = configs[key] || {} if (selectedNode.data?.type === 'start' && key === 'variables' && config.type === 'define') { return (
{t(`workflow.config.${selectedNode.data.type}.${key}`)}
{Array.isArray(config.defaultValue) && config.defaultValue?.map((vo, index) =>
{vo.name}ยท{vo.description}
{vo.required && {t('workflow.config.start.required')}} {vo.type}
handleEditVariable(index, vo)} >
handleDeleteVariable(index, vo)} >
)} {config.sys?.map((vo, index) =>
sys.{vo.name}
{vo.type}
)}
) } if (selectedNode.data?.type === 'llm' && key === 'messages' && config.type === 'define') { return ( ) } if (selectedNode.data?.type === 'end' && key === 'output') { return ( ) } if (config.type === 'define') { return null } return ( {config.type === 'input' ? : config.type === 'textarea' ? : config.type === 'select' ?