SafetyScreen-ui/src/views/Workbench/components/workbenchEdit.vue

846 lines
26 KiB
Vue

<template>
<div class="workbench-edit">
<!-- 头部操作区域 -->
<div class="workbench-header">
<div style="color: #878787; font-size: 16px; padding-left: 16px">
<i class="el-icon-warning" style="padding-right: 8px"></i>您可以对卡片进行添加移动删除等自定义操作
</div>
<div class="btn-list">
<el-button size="small" @click="handleClearPanel" style="font-size: 16px"
>清空面板</el-button
>
<el-button size="small" type="primary" @click="handleSubmit" style="font-size: 16px"
>保存</el-button
>
<el-button size="small" @click="handleExitEdit" style="font-size: 16px"
>退出编辑</el-button
>
</div>
</div>
<!-- 编辑整理内容区域 -->
<div class="workbench-container">
<div class="left-content" ref="gridLayoutRef">
<GridLayout
:layout.sync="layout"
:col-num="12"
:rowHeight="rowHeight"
:is-draggable="false"
:is-resizable="false"
:is-mirrored="false"
:vertical-compact="true"
:margin="[5, 5]"
>
<GridItem
v-for="item in layout"
:x="item.x"
:y="item.y"
:w="item.w"
:h="item.h"
:i="item.i"
:key="item.i"
class="gridItem"
>
<div :ref="`gridItem_${item.i}Ref`" class="item-box">
<component :is="item.componentName" />
</div>
<div class="delBtn" @click="delComponent(item)">
<i class="el-icon-delete" style="font-size: 24px;"></i>
</div>
</GridItem>
<GridItem
v-for="item in previewLayout"
:x="item.x"
:y="item.y"
:w="item.w"
:h="item.h"
:i="item.name"
:key="item.name"
class="gridItem-preview"
>
<div
class="item-box-preview"
:style="{
backgroundColor: item.isSuccess
? '#015912'
: '#F56C6C',
}"
>
预览
</div>
</GridItem>
</GridLayout>
</div>
<div class="right-list">
<el-input
placeholder="请输入内容"
suffix-icon="el-icon-search"
v-model="searchIpt"
style="margin-bottom: 15px; margin-top: 15px"
/>
<div
class="right-menu-item"
v-for="item in searchComp"
:key="item.id"
@drag="drag($event, item)"
@dragend="dragend($event, item)"
@mouseover="mouseover(item.id)"
@mouseout="mouseout()"
:class="[{ isPosition: item.id === isActiveId },{isGray: item.isPut == 1}]"
draggable="true"
>
<span>{{ item.name }}</span>
<span>{{ item.rigCont }}</span>
<div
:class="[
{ isShow: item.id === isActiveId },
'hover-items',
]"
>
<component :is="item.componentName" />
</div>
</div>
</div>
</div>
</div>
</template>
<script>
import VueGridLayout from 'vue-grid-layout'
import LeftOne from '@/components/home/leftOne.vue'
import LeftTwo from '@/components/home/leftTwo.vue'
import LeftThree from '@/components/home/leftThree.vue'
import LeftFive from '@/components/home/leftFive.vue'
import LeftSix from '@/components/home/leftSix.vue'
import LeftSeven from '@/components/home/leftSeven.vue'
import leftEight from '@/components/home/leftEight.vue'
import RightOne from '@/components/home/rightOne.vue'
import RightTwo from '@/components/home/rightTwo.vue'
import CountryMap from '@/components/home/countryMap.vue'
import {
queryTableApi,
editTableApi
} from '@/api/home/home'
export default {
components: {
GridLayout: VueGridLayout.GridLayout,
GridItem: VueGridLayout.GridItem,
LeftOne,
LeftTwo,
LeftThree,
RightOne,
RightTwo,
CountryMap,
LeftFive,
LeftSix,
LeftSeven,
leftEight
},
computed: {
searchComp() {
if(!this.searchIpt) {
return this.menuLayout
}
return this.menuLayout.filter(item => {
return item.name.includes(this.searchIpt)
})
}
},
mounted() {
this.getTableList()
this.rowHeight = (this.$refs['gridLayoutRef'].clientHeight - 56) / 12
},
beforeDestroy() {},
data() {
return {
searchIpt: undefined,
layout: [
// 第一行
{
x: 0,
y: 0,
w: 3,
h: 4,
i: 0,
isAccord: '1*1',
componentName: '',
},
{
x: 3,
y: 0,
w: 3,
h: 4,
i: 1,
isAccord: '1*1',
componentName: '',
},
{
x: 6,
y: 0,
w: 3,
h: 4,
i: 2,
isAccord: '1*1',
componentName: '',
},
{
x: 9,
y: 0,
w: 3,
h: 4,
i: 3,
isAccord: '1*1',
componentName: '',
},
// 第二行
{
x: 0,
y: 1,
w: 3,
h: 4,
i: 4,
isAccord: '1*1',
componentName: '',
},
{
x: 3,
y: 1,
w: 3,
h: 4,
i: 5,
isAccord: '1*1',
componentName: '',
},
{
x: 6,
y: 1,
w: 3,
h: 4,
i: 6,
isAccord: '1*1',
componentName: '',
},
{
x: 9,
y: 1,
w: 3,
h: 4,
i: 7,
isAccord: '1*1',
componentName: '',
},
// 第三行
{
x: 0,
y: 2,
w: 3,
h: 4,
i: 8,
isAccord: '1*1',
componentName: '',
},
{
x: 3,
y: 2,
w: 3,
h: 4,
i: 9,
isAccord: '1*1',
componentName: '',
},
{
x: 6,
y: 2,
w: 3,
h: 4,
i: 10,
isAccord: '1*1',
componentName: '',
},
{
x: 9,
y: 2,
w: 3,
h: 4,
i: 11,
isAccord: '1*1',
componentName: '',
},
],
layoutT: [
// 第一行
{
x: 0,
y: 0,
w: 3,
h: 4,
i: 0,
isAccord: '1*1',
componentName: '',
},
{
x: 3,
y: 0,
w: 3,
h: 4,
i: 1,
isAccord: '1*1',
componentName: '',
},
{
x: 6,
y: 0,
w: 3,
h: 4,
i: 2,
isAccord: '1*1',
componentName: '',
},
{
x: 9,
y: 0,
w: 3,
h: 4,
i: 3,
isAccord: '1*1',
componentName: '',
},
// 第二行
{
x: 0,
y: 1,
w: 3,
h: 4,
i: 4,
isAccord: '1*1',
componentName: '',
},
{
x: 3,
y: 1,
w: 3,
h: 4,
i: 5,
isAccord: '1*1',
componentName: '',
},
{
x: 6,
y: 1,
w: 3,
h: 4,
i: 6,
isAccord: '1*1',
componentName: '',
},
{
x: 9,
y: 1,
w: 3,
h: 4,
i: 7,
isAccord: '1*1',
componentName: '',
},
// 第三行
{
x: 0,
y: 2,
w: 3,
h: 4,
i: 8,
isAccord: '1*1',
componentName: '',
},
{
x: 3,
y: 2,
w: 3,
h: 4,
i: 9,
isAccord: '1*1',
componentName: '',
},
{
x: 6,
y: 2,
w: 3,
h: 4,
i: 10,
isAccord: '1*1',
componentName: '',
},
{
x: 9,
y: 2,
w: 3,
h: 4,
i: 11,
isAccord: '1*1',
componentName: '',
}
],
menuLayout: [
{
id: 1,
name: '边缘物联代理设备统计',
componentName: 'LeftOne',
w: 1,
h: 1,
isAccord: '1*1',
rigCont: '1*1',
isPut:"0"
},
{
id: 2,
name: '感知设备统计',
componentName: 'LeftTwo',
w: 1,
h: 1,
isAccord: '1*1',
rigCont: '1*1',
isPut:"0"
},
{
id: 3,
name: '工程信息',
componentName: 'LeftThree',
w: 1,
h: 1,
isAccord: '1*1',
rigCont: '1*1',
isPut:"0"
},
{
id: 4,
name: '安全隐患预测预警',
componentName: 'RightOne',
w: 1,
h: 1,
isAccord: '1*1',
rigCont: '1*1',
isPut:"0"
},
{
id: 5,
name: '施工风险实时预警',
componentName: 'RightTwo',
w: 1,
h: 1,
isAccord: '1*1',
rigCont: '1*1',
isPut:"0"
},
{
id: 6,
name: '地图',
componentName: 'CountryMap',
w: 2,
h: 2,
isAccord: '1*1',
rigCont: '2*2',
isPut:"0"
},
{
id: 7,
name: '环境检测',
componentName: 'LeftFive',
w: 3,
h: 1,
isAccord: '1*1',
rigCont: '1*3',
isPut:"0"
},
{
id: 8,
name: '组塔检测',
componentName: 'LeftSix',
w: 2,
h: 2,
isAccord: '1*1',
rigCont: '2*2',
isPut:"0"
},
{
id: 9,
name: '基坑检测',
componentName: 'LeftSeven',
w: 3,
h: 1,
isAccord: '1*1',
rigCont: '1*3',
isPut:"0"
},
{
id: 10,
name: '班组人员',
componentName: 'leftEight',
w: 1,
h: 1,
isAccord: '1*1',
rigCont: '1*1',
isPut:"0"
},
],
rowHeight: 0,
previewLayout: [],
itemPosition: null,
itemX: 0,
itemY: 0,
isActiveId: null,
}
},
methods: {
async getTableList() {
let res = await queryTableApi()
this.layout = res.data;
console.log(this.layout)
this.layout.forEach(item=>{
setTimeout(()=>{
let index2 = this.menuLayout.findIndex(v => v.componentName == item.componentName)
this.menuLayout[index2].isPut = "1"
},500)
})
},
handleClearPanel() {
this.$confirm('确认清空编辑面板, 是否继续?', '提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning'
}).then(() => {
// this.layout = this.layoutT.slice()
this.layout = [
// 第一行
{x: 0,y: 0,w: 3,h: 4,i: 0,isAccord: '1*1',componentName: '',},
{x: 3,y: 0,w: 3,h: 4,i: 1,isAccord: '1*1',componentName: '',},
{x: 6,y: 0,w: 3,h: 4,i: 2,isAccord: '1*1',componentName: '',},
{x: 9,y: 0,w: 3,h: 4,i: 3,isAccord: '1*1',componentName: '',},
// 第二行
{x: 0,y: 1,w: 3,h: 4,i: 4,isAccord: '1*1',componentName: '',},
{x: 3,y: 1,w: 3,h: 4,i: 5,isAccord: '1*1',componentName: '',},
{x: 6,y: 1,w: 3,h: 4,i: 6,isAccord: '1*1',componentName: '',},
{x: 9,y: 1,w: 3,h: 4,i: 7,isAccord: '1*1',componentName: '',},
// 第三行
{x: 0,y: 2,w: 3,h: 4,i: 8,isAccord: '1*1',componentName: '',},
{x: 3,y: 2,w: 3,h: 4,i: 9,isAccord: '1*1',componentName: '',},
{x: 6,y: 2,w: 3,h: 4,i: 10,isAccord: '1*1',componentName: '',},
{x: 9,y: 2,w: 3,h: 4,i: 11,isAccord: '1*1',componentName: '',}
]
this.$message({
type: 'success',
message: '清空完成!'
});
}).catch(() => {
// this.$message({
// type: 'info',
// message: '已取消'
// });
});
},
async handleSubmit() {
// 1. 掉后台接口
console.log(this.layout, '===============')
let res = await editTableApi(this.layout)
if(res.code === 200) {
this.$modal.msgSuccess('操作成功')
this.$emit('handleSubmit')
}
},
handleExitEdit() {
this.$emit('handleExitEdit')
},
drag(e, item) {
const { x, y } = e
this.itemX = x
this.itemY = y
this.itemPosition = item
},
dragend(e, item) {
let index = this.layout.findIndex(v => v.componentName === item.componentName)
console.log(index)
if(index>-1){
this.$message({
type: 'error',
message: '所选模块已存在,请先删除!'
});
this.previewLayout.splice(0, 1)
return
}else{
const { x, y } = e
let currentIndex = null
let currentItems = null
try {
this.layout.forEach((e, index) => {
const { left, right, top, bottom } = this.$refs[`gridItem_${e.i}Ref`][0].getBoundingClientRect()
if (x >= left && x <= right && y >= top && y <= bottom) {
// alert('当前所在行' + e.y + '当前所在列' + e.x)
currentIndex = index
currentItems = e
throw new Error()
}
})
} catch (error) {}
this.previewLayout.splice(0, 1)
if (!currentIndex && !currentItems) return
// console.log(item)
// console.log(currentIndex)
// console.log(currentItems)
// console.log(this.layout)
if(item.id==6||item.id==8){
if(currentIndex==3||currentIndex==7||currentIndex==8||currentIndex==9||currentIndex==10||currentIndex==11){
this.$message({
type: 'error',
message: '不支持当前位置!'
});
return
}
}
if(item.id==7||item.id==9){
if(currentIndex==2||currentIndex==3||currentIndex==6||currentIndex==7||currentIndex==10||currentIndex==11){
this.$message({
type: 'error',
message: '不支持当前位置!'
});
return
}
}
let index2 = this.menuLayout.findIndex(v => v.id === item.id)
this.menuLayout[index2].isPut = "1"
currentItems.w *= item.w
currentItems.h *= item.h
this.layout.splice(currentIndex, 1)
// if (currentIndex === 6 && item.h > 1) {
// this.layout.splice(3, 1)
// this.layout.splice(3, 0, currentItems)
// return
// }
// if (currentIndex === 7 && item.h > 1) {
// this.layout.splice(4, 1)
// this.layout.splice(4, 0, currentItems)
// return
// }
// if (currentIndex === 8 && item.h > 1) {
// this.layout.splice(5, 1)
// this.layout.splice(5, 0, currentItems)
// return
// }
if (currentItems.isAccord === item.isAccord) {
currentItems.componentName = item.componentName
}
this.layout.splice(currentIndex, 0, currentItems)
}
},
delComponent(item){
// console.log(item)
if(item.componentName!=""){
let obj = {
x: item.x,y: item.y,w: 3,h: 4,i: item.i,isAccord: '1*1',componentName: '',
}
this.layout.splice(item.i, 1, obj)
let index2 = this.menuLayout.findIndex(v => v.componentName == item.componentName)
this.menuLayout[index2].isPut = "0"
}
},
mouseover(id) {
this.isActiveId = id
},
mouseout() {
this.isActiveId = null
},
},
watch: {
itemX: {
handler(newValue, oldValue) {
if (newValue !== oldValue) {
try {
let preItem = null
this.layout.forEach((e) => {
const { left, right, top, bottom } =
this.$refs[
`gridItem_${e.i}Ref`
][0].getBoundingClientRect()
if (
newValue >= left &&
newValue <= right &&
this.itemY >= top &&
this.itemY <= bottom
) {
preItem = e
if (
preItem.isAccord ===
this.itemPosition.isAccord
) {
preItem.isSuccess = true
} else {
preItem.isSuccess = false
}
this.previewLayout.splice(0, 1)
this.previewLayout.splice(0, 0, preItem)
throw new Error()
}
})
} catch (error) {}
}
},
},
itemY: {
handler(newValue, oldValue) {
if (newValue !== oldValue) {
try {
let preItem = null
this.layout.forEach((e) => {
const { left, right, top, bottom } =
this.$refs[
`gridItem_${e.i}Ref`
][0].getBoundingClientRect()
if (
itemX >= left &&
itemX <= right &&
newValue >= top &&
newValue <= bottom
) {
preItem = e
if (
preItem.isAccord ===
this.itemPosition.isAccord
) {
preItem.isSuccess = true
} else {
preItem.isSuccess = false
}
this.previewLayout.splice(0, 1)
this.previewLayout.splice(0, 0, preItem)
throw new Error()
}
})
} catch (error) {}
}
},
},
},
}
</script>
<style lang="less" scoped>
.workbench-edit {
width: 100%;
height: 100%;
.workbench-header {
height: 68px;
display: flex;
justify-content: space-between;
align-items: center;
padding: 0 10px;
background-color: #f3f7ff;
}
.workbench-container {
height: calc(100% - 68px);
width: calc(100% - 10px);
display: grid;
grid-template-columns: 80% 20%;
grid-gap: 20px;
.left-content,
.right-list {
// border: 1px solid #000;
}
.left-content {
height: 100%;
}
.gridItem {
color: #fff;
background-color: #F3F7FF;
border: 1px solid #EFF2FC;
box-shadow: 3px 3px 3px #D9E0F3;
border-radius: 5px;
.item-box {
width: 100%;
height: 100%;
// background-color: #015912;
}
}
.item-box-preview {
width: 100%;
height: 100%;
}
.right-list {
padding: 0 10px;
.isPosition {
position: relative;
}
.isGray{
color: gray!important;
}
.hover-items {
display: none;
}
.isShow {
position: absolute;
top: 50px;
right: 0;
display: block;
width: 100%;
// border: 1px dashed #031e2c;
border-radius: 5px;
height: 300px;
background-color: #e4ecff;
box-shadow: 2px 2px #ccc;
}
}
.right-list .right-menu-item {
height: 46px;
margin-bottom: 8px;
padding-left: 8px;
padding-right: 8px;
line-height: 46px;
font-size: 18px;
color: #000;
border: 1px solid #ccc;
border-radius: 8px;
cursor: move;
display: flex;
align-items: center;
justify-content: space-between;
&:hover {
background-color: #9fc2f2;
}
}
.right-list .right-menu-item:first-child {
margin-top: 8px;
}
.delBtn{
position: absolute;
top: 20px;
right: 35px;
color: red;
cursor: pointer;
z-index: 999999;
}
}
}
</style>