You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 

307 lines
10 KiB

<template>
<div class="app-wrap">
<div class="app-header">
<div class="logo"><img :src="Logo" alt="" style="height: 30px;width: 169px"></div>
<div class="app-header-menu-wrap">
<div class="app-header-menu" v-for="rootMenu in calcRootMenu" @click="clickRootMenu"
v-menus:left="rootMenu.children"
>{{ rootMenu.label }}
<component :is="renderIcon('element ArrowDown')"></component>
</div>
</div>
<div class="user">
<span>
<component :is="renderIcon('element User')"></component>
</span>
</div>
</div>
<div class="app-section" v-if="worldModel.state.isOpened">
<div class="btns-toolbar btns-toolbar-left">
<div class="btns btns-top">
<template v-for="panel in getWidgetBySide('left')">
<div class="item" :class="{selected:sectionLeftName===panel.name}" @click="btnLeftMe(panel)"
:title="panel.title + (panel.shortcut?' (' + panel.shortcut + ')':'')">
<component :is="panel.icon" />
</div>
</template>
</div>
<div class="btns btns-bottom">
<template v-for="panel in getWidgetBySide('bottom')">
<div class="item" :class="{selected:sectionBottomName===panel.name}" @click="btnBottomMe(panel)"
:title="panel.title + (panel.shortcut?' (' + panel.shortcut + ')':'')">
<component :is="panel.icon" />
</div>
</template>
</div>
</div>
<Split class="section" :direction="'vertical'" style="flex-shrink: 0;flex-grow:1;" ref="mainSplit"
@onDragEnd="bottomDragEnd">
<SplitArea class="section-top" :size="hideBottom ? 100 : (100 - bottomSize)" :min-size="50"
:class="{'hidden-split':hideBottom}">
<Split class="section" :direction="'horizontal'" style="flex-shrink: 0;flex-grow:1;" ref="centerSplit"
@onDragEnd="centerDragEnd">
<SplitArea v-show="!hideLeft" class="section-left" :class="{'hidden-split':hideLeft}"
:size="hideLeft ? 0 : sectionLeftSize">
<div class="section-item-wrap">
<keep-alive>
<component v-if="calcLeftPanel?.component" :is="calcLeftPanel.component"
@close="closeMe('hideLeft')" :key="calcLeftPanel?.name"
:viewport="currentViewport" />
</keep-alive>
</div>
</SplitArea>
<SplitArea class="section-center" :class="{'hidden-split':hideRight}" :size="calcCenterSize">
<el-tabs type="card" class="section-tabs" v-model="centerActiveName" @tab-click="handleCenterTabClick">
<el-tab-pane label="2D视图" name="ModelEditor" lazy>
<Model2DEditor @viewportChanged="setCurrentViewport" />
</el-tab-pane>
<el-tab-pane label="3D视图" name="ModelView" lazy>
<Model3DViewer />
</el-tab-pane>
<el-tab-pane label="模型属性" name="ModelFile" lazy>
<el-empty description="暂无数据" />
</el-tab-pane>
<el-tab-pane label="基础资料" name="ModelDataSet" lazy>
<el-empty description="暂无数据" />
</el-tab-pane>
</el-tabs>
</SplitArea>
<SplitArea v-show="!hideRight" class="section-right" :size="hideRight ? 0 : sectionRightSize">
<div class="section-item-wrap">
<keep-alive>
<component v-if="calcRightPanel?.component" :is="calcRightPanel.component"
@close="()=>closeMe('hideRight')" :key="calcRightPanel.name"
:viewport="currentViewport" />
</keep-alive>
</div>
</SplitArea>
</Split>
</SplitArea>
<SplitArea v-show="!hideBottom" :class="['section-bottom']" :size="hideBottom ? 0 : bottomSize" :min-size="0">
<div class="section-item-wrap">
<keep-alive>
<component v-if="calcBottomPanel?.component" :is="calcBottomPanel.component"
@close="()=>closeMe('hideBottom')" :key="calcBottomPanel.name"
:viewport="currentViewport"
/>
</keep-alive>
</div>
</SplitArea>
</Split>
<div class="btns-toolbar btns-toolbar-right">
<div class="btns btns-top">
<template v-for="panel in getWidgetBySide('right')">
<div class="item" :class="{selected:sectionRightName===panel.name}" @click="btnRightMe(panel)"
:title="panel.title + (panel.shortcut?' (' + panel.shortcut + ')':'')">
<component :is="panel.icon" />
</div>
</template>
</div>
</div>
</div>
</div>
</template>
<script>
import { markRaw } from 'vue'
import { renderIcon } from '@/utils/webutils.js'
import Split from '@/components/split/split.vue'
import SplitArea from '@/components/split/split-area.vue'
import { ModelMainInit, ModelMainMounted, ModelMainUnmounted } from './ModelMainInit.js'
import { getRootMenu } from '@/runtime/DefineMenu.js'
import { getWidgetByName, getWidgetBySide, getAllWidget } from '@/runtime/DefineWidget.js'
import Model2DEditor from './Model2DEditor.vue'
import Model3DViewer from './Model3DViewer.vue'
import { normalizeShortKey } from '@/utils/webutils.ts'
import Logo from '@/assets/images/logo.png'
import './ModelMain.less'
export default {
components: { Model2DEditor, Model3DViewer, Split, SplitArea },
created() {
ModelMainInit()
},
mounted() {
ModelMainMounted().then(() => {
// 注册 widget 快捷键
const allWidget = getAllWidget()
allWidget.forEach((widget) => {
if (widget?.shortcut && widget?.name && widget?.side) {
const shortKey = normalizeShortKey(widget.shortcut)
widget.shortcut = shortKey
if (shortKey) {
system.hotkeys(shortKey, (event) => {
if (widget.side === 'left') {
this.sectionLeftName = widget.name
this.hideLeft = false
} else if (widget.side === 'right') {
this.sectionRightName = widget.name
this.hideRight = false
} else if (widget.side === 'bottom') {
this.sectionBottomName = widget.name
this.hideBottom = false
}
event.preventDefault()
})
}
}
})
})
},
unmounted() {
ModelMainUnmounted()
},
data() {
return {
Logo,
currentViewport: null,
calcRootMenu: getRootMenu(),
bottomSize: 30,
hideBottom: true,
hideLeft: false,
hideRight: false,
sectionLeftSize: 20,
sectionRightSize: 20,
sectionLeftName: 'modeltree',
sectionRightName: 'property',
sectionBottomName: '',
sectionLeftSearch: '',
centerActiveName: 'ModelEditor'
}
},
computed: {
worldModel() {
return window['worldModel']
},
calcLeftPanel() {
if (!this.sectionLeftName || this.hideLeft) {
return undefined
}
return getWidgetByName(this.sectionLeftName)
},
calcRightPanel() {
if (!this.sectionRightName || this.hideRight) {
return undefined
}
return getWidgetByName(this.sectionRightName)
},
calcBottomPanel() {
if (!this.sectionBottomName || this.hideBottom) {
return undefined
}
return getWidgetByName(this.sectionBottomName)
},
calcCenterSize() {
if (this.hideLeft && this.hideRight) {
return 100
} else if (this.hideLeft) {
return 100 - this.sectionRightSize
} else if (this.hideRight) {
return 100 - this.sectionLeftSize
}
return 100 - this.sectionLeftSize - this.sectionRightSize
}
},
watch: {
hideBottom(value) {
if (value) {
this.$refs.mainSplit.refreshSize([100, 0])
} else {
this.$refs.mainSplit.refreshSize([100 - this.bottomSize, this.bottomSize])
}
},
hideLeft() {
this.recalcCenterSize()
},
hideRight() {
this.recalcCenterSize()
}
},
methods: {
renderIcon,
getWidgetBySide,
setCurrentViewport(viewport) {
this.currentViewport = viewport
},
handleCenterTabClick(tab) {
if (tab?.name) {
this.centerActiveName = tab.name
}
},
centerDragEnd(sizes) {
this.sectionLeftSize = sizes[0]
this.sectionRightSize = sizes[2]
},
bottomDragEnd(sizes) {
this.bottomSize = sizes[1]
},
recalcCenterSize() {
if (this.hideLeft && this.hideRight) {
this.$refs.centerSplit.refreshSize([0, 100, 0])
} else if (this.hideLeft) {
this.$refs.centerSplit.refreshSize([0, 100 - this.sectionRightSize, this.sectionRightSize])
} else if (this.hideRight) {
this.$refs.centerSplit.refreshSize([this.sectionLeftSize, 100 - this.sectionLeftSize, 0])
} else {
this.$refs.centerSplit.refreshSize([this.sectionLeftSize, 100 - this.sectionLeftSize - this.sectionRightSize, this.sectionRightSize])
}
},
clickRootMenu() {
},
handleSelect() {
},
btnLeftMe(panel) {
if (this.sectionLeftName === panel.name) {
this.hideLeft = true
this.sectionLeftName = ''
} else {
this.hideLeft = false
this.sectionLeftName = panel.name
}
},
btnRightMe(panel) {
if (this.sectionRightName === panel.name) {
this.hideRight = true
this.sectionRightName = ''
} else {
this.hideRight = false
this.sectionRightName = panel.name
}
},
btnBottomMe(panel) {
if (this.sectionBottomName === panel.name) {
this.hideBottom = true
this.sectionBottomName = ''
} else {
this.hideBottom = false
this.sectionBottomName = panel.name
}
},
closeMe(btn) {
if (btn === 'hideLeft') {
this.hideLeft = true
this.sectionLeftName = ''
} else if (btn === 'hideRight') {
this.hideRight = true
this.sectionRightName = ''
} else if (btn === 'hideBottom') {
this.hideBottom = true
this.sectionBottomName = ''
}
}
}
}
</script>