121 lines
3.2 KiB
Vue
121 lines
3.2 KiB
Vue
<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%;">
|
||
<Render
|
||
:type="child.type"
|
||
:config="child"
|
||
:debug="debug"
|
||
/>
|
||
</div>
|
||
</template>
|
||
</component>
|
||
</template>
|
||
|
||
<script setup>
|
||
import { computed, defineAsyncComponent } from 'vue'
|
||
const Area = defineAsyncComponent(() => import('./Area.vue'))
|
||
const TabPage = defineAsyncComponent(() => import('./TabPage.vue'))
|
||
const Panel = defineAsyncComponent(() => import('./Panel.vue'))
|
||
import { eventBus, EVENT_TYPES } from './eventBus'
|
||
|
||
// 定义组件属性
|
||
const props = defineProps({
|
||
// 组件类型:area, TabPage, panel
|
||
type: {
|
||
type: String,
|
||
required: true,
|
||
validator: (value) => ['Area', 'TabPage', 'Panel'].includes(value)
|
||
},
|
||
// 组件配置数据
|
||
config: {
|
||
type: Object,
|
||
required: true
|
||
},
|
||
// 是否转发所有事件(用于调试)
|
||
debug: {
|
||
type: Boolean,
|
||
default: false
|
||
}
|
||
})
|
||
|
||
// 不再需要定义emit,因为事件将通过事件总线发送
|
||
|
||
// 根据type计算要渲染的组件
|
||
const componentType = computed(() => {
|
||
const typeMap = {
|
||
'Area': Area,
|
||
'TabPage': TabPage,
|
||
'Panel': Panel
|
||
}
|
||
return typeMap[props.type]
|
||
})
|
||
|
||
// 根据type和config计算组件的属性
|
||
const componentProps = computed(() => {
|
||
const { config } = props
|
||
|
||
switch (props.type) {
|
||
case 'Area':
|
||
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,
|
||
draggable: config.draggable !== false,
|
||
children: config.children
|
||
}
|
||
|
||
case 'TabPage':
|
||
return {
|
||
id: config.id,
|
||
title: config.title || '标签页',
|
||
showTabs: config.showTabs !== false,
|
||
tabPosition: config.tabPosition || 'top',
|
||
children: config.children
|
||
}
|
||
|
||
case 'Panel':
|
||
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 {}
|
||
}
|
||
})
|
||
|
||
|
||
|
||
// 暴露组件实例方法
|
||
defineExpose({
|
||
getComponentType: () => props.type,
|
||
getConfig: () => props.config,
|
||
getComponentProps: () => componentProps.value,
|
||
isDebugMode: () => props.debug
|
||
})
|
||
</script>
|
||
|
||
<style scoped>
|
||
/* Render组件本身不添加额外样式,由子组件控制 */
|
||
</style> |