完成节点遍历
This commit is contained in:
parent
cf66dfec5a
commit
0c58ae4d3d
@ -1,16 +1,96 @@
|
||||
import { ReactNode, useContext } from 'react';
|
||||
import { Handle, Position, NodeProps } from '@xyflow/react';
|
||||
import { AppNode, SettingsContext } from '../types/graph';
|
||||
import { Handle, Position, NodeProps, useReactFlow} from '@xyflow/react';
|
||||
import { AppNode, AppEdge, SettingsContext, NodeData } from '../types/graph';
|
||||
import './CustomNode.css';
|
||||
import toast from 'react-hot-toast';
|
||||
|
||||
class ConfigResult {
|
||||
constructor(
|
||||
public success: boolean,
|
||||
public config?: string,
|
||||
public error?: string
|
||||
) {}
|
||||
}
|
||||
|
||||
function generateConfig(
|
||||
data : NodeData,
|
||||
getEdges : () => AppEdge[],
|
||||
getNode : (id: string) => AppNode | undefined) : ConfigResult {
|
||||
|
||||
const getNearEdges = (node: AppNode) : AppEdge[] => {
|
||||
return getEdges().filter(edge => edge.source === node.id || edge.target === node.id);
|
||||
};
|
||||
|
||||
const getNextNode = (edge: AppEdge, node: AppNode) : AppNode | undefined => {
|
||||
const nextNodeId = edge.source === node.id ? edge.target : edge.source;
|
||||
return getNode(nextNodeId);
|
||||
};
|
||||
|
||||
const node = getNode(data.id);
|
||||
if(!node) {
|
||||
return new ConfigResult(false, undefined, "节点未找到");
|
||||
}
|
||||
|
||||
const belongsToEdge : Record<string, string | undefined> = {[node.id]: node.id};
|
||||
|
||||
const queue : AppNode[] = [];
|
||||
const nearEdges = getNearEdges(node);
|
||||
nearEdges.forEach(edge => {
|
||||
const nextNode = getNextNode(edge, node);
|
||||
if(nextNode) {
|
||||
belongsToEdge[nextNode.id] = edge.id;
|
||||
queue.push(nextNode);
|
||||
}
|
||||
});
|
||||
|
||||
while(queue.length > 0) {
|
||||
const currentNode = queue.shift()!;
|
||||
const fromEdgeId = belongsToEdge[currentNode.id];
|
||||
if(!fromEdgeId) continue;
|
||||
|
||||
getNearEdges(currentNode).forEach(edge => {
|
||||
const nextNode = getNextNode(edge, currentNode);
|
||||
if(nextNode && !belongsToEdge[nextNode.id]) {
|
||||
belongsToEdge[nextNode.id] = fromEdgeId;
|
||||
queue.push(nextNode);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
const groupedByEdge: Record<string, string[] | undefined> = {};
|
||||
for (const nodeId in belongsToEdge) {
|
||||
const edgeId = belongsToEdge[nodeId];
|
||||
if(edgeId === nodeId) continue; // 跳过起始节点
|
||||
if(!edgeId) continue;
|
||||
|
||||
if (!groupedByEdge[edgeId]) {
|
||||
groupedByEdge[edgeId] = [];
|
||||
}
|
||||
|
||||
groupedByEdge[edgeId].push(nodeId);
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
export default function CustomNode({
|
||||
data,
|
||||
selected
|
||||
}: NodeProps<AppNode>): ReactNode {
|
||||
const handleGenerate = (e: React.MouseEvent) => {
|
||||
e.stopPropagation();
|
||||
toast.success('保存成功!');
|
||||
const { getNode, getEdges } = useReactFlow<AppNode, AppEdge>();
|
||||
|
||||
const handleGenerate = (node : NodeData) => {
|
||||
const result = generateConfig(node, getEdges, getNode);
|
||||
if(result.success && result.config) {
|
||||
navigator.clipboard.writeText(result.config).then(() => {
|
||||
toast.success("配置已复制到剪贴板");
|
||||
}).catch(() => {
|
||||
toast.error("复制失败,请手动复制");
|
||||
});
|
||||
} else {
|
||||
toast.error("配置生成失败:" + (result.error || "未知错误"));
|
||||
}
|
||||
};
|
||||
|
||||
const settings = useContext(SettingsContext);
|
||||
@ -38,13 +118,16 @@ export default function CustomNode({
|
||||
|
||||
{(!settings.ipv4Subnet && !settings.ipv6Subnet) && (
|
||||
<div className="info-item">
|
||||
<span className="label">未设置任何子网,请在设置中设置</span>
|
||||
<span className="label">未设置任何子网</span>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
|
||||
<div className="node-actions">
|
||||
<button className="gen-btn" onClick={handleGenerate} onDoubleClick={e => e.stopPropagation()}>生成配置并复制</button>
|
||||
<button className="gen-btn" onClick={e => {
|
||||
e.stopPropagation();
|
||||
handleGenerate(data);
|
||||
}} onDoubleClick={e => e.stopPropagation()}>生成配置并复制</button>
|
||||
</div>
|
||||
|
||||
{[Position.Top, Position.Bottom, Position.Right, Position.Left].map((position) => (
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user