面板关闭事件接入总线

This commit is contained in:
zqm
2025-11-20 09:44:51 +08:00
parent f978a42990
commit f92d3ca474
4 changed files with 202 additions and 30 deletions

View File

@@ -1,6 +1,7 @@
<template>
<div class="panel bg-white overflow-hidden"
:style="{ width: '100%', height: '100%' }">
:style="{ width: '100%', height: '100%' }"
:data-panel-id="id">
<div class="flex flex-col h-full">
<!-- 标题栏 -->
<div class="title-bar h-6 bg-[#435d9c] text-white px-2 flex items-center justify-between select-none cursor-move"
@@ -111,7 +112,13 @@
</template>
<script setup>
import { defineProps, defineEmits } from 'vue';
import { defineProps, onMounted, onUnmounted } from 'vue';
import {
eventBus,
EVENT_TYPES,
emitEvent,
onEvent
} from './eventBus.js';
// 定义组件属性
const props = defineProps({
@@ -154,27 +161,76 @@ const props = defineProps({
content: {
type: Object,
default: null
}
},
// 移除areaId属性因为面板会被拖拽到不同区域
// 改为通过DOM动态获取当前所在区域
});
// 定义事件
const emit = defineEmits(['toggleCollapse', 'maximize', 'close', 'toggleToolbar', 'dragStart', 'dragMove', 'dragEnd']);
// 事件订阅管理
const subscriptions = new Map();
// 事件处理函数
// 动态获取当前面板所在的Area ID
const getCurrentAreaId = () => {
// 通过DOM向上查找最近的Area容器
const panelElement = document.querySelector(`[data-panel-id="${props.id}"]`);
if (panelElement) {
const areaElement = panelElement.closest('[data-area-id]');
if (areaElement) {
return areaElement.getAttribute('data-area-id');
}
}
// 备用方法:通过父组件查找
// 向上查找vs-area容器
const parentElement = document.querySelector(`[data-panel-id="${props.id}"]`)?.parentElement;
if (parentElement) {
const areaElement = parentElement.closest('.vs-area');
if (areaElement) {
return areaElement.getAttribute('data-area-id');
}
}
console.warn(`[Panel:${props.id}] 无法找到当前所在的AreaPanel可能未正确挂载`);
return null;
};
// 事件处理函数 - 使用事件总线
const onToggleCollapse = () => {
emit('toggleCollapse', props.id);
console.log(`[Panel:${props.id}] 触发折叠/展开事件`)
emitEvent(EVENT_TYPES.PANEL_TOGGLE_COLLAPSE, {
panelId: props.id,
areaId: getCurrentAreaId(),
currentState: props.collapsed
})
};
const onMaximize = () => {
emit('maximize', props.id);
console.log(`[Panel:${props.id}] 触发最大化事件`)
emitEvent(EVENT_TYPES.PANEL_MAXIMIZE, {
panelId: props.id,
areaId: getCurrentAreaId(),
currentState: props.maximized
})
};
const onClose = () => {
emit('close', props.id);
// console.log(`[Panel:${props.id}] 触发关闭请求事件`)
// 首先发送关闭请求,让父组件可以处理确认逻辑
emitEvent(EVENT_TYPES.PANEL_CLOSE_REQUEST, {
panelId: props.id,
areaId: getCurrentAreaId(),
panelTitle: props.title,
requestTime: Date.now()
})
};
const onToggleToolbar = () => {
emit('toggleToolbar', props.id);
console.log(`[Panel:${props.id}] 触发工具栏切换事件`)
emitEvent(EVENT_TYPES.PANEL_TOGGLE_TOOLBAR, {
panelId: props.id,
areaId: getCurrentAreaId(),
currentState: props.toolbarExpanded
})
};
// 拖拽相关状态
@@ -185,12 +241,18 @@ const onDragStart = (e) => {
// 只有当点击的是标题栏区域(不是按钮)时才触发拖拽
if (!e.target.closest('.title-bar-buttons') && !e.target.closest('button')) {
isDragging = true;
// 传递panelId和鼠标位置
emit('dragStart', {
clientX: e.clientX,
clientY: e.clientY,
panelId: props.id
});
console.log(`[Panel:${props.id}] 开始拖拽`)
// 使用事件总线触发拖拽开始事件
emitEvent(EVENT_TYPES.PANEL_DRAG_START, {
panelId: props.id,
areaId: getCurrentAreaId(),
position: { x: e.clientX, y: e.clientY },
timestamp: Date.now()
}, {
source: { component: 'Panel', panelId: props.id }
})
// 防止文本选择和默认行为
e.preventDefault();
e.stopPropagation();
@@ -208,11 +270,16 @@ const onDragMove = (e) => {
// 防止文本选择和默认行为
e.preventDefault();
e.stopPropagation();
emit('dragMove', {
clientX: e.clientX,
clientY: e.clientY,
panelId: props.id
});
// 使用事件总线触发拖拽移动事件
emitEvent(EVENT_TYPES.PANEL_DRAG_MOVE, {
panelId: props.id,
areaId: getCurrentAreaId(),
position: { x: e.clientX, y: e.clientY },
timestamp: Date.now()
}, {
source: { component: 'Panel', panelId: props.id }
})
}
};
@@ -220,7 +287,16 @@ const onDragMove = (e) => {
const onDragEnd = () => {
if (isDragging) {
isDragging = false;
emit('dragEnd', { panelId: props.id });
console.log(`[Panel:${props.id}] 结束拖拽`)
// 使用事件总线触发拖拽结束事件
emitEvent(EVENT_TYPES.PANEL_DRAG_END, {
panelId: props.id,
areaId: getCurrentAreaId(),
timestamp: Date.now()
}, {
source: { component: 'Panel', panelId: props.id }
})
// 拖拽结束后移除事件监听器
document.removeEventListener('mousemove', onDragMove);
@@ -228,6 +304,61 @@ const onDragEnd = () => {
document.removeEventListener('mouseleave', onDragEnd);
}
};
/**
* 监听面板关闭事件,更新组件状态(可选)
*/
const setupEventListeners = () => {
// 监听面板最大化同步事件
const unsubscribeMaximizeSync = onEvent(EVENT_TYPES.PANEL_MAXIMIZE_SYNC, (data) => {
if (data.panelId === props.id) {
// 这里可以添加最大化状态同步的逻辑
console.log(`[Panel:${props.id}] 收到最大化同步事件`)
}
})
subscriptions.set('maximizeSync', unsubscribeMaximizeSync)
}
/**
* 清理所有事件订阅
*/
const cleanupEventListeners = () => {
subscriptions.forEach((unsubscribe) => {
if (typeof unsubscribe === 'function') {
unsubscribe()
}
})
subscriptions.clear()
}
// 生命周期钩子
onMounted(() => {
console.log(`[Panel:${props.id}] 组件已挂载`)
// 启用调试模式(开发环境)
if (import.meta.env.DEV) {
eventBus.setDebugMode(true)
}
// 设置事件监听器
setupEventListeners()
})
onUnmounted(() => {
console.log(`[Panel:${props.id}] 组件即将卸载`)
// 清理事件监听器
cleanupEventListeners()
// 确保拖拽状态已清理
if (isDragging) {
document.removeEventListener('mousemove', onDragMove);
document.removeEventListener('mouseup', onDragEnd);
document.removeEventListener('mouseleave', onDragEnd);
isDragging = false
}
})
</script>
<style scoped>