feat(flowEditor): 实现自定义边的数据展示与事件选择功能

master
钟良源 3 months ago
parent 018d06a63a
commit ec578f9cde

@ -39,3 +39,8 @@ export function queryEventItemBySceneId(sceneId: string) {
return axios.get(`${urlPrefix}/event/${sceneId}/get`); return axios.get(`${urlPrefix}/event/${sceneId}/get`);
} }
// 事件管理-获取工程下可用的topic
export function getTopicList(id: string) {
return axios.get(`${urlPrefix}/event/${id}/topic`);
}

@ -1,6 +1,9 @@
import React from 'react'; import React, { useState, useEffect, useRef } from 'react';
import { BaseEdge, EdgeLabelRenderer, EdgeProps, getSmoothStepPath, useReactFlow } from '@xyflow/react'; import { BaseEdge, EdgeLabelRenderer, EdgeProps, getSmoothStepPath, useReactFlow } from '@xyflow/react';
import EdgeAddNodeButton from '@/pages/flowEditor/components/edgeAddNodeButton'; import EdgeAddNodeButton from '@/pages/flowEditor/components/edgeAddNodeButton';
import { getTopicList } from '@/api/event';
import { useSelector } from 'react-redux';
import { Message } from '@arco-design/web-react';
type DataDisplayEdgeData = { type DataDisplayEdgeData = {
label?: string; label?: string;
@ -23,6 +26,10 @@ const DataDisplayEdge: React.FC<EdgeProps> = ({
selected, selected,
data data
}) => { }) => {
const [options, setOptions] = useState([]);
const [isOpen, setIsOpen] = useState(false);
const [selectedValue, setSelectedValue] = useState('');
const dropdownRef = useRef<HTMLDivElement>(null);
const [edgePath, labelX, labelY] = getSmoothStepPath({ const [edgePath, labelX, labelY] = getSmoothStepPath({
sourceX, sourceX,
sourceY, sourceY,
@ -32,6 +39,7 @@ const DataDisplayEdge: React.FC<EdgeProps> = ({
targetPosition, targetPosition,
borderRadius: 8 // 设置圆角半径 borderRadius: 8 // 设置圆角半径
}); });
const { info } = useSelector((state: any) => state.ideContainer);
// 从数据中获取悬停状态 // 从数据中获取悬停状态
const hovered = data?.hovered || false; const hovered = data?.hovered || false;
@ -61,8 +69,35 @@ const DataDisplayEdge: React.FC<EdgeProps> = ({
})); }));
}; };
const handleDataClick = (e) => { const getEventList = async () => {
console.log('click:', e); const res: any = await getTopicList(info.id);
if (res.code === 200) {
setOptions(res.data.map(v => {
return { label: v.eventName, value: v.topic };
}));
}
};
useEffect(() => {
getEventList();
}, [displayData]);
useEffect(() => {
const handleClickOutside = (event: MouseEvent) => {
if (dropdownRef.current && !dropdownRef.current.contains(event.target as Node)) {
setIsOpen(false);
}
};
document.addEventListener('mousedown', handleClickOutside);
return () => {
document.removeEventListener('mousedown', handleClickOutside);
};
}, []);
const handleSelect = (option) => {
setSelectedValue(option.label);
setIsOpen(false);
}; };
return ( return (
@ -89,29 +124,60 @@ const DataDisplayEdge: React.FC<EdgeProps> = ({
{/* 数据展示框 */} {/* 数据展示框 */}
{displayData && Object.keys(displayData).length > 0 && ( {displayData && Object.keys(displayData).length > 0 && (
<div <div
onClick={(e) => handleDataClick(e)} ref={dropdownRef}
style={{ style={{
background: '#ffffff', width: 150,
border: '1px solid #ddd', border: isOpen ? '1px solid #1890ff' : '1px solid #d9d9d9',
borderRadius: 4, borderRadius: 4,
padding: 4, backgroundColor: '#fff',
boxShadow: '0 2px 4px rgba(0,0,0,0.1)', position: 'relative'
minWidth: 100,
marginBottom: 4,
fontSize: 12,
textAlign: 'center'
}} }}
> >
{displayData.name && ( <div
<div style={{ fontWeight: 'bold', marginBottom: 2 }}> onClick={() => setIsOpen(!isOpen)}
{displayData.name} style={{
</div> padding: '4px 11px',
)} cursor: 'pointer',
{displayData.value !== undefined && ( display: 'flex',
<div> justifyContent: 'space-between',
{typeof displayData.value === 'object' alignItems: 'center'
? JSON.stringify(displayData.value) }}
: String(displayData.value)} >
<span>{selectedValue || displayData.name}</span>
<span>{isOpen ? '▲' : '▼'}</span>
</div>
{isOpen && (
<div
style={{
position: 'absolute',
top: '105%',
left: 0,
right: 0,
border: '1px solid #d9d9d9',
borderTop: 'none',
borderRadius: '0 0 4px 4px',
backgroundColor: '#fff',
zIndex: 1000,
maxHeight: 200,
overflowY: 'auto'
}}
>
{options.map((option: { value: string; label: string }) => (
<div
key={option.value}
onClick={() => handleSelect(option)}
style={{
padding: '5px 12px',
cursor: 'pointer',
borderBottom: '1px solid #f0f0f0'
}}
onMouseEnter={(e) => e.currentTarget.style.backgroundColor = '#f5f5f5'}
onMouseLeave={(e) => e.currentTarget.style.backgroundColor = '#fff'}
>
{option.label}
</div>
))}
</div> </div>
)} )}
</div> </div>

Loading…
Cancel
Save