You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
606 lines
15 KiB
Vue
606 lines
15 KiB
Vue
<!--
|
|
* @description: 左侧组件列表
|
|
* @Date: 2022-05-24 15:35:07
|
|
* @Author: xingheng
|
|
-->
|
|
<template>
|
|
<transition name="slide-fade">
|
|
<div
|
|
class="bs-left-panel"
|
|
@click.stop
|
|
>
|
|
<div
|
|
:class="fold ? 'page-left page-left-fold' : 'page-left'"
|
|
:style="{ height }"
|
|
>
|
|
<el-tabs
|
|
v-model="activeName"
|
|
tab-position="left"
|
|
style="height: 200px"
|
|
class="left-tabs-box"
|
|
@tab-click="tabClick"
|
|
>
|
|
<el-tab-pane
|
|
name="default"
|
|
@click.native="changeActiveCode('')"
|
|
>
|
|
<span
|
|
slot="label"
|
|
class="menu-slot"
|
|
name="default"
|
|
@click="toggleSidebar"
|
|
>
|
|
<i
|
|
class="iconfont-bigscreen menu-icon"
|
|
:class="fold ? 'icon-zhankaicaidan' : 'icon-shouqicaidan'"
|
|
/>
|
|
<span class="menu-title-span">{{ foldText }}</span>
|
|
</span>
|
|
</el-tab-pane>
|
|
<el-tab-pane name="layer">
|
|
<div
|
|
slot="label"
|
|
class="menu-slot"
|
|
name="layer"
|
|
@dbclick="toggleSidebar"
|
|
>
|
|
<i
|
|
:class="['iconfont-bigscreen', 'icon-layer']"
|
|
class="menu-icon"
|
|
/>
|
|
<span class="menu-title-span">图层</span>
|
|
</div>
|
|
<div class="page-left-content">
|
|
<div class="page-left-content-title">
|
|
<div class="page-left-content-title-text">
|
|
图层
|
|
</div>
|
|
</div>
|
|
<div class="page-left-content-components">
|
|
<el-scrollbar>
|
|
<LayerList @openRightPanel="openRightPanel" />
|
|
</el-scrollbar>
|
|
</div>
|
|
</div>
|
|
</el-tab-pane>
|
|
<el-tab-pane
|
|
v-for="menu in menuList"
|
|
:key="menu.id"
|
|
:name="menu.name"
|
|
@click.stop.native="
|
|
fold = false
|
|
changeActiveCode('')
|
|
"
|
|
>
|
|
<div
|
|
slot="label"
|
|
class="menu-slot"
|
|
@dbclick="toggleSidebar"
|
|
>
|
|
<i
|
|
:class="['iconfont-bigscreen', menu.icon]"
|
|
class="menu-icon"
|
|
/>
|
|
<span class="menu-title-span">{{ menu.title }}</span>
|
|
</div>
|
|
<div class="page-left-content">
|
|
<div class="page-left-content-title">
|
|
<div class="page-left-content-title-text">
|
|
{{ menu.title }}
|
|
</div>
|
|
</div>
|
|
<el-scrollbar>
|
|
<div class="page-left-content-components">
|
|
<div class="draggable chat-list">
|
|
<div
|
|
v-for="element in menu.components"
|
|
:key="element.type + element.name"
|
|
:class="element.component
|
|
? 'item menu-component drag-node'
|
|
: 'item drag-node'
|
|
"
|
|
draggable="true"
|
|
:data-type="element.type"
|
|
:data-name="element.name"
|
|
>
|
|
<div class="component-name">
|
|
{{ element.title || element.name }}
|
|
</div>
|
|
<div
|
|
class="img_dispaly chooseDragNode"
|
|
@click.stop="addComponent(element)"
|
|
>
|
|
<!-- <svg
|
|
v-if="element.icon"
|
|
class="icon-svg"
|
|
aria-hidden="true"
|
|
>
|
|
<use :xlink:href="`#icon-a-${element.icon}`" />
|
|
</svg> -->
|
|
<icon-svg
|
|
v-if="element.icon"
|
|
:name="element.icon"
|
|
class="page-opt-list-icon"
|
|
/>
|
|
<img
|
|
v-else-if="element.img"
|
|
:src="element.img"
|
|
class="page-opt-list-img"
|
|
alt=""
|
|
>
|
|
<component
|
|
:is="element.component"
|
|
:key="new Date().getTime() + 1"
|
|
class="page-opt-list-component"
|
|
/>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</el-scrollbar>
|
|
</div>
|
|
</el-tab-pane>
|
|
</el-tabs>
|
|
</div>
|
|
</div>
|
|
</transition>
|
|
</template>
|
|
<script>
|
|
import cloneDeep from 'lodash/cloneDeep'
|
|
import basicComponents from 'data-room-ui/js/config/basicComponentsConfig'
|
|
import g2PlotComponents, { getCustomPlots } from '../G2Plots/plotList'
|
|
import echartsComponents from '../Echarts/echartList'
|
|
import borderComponents from 'data-room-ui/js/config/borderComponentsConfig'
|
|
import decorationComponents from 'data-room-ui/js/config/decorationComponentsConfig'
|
|
import LayerList from './LayerList/index.vue'
|
|
import { mapMutations } from 'vuex'
|
|
import IconSvg from 'data-room-ui/SvgIcon'
|
|
import { customSerialize } from 'data-room-ui/js/utils/jsonSerialize.js'
|
|
export default {
|
|
name: 'PageLeftPanel',
|
|
components: {
|
|
LayerList,
|
|
IconSvg
|
|
},
|
|
props: {
|
|
headerShow: {
|
|
type: Boolean,
|
|
default: true
|
|
},
|
|
height: {
|
|
type: String,
|
|
default: '100vh'
|
|
}
|
|
},
|
|
data () {
|
|
return {
|
|
echartsComponents,
|
|
g2PlotComponents,
|
|
activeName: 'chart', // 设置左侧tab栏的默认值
|
|
fold: false, // 控制左侧菜单栏伸缩
|
|
currentTab: 'basic',
|
|
menuList: [
|
|
{
|
|
id: 1,
|
|
name: 'chart',
|
|
title: '基础',
|
|
icon: 'icon-zujian',
|
|
components: basicComponents
|
|
},
|
|
{
|
|
id: 2,
|
|
name: 'g2PlotComponents',
|
|
title: '图表',
|
|
icon: 'icon-jichushuju',
|
|
components: this.g2PlotComponents
|
|
},
|
|
{
|
|
id: 7,
|
|
name: 'echart',
|
|
title: '3D',
|
|
icon: 'icon-jichushuju',
|
|
components: this.echartsComponents
|
|
},
|
|
{
|
|
id: 3,
|
|
name: 'dataV',
|
|
title: '边框',
|
|
icon: 'icon-border-outer',
|
|
components: borderComponents
|
|
},
|
|
{
|
|
id: 4,
|
|
name: 'decoration',
|
|
title: '装饰',
|
|
icon: 'icon-a-1',
|
|
components: decorationComponents
|
|
},
|
|
{
|
|
id: 5,
|
|
name: 'source',
|
|
title: '资源',
|
|
icon: 'icon-tupian',
|
|
components: []
|
|
},
|
|
{
|
|
id: 6,
|
|
name: 'component',
|
|
title: '组件',
|
|
icon: 'icon-zujian1',
|
|
components: ''
|
|
}
|
|
],
|
|
currentActive: 'chart'
|
|
}
|
|
},
|
|
computed: {
|
|
// 获取当前类型的组件
|
|
currentComponentList () {
|
|
return this.componentList.filter((item) => item.type === this.currentTab)
|
|
},
|
|
foldText () {
|
|
return this.fold ? '展开' : '收起'
|
|
}
|
|
},
|
|
watch: {
|
|
fold (isExpand) {
|
|
if (isExpand && this.activeName === 'default') {
|
|
this.activeName = 'chart'
|
|
}
|
|
}
|
|
},
|
|
created () {
|
|
this.initList()
|
|
this.g2PlotComponents = [...this.g2PlotComponents, ...getCustomPlots()]
|
|
this.menuList[1].components = this.g2PlotComponents
|
|
this.menuList[2].components = this.echartsComponents
|
|
},
|
|
mounted () {
|
|
this.nodeDrag()
|
|
},
|
|
methods: {
|
|
...mapMutations('bigScreen', ['changeActiveCode']),
|
|
nodeDrag () {
|
|
this.$nextTick(() => {
|
|
const nodes = document.querySelectorAll('.drag-node')
|
|
nodes.forEach((node) => {
|
|
node.addEventListener('dragstart', (event) => {
|
|
const type = node.getAttribute('data-type')
|
|
const name = node.getAttribute('data-name')
|
|
// 从menuList中获取当前拖拽的组件
|
|
const element = this.menuList
|
|
.find((item) => item.name === this.activeName)
|
|
?.components.find(
|
|
(item) => item.type === type && item.name === name
|
|
)
|
|
/* 设置拖拽传输数据 */
|
|
event.dataTransfer.setData(
|
|
'dragComponent',
|
|
customSerialize({
|
|
...element,
|
|
offsetX: event.offsetX,
|
|
offsetY: event.offsetY
|
|
})
|
|
)
|
|
})
|
|
})
|
|
// 阻止默认动作
|
|
document.addEventListener(
|
|
'drop',
|
|
(e) => {
|
|
e.preventDefault()
|
|
},
|
|
false
|
|
)
|
|
})
|
|
},
|
|
onClone (e) {
|
|
return cloneDeep(e)
|
|
},
|
|
onStart (e) {
|
|
// this.$emit('onStart', e)
|
|
},
|
|
// 拖拽组件时触发
|
|
onEnd (e) { },
|
|
// 点击左侧组件时触发
|
|
addComponent (element) {
|
|
this.$store.commit('bigScreen/changeActiveItem', element)
|
|
this.$emit('addComponent', element)
|
|
},
|
|
// 初始化
|
|
initList () { },
|
|
// 点击tab标签
|
|
tabClick (tab) {
|
|
this.nodeDrag()
|
|
if (tab.index !== '0') {
|
|
this.fold = false
|
|
this.currentActive = this.activeName
|
|
}
|
|
if (tab.name === 'source') {
|
|
this.fold = true
|
|
this.$emit('toggleLeftSidebar')
|
|
this.$emit('openResource')
|
|
this.$emit('toggleLeftSidebar')
|
|
}
|
|
if (tab.name === 'component') {
|
|
this.fold = true
|
|
this.$emit('toggleLeftSidebar')
|
|
this.$emit('openComponent')
|
|
}
|
|
},
|
|
toggleSidebar () {
|
|
this.fold = !this.fold
|
|
this.$emit('toggleLeftSidebar')
|
|
setTimeout(() => {
|
|
this.activeName = this.currentActive
|
|
})
|
|
},
|
|
openRightPanel (config) {
|
|
this.$emit('openRightPanel', config)
|
|
}
|
|
}
|
|
}
|
|
</script>
|
|
|
|
<style lang="scss" scoped>
|
|
@import '../BigScreenDesign/fonts/iconfont.css';
|
|
|
|
.bs-left-panel {
|
|
display: flex;
|
|
background-color: var(--bs-background-1);
|
|
|
|
.bs-folder-wrap {
|
|
width: 20px;
|
|
position: relative;
|
|
|
|
i {
|
|
position: absolute;
|
|
top: 50%;
|
|
left: 0;
|
|
transform: translateY(-50%);
|
|
font-size: 20px;
|
|
color: #fff;
|
|
cursor: pointer;
|
|
z-index: 1;
|
|
}
|
|
|
|
&:hover {
|
|
background: rgba(143, 225, 255, 0.1);
|
|
}
|
|
}
|
|
|
|
.page-left {
|
|
box-sizing: border-box;
|
|
|
|
>* {
|
|
color: #fff;
|
|
}
|
|
|
|
.iconfont-bigscreen {
|
|
color: #fff;
|
|
}
|
|
|
|
.flexible {
|
|
width: 45px;
|
|
/* border-right: 1px solid #ccc; */
|
|
text-align: center;
|
|
}
|
|
|
|
.el-tabs {
|
|
width: 250;
|
|
position: relative;
|
|
height: 100% !important;
|
|
overflow: visible;
|
|
|
|
.is-active {
|
|
.iconfont-bigscreen {
|
|
color: var(--bs-el-color-primary);
|
|
}
|
|
|
|
.menu-title-span {
|
|
color: var(--bs-el-color-primary);
|
|
}
|
|
}
|
|
|
|
.el-tab-pane {
|
|
height: 100%;
|
|
}
|
|
|
|
.page-left-content {
|
|
height: 100%;
|
|
}
|
|
|
|
::v-deep .el-tabs__content {
|
|
height: 100%;
|
|
width: 160px;
|
|
|
|
.page-left-content-title {
|
|
background-color: var(--bs-background-2);
|
|
color: var(--bs-el-title);
|
|
font-size: 14px;
|
|
margin: 8px;
|
|
padding: 8px 0;
|
|
|
|
.page-left-content-title-text {
|
|
/*border-left: 4px solid #007aff;*/
|
|
position: relative;
|
|
padding-left: 12px;
|
|
|
|
&:after {
|
|
position: absolute;
|
|
left: 0;
|
|
top: 50%;
|
|
transform: translateY(-50%);
|
|
content: '';
|
|
width: 4px;
|
|
height: 14px;
|
|
background-color: var(--bs-el-color-primary);
|
|
}
|
|
}
|
|
}
|
|
|
|
.el-scrollbar__view {
|
|
height: calc(100vh - 55px);
|
|
}
|
|
|
|
.page-left-content-components {
|
|
width: 100%;
|
|
text-align: center;
|
|
padding-bottom: 20px;
|
|
margin-bottom: 20px;
|
|
|
|
.draggable {
|
|
display: flex;
|
|
flex-wrap: wrap;
|
|
cursor: pointer;
|
|
box-sizing: border-box;
|
|
justify-content: center;
|
|
padding: 8px;
|
|
cursor: move;
|
|
|
|
.item {
|
|
width: 100%;
|
|
background: var(--bs-background-2);
|
|
margin-bottom: 8px;
|
|
|
|
.component-name {
|
|
background: var(--bs-el-background-3);
|
|
color: var(--bs-el-title);
|
|
font-size: 12px;
|
|
padding: 4px 8px;
|
|
text-align: left;
|
|
}
|
|
|
|
.sampleImg {
|
|
margin: 0 auto;
|
|
width: 102px;
|
|
height: 73px;
|
|
display: block;
|
|
}
|
|
|
|
.img_dispaly {
|
|
padding: 8px 0;
|
|
margin: 0 auto;
|
|
text-align: center;
|
|
width: 120px;
|
|
|
|
.icon-svg {
|
|
width: 60px !important;
|
|
height: 60px !important;
|
|
vertical-align: -0.15em;
|
|
fill: currentColor;
|
|
overflow: hidden;
|
|
}
|
|
|
|
img {
|
|
height: 60px;
|
|
max-width: 100%;
|
|
}
|
|
}
|
|
}
|
|
|
|
.menu-component {
|
|
.page-opt-list-component {
|
|
width: 102px;
|
|
height: 75px;
|
|
margin: 0 auto;
|
|
}
|
|
|
|
.img_dispaly {
|
|
height: 80px;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
::v-deep .el-tabs__header {
|
|
width: 45px;
|
|
height: 100%;
|
|
margin-right: 0 !important;
|
|
}
|
|
|
|
::v-deep .el-tabs--left .el-tabs__nav-wrap.is-left::after {
|
|
width: 0 !important;
|
|
}
|
|
|
|
.el-tabs__active-bar {
|
|
transform: none !important;
|
|
height: 0 !important;
|
|
}
|
|
|
|
.el-tabs__nav-wrap.is-left::after {
|
|
left: 0;
|
|
}
|
|
|
|
.el-tabs__nav-wrap {
|
|
height: 100%;
|
|
/* border-right: 1px solid #ccc; */
|
|
}
|
|
|
|
::v-deep .el-tabs__nav-scroll {
|
|
background-color: var(--bs-background-2);
|
|
}
|
|
}
|
|
|
|
.page-left-fold {
|
|
width: 45px;
|
|
overflow: hidden;
|
|
/* border-right: 1px solid #ccc; */
|
|
|
|
.el-tabs__content {
|
|
border: none;
|
|
}
|
|
}
|
|
|
|
.left-tabs-box {
|
|
::v-deep .el-tabs__item {
|
|
height: 70px !important;
|
|
|
|
.menu-slot {
|
|
height: 100%;
|
|
display: flex;
|
|
justify-content: center;
|
|
align-items: center;
|
|
flex-wrap: wrap;
|
|
color: #bcc9d4;
|
|
|
|
.menu-icon {
|
|
height: 20px;
|
|
}
|
|
|
|
.menu-title-span {
|
|
display: block;
|
|
width: 100%;
|
|
font-size: 12px;
|
|
text-align: center;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
.slide-fade-enter-active {
|
|
transition: all 0.3s ease;
|
|
}
|
|
|
|
.slide-fade-leave-active {
|
|
transition: all 0.8s cubic-bezier(1, 0.5, 0.8, 1);
|
|
}
|
|
|
|
.slide-fade-enter,
|
|
.slide-fade-leave-to
|
|
|
|
/* .slide-fade-leave-active for below version 2.1.8 */
|
|
{
|
|
transform: translateX(10px);
|
|
opacity: 0;
|
|
}
|
|
|
|
::v-deep .el-tabs__item.is-left {
|
|
text-align: center;
|
|
padding: 0;
|
|
}
|
|
</style>
|