如下图所有,有个需求更新, 实现拖拽。
1,当新增了测点类型的时候每个对应的回路子数据都会新增对应的测点类型。
2,当拖动测点类型结束的时候对应的回路里面的内容也会跟着测点类型的排序自动排序
其实很简单,只要会了拖拽,然后再定的数据处理里面加上对应的处理逻辑就好了。
我这边直接展示代码了。
template>
<div class="box">
<div class="assembly-wrap">
<div class="assembly-div">
<div class="assemblyimg">
<img v-show="Number(dataInfos.assembly.value) === 1" src="../../../assets/images/switch/onAssembly.png" alt="">
<img v-show="Number(dataInfos.assembly.value) !== 1" src="../../../assets/images/switch/assembly.png" alt="">
</div>
<div class="flexCloum">
<div class="title" :class="{'title2': dataInfos.title.position === 2}">
{{ dataInfos.title.value }}
</div>
<div v-show="dataInfos.networkVoltageFlag" class="network-voltage" :class="{'title2': dataInfos.title.position === 2}">电网电压 <span>{{ dataInfos?.networkVoltageInfo?.value }} v </span></div>
</div>
<div class="switch-line"></div>
<div class="switch-wrap">
<div v-for="(item, i) in dataInfos.loopList" :key="i" class="switch-row">
<div class="loop">回路{{ i+1 }}</div>
<div v-show="Number(item.value) === 1" class="loopimgwrap">
<img class="loopimg1" src="../../../assets/images/switch/on.png" alt="">
</div>
<img v-show="Number(item.value) !== 1" :class="{'loopimg2': i+1 !== dataInfos.loopList.length}" src="../../../assets/images/switch/off.png" alt="">
<div class="label" :class="{'label2': item.value !== 1}" :title="item.label">{{ item.label }}</div>
<div class="switchmine">
<div v-for="(item2, i) in item.list" :key="i">
<span @dblclick="triggerDblclick(item, item2)">{{ item2.value | isNull }}{{ item2.unit }}</span>
</div>
</div>
</div>
</div>
<div class="labellist">
<div v-for="(item, i) in dataInfos.options" :key="i">
<el-tooltip v-if="item.label.length > 4 " class="item" effect="dark" :content="item.label" placement="top">
<span>{{ item.label }}</span>
</el-tooltip>
<span v-else>{{ item.label }}</span>
</div>
</div>
</div>
</div>
<zmjdialog ref="zmjdialog" top="10vh" width="1000px" @confirm="confirm" @cancel="cancel" >
<el-form ref="ruleForm" :model="formData" label-width="150px">
<div class="df">
<!-- :rules="[{ required: true, message: '请输入测点', trigger: ['blur', 'change'] }]" -->
<el-form-item
label="组件标题"
>
<el-input v-model="formData.title.value" placeholder="请输入组件标题">
</el-input>
</el-form-item>
<el-form-item
label="标题位置"
>
<el-radio v-model="formData.title.position" :label="1">左</el-radio>
<el-radio v-model="formData.title.position" :label="2">右</el-radio>
</el-form-item>
</div>
<div class="df" >
<!-- :label="`${formData.title.value}测点`" -->
<el-form-item
label="测点"
>
<el-input v-model="formData.assembly.site" placeholder="请输入标题测点">
</el-input>
</el-form-item>
</div>
<div class="df" >
<el-form-item
label="电网电压"
>
<el-switch v-model="formData.networkVoltageFlag" />
</el-form-item>
</div>
<div class="df" v-show="formData.networkVoltageFlag">
<el-form-item
label="电网电压测点"
>
<el-input v-model="formData.networkVoltageInfo.site" placeholder="请输入电网电压测点">
</el-input>
</el-form-item>
</div>
<div class="pump-list">
<div class="title">
<span>回路</span>
<ul>
<!-- <li @click="pumpcancel">取消</li> -->
<li @click="addpump">添加回路</li>
</ul>
</div>
<div class="df site-wrap" style="margin-top: 20px;">
<el-form-item
label-width="100px"
label="测点类型"
>
<el-input v-model="sitetypes" placeholder="请输入测点类型">
</el-input>
</el-form-item>
<div class="addsitetype" @click="addsitetype()">添加测点类型</div>
</div>
<div class="optionsList">
<div v-for="(item, i) in formData.options"
:key="i"
draggable="true"
@dragstart="dragStart(i, item)"
@dragover.prevent="dragOver(i)"
@dragend="dragEnd()"
>
{{ item.label }}
<i class="el-tag__close el-icon-close" @click="optionclose(i)"></i>
</div>
</div>
<div class="ulmine">
<el-collapse v-model="activeNames" @change="handleChange">
<el-collapse-item v-for="(item, i) in formData.loopList" :key="i" :name="i">
<template slot="title">
回路{{ i+1 }}
<div class="pumpdelete" @click.stop="pumpdelete(i)">删除</div>
</template>
<div class="ulmine-div">
<!-- <div class="addpumpsite" @click="addpumpsite(i)">添加测点</div> -->
<div class="df">
<el-form-item
label-width="100px"
label="回路名称"
>
<el-input v-model="item.label" placeholder="请输入名称">
</el-input>
</el-form-item>
<el-form-item
label-width="120px"
label="回路测点"
>
<el-input v-model="item.site" placeholder="请输入测点">
</el-input>
</el-form-item>
</div>
<div v-for="(item2, j) in item.list"
:key="j"
draggable="true"
ref="optionsRef"
>
<div class="df">
<el-form-item
label-width="100px"
label="测点类型:"
>
<div class="typetext">{{ item2.type }}</div>
</el-form-item>
<el-form-item
label-width="50px"
label="测点"
>
<el-input v-model="item2.site" :style="{width: '120px'}" placeholder="请输入测点">
</el-input>
</el-form-item>
<el-form-item
label-width="80px"
label="单位"
>
<el-input v-model="item2.unit" :style="{width: '120px'}" placeholder="请输入单位">
</el-input>
</el-form-item>
<el-form-item label-width="20px" label="" class="ponits_value">
<el-radio v-model="item2.state" :label="1">初始值</el-radio>
<el-radio v-model="item2.state" :label="2">转换值</el-radio>
</el-form-item>
<div v-show="item2.state === 2">
<div class="add_point conversion" @click="addConversion(item2)">添加转换值</div>
</div>
</div>
<div v-show="item2.state === 2">
<div v-for="(item3,indexs) in item2.children" :key="indexs">
<div class="points_items" style="margin-bottom:20px">
<el-form-item label-width="100px" label="转换标识">
<el-input v-model="item3.value" placeholder="转换标识"></el-input>
</el-form-item>
<el-form-item label-width="100px" label="转换值">
<el-input v-model="item3.label" placeholder="转换值"></el-input>
</el-form-item>
<i class="el-icon-remove" style="margin-left:30px;font-size:25px;cursor: pointer;" @click="deleteConversion(item2,indexs)"></i>
</div>
</div>
</div>
<!-- <div class="el-icon-remove" @click="deletepumpsite(i,j)"></div> -->
</div>
</div>
</el-collapse-item>
</el-collapse>
</div>
</div>
</el-form>
</zmjdialog>
<zmjdialog ref="childInfoDialog" width="850px" top="30vh" :title="`${label}&${labelItem}历史数据`" @confirm="childInfoDialog">
<zmj-echarts :ref="`historicalLineEcharts${chartId}`" :echarts-id="`historicalLineEcharts${chartId}`" :height="'200px'"></zmj-echarts>
</zmjdialog>
</div>
</template>
<script>
import ZmjEcharts from '@/components/zmjEcharts.vue'
import { shearerOptions } from '../../components/echarts/Historicalline.js'
export default {
components: {ZmjEcharts},
props: {
dataInfo:{
type: Object,
default (){
return {
}
}
}
},
data () {
return {
sitetypes: null,
formData: {},
activeNames: [0],
dataInfos: {},
groupName: '', // 测点大类
dataName: '', // 测名称
deviceIdList: 1, // 设备号
label: null,
labelItem: null,
chartId: `Id${new Date().getTime()}`,
dragStartIndex: '',
dragStartData: '',
copyStartData:''
}
},
watch: {
dataInfo: {
immediate: true,
deep: true,
handler (val) {
this.formData = JSON.parse(JSON.stringify(val))
this.dataInfos = JSON.parse(JSON.stringify(val))
// 处理后加入字段
this.formData.loopList.forEach(v => {
v.list&&v.list.forEach(v2 => {
if(!v2.state){
v2.state = 1
}
if(!v2.children){
v2.children = []
}
})
})
console.log(this.formData, 'this.formData')
}
}
},
computed: {},
created () {},
filters: {
isNull (val) {
return val === null ? '--' : val
}
},
mounted () {
window.$eventBus.$on('wsMessage', message => {
let dataType = message.dataType
// message.data.forEach(val => {})
for(let i in this.dataInfos){
if(i === 'loopList'){
this.dataInfos[i].forEach(v => {
if(this.sifn(v.site) === dataType){
this.messagefn(message.data, v)
}
v.list && v.list.forEach(v2 => {
if(this.sifn(v2.site) === dataType){
this.messagefn(message.data, v2)
}
})
})
}
if(i === 'assembly'){
if(this.sifn(this.dataInfos[i].site) === dataType){
this.messagefn(message.data, this.dataInfos[i])
}
}
if(i === 'networkVoltageInfo'){
if(this.sifn(this.dataInfos[i].site) === dataType){
this.messagefn(message.data, this.dataInfos[i])
}
}
}
})
},
beforeDestroy () {
window.$eventBus.$off('wsMessage')
},
methods: {
// 拖拽逻辑在这里。
dragStart (index, item) {
console.log(index, item);
this.dragStartIndex = index
this.dragStartData = item
// 拿到测点类型 的第 index 个 数据对应的list
this.formData.loopList.forEach(item => {
this.copyStartData = item.list[index]
})
},
// 只要拖拽元素进入到放置区域就触发,这里实际是鼠标指针进入放置区域才触发
dragOver (index) {
this.dragOverIndex = index
},
// 结束拖拽逻辑的时候进行对应的子向排序。
dragEnd () {
const copyTodolist = [...this.formData.options]
// 删除老的节点
copyTodolist.splice(this.dragStartIndex, 1)
// 在列表中目标位置增加新的节点
copyTodolist.splice(this.dragOverIndex, 0, this.dragStartData)
// ... 上边是测点类型的排序,结束后对应的回路跟着类型调整位置
this.formData.options = [...copyTodolist] // 获取测点类型调整后的顺序
// console.log('drag end', this.formData.loopList, '所有的对应类型loopList');
this.formData.loopList.map((item, v) => {
const copyList = [...item.list] // 所有的对应类型loopList的对应测点list
// 删除对应的老的节点
copyList.splice(this.dragStartIndex, 1)
// 在列表中目标位置增加新的节点
copyList.splice(this.dragOverIndex, 0, this.copyStartData)
return item.list = [...copyList]
})
this.dragOverIndex = ''
},
// '双击事件 展示折线图
triggerDblclick (info, info2) {
console.log(info, info2, '双击事件');
this.$refs.childInfoDialog.open()
this.label = info.label
this.labelItem = info2.type
if(info2.site){
let arr = info2?.site?.split('/') || []
console.log(arr);
this.groupName = `${arr[0]}` // 测点大类
this.deviceIdList = `${arr[1]}` // 设备号
this.dataName = `${arr[2]}` // 测名称
}
let params = {
workFaceCode: window.$getStorage('workFaceInfo').workFaceCode,
startTime: window.$dayjs().format('YYYY-MM-DD 00:00:00'),
endTime: window.$dayjs().add(1, 'day').format('YYYY-MM-DD 00:00:00'),
aggregateType : 'none', // 聚合类型 传none获取原始历史值
groupName: this.groupName, // 测点大类
dataName: this.dataName, // 测名称
deviceIdList: this.deviceIdList // 设备号
}
let thisDataList = null
window.$axiosGet('deviceHistory', params).then((res) => {
if(!res.length){
this.$refs[`historicalLineEcharts${this.chartId}`] && this.$refs[`historicalLineEcharts${this.chartId}`].upDataEcharts(shearerOptions(res || [], params, this.dataInfos))
return
}
thisDataList = res.map(item => {
return item.data
})
this.$nextTick(() => {
this.$refs[`historicalLineEcharts${this.chartId}`] && this.$refs[`historicalLineEcharts${this.chartId}`].getEchartsLiving();
this.$refs[`historicalLineEcharts${this.chartId}`] && this.$refs[`historicalLineEcharts${this.chartId}`].upDataEcharts(shearerOptions(thisDataList || [], params, this.dataInfos))
})
}).catch(() => {
this.$refs[`historicalLineEcharts${this.chartId}`] && this.$refs[`historicalLineEcharts${this.chartId}`].upDataEcharts(shearerOptions(thisDataList || [], params, this.dataInfos))
})
},
childInfoDialog () {
this.$refs.childInfoDialog.close()
},
messagefn (e, v){
e.forEach(val => {
if(val.deviceId === this.sifn(v.site, 2)){
v.value = val.value
if(v.state === 2){
v.children&&v.children.forEach(v2 => {
if(String(val.value) === String(v2.value)){
v.value = v2.label
}
})
}
}
})
},
sifn (v, i = 1) {
if(v){
let arr = v.split('/')
if(arr.length === 3){
if(i === 1){
return `${arr[0]}_${arr[2]}`
}else if(i === 2) {
return Number(arr[1])
}
}else{
return v
}
}else{
return v
}
},
deleteConversion (items, indexs){
items.children.splice(indexs, 1)
},
// 添加转换值
addConversion (item){
item.children?.push({
label:'',
value:''
})
},
handleChange (val) {
console.log(val)
},
// 回路删除
pumpdelete (i) {
if(this.formData.loopList.length <= 2){
this.$message.warning('回路最少有2个')
return
}
this.formData.loopList.splice(i, 1)
},
// 添加回路
addpump () {
this.formData.loopList.push(
{
site: null,
value: null,
label: null,
list: this.formData.options.map(v => {
return {
site: null,
value: null,
type: v.label,
unit: null,
state: 1,
children: []
}
})
}
)
},
// 回路类型添加
addsitetype () {
if(this.sitetypes === '' || this.sitetypes === null|| this.sitetypes === undefined){
return this.$message.warning('请添加测点类型')
}
this.formData.options.push({label: this.sitetypes})
this.formData.loopList.forEach(v => {
v.list.push({
site: null,
value: null,
type: this.sitetypes,
unit: null,
state: 1,
children: []
})
})
this.sitetypes = ''
},
// 回路类型添加删除
optionclose (i) {
this.formData.options.splice(i, 1)
this.formData.loopList.forEach(v => {
v.list.splice(i, 1)
})
},
// 乳化泵测点添加
// addpumpsite (i) {
// this.formData.loopList[i].list.push({
// site: null,
// value: null,
// type: null,
// unit: null
// })
// },
// 乳化泵测点删除
// deletepumpsite (i, j) {
// this.formData.loopList[i].list.splice(j, 1)
// },
edit () {
// this.formData = window.$utils.cloneDeep(this.formData)
this.$refs.zmjdialog.open()
},
confirm (){
this.dragStartIndex = '';
this.$refs.ruleForm.validate((valid) => {
if (valid) {
this.$refs.zmjdialog.close()
// let arr = [ this.formData.assembly.site, this.formData.networkVoltageInfo.site]
let arr = [ this.formData.assembly.site]
this.formData.loopList.forEach(v => {
arr.push(v.site)
v.list && v.list.forEach(v2 => {
arr.push(v2.site)
})
})
let newArr = []
newArr.push(this.formData.networkVoltageInfo.site, ...arr)
this.$emit('update:dataTypeList', newArr)
this.$emit('update:dataInfo', this.formData)
this.$message.success('保存成功')
} else {
return false
}
})
},
cancel () {
this.dragStartIndex = '';
console.log('取消')
}
}
}
</script>
<style lang="scss" scoped>
.box{
padding-top: 20px;
font-size: 14px;
}
.assembly-wrap{
border: 1px solid #707070;
border-radius: 2px;
width: 100%;
height: 100%;
}
.assembly-div{
width: calc(100% - 80px);
margin-left: 80px;
position: relative;
.assemblyimg{
width: 95%;
position: relative;
>img{
position: absolute;
top: -20px;
left: 50%;
margin-left: -32px;
}
}
.network-voltage{
position: absolute;
top: 60px;
font-size: 12px;
width: 60%;
left: -20%;
text-align: right;
padding: 0 60px 0 0;
span{
margin-left: 10px;
color: #31E8B4;
}
}
.flexCloum{
display: flex;
flex-direction: column;
}
.title{
position: absolute;
top: 30px;
font-size: 20px;
color: #FFBB00;
width: 60%;
left: -10%;
text-align: right;
padding:0 60px 0 0;
}
.title2{
text-align: left;
width: 50%;
padding:0 0 0 30px;
left: auto;
right: 0;
}
.switch-line{
width: calc(95% - 11px);
height: 2px;
position: absolute;
top: 102px;
left: 5px;
background: #31E8B4;
}
.switch-wrap{
position: absolute;
top: 104px;
width: 95%;
display: flex;
justify-content: space-between;
.switch-row{
position: relative;
.loopimgwrap{
width: 21px;
}
.loopimg2{
position: relative;
left: -8px;
}
}
.switch-row:last-child{
.loopimg1{
position: relative;
left: 4px;
}
}
.switch-row:first-child{
.loopimg1{
position: relative;
left: -7px;
}
}
.loop{
position: absolute;
width: 70px;
text-align: left;
top: -25px;
}
.label{
position: absolute;
width:70px;
bottom: -40px;
left: -31px;
}
.label2{
left: -22px;
// height: 40px;
// line-height: 16px;
// overflow: hidden;
// text-overflow: ellipsis;
// white-space: nowrap;
}
.switchmine{
position: absolute;
top: 160px;
left: -25px;
>div{
width: 70px;
line-height: 20px;
height: 20px;
margin-bottom: 10px;
color: #31E8B4;
}
}
}
.labellist{
position: absolute;
left: -80px;
top: 264px;
line-height: 20px;
>div{
width: 60px;
overflow: hidden;
white-space:nowrap;
text-overflow: ellipsis;
margin-bottom: 10px;
}
}
}
.pump-list{
position: relative;
color: #fff;
border:1px solid #999;
border-radius: 5px;
.title{
display: flex;
justify-content: space-between;
align-items: center;
padding: 0 16px;
width: 100%;
height: 36px;
background: rgba(238, 238, 238, 0.08);
border-bottom: 1px solid #314150;
box-sizing: border-box;
ul{
display: flex;
li{
margin-left: 8px;
width: 64px;
line-height: 24px;
font-size: 14px;
text-align: center;
border-radius: 3px;
user-select: none;
cursor: pointer;
}
// >li:nth-child(1){
// border: 1px solid rgba(255, 255, 255, 0.24);
// }
>li:nth-child(1){
border: 1px solid #0088FF;
}
}
}
.ulmine{
padding:0 20px 10px 20px;
height: 400px;
overflow: hidden;
overflow-y: scroll;
.ulmine-div{
position: relative;
padding: 15px 0;
}
.el-icon-remove{
cursor: pointer;
height: 36px;
line-height: 36px;
font-size: 20px;
padding-left: 15px;
color: #999;
}
.pumpdelete{
width: 64px;
line-height: 24px;
font-size: 14px;
text-align: center;
border-radius: 3px;
cursor: pointer;
border: 1px solid #B23B3B;
margin-left: 620px;
}
.addpumpsite{
position: absolute;
line-height: 24px;
font-size: 14px;
text-align: center;
border-radius: 3px;
cursor: pointer;
right: 10px;
top: 20px;
width: 84px;
right: 30px;
border: 1px solid #0088FF;
}
::v-deep{
.el-collapse{
border: none;
}
.el-collapse-item__header{
padding-left: 20px;
background: transparent;
color: #fff;
border-bottom:none;
background: rgba(238, 238, 238, 0.08);
}
.el-collapse-item__wrap{
background: transparent;
border-bottom: 1px dashed #7a7d80;
}
.el-collapse-item__content{
color: #fff;
padding-bottom: 0;
}
}
}
.ulmine::-webkit-scrollbar {
display: none;
}
}
.addsitetype{
position: absolute;
line-height: 24px;
font-size: 14px;
text-align: center;
border-radius: 3px;
cursor: pointer;
top: 62px;
width: 104px;
left: 370px;
border: 1px solid #0088FF;
}
.optionsList{
display: flex;
flex-wrap:wrap;
padding-bottom: 5px;
margin-left: 80px;
>div{
margin-left: 20px;
background-color: #f4f4f5;
border-color: #e9e9eb;
color: #909399;
padding:7px 12px;
border-radius: 4px;
position: relative;
margin-bottom: 10px;
.el-tag__close{
color: #909399;
background-color: #c0c4cc;
border-radius: 50%;
font-size: 15px;
text-align: center;
margin-left: 5px;
cursor: pointer;
}
}
}
.site-wrap{
::v-deep{
.el-form-item{
margin-bottom: 10px;
}
}
}
.typetext{
width: 100px;
overflow: hidden;
}
.add_point{
display: inline-block;
margin-left: 30px;
width: 80px;
height: 32px;
border-radius: 4px;
font-size: 14px;
color: #fff;
line-height: 30px;
border: 1px solid #409EFF;
cursor: pointer;
text-align: center;
user-select: none;
}
.conversion{
margin-left: 20px;
margin-top: 5px;
font-size: 13px;
height: 28px;
line-height: 26px;
}
.points_items{
display: flex;
align-items: center;
::v-deep{
.el-form-item{
margin-bottom: 0;
}
}
}
</style>
保存后的图例对比