Files
JoyD/AutoRobot/Windows/Robot/Web/src/DockLayout/Render.vue

121 lines
3.2 KiB
Vue
Raw Normal View History

2025-11-19 11:31:21 +08:00
<template>
<!-- 根据type属性动态渲染对应的组件 -->
<component
:is="componentType"
v-bind="componentProps"
>
<!-- 统一处理children属性不区分组件类型只要有children就渲染 -->
<template v-if="config.children">
<!-- 统一处理children为数组或单个对象的情况 -->
<div v-for="child in Array.isArray(config.children) ? config.children : [config.children]" :key="child.id" style="width: 100%; height: 100%;">
2025-11-19 13:57:51 +08:00
<Render
:type="child.type"
:config="child"
2025-11-19 13:57:51 +08:00
:debug="debug"
/>
</div>
2025-11-19 11:31:21 +08:00
</template>
</component>
</template>
<script setup>
2025-12-31 10:51:47 +08:00
import { computed, defineAsyncComponent } from 'vue'
const Area = defineAsyncComponent(() => import('./Area.vue'))
const TabPage = defineAsyncComponent(() => import('./TabPage.vue'))
const Panel = defineAsyncComponent(() => import('./Panel.vue'))
2025-12-25 13:53:52 +08:00
import { eventBus, EVENT_TYPES } from './eventBus'
2025-11-19 11:31:21 +08:00
// 定义组件属性
const props = defineProps({
2025-11-19 15:26:39 +08:00
// 组件类型area, TabPage, panel
2025-11-19 11:31:21 +08:00
type: {
type: String,
required: true,
2025-11-19 15:26:39 +08:00
validator: (value) => ['Area', 'TabPage', 'Panel'].includes(value)
2025-11-19 11:31:21 +08:00
},
// 组件配置数据
config: {
type: Object,
required: true
},
// 是否转发所有事件(用于调试)
debug: {
type: Boolean,
default: false
}
})
2025-12-15 09:03:32 +08:00
// 不再需要定义emit因为事件将通过事件总线发送
2025-11-19 11:31:21 +08:00
// 根据type计算要渲染的组件
const componentType = computed(() => {
const typeMap = {
2025-11-19 15:26:39 +08:00
'Area': Area,
'TabPage': TabPage,
'Panel': Panel
2025-11-19 11:31:21 +08:00
}
return typeMap[props.type]
})
// 根据type和config计算组件的属性
const componentProps = computed(() => {
const { config } = props
switch (props.type) {
2025-11-19 15:26:39 +08:00
case 'Area':
2025-11-19 11:31:21 +08:00
return {
id: config.id,
title: config.title || '面板区',
resizable: config.resizable !== false,
windowState: config.windowState || '正常',
width: config.width || 300,
height: config.height || 250,
showTitleBar: config.showTitleBar !== false,
left: config.left,
top: config.top,
2025-12-29 09:05:37 +08:00
draggable: config.draggable !== false,
children: config.children
2025-11-19 11:31:21 +08:00
}
2025-11-19 15:26:39 +08:00
case 'TabPage':
2025-11-19 11:31:21 +08:00
return {
id: config.id,
title: config.title || '标签页',
showTabs: config.showTabs !== false,
2025-12-29 09:05:37 +08:00
tabPosition: config.tabPosition || 'top',
children: config.children
2025-11-19 11:31:21 +08:00
}
2025-11-19 15:26:39 +08:00
case 'Panel':
2025-11-19 11:31:21 +08:00
return {
id: config.id,
title: config.title || '',
x: config.x || 0,
y: config.y || 0,
width: config.width || 300,
height: config.height || 200,
collapsed: config.collapsed || false,
toolbarExpanded: config.toolbarExpanded || false,
maximized: config.maximized || false,
content: config.content
}
default:
return {}
}
})
2025-11-19 11:31:21 +08:00
// 暴露组件实例方法
defineExpose({
getComponentType: () => props.type,
getConfig: () => props.config,
getComponentProps: () => componentProps.value,
2025-11-19 11:31:21 +08:00
isDebugMode: () => props.debug
})
</script>
<style scoped>
2025-11-19 13:57:51 +08:00
/* Render组件本身不添加额外样式由子组件控制 */
2025-11-19 11:31:21 +08:00
</style>