import { ref, computed, h } from 'vue'; const DockPanel = { name: 'DockPanel', props: { panel: { type: Object, required: true }, position: { type: String, required: true }, index: { type: Number, required: true } }, emits: ['close', 'float', 'collapse', 'expand', 'move', 'showContextMenu'], setup(props, { emit }) { const isDragging = ref(false) const dragStart = ref({ x: 0, y: 0 }) // 简化样式计算逻辑,大部分样式通过CSS类实现 const panelStyle = computed(() => { const style = {} // 尺寸样式 if (props.panel.width) { style.width = `${props.panel.width}px` } if (props.panel.height) { style.height = `${props.panel.height}px` } // 折叠状态样式 if (props.panel.isCollapsed) { if (props.position === 'left' || props.position === 'right') { style.width = '40px' } else { style.height = '40px' } } return style }) const handleClose = () => { emit('close', props.panel.id) } const handleFloat = () => { emit('float', props.panel.id) } const handleCollapse = () => { emit('collapse', props.panel.id) } const handleExpand = () => { emit('expand', props.panel.id) } const handleDragStart = (e) => { isDragging.value = true dragStart.value = { x: e.clientX, y: e.clientY } e.stopPropagation() } const handleDragMove = (e) => { if (isDragging.value) { const dx = e.clientX - dragStart.value.x const dy = e.clientY - dragStart.value.y emit('move', props.panel.id, { x: dx, y: dy }) dragStart.value = { x: e.clientX, y: e.clientY } e.preventDefault() e.stopPropagation() } } const handleDragEnd = () => { isDragging.value = false } const handleContextMenu = (e) => { e.preventDefault() emit('showContextMenu', props.panel.id, { x: e.clientX, y: e.clientY }) } const renderIcon = () => { if (props.panel.icon) { return h('div', { class: 'dock-panel-icon' }, props.panel.icon) } return null } const renderTitle = () => { if (props.panel.title) { return h('div', { class: 'dock-panel-title' }, props.panel.title) } return null } const renderContent = () => { if (props.panel.content) { // 检查内容是否是HTML字符串 if (typeof props.panel.content === 'string' && props.panel.content.includes('<')) { // 对于HTML字符串,创建一个div容器并使用innerHTML设置内容 const div = document.createElement('div'); div.innerHTML = props.panel.content; return h('div', { class: 'dock-panel-html-content', innerHTML: props.panel.content }); } else { // 对于组件或普通文本,正常处理 return h(props.panel.content, { panelId: props.panel.id, ...props.panel.props }) } } return h('div', { class: 'dock-panel-empty-content' }, 'Empty Panel') } return () => { // 面板根元素 return h('div', { class: [ 'dock-panel', `dock-panel-${props.position}`, { 'dock-panel-collapsed': props.panel.isCollapsed } ], style: panelStyle.value, onMousedown: handleDragStart, onMousemove: handleDragMove, onMouseup: handleDragEnd, onMouseleave: handleDragEnd, onContextmenu: handleContextMenu }, [ // 折叠状态下的展开按钮 props.panel.isCollapsed ? ( h('div', { class: 'dock-panel-expand-btn', onClick: handleExpand, title: props.panel.title }, renderIcon()) ) : ( // 非折叠状态 [ // 标题栏 h('div', { class: 'dock-panel-titlebar' }, [ renderIcon(), renderTitle(), h('div', { class: 'dock-panel-actions' }, [ h('button', { class: 'dock-panel-btn dock-panel-collapse-btn', onClick: handleCollapse, title: 'Collapse' }, '◀'), h('button', { class: 'dock-panel-btn dock-panel-float-btn', onClick: handleFloat, title: 'Float' }, '↗'), h('button', { class: 'dock-panel-btn dock-panel-close-btn', onClick: handleClose, title: 'Close' }, '×') ]) ]), // 内容区 h('div', { class: 'dock-panel-content' }, renderContent()) ] ) ]) } } } export default DockPanel