fix: 修复 AgentRun 导图连线与详情遮挡

This commit is contained in:
root
2026-07-16 12:57:14 +02:00
parent 2f9281c589
commit ebd4dccdc1
3 changed files with 29 additions and 4 deletions
@@ -11,6 +11,7 @@ import {
const viewSource = readSource("../src/views/agents/AgentRunsView.vue");
const inspectorSource = readSource("../src/components/agents/AgentRunInspector.vue");
const inspectorPanelSource = readSource("../src/components/console/InspectorPanel.vue");
const mindMapSource = readSource("../src/components/agents/AgentRunMindMap.vue");
const virtualGridSource = readSource("../src/components/common/VirtualGrid.vue");
const styleSource = readSource("../src/styles/agent-observer.css");
@@ -88,6 +89,19 @@ test("AgentRun mind map always owns the flexible tree row", () => {
assert.match(styleSource, /agent-observer-tree > \.agent-mind-map \{ grid-row: -2 \/ -1; \}/);
});
test("AgentRun mind map connects custom nodes through Vue Flow handles", () => {
assert.match(mindMapSource, /import \{ Handle, MarkerType, Position, VueFlow/);
assert.match(mindMapSource, /<Handle v-if="data\.row\.parentId" type="target" :position="Position\.Left" \/>/);
assert.match(mindMapSource, /<Handle v-if="data\.row\.childCount > 0" type="source" :position="Position\.Right" \/>/);
assert.match(styleSource, /agent-mind-map-flow \.vue-flow__handle/);
});
test("AgentRun inspector keeps chrome fixed and scrolls only its body", () => {
assert.match(styleSource, /agent-observer-inspector \{[^}]*overflow: hidden;/);
assert.match(styleSource, /agent-observer-inspector > \.operations-inspector-panel \{[^}]*grid-template-rows: auto auto minmax\(0, 1fr\) auto;/);
assert.match(styleSource, /agent-observer-inspector \.operations-inspector-body \{[^}]*overflow: auto;/);
});
function readSource(relativePath: string): string {
return readFileSync(new URL(relativePath, import.meta.url), "utf8");
}
@@ -1,7 +1,7 @@
<script setup lang="ts">
import { computed, nextTick } from "vue";
import dagre from "@dagrejs/dagre";
import { MarkerType, Position, VueFlow, useVueFlow, type Edge, type Node } from "@vue-flow/core";
import { Handle, MarkerType, Position, VueFlow, useVueFlow, type Edge, type Node } from "@vue-flow/core";
import { Focus, Minus, Plus } from "lucide-vue-next";
import StatusBadge from "@/components/common/StatusBadge.vue";
import {
@@ -119,6 +119,8 @@ async function fit(): Promise<void> {
@keydown.enter.prevent="activate(data.row)"
@keydown.space.prevent="activate(data.row)"
>
<Handle v-if="data.row.parentId" type="target" :position="Position.Left" />
<Handle v-if="data.row.childCount > 0" type="source" :position="Position.Right" />
<header>
<span>{{ nodeLabel(data.row.kind) }}</span>
<StatusBadge v-if="data.row.status" :status="agentObserverStatusToken(data.row.status).tone" :label="agentObserverStatusToken(data.row.status).label" />
@@ -102,8 +102,9 @@
.agent-mind-map-flow { width: 100%; height: 100%; }
.agent-mind-map-flow .vue-flow__pane { cursor: grab; }
.agent-mind-map-flow .vue-flow__pane.dragging { cursor: grabbing; }
.agent-mind-map-flow .vue-flow__edge-path { stroke: color-mix(in srgb, var(--console-muted) 55%, var(--console-border)); stroke-width: 1.4; }
.agent-mind-map-flow .vue-flow__arrowhead { fill: var(--console-muted); }
.agent-mind-map-flow .vue-flow__edge-path { stroke: color-mix(in srgb, var(--console-muted) 68%, var(--console-text)); stroke-width: 1.8; }
.agent-mind-map-flow .vue-flow__arrowhead { fill: color-mix(in srgb, var(--console-muted) 68%, var(--console-text)); }
.agent-mind-map-flow .vue-flow__handle { width: 1px; height: 1px; min-width: 1px; min-height: 1px; border: 0; opacity: 0; pointer-events: none; }
.agent-mind-map-node { width: 220px; height: 70px; min-width: 0; display: grid; grid-template-rows: 19px 1fr 16px; gap: 2px; padding: 7px 9px; border: 1px solid var(--console-border); border-left: 3px solid var(--console-muted); border-radius: 5px; background: var(--console-surface); color: var(--console-text); outline: 0; box-shadow: 0 2px 7px rgb(15 23 42 / 8%); cursor: pointer; }
.agent-mind-map-node[data-kind="scope"] { width: 260px; }
.agent-mind-map-node[data-kind="run"] { width: 244px; }
@@ -125,7 +126,15 @@
.agent-mind-map-controls button:last-child { border-right: 0; }
.agent-mind-map-controls button:hover { background: var(--console-accent-soft); color: var(--console-accent); }
.agent-observer-inspector { min-width: 0; min-height: 0; overflow: auto; border-left: 1px solid var(--console-border); background: var(--console-surface); }
.agent-observer-inspector { min-width: 0; min-height: 0; overflow: hidden; border-left: 1px solid var(--console-border); background: var(--console-surface); }
.agent-observer-inspector > .operations-inspector-panel { height: 100%; min-height: 0; display: grid; grid-template-rows: auto auto minmax(0, 1fr) auto; }
.agent-observer-inspector .operations-inspector-header { position: static; min-width: 0; }
.agent-observer-inspector .operations-inspector-header > div { min-width: 0; }
.agent-observer-inspector .operations-inspector-header h2,
.agent-observer-inspector .operations-inspector-header p { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.agent-observer-inspector .operations-inspector-tabs { min-width: 0; overflow-y: hidden; scrollbar-width: none; }
.agent-observer-inspector .operations-inspector-tabs::-webkit-scrollbar { display: none; }
.agent-observer-inspector .operations-inspector-body { min-height: 0; overflow: auto; overscroll-behavior: contain; }
.agent-observer-inspector-section { display: grid; gap: 14px; }
.agent-observer-status-matrix { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 8px; }
.agent-observer-status-matrix > span { min-width: 0; display: grid; gap: 5px; padding: 8px; border: 1px solid var(--console-border); }