fix(embed): adapt toolbar and canvas sizing inside modal

This commit is contained in:
2026-02-24 23:46:49 +08:00
parent 745204f2f4
commit 81326d5287
3 changed files with 68 additions and 14 deletions

View File

@@ -16,14 +16,14 @@
/> />
<!-- 主内容区 --> <!-- 主内容区 -->
<div class="editor-content" :style="{ height: contentHeight }"> <div class="editor-content">
<!-- 左侧组件库 --> <!-- 左侧组件库 -->
<ComponentsPanel v-if="showComponentPanel" /> <ComponentsPanel v-if="showComponentPanel" />
<!-- 中间画布 + 右侧属性面板 --> <!-- 中间画布 + 右侧属性面板 -->
<FlowEditor <FlowEditor
ref="flowEditorRef" ref="flowEditorRef"
:height="contentHeight" height="100%"
/> />
</div> </div>
</template> </template>
@@ -38,7 +38,7 @@
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import { ref, computed, watch, onMounted, onBeforeUnmount } from 'vue' import { ref, computed, watch, onMounted, onBeforeUnmount, nextTick } from 'vue'
import { createPinia, setActivePinia } from 'pinia' import { createPinia, setActivePinia } from 'pinia'
import LogicFlow from '@logicflow/core' import LogicFlow from '@logicflow/core'
import '@logicflow/core/lib/style/index.css' import '@logicflow/core/lib/style/index.css'
@@ -151,14 +151,11 @@ const containerHeight = computed(() => {
return typeof props.height === 'number' ? `${props.height}px` : props.height return typeof props.height === 'number' ? `${props.height}px` : props.height
}) })
const contentHeight = computed(() => { const triggerEditorResize = () => {
if (props.showToolbar) { nextTick(() => {
const toolbarHeight = 48 (flowEditorRef.value as any)?.resizeCanvas?.()
const totalHeight = typeof props.height === 'number' ? props.height : 600
return `${totalHeight - toolbarHeight}px`
}
return containerHeight.value
}) })
}
const destroyPreviewMode = () => { const destroyPreviewMode = () => {
if (previewLf.value) { if (previewLf.value) {
@@ -243,7 +240,8 @@ const setGraphData = (data: GraphData) => {
defineExpose({ defineExpose({
getGraphData, getGraphData,
setGraphData setGraphData,
resizeCanvas: triggerEditorResize
}) })
// 监听 data 变化 // 监听 data 变化
@@ -262,6 +260,7 @@ watch(() => props.mode, (newMode) => {
}, 100) }, 100)
} else { } else {
destroyPreviewMode() destroyPreviewMode()
triggerEditorResize()
} }
}) })
@@ -277,17 +276,28 @@ watch(
{ deep: true } { deep: true }
) )
watch(
[() => props.width, () => props.height, () => props.showToolbar, () => props.showComponentPanel],
() => {
if (props.mode === 'edit') {
triggerEditorResize()
}
}
)
// 初始化 // 初始化
onMounted(() => { onMounted(() => {
if (props.mode === 'preview') { if (props.mode === 'preview') {
initPreviewMode() initPreviewMode()
} else if (props.mode === 'edit') { } else if (props.mode === 'edit') {
triggerEditorResize()
// 编辑模式由 FlowEditor 组件初始化 // 编辑模式由 FlowEditor 组件初始化
// 等待 FlowEditor 初始化完成后加载数据 // 等待 FlowEditor 初始化完成后加载数据
setTimeout(() => { setTimeout(() => {
if (props.data) { if (props.data) {
setGraphData(props.data) setGraphData(props.data)
} }
triggerEditorResize()
}, 500) }, 500)
} }
}) })
@@ -311,6 +321,7 @@ onBeforeUnmount(() => {
.editor-content { .editor-content {
display: flex; display: flex;
flex: 1; flex: 1;
min-height: 0;
overflow: hidden; overflow: hidden;
} }

View File

@@ -1,5 +1,5 @@
<template> <template>
<div class="toolbar"> <div class="toolbar" :class="{ 'toolbar--embed': props.isEmbed }">
<div> <div>
<el-button icon="Upload" type="primary" @click="handleImport">{{ t('import') }}</el-button> <el-button icon="Upload" type="primary" @click="handleImport">{{ t('import') }}</el-button>
<el-button icon="Download" type="primary" @click="handleExport">{{ t('export') }}</el-button> <el-button icon="Download" type="primary" @click="handleExport">{{ t('export') }}</el-button>
@@ -486,6 +486,13 @@ const handleClose = (done) => {
z-index: 100; z-index: 100;
} }
.toolbar--embed {
position: relative;
top: auto;
left: auto;
right: auto;
}
.toolbar-controls { .toolbar-controls {
display: flex; display: flex;
align-items: center; align-items: center;

View File

@@ -58,7 +58,7 @@
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import { ref, watch, onMounted, onBeforeUnmount } from 'vue'; import { ref, watch, onMounted, onBeforeUnmount, nextTick } from 'vue';
import LogicFlow, { EventType } from '@logicflow/core'; import LogicFlow, { EventType } from '@logicflow/core';
import type { Position, NodeData, EdgeData, BaseNodeModel, GraphModel, GraphData } from '@logicflow/core'; import type { Position, NodeData, EdgeData, BaseNodeModel, GraphModel, GraphData } from '@logicflow/core';
import '@logicflow/core/lib/style/index.css'; import '@logicflow/core/lib/style/index.css';
@@ -116,6 +116,23 @@ const selectedNode = ref<any>(null);
const copyBuffer = ref<GraphData | null>(null); const copyBuffer = ref<GraphData | null>(null);
let nextPasteDistance = COPY_TRANSLATION; let nextPasteDistance = COPY_TRANSLATION;
const resizeCanvas = () => {
const lfInstance = lf.value as any;
const container = containerRef.value;
if (!lfInstance || !container || typeof lfInstance.resize !== 'function') {
return;
}
const width = container.clientWidth;
const height = container.clientHeight;
if (width > 0 && height > 0) {
lfInstance.resize(width, height);
}
};
const handleWindowResize = () => {
resizeCanvas();
};
function isInputLike(event?: KeyboardEvent) { function isInputLike(event?: KeyboardEvent) {
const target = event?.target as HTMLElement | null; const target = event?.target as HTMLElement | null;
if (!target) return false; if (!target) return false;
@@ -969,6 +986,11 @@ onMounted(() => {
lfInstance.on('selection:selected', () => updateSelectedCount()); lfInstance.on('selection:selected', () => updateSelectedCount());
lfInstance.on('selection:drop', () => updateSelectedCount()); lfInstance.on('selection:drop', () => updateSelectedCount());
nextTick(() => {
resizeCanvas();
});
window.addEventListener('resize', handleWindowResize);
}); });
watch(selectionEnabled, (enabled) => { watch(selectionEnabled, (enabled) => {
@@ -987,8 +1009,22 @@ watch(snaplineEnabled, (enabled) => {
} }
}); });
watch(
() => props.height,
() => {
nextTick(() => {
resizeCanvas();
});
}
);
defineExpose({
resizeCanvas
});
// 销毁 LogicFlow // 销毁 LogicFlow
onBeforeUnmount(() => { onBeforeUnmount(() => {
window.removeEventListener('resize', handleWindowResize);
lf.value?.destroy(); lf.value?.destroy();
lf.value = null; lf.value = null;
destroyLogicFlowInstance(); destroyLogicFlowInstance();