From a7f8138b1aafaaf35cbe15e45d1d1e8648a3245c Mon Sep 17 00:00:00 2001 From: liuziting <57311725+liu-ziting@users.noreply.github.com> Date: Wed, 21 Jan 2026 23:01:56 +0800 Subject: [PATCH] =?UTF-8?q?feat(=E8=8A=82=E7=82=B9=E4=BA=A4=E4=BA=92):=20?= =?UTF-8?q?=E5=AE=9E=E7=8E=B0=E8=81=94=E5=8A=A8=E6=8B=96=E6=8B=BD=E5=8A=9F?= =?UTF-8?q?=E8=83=BD=E5=B9=B6=E4=BC=98=E5=8C=96=E8=8A=82=E7=82=B9=E8=81=9A?= =?UTF-8?q?=E7=84=A6=E4=BD=93=E9=AA=8C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 新增联动拖拽功能,支持配置开关,拖动父节点时自动移动子节点 - 优化节点聚焦交互,聚焦时放大节点并居中视图 - 重构后代节点查找逻辑,改用迭代方式提高性能 - 在顶部导航栏添加联动拖拽开关按钮 - 为i18n添加相关翻译字段 - 调整markdown渲染样式增加内边距 --- src/App.vue | 3 + src/components/TopNav.vue | 189 ++++++++++++++++++++++++++++---- src/components/WindowNode.vue | 30 ++++- src/composables/useThinkFlow.ts | 102 +++++++++++++++-- src/i18n/locales/en.json | 3 +- src/i18n/locales/zh.json | 3 +- src/style.css | 1 + 7 files changed, 290 insertions(+), 41 deletions(-) diff --git a/src/App.vue b/src/App.vue index 3d04ce9..a3a5153 100644 --- a/src/App.vue +++ b/src/App.vue @@ -91,6 +91,7 @@ const { fitView, resetLayout, centerRoot, + handleNodeDrag, startNewSession, executeReset, generateSummary, @@ -139,6 +140,7 @@ const fitToView = () => { :class="{ 'space-pressed': isSpacePressed }" :pan-on-drag="panOnDrag" :selection-key-code="'Shift'" + @node-drag="handleNodeDrag" > { :selected="selected" :t="t" :config="config" + :fitView="fitView" :activeNodeId="activeNodeId" :activePath="activePath" :flowNodes="flowNodes" diff --git a/src/components/TopNav.vue b/src/components/TopNav.vue index 65decc6..47bdee2 100644 --- a/src/components/TopNav.vue +++ b/src/components/TopNav.vue @@ -6,13 +6,14 @@ */ // 基础依赖 -import { ref } from 'vue' +import { computed, onMounted, onUnmounted, ref } from 'vue' // 背景样式枚举(用于切换 Lines/Dots) import { BackgroundVariant } from '@vue-flow/background' // 图标:所有按钮与状态展示 import { + ArrowLeftRight, ChevronDown, ChevronUp, Download, @@ -58,6 +59,74 @@ const emit = defineEmits<{ */ const isToolsExpanded = ref(false) +const isEdgeTypeMenuOpen = ref(false) +const isBackgroundMenuOpen = ref(false) + +const edgeTypeOptions = [ + { value: 'default', labelKey: 'nav.edgeTypes.default' }, + { value: 'straight', labelKey: 'nav.edgeTypes.straight' }, + { value: 'step', labelKey: 'nav.edgeTypes.step' }, + { value: 'smoothstep', labelKey: 'nav.edgeTypes.smoothstep' }, + { value: 'simplebezier', labelKey: 'nav.edgeTypes.simplebezier' } +] + +const backgroundOptions = [ + { value: BackgroundVariant.Lines, labelKey: 'nav.lines' }, + { value: BackgroundVariant.Dots, labelKey: 'nav.dots' } +] + +const currentEdgeTypeLabel = computed(() => { + const option = edgeTypeOptions.find(o => o.value === props.config.edgeType) + return option ? props.t(option.labelKey) : props.config.edgeType +}) + +const currentBackgroundLabel = computed(() => { + const option = backgroundOptions.find(o => o.value === props.config.backgroundVariant) + return option ? props.t(option.labelKey) : String(props.config.backgroundVariant) +}) + +const closeMenus = () => { + isEdgeTypeMenuOpen.value = false + isBackgroundMenuOpen.value = false +} + +const toggleEdgeTypeMenu = () => { + isEdgeTypeMenuOpen.value = !isEdgeTypeMenuOpen.value + if (isEdgeTypeMenuOpen.value) isBackgroundMenuOpen.value = false +} + +const toggleBackgroundMenu = () => { + isBackgroundMenuOpen.value = !isBackgroundMenuOpen.value + if (isBackgroundMenuOpen.value) isEdgeTypeMenuOpen.value = false +} + +const setEdgeType = (value: string) => { + props.config.edgeType = value + closeMenus() +} + +const setBackgroundVariant = (value: any) => { + props.config.backgroundVariant = value + closeMenus() +} + +const handleDocumentPointerDown = (e: Event) => { + const target = e.target as HTMLElement | null + if (!target) return + + if (target.closest('[data-edge-type-menu="true"]')) return + if (target.closest('[data-background-menu="true"]')) return + closeMenus() +} + +onMounted(() => { + document.addEventListener('pointerdown', handleDocumentPointerDown) +}) + +onUnmounted(() => { + document.removeEventListener('pointerdown', handleDocumentPointerDown) +}) + /** * 执行某个工具动作后自动收起移动端面板 */ @@ -95,6 +164,18 @@ const callAndClose = (fn: () => void) => {
+ + +
+ +
+ +
+ - +
+ +
+ +
+
@@ -212,18 +324,49 @@ const callAndClose = (fn: () => void) => { {{ props.t('nav.edge') }} - +
+ +
+ +
+
- +
+ +
+ +
+