124 lines
3.8 KiB
TypeScript
124 lines
3.8 KiB
TypeScript
import { Panel, useReactFlow, useStore, useStoreApi } from '@xyflow/react';
|
||
import clsx from 'clsx';
|
||
import { useEffect, useState } from 'react';
|
||
import { debounce } from 'lodash-es';
|
||
import { Button, Form, Input, message, Tooltip } from 'antd';
|
||
import { Select } from '@/pages/container/module/Select';
|
||
import { MessageOutlined, SaveOutlined } from '@ant-design/icons';
|
||
import { emitter } from '@kevisual/container';
|
||
import { usePanelStore } from '../../store';
|
||
import { useShallow } from 'zustand/react/shallow';
|
||
import { useAiStore } from '@/pages/ai-chat';
|
||
export const NodeProperties = () => {
|
||
const reactflow = useReactFlow();
|
||
const [open, setOpen] = useState(false);
|
||
const [form] = Form.useForm();
|
||
const panelStore = usePanelStore((state) => {
|
||
return {
|
||
updateNodeData: state.updateNodeData,
|
||
};
|
||
});
|
||
const aiStore = useAiStore(
|
||
useShallow((state) => {
|
||
return {
|
||
setOpen: state.setOpen,
|
||
setKey: state.setKey,
|
||
};
|
||
}),
|
||
);
|
||
const store = useStore((state) => {
|
||
const setNode = (node: any) => {
|
||
const newNodes = state.nodes.map((item) => {
|
||
if (item.id === node.id) {
|
||
// return { ...item, ...node };
|
||
return { ...node };
|
||
}
|
||
return item;
|
||
});
|
||
// console.log('newNodes', newNodes);
|
||
// state.setNodes(newNodes); // 会丢失数据,因为最终没有调用context的setNodes方法
|
||
emitter.emit('setNodes', newNodes);
|
||
};
|
||
return {
|
||
nodesFocusable: state.nodesFocusable,
|
||
selected: state.nodes.filter((node) => node.selected),
|
||
setNode: setNode,
|
||
};
|
||
});
|
||
const [nodeData] = store.selected as any[];
|
||
useEffect(() => {
|
||
if (!nodeData) return;
|
||
// console.log('nodeData', nodeData);
|
||
const { data } = nodeData || {};
|
||
form.setFieldsValue({
|
||
cid: data.cid,
|
||
title: data.title,
|
||
});
|
||
}, [nodeData]);
|
||
const onSave = () => {
|
||
const values = form.getFieldsValue();
|
||
// console.log('values', values);
|
||
const { cid, title } = values;
|
||
if (!cid) {
|
||
message.error('请选择容器');
|
||
return;
|
||
}
|
||
const { data, id, position, type } = nodeData || {};
|
||
// console.log('data', data, cid);
|
||
const newNodeData = {
|
||
id,
|
||
position,
|
||
selected: true,
|
||
type,
|
||
data: {
|
||
...data,
|
||
cid,
|
||
title,
|
||
},
|
||
};
|
||
// console.log('newNodeData', newNodeData, nodeData);
|
||
store.setNode(newNodeData);
|
||
panelStore.updateNodeData(newNodeData);
|
||
};
|
||
return (
|
||
<Panel title='节点属性' position='bottom-center' className='w-full'>
|
||
<div className={clsx('w-full h-[200px] card', store.selected.length > 0 ? '' : 'hidden')}>
|
||
<div className='card-title'>
|
||
{nodeData?.data?.label}
|
||
<Button.Group className='ml-2'>
|
||
<Tooltip title='Save'>
|
||
<Button onClick={onSave} icon={<SaveOutlined />}></Button>
|
||
</Tooltip>
|
||
<Tooltip title='Ai Chat'>
|
||
<Button
|
||
onClick={() => {
|
||
aiStore.setKey(location.pathname);
|
||
aiStore.setOpen(true);
|
||
}}
|
||
icon={<MessageOutlined />}></Button>
|
||
</Tooltip>
|
||
</Button.Group>
|
||
</div>
|
||
<div className='p-4'>
|
||
<Form form={form}>
|
||
<Form.Item label='名称' name='cid'>
|
||
<Select
|
||
onChange={(e, options) => {
|
||
if (Array.isArray(options)) {
|
||
} else {
|
||
const title = options?.label;
|
||
form.setFieldsValue({ title });
|
||
}
|
||
}}
|
||
/>
|
||
</Form.Item>
|
||
<Form.Item label='标题' name='title'>
|
||
<Input />
|
||
</Form.Item>
|
||
</Form>
|
||
</div>
|
||
</div>
|
||
</Panel>
|
||
);
|
||
};
|