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') }} - +
+ +
+ +
+
- +
+ +
+ +
+