|
@@ -3,9 +3,10 @@ import { computed, ref } from 'vue'
|
|
|
import { Icon } from '@repo/ui'
|
|
import { Icon } from '@repo/ui'
|
|
|
import { NodeResizer } from '@vue-flow/node-resizer'
|
|
import { NodeResizer } from '@vue-flow/node-resizer'
|
|
|
import type { OnResize } from '@vue-flow/node-resizer'
|
|
import type { OnResize } from '@vue-flow/node-resizer'
|
|
|
|
|
+import { useElementSize } from '@vueuse/core'
|
|
|
import Canvas from '../../../Canvas.vue'
|
|
import Canvas from '../../../Canvas.vue'
|
|
|
|
|
|
|
|
-import type { XYPosition, Connection } from '@vue-flow/core'
|
|
|
|
|
|
|
+import type { XYPosition, Connection, CoordinateExtent } from '@vue-flow/core'
|
|
|
import type { CanvasNodeMoveEvent, ConnectStartEvent } from '../../../../Interface'
|
|
import type { CanvasNodeMoveEvent, ConnectStartEvent } from '../../../../Interface'
|
|
|
import { useCanvasNodeContext } from '../../../../hooks/useCanvasNodeContext'
|
|
import { useCanvasNodeContext } from '../../../../hooks/useCanvasNodeContext'
|
|
|
import { useVueFlowContext } from '../../../../hooks/useVueFlowContext'
|
|
import { useVueFlowContext } from '../../../../hooks/useVueFlowContext'
|
|
@@ -58,6 +59,18 @@ const isReadOnly = computed(() => node.props.value.readOnly ?? false)
|
|
|
const width = computed(() => Number(nodeData.value?.width) || 424)
|
|
const width = computed(() => Number(nodeData.value?.width) || 424)
|
|
|
const height = computed(() => Number(nodeData.value?.height) || 244)
|
|
const height = computed(() => Number(nodeData.value?.height) || 244)
|
|
|
const executionStatus = computed(() => getNodeExecutionStatus(node.props.value.node))
|
|
const executionStatus = computed(() => getNodeExecutionStatus(node.props.value.node))
|
|
|
|
|
+const innerCanvasRef = ref<HTMLDivElement>()
|
|
|
|
|
+const { width: innerCanvasWidth, height: innerCanvasHeight } = useElementSize(innerCanvasRef)
|
|
|
|
|
+const innerCanvasExtent = computed<CoordinateExtent | undefined>(() => {
|
|
|
|
|
+ if (innerCanvasWidth.value <= 0 || innerCanvasHeight.value <= 0) {
|
|
|
|
|
+ return undefined
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ return [
|
|
|
|
|
+ [0, 0],
|
|
|
|
|
+ [Math.max(innerCanvasWidth.value - 1, 0), Math.max(innerCanvasHeight.value - 1, 0)]
|
|
|
|
|
+ ]
|
|
|
|
|
+})
|
|
|
|
|
|
|
|
const nodeClass = computed(() => {
|
|
const nodeClass = computed(() => {
|
|
|
const classes: string[] = []
|
|
const classes: string[] = []
|
|
@@ -124,7 +137,8 @@ function onAddEdge(connection: Connection) {
|
|
|
<!-- 内部画布区域:虚线网格 + 占位内容 -->
|
|
<!-- 内部画布区域:虚线网格 + 占位内容 -->
|
|
|
<div class="loop-body flex-1 min-h-0 relative">
|
|
<div class="loop-body flex-1 min-h-0 relative">
|
|
|
<div
|
|
<div
|
|
|
- class="absolute top-16px right-16px bottom-16px left-16px z-1 rounded-8px border-1 border-dashed border-#d9d9d9 nopan"
|
|
|
|
|
|
|
+ ref="innerCanvasRef"
|
|
|
|
|
+ class="absolute top-16px right-16px bottom-16px left-16px z-1 rounded-8px border-1 border-dashed border-#d9d9d9 nopan overflow-hidden"
|
|
|
@click.stop
|
|
@click.stop
|
|
|
@dblclick.stop
|
|
@dblclick.stop
|
|
|
>
|
|
>
|
|
@@ -141,6 +155,8 @@ function onAddEdge(connection: Connection) {
|
|
|
:min-zoom="1"
|
|
:min-zoom="1"
|
|
|
:pan-on-drag="false"
|
|
:pan-on-drag="false"
|
|
|
:auto-pan-on-node-drag="false"
|
|
:auto-pan-on-node-drag="false"
|
|
|
|
|
+ :translate-extent="innerCanvasExtent"
|
|
|
|
|
+ :node-extent="innerCanvasExtent"
|
|
|
@click:node="(id, position) => emit('click:node', id, position)"
|
|
@click:node="(id, position) => emit('click:node', id, position)"
|
|
|
@dblclick:node="(id, position) => emit('dblclick:node', id, position)"
|
|
@dblclick:node="(id, position) => emit('dblclick:node', id, position)"
|
|
|
@click:node:add="emit('click:node:add', $event)"
|
|
@click:node:add="emit('click:node:add', $event)"
|