perf: 优化工作流的节点UI和交互
This commit is contained in:
@@ -1,7 +1,6 @@
|
||||
import {
|
||||
arrow,
|
||||
computePosition,
|
||||
flip,
|
||||
type FlipOptions,
|
||||
offset,
|
||||
type OffsetOptions,
|
||||
@@ -20,6 +19,8 @@ export type FloatingOptions = {
|
||||
shiftOptions?: ShiftOptions;
|
||||
interactive?: boolean;
|
||||
showArrow?: boolean;
|
||||
onShow?: () => void;
|
||||
onHide?: () => void;
|
||||
};
|
||||
|
||||
export type FloatingInstance = {
|
||||
@@ -37,7 +38,9 @@ export const createFloating = ({
|
||||
flipOptions,
|
||||
shiftOptions,
|
||||
interactive,
|
||||
showArrow
|
||||
showArrow,
|
||||
onShow,
|
||||
onHide
|
||||
}: FloatingOptions): FloatingInstance => {
|
||||
if (typeof trigger === 'string') {
|
||||
const triggerEl = document.querySelector(trigger);
|
||||
@@ -78,14 +81,15 @@ export const createFloating = ({
|
||||
placement: placement,
|
||||
middleware: [
|
||||
offset(offsetOptions), // 手动偏移配置
|
||||
flip(flipOptions), //自动翻转
|
||||
// flip(flipOptions), // 注释掉自动翻转,强制向下弹出,避免遮挡顶部工具栏
|
||||
shift(shiftOptions), //自动偏移(使得浮动元素能够进入视野)
|
||||
...(showArrow ? [arrow({ element: arrowElement })] : [])
|
||||
]
|
||||
}).then(({ x, y, placement, middlewareData }) => {
|
||||
Object.assign(floating.style, {
|
||||
left: `${x}px`,
|
||||
top: `${y}px`
|
||||
top: `${y}px`,
|
||||
position: 'absolute'
|
||||
});
|
||||
|
||||
if (showArrow) {
|
||||
@@ -113,7 +117,7 @@ export const createFloating = ({
|
||||
|
||||
function showTooltip() {
|
||||
floating.style.display = 'block';
|
||||
floating.style.visibility = 'block';
|
||||
floating.style.visibility = 'visible';
|
||||
floating.style.position = 'absolute';
|
||||
|
||||
if (showArrow) {
|
||||
@@ -122,6 +126,7 @@ export const createFloating = ({
|
||||
|
||||
visible = true;
|
||||
updatePosition();
|
||||
onShow?.();
|
||||
}
|
||||
|
||||
function hideTooltip() {
|
||||
@@ -130,10 +135,10 @@ export const createFloating = ({
|
||||
arrowElement.style.display = 'none';
|
||||
}
|
||||
visible = false;
|
||||
onHide?.();
|
||||
}
|
||||
|
||||
function onTrigger(event: any) {
|
||||
event.stopPropagation();
|
||||
if (!visible) {
|
||||
showTooltip();
|
||||
} else {
|
||||
@@ -142,7 +147,7 @@ export const createFloating = ({
|
||||
}
|
||||
|
||||
function hideTooltipCompute(event: any) {
|
||||
if (floating.contains(event.target as Node)) {
|
||||
if (floating.contains(event.target as Node) || (trigger as Node).contains(event.target as Node)) {
|
||||
return;
|
||||
}
|
||||
hideTooltip();
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import {type Edge, type Node, useNodesData, useStore} from '@xyflow/svelte';
|
||||
import type {Parameter} from '#types';
|
||||
import {getCurrentNodeId} from '#components/utils/NodeUtils';
|
||||
import {getCurrentNodeId, getOptions} from '#components/utils/NodeUtils';
|
||||
import {nodeIcons} from '../../consts';
|
||||
|
||||
const fillRefNodeIds = (refNodeIds: string[], currentNodeId: string, edges: Edge[]) => {
|
||||
for (const edge of edges) {
|
||||
@@ -11,51 +12,82 @@ const fillRefNodeIds = (refNodeIds: string[], currentNodeId: string, edges: Edge
|
||||
}
|
||||
};
|
||||
|
||||
const getChildren = (params: any, parentId: string, nodeIsChildren: boolean) => {
|
||||
const getChildren = (params: any, parentId: string, nodeIsChildren: boolean, nodeType: string) => {
|
||||
if (!params || params.length === 0) return [];
|
||||
return params.map((param: any) => ({
|
||||
label:
|
||||
param.name +
|
||||
(nodeIsChildren
|
||||
? ` (Array<${param.dataType || 'String'}>)`
|
||||
: ` (${param.dataType || 'String'})`),
|
||||
value: parentId + '.' + param.name,
|
||||
children: getChildren(param.children, parentId + '.' + param.name, nodeIsChildren)
|
||||
}));
|
||||
return params.map((param: any) => {
|
||||
const dataType = nodeIsChildren
|
||||
? `Array<${param.dataType || 'String'}>`
|
||||
: (param.dataType || 'String');
|
||||
return {
|
||||
label: param.name,
|
||||
dataType: dataType,
|
||||
value: parentId + '.' + param.name,
|
||||
selectable: true,
|
||||
nodeType: nodeType,
|
||||
children: getChildren(param.children, parentId + '.' + param.name, nodeIsChildren, nodeType)
|
||||
};
|
||||
});
|
||||
};
|
||||
|
||||
const nodeToOptions = (node: Node, nodeIsChildren: boolean, currentNode: Node) => {
|
||||
const options = getOptions();
|
||||
let icon = nodeIcons[node.type];
|
||||
if (!icon && options?.customNodes && options.customNodes[node.type]) {
|
||||
icon = options.customNodes[node.type].icon;
|
||||
}
|
||||
|
||||
// 如果仍然获取不到,尝试使用 data.icon (作为回退)
|
||||
if (!icon && node.data && node.data.icon) {
|
||||
icon = node.data.icon as string;
|
||||
}
|
||||
|
||||
const title = node.data.title;
|
||||
|
||||
if (node.type === 'startNode') {
|
||||
const parameters = node.data.parameters as Array<Parameter>;
|
||||
const children = [];
|
||||
if (parameters)
|
||||
for (const parameter of parameters) {
|
||||
const dataType = nodeIsChildren
|
||||
? `Array<${parameter.dataType || 'String'}>`
|
||||
: (parameter.dataType || 'String');
|
||||
children.push({
|
||||
label:
|
||||
parameter.name +
|
||||
(nodeIsChildren
|
||||
? ` (Array<${parameter.dataType || 'String'}>)`
|
||||
: ` (${parameter.dataType || 'String'})`),
|
||||
value: node.id + '.' + parameter.name
|
||||
label: parameter.name,
|
||||
dataType: dataType,
|
||||
value: node.id + '.' + parameter.name,
|
||||
selectable: true,
|
||||
nodeType: node.type
|
||||
});
|
||||
}
|
||||
return {
|
||||
label: node.data.title,
|
||||
label: title,
|
||||
icon: icon,
|
||||
value: node.id,
|
||||
selectable: false,
|
||||
nodeType: node.type,
|
||||
children
|
||||
};
|
||||
} else if (node.type === 'loopNode' && currentNode.parentId) {
|
||||
return {
|
||||
label: node.data.title,
|
||||
label: title,
|
||||
icon: icon,
|
||||
value: node.id,
|
||||
selectable: false,
|
||||
nodeType: node.type,
|
||||
children: [
|
||||
{
|
||||
label: 'loopItem',
|
||||
value: node.id + '.loopItem'
|
||||
dataType: 'Any',
|
||||
value: node.id + '.loopItem',
|
||||
selectable: true,
|
||||
nodeType: node.type
|
||||
},
|
||||
{
|
||||
label: 'index (Number)',
|
||||
value: node.id + '.index'
|
||||
label: 'index',
|
||||
dataType: 'Number',
|
||||
value: node.id + '.index',
|
||||
selectable: true,
|
||||
nodeType: node.type
|
||||
}
|
||||
]
|
||||
};
|
||||
@@ -63,9 +95,12 @@ const nodeToOptions = (node: Node, nodeIsChildren: boolean, currentNode: Node) =
|
||||
const outputDefs = node.data.outputDefs;
|
||||
if (outputDefs) {
|
||||
return {
|
||||
label: node.data.title,
|
||||
label: title,
|
||||
icon: icon,
|
||||
value: node.id,
|
||||
children: getChildren(outputDefs, node.id, nodeIsChildren)
|
||||
selectable: false,
|
||||
nodeType: node.type,
|
||||
children: getChildren(outputDefs, node.id, nodeIsChildren, node.type)
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user