UPDATE: VERSION-20260327
This commit is contained in:
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
* This file is part of the kernelstudio package.
|
||||
*
|
||||
* (c) 2014-2025 zlin <admin@kernelstudio.com>
|
||||
* (c) 2014-2026 zlin <admin@kernelstudio.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE file
|
||||
* that was distributed with this source code.
|
||||
@@ -23,14 +23,14 @@ export class EventError {
|
||||
|
||||
export class EventListener {
|
||||
|
||||
private readonly _listeners: Record<string, Function[]>;
|
||||
private _listeners: Record<string, Function[]>;
|
||||
|
||||
constructor(listeners: Record<string, Function[]> = {}) {
|
||||
this._listeners = listeners;
|
||||
}
|
||||
|
||||
all(): Record<string, Function[]> {
|
||||
return {...this._listeners}; // 返回副本,避免外部直接修改
|
||||
return { ...this._listeners }; // 返回副本,避免外部直接修改
|
||||
}
|
||||
|
||||
has(name: string): boolean {
|
||||
@@ -55,16 +55,24 @@ export class EventListener {
|
||||
[...listeners].forEach(f => f(options));
|
||||
}
|
||||
}
|
||||
|
||||
clear(){
|
||||
for (const key in this._listeners) {
|
||||
if (this._listeners.hasOwnProperty(key)) {
|
||||
delete this._listeners[key];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export const safePreventDefault = (event: any) => {
|
||||
if (event && typeof event.preventDefault === 'function') {
|
||||
event.preventDefault();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
export const safeStopPropagation = (event: any) => {
|
||||
if (event && typeof event.stopPropagation === 'function') {
|
||||
event.stopPropagation();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
@@ -114,8 +114,16 @@ export default defineComponent({
|
||||
fitToScreen,
|
||||
centerContent,
|
||||
resizeCanvas,
|
||||
destroyGraph,
|
||||
clearGraph,
|
||||
} = useGraphCanvas();
|
||||
|
||||
const destroy = ()=> {
|
||||
window.removeEventListener('resize', handleResize);
|
||||
destroyGraph();
|
||||
graph.value = null;
|
||||
}
|
||||
|
||||
const loadPlatforms = () => {
|
||||
platforms.value = [];
|
||||
findAllBasicPlatforms().then(r => {
|
||||
@@ -213,6 +221,8 @@ export default defineComponent({
|
||||
};
|
||||
|
||||
const handleSelectTree = (tree: BehaviorTree) => {
|
||||
destroyGraph();
|
||||
|
||||
console.info('handleSelectTree', tree);
|
||||
findOneTreeById(tree.id).then(r => {
|
||||
if (r.data) {
|
||||
@@ -233,7 +243,9 @@ export default defineComponent({
|
||||
graph: nodeGraph,
|
||||
};
|
||||
currentTreeEditing.value = true;
|
||||
createElements();
|
||||
nextTick(() => {
|
||||
initGraph();
|
||||
});
|
||||
} else {
|
||||
message.error(r.msg ?? '行为树不存在.');
|
||||
}
|
||||
@@ -241,12 +253,8 @@ export default defineComponent({
|
||||
};
|
||||
|
||||
const createElements = () => {
|
||||
clearGraph();
|
||||
nextTick(() => {
|
||||
try {
|
||||
graph.value?.clearCells();
|
||||
} catch (e: any) {
|
||||
console.error('clear cells error, cause:', e);
|
||||
}
|
||||
setTimeout(() => {
|
||||
if (currentBehaviorTree.value?.graph && graph.value) {
|
||||
if (currentBehaviorTree.value?.graph.nodes) {
|
||||
@@ -274,6 +282,8 @@ export default defineComponent({
|
||||
};
|
||||
|
||||
const handleCreateTree = () => {
|
||||
destroyGraph();
|
||||
|
||||
currentBehaviorTree.value = {
|
||||
id: 0,
|
||||
name: '行为树',
|
||||
@@ -294,7 +304,9 @@ export default defineComponent({
|
||||
selectedModelNode.value = null;
|
||||
selectedNodeTaskElement.value = null;
|
||||
|
||||
createElements();
|
||||
nextTick(() => {
|
||||
initGraph();
|
||||
});
|
||||
};
|
||||
|
||||
// 初始化X6画布
|
||||
@@ -417,18 +429,7 @@ export default defineComponent({
|
||||
});
|
||||
|
||||
// 清理
|
||||
onBeforeUnmount(() => {
|
||||
window.removeEventListener('resize', handleResize);
|
||||
if (graph.value) {
|
||||
try {
|
||||
graph.value.clearCells();
|
||||
} catch (error) {
|
||||
console.warn('销毁画布时出错:', error);
|
||||
}
|
||||
graph.value = null;
|
||||
console.log('画布已销毁');
|
||||
}
|
||||
});
|
||||
onBeforeUnmount(() => destroy());
|
||||
|
||||
return {
|
||||
platforms,
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
* that was distributed with this source code.
|
||||
*/
|
||||
|
||||
import { computed, type ComputedRef, ref, type Ref } from 'vue';
|
||||
import { computed, type ComputedRef, ref, type Ref, nextTick } from 'vue';
|
||||
import { type Dom, Graph, Node } from '@antv/x6';
|
||||
import type { NodeViewPositionEventArgs } from '@antv/x6/es/view/node/type';
|
||||
import { createGraphCanvas } from './canvas';
|
||||
@@ -24,6 +24,8 @@ export interface UseGraphCanvas {
|
||||
graph: ComputedRef<Graph>;
|
||||
zoomIn: () => void;
|
||||
zoomOut: () => void;
|
||||
destroyGraph: () => void;
|
||||
clearGraph: () => void;
|
||||
fitToScreen: () => void;
|
||||
centerContent: () => void;
|
||||
resizeCanvas: () => void;
|
||||
@@ -39,6 +41,36 @@ export const useGraphCanvas = (readonly: boolean = false): UseGraphCanvas => {
|
||||
const eventListener = new EventListener();
|
||||
const currentZoom = ref<number>(0);
|
||||
|
||||
|
||||
const clearGraph = ()=> {
|
||||
if (graph.value) {
|
||||
try {
|
||||
graph.value.off();
|
||||
graph.value.clearCells();
|
||||
} catch (e) {
|
||||
console.error('清空画布失败:', e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const destroyGraph = ()=> {
|
||||
eventListener.clear();
|
||||
if (graph.value) {
|
||||
clearGraph();
|
||||
|
||||
// 等待 Vue 完成卸载
|
||||
nextTick(() => {
|
||||
graph.value?.dispose(); // 销毁 Graph 实例
|
||||
graph.value = null;
|
||||
if (container.value) {
|
||||
container.value.innerHTML = ''; // 清空容器内容
|
||||
}
|
||||
});
|
||||
} else if (container.value) {
|
||||
container.value.innerHTML = '';
|
||||
}
|
||||
}
|
||||
|
||||
const handleGraphEvent = (name: string, fn: Function) => {
|
||||
eventListener.on(name, fn);
|
||||
};
|
||||
@@ -243,6 +275,8 @@ export const useGraphCanvas = (readonly: boolean = false): UseGraphCanvas => {
|
||||
return {
|
||||
container,
|
||||
readonly,
|
||||
destroyGraph,
|
||||
clearGraph,
|
||||
graph: graphInstance,
|
||||
eventListener,
|
||||
currentZoom,
|
||||
|
||||
Reference in New Issue
Block a user