Files
fad-dashboard/frontend/packages/BigScreenDesign/LeftPanel-old02.vue
2025-11-08 10:38:36 +08:00

553 lines
14 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="fixed-element">
<div class="graphic" draggable="true">
<div class="t-image__wrapper t-image__wrapper--shape-square">
<img :src="'https://assets.le5lecdn.com/png/2.5D-制冷站/冷却塔.svg'"
class="t-image t-image--fit-contain t-image--position-center" alt="" />
</div>
<p>冷却塔</p>
</div>
</div>
<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)">
<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 configurationComponents from 'data-room-ui/js/config/configurationComponentsConfig'
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: ''
}, {
id: 8,
name: 'configuration',
title: '组态',
icon: 'icon-zujian',
components: configurationComponents
}
],
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) => {
console.log('node: ', 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>