Add AutoRobot directory with Windows line endings
This commit is contained in:
184
AutoRobot/Windows/Robot/Web/src/components/DockPanel.js
Normal file
184
AutoRobot/Windows/Robot/Web/src/components/DockPanel.js
Normal file
@@ -0,0 +1,184 @@
|
||||
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
|
||||
Reference in New Issue
Block a user