From 1a08e801f4aea3191fc0b90f3868d380e941b7cd Mon Sep 17 00:00:00 2001 From: Hermes CI Fix Date: Tue, 14 Jul 2026 16:22:29 +0800 Subject: [PATCH] =?UTF-8?q?fix:=20=E7=BA=A7=E8=81=94/=E5=9B=A0=E6=9E=9C?= =?UTF-8?q?=E8=A7=86=E8=A7=92=E5=88=87=E6=8D=A2=20=E2=80=94=20=E8=B7=A8?= =?UTF-8?q?=E5=B1=82=E7=AE=AD=E5=A4=B4=E6=96=B9=E5=90=91+SVG=E4=B8=89?= =?UTF-8?q?=E8=A7=92+ConnectionLines=E8=81=94=E5=8A=A8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../components/strategy/ConnectionLines.vue | 39 +++++++++++++------ frontend/src/views/MapCanvas.vue | 8 ++-- 2 files changed, 32 insertions(+), 15 deletions(-) diff --git a/frontend/src/components/strategy/ConnectionLines.vue b/frontend/src/components/strategy/ConnectionLines.vue index a60d52d4..936775ec 100644 --- a/frontend/src/components/strategy/ConnectionLines.vue +++ b/frontend/src/components/strategy/ConnectionLines.vue @@ -147,6 +147,8 @@ const props = defineProps({ tempLine: { type: Object, default: null }, /** 容器尺寸变化触发重算 */ containerKey: { type: Number, default: 0 }, + /** 视角方向:cascade(级联,上层→下层) / causal(因果,下层→上层) */ + viewDirection: { type: String, default: 'cascade' }, }) const emit = defineEmits(['select-connection', 'delete-connection']) @@ -159,28 +161,41 @@ const crossLayerLines = ref([]) /** * 计算跨层固定箭头 - * 从上层底部中心 → 下层顶部中心 + * cascade: 从上层底部中心 → 下层顶部中心(管理视角,上层驱动下层) + * causal: 从下层顶部中心 → 上层底部中心(因果视角,下层驱动上层) */ function calcCrossLayerLines() { const lines = [] const keys = props.layerKeys + const isCausal = props.viewDirection === 'causal' for (let i = 0; i < keys.length - 1; i++) { - const fromEl = props.layerRefs[keys[i]] - const toEl = props.layerRefs[keys[i + 1]] - if (!fromEl || !toEl) continue + const upperEl = props.layerRefs[keys[i]] + const lowerEl = props.layerRefs[keys[i + 1]] + if (!upperEl || !lowerEl) continue - const fr = fromEl.getBoundingClientRect() - const tr = toEl.getBoundingClientRect() + const ur = upperEl.getBoundingClientRect() + const lr = lowerEl.getBoundingClientRect() const svg = svgRef.value if (!svg) continue const svgRect = svg.getBoundingClientRect() - lines.push({ - x1: fr.left + fr.width / 2 - svgRect.left, - y1: fr.bottom - svgRect.top, - x2: tr.left + tr.width / 2 - svgRect.left, - y2: tr.top - svgRect.top, - }) + if (isCausal) { + // 因果视角:从下层顶 → 上层底(箭头向上) + lines.push({ + x1: lr.left + lr.width / 2 - svgRect.left, + y1: lr.top - svgRect.top, + x2: ur.left + ur.width / 2 - svgRect.left, + y2: ur.bottom - svgRect.top, + }) + } else { + // 级联视角:从上层底 → 下层顶(箭头向下) + lines.push({ + x1: ur.left + ur.width / 2 - svgRect.left, + y1: ur.bottom - svgRect.top, + x2: lr.left + lr.width / 2 - svgRect.left, + y2: lr.top - svgRect.top, + }) + } } crossLayerLines.value = lines } diff --git a/frontend/src/views/MapCanvas.vue b/frontend/src/views/MapCanvas.vue index 7c768ea9..cb58ff4c 100644 --- a/frontend/src/views/MapCanvas.vue +++ b/frontend/src/views/MapCanvas.vue @@ -92,11 +92,12 @@ @reorder="(dk: string) => onLayerReorder(dk)" /> - +
- + +
@@ -107,11 +108,12 @@