finish work

This commit is contained in:
锦恢 2025-07-01 02:46:14 +08:00
parent 60196889bb
commit fba7ed29f0

View File

@ -9,6 +9,8 @@ import ELK, { type ElkNode } from 'elkjs/lib/elk.bundled.js';
import { mcpClientAdapter } from '@/views/connect/core';
const svgContainer = ref<HTMLDivElement | null>(null);
let prevNodes: any[] = [];
let prevEdges: any[] = [];
type Node = ElkNode & {
[key: string]: any;
@ -59,26 +61,39 @@ const recomputeLayout = async () => {
const drawDiagram = async () => {
const tools = await getAllTools();
state.nodes = tools.map((tool, i) => ({
id: String(i),
id: tool.name,
width: 160,
height: 48,
labels: [{ text: tool.name || 'Tool' }]
}));
//
state.edges = tools.slice(1).map((_, i) => ({
id: `e${i}`,
sources: [String(i)],
targets: [String(i + 1)]
}));
const edges = [];
for (let i = 0; i < tools.length - 1; ++ i) {
const prev = tools[i];
const next = tools[i + 1];
edges.push({
id: prev.name + '-' + next.name,
sources: [prev.name],
targets: [next.name]
})
}
state.edges = edges;
//
await recomputeLayout();
// svg
renderSvg();
};
function renderSvg() {
const prevNodeMap = new Map(prevNodes.map(n => [n.id, n]));
const prevEdgeMap = new Map(prevEdges.map(e => [e.id, e]));
const width = Math.max(...state.nodes.map(n => (n.x || 0) + (n.width || 160)), 400) + 60;
const height = Math.max(...state.nodes.map(n => (n.y || 0) + (n.height || 48)), 300) + 60;
@ -131,10 +146,30 @@ function renderSvg() {
const edgeEnter = edgeSelection.enter()
.append('line')
.attr('class', 'edge')
.attr('x1', d => d.section.startPoint.x + 30)
.attr('y1', d => d.section.startPoint.y + 30)
.attr('x2', d => d.section.endPoint.x + 30)
.attr('y2', d => d.section.endPoint.y + 30)
.attr('x1', d => {
const prev = prevEdgeMap.get(d.id);
return prev && prev.sections && prev.sections[0]
? prev.sections[0].startPoint.x + 30
: d.section.startPoint.x + 30;
})
.attr('y1', d => {
const prev = prevEdgeMap.get(d.id);
return prev && prev.sections && prev.sections[0]
? prev.sections[0].startPoint.y + 30
: d.section.startPoint.y + 30;
})
.attr('x2', d => {
const prev = prevEdgeMap.get(d.id);
return prev && prev.sections && prev.sections[0]
? prev.sections[0].endPoint.x + 30
: d.section.endPoint.x + 30;
})
.attr('y2', d => {
const prev = prevEdgeMap.get(d.id);
return prev && prev.sections && prev.sections[0]
? prev.sections[0].endPoint.y + 30
: d.section.endPoint.y + 30;
})
.attr('stroke', 'var(--main-color)')
.attr('stroke-width', 2.5)
.attr('marker-end', 'url(#arrow)')
@ -143,8 +178,13 @@ function renderSvg() {
edgeEnter
.transition()
.duration(600)
.attr('opacity', 1);
.attr('opacity', 1)
.attr('x1', d => d.section.startPoint.x + 30)
.attr('y1', d => d.section.startPoint.y + 30)
.attr('x2', d => d.section.endPoint.x + 30)
.attr('y2', d => d.section.endPoint.y + 30);
// update + transition opacity
edgeSelection.merge(edgeEnter)
.transition()
.duration(600)
@ -152,7 +192,8 @@ function renderSvg() {
.attr('x1', d => d.section.startPoint.x + 30)
.attr('y1', d => d.section.startPoint.y + 30)
.attr('x2', d => d.section.endPoint.x + 30)
.attr('y2', d => d.section.endPoint.y + 30);
.attr('y2', d => d.section.endPoint.y + 30)
.attr('opacity', 1); // update opacity 1
// --- ---
const nodeGroup = svg.selectAll<SVGGElement, any>('.node')
@ -163,7 +204,13 @@ function renderSvg() {
const nodeGroupEnter = nodeGroup.enter()
.append('g')
.attr('class', 'node')
.attr('transform', d => `translate(${(d.x || 0) + 30}, ${(d.y || 0) + 30})`)
.attr('transform', d => {
const prev = prevNodeMap.get(d.id);
if (prev) {
return `translate(${(prev.x || 0) + 30}, ${(prev.y || 0) + 30})`;
}
return `translate(${(d.x || 0) + 30}, ${(d.y || 0) + 30})`;
})
.style('cursor', 'pointer')
.attr('opacity', 0)
.on('mousedown', null)
@ -206,7 +253,8 @@ function renderSvg() {
nodeGroupEnter
.transition()
.duration(600)
.attr('opacity', 1);
.attr('opacity', 1)
.attr('transform', d => `translate(${(d.x || 0) + 30}, ${(d.y || 0) + 30})`);
// update
nodeGroup
@ -214,6 +262,10 @@ function renderSvg() {
.duration(600)
.ease(d3.easeCubicInOut)
.attr('transform', d => `translate(${(d.x || 0) + 30}, ${(d.y || 0) + 30})`);
//
prevNodes = state.nodes.map(n => ({ ...n }));
prevEdges = (state.edges || []).map(e => ({ ...e, sections: e.sections ? e.sections.map(s => ({ ...s })) : [] }));
}
onMounted(() => {