欢迎您访问 最编程 本站为您分享编程语言代码,编程技术文章!
您现在的位置是: 首页

深入了解 React Flow 渲染器(二):构建拖动操作栏

最编程 2024-07-11 11:22:13
...
// Slider/index.jsx import React from 'react'; //项目中自定义的手风琴组件,请你使用自己项目中的组件 import { CustomAccordion } from '@/components/CustomeAccordion'; // 模拟节点 const mockComponent = [ { 'name': 'clear alarm', 'type': 'ACTION', 'clazz': 'action.TbClearAlarmNode' }, { 'name': 'create alarm', 'type': 'ACTION', 'clazz': 'action.TbCreateAlarmNode' }, { 'name': 'device profile', 'type': 'ACTION', 'clazz': 'profile.TbDeviceProfileNode' }, { 'name': 'log', 'type': 'ACTION', 'clazz': 'action.TbLogNode' }, { 'name': 'message type switch', 'type': 'FILTER', 'clazz': 'filter.TbMsgTypeSwitchNode' }, { 'name': 'rpc call request', 'type': 'ACTION', 'clazz': 'rpc.TbSendRPCRequestNode' }, { 'name': 'rule chain', 'type': 'FLOW', 'clazz': 'flow.TbRuleChainInputNode' }, { 'name': 'save attributes', 'type': 'ACTION', 'clazz': 'telemetry.TbMsgAttributesNode' }, { 'name': 'save timeseries', 'type': 'ACTION', 'clazz': 'telemetry.TbMsgTimeseriesNode' }, { 'name': 'script', 'type': 'TRANSFORMATION', 'clazz': 'transform.TbTransformMsgNode' } ]; export enum RuleNodeType { FILTER = 'FILTER', ENRICHMENT = 'ENRICHMENT', TRANSFORMATION = 'TRANSFORMATION', ACTION = 'ACTION', EXTERNAL = 'EXTERNAL', FLOW = 'FLOW', UNKNOWN = 'UNKNOWN', INPUT = 'INPUT', } export const ruleNodeTypeDescriptors = new Map<RuleNodeType, any>( [ [ RuleNodeType.FILTER, { value: RuleNodeType.FILTER, name: 'rulenode.type-filter', details: 'rulenode.type-filter-details', nodeClass: 'tb-filter-type', icon: 'filter_list' } ], [ RuleNodeType.ENRICHMENT, { value: RuleNodeType.ENRICHMENT, name: 'rulenode.type-enrichment', details: 'rulenode.type-enrichment-details', nodeClass: 'tb-enrichment-type', icon: 'playlist_add' } ], [ RuleNodeType.TRANSFORMATION, { value: RuleNodeType.TRANSFORMATION, name: 'rulenode.type-transformation', details: 'rulenode.type-transformation-details', nodeClass: 'tb-transformation-type', icon: 'transform' } ], [ RuleNodeType.ACTION, { value: RuleNodeType.ACTION, name: 'rulenode.type-action', details: 'rulenode.type-action-details', nodeClass: 'tb-action-type', icon: 'flash_on' } ], [ RuleNodeType.EXTERNAL, { value: RuleNodeType.EXTERNAL, name: 'rulenode.type-external', details: 'rulenode.type-external-details', nodeClass: 'tb-external-type', icon: 'cloud_upload' } ], [ RuleNodeType.FLOW, { value: RuleNodeType.FLOW, name: 'rulenode.type-flow', details: 'rulenode.type-flow-details', nodeClass: 'tb-flow-type', icon: 'settings_ethernet' } ], [ RuleNodeType.INPUT, { value: RuleNodeType.INPUT, name: 'rulenode.type-input', details: 'rulenode.type-input-details', nodeClass: 'tb-input-type', icon: 'input', special: true } ], [ RuleNodeType.UNKNOWN, { value: RuleNodeType.UNKNOWN, name: 'rulenode.type-unknown', details: 'rulenode.type-unknown-details', nodeClass: 'tb-unknown-type', icon: 'help_outline' } ] ] ); const classMap = new Map([ ['ACTION', 'relation-node'], ['input', 'input-node'], ['FILTER', 'filter-node'], ['ENRICHMENT', 'enrichment-node'], ['TRANSFORMATION', 'transformation-node'], ['EXTERNAL', 'external-node'], ['FLOW', 'flow-node'] ]); // const allowType = ruleNodeTypeComponentTypes; const allowNodesClazz = [ 'telemetry.TbMsgAttributesNode', 'filter.TbMsgTypeSwitchNode', 'action.TbLogNode', 'rpc.TbSendRPCRequestNode', 'profile.TbDeviceProfileNode', 'telemetry.TbMsgTimeseriesNode', 'action.TbCreateAlarmNode', 'action.TbClearAlarmNode', 'flow.TbRuleChainInputNode', 'transform.TbTransformMsgNode' ]; export default function Slider() { const [allowType, setAllowType] = React.useState<any>(['input']); const [allowedNodes, setAllowedNodes] = React.useState<any>([]); React.useEffect(() => { // 将组件按名称进行排序 const sortedComponents = mockComponent?.sort((a: any, b: any) => a.name?.localeCompare(b.name) ); // 过滤出符合条件的组件并拼接到allowedNodes数组中 const filteredComponents = sortedComponents?.filter((component: any) => allowNodesClazz.includes(component.clazz) ) || []; const updatedAllowedNodes = [...filteredComponents]; // 获取所有组件的类型,并和allowType数组进行合并 const updatedTypes = updatedAllowedNodes.map((component) => component.type); // 去除重复的节点并更新allowedNodes状态 setAllowedNodes(Array.from(new Set(updatedAllowedNodes))); // 去除重复的类型并更新allowType状态(如果为空数组,则设置为默认值) setAllowType(Array.from(new Set(updatedTypes)) || []); }, []); return ( <div className="sider"> {allowType.map((type: any) => //自定义手风琴,项目中使用的是mui,你可以使用其他组件库,这里就不贴出手风琴的代码了,请你根据你的项目,使用对应的组件。如果不需要手风琴组件。可以拥<div>来代替 <CustomAccordion title={ ruleNodeTypeDescriptors.get(type as any)?.name as string} key={type} > <div className="nodes"> {allowedNodes .filter((node: any) => node.type === type) .map((x: any, i: number) => <div key={`${x.type}-${i}`} className={`sider-node ${ classMap.get(x.type) || 'default-node' }`} onDragStart={(e) => onDragStart(e, x)} draggable > <div>{x.name}</div> {/* 黑色遮罩层 */} <div className="overlay"></div> </div> )} </div> </CustomAccordion> )} </div> ); }