el-table树形数据 + jsPlumb , 批量映射字段

<template>

<el-dialog
:title=" routeRow ? routeRow.mappingname : '映射' "
append-to-body
:visible.sync="mappingShow"
:close-on-click-modal="false"
:before-close="closeFileMappingDialog"
class="mapppingDialog"
width="1000px"
>
<el-card class="box-card" shadow="always">

<!-- <el-row style="margin-bottom: 10px;" >-->
<!-- <el-col :span="24" >-->
<!-- {{ routeRow.mappingname }}-->
<!-- </el-col>-->
<!-- </el-row>-->
<el-row >
<!-- :gutter="20" -->

<div id="jsplumbContainer" @scroll="connect" >

<el-col :span="8">
<el-table id="leftTable"
:data="leftTab"
row-key="code"
default-expand-all
border
:tree-props="{children: 'children', hasChildren: 'hasChildren'}"
@expand-change="getLeftExpand"
>
<!-- :row-class-name="({row}) => `leftRow Id-${row.code}`" -->
<el-table-column label="名称" prop="name"></el-table-column>
<el-table-column label="代码" width="80" >
<template slot-scope="scope" >
<div :class="`leftRow leftId-${scope.row.code}`" :id="scope.row.code" >
{{ scope.row.code }}
</div>
</template>
</el-table-column>
</el-table>
</el-col>

<el-col :span="8" :offset="8">
<el-table id="rightTable"
:data="rightTab"
row-key="code"
:tree-props="{children: 'children', hasChildren: 'hasChildren'}"
default-expand-all
border
:row-class-name="({row}) => `rightRow rightId-${row.code}`"
>

<el-table-column label="名称" prop="name"></el-table-column>
<el-table-column label="代码" width="80" >
<template slot-scope="scope">
<div >
{{ scope.row.code }}
</div>
</template>
</el-table-column>
</el-table>

</el-col>
</div>

</el-row>


</el-card>

<div class="dialog_foot ">
<el-button type="primary" size="small" @click="confirmFileMapping">
确定
</el-button>
<el-button size="small" plain @click="closeFileMappingDialog">
取消
</el-button>
</div>

</el-dialog>

</template>

<script>

import { submitlist, listall } from "@/api/dic/dicmapping";

// import { jsPlumb } from 'jsplumb'
import jsPlumb from 'jsplumb'
//jsplumb使用
let $jsPlumb = jsPlumb.jsPlumb;

let instance = null;

export default {
name: "fieldMapping",
props:{
currentTreeData:{},
leftTab: [],
rightTab: [],
},
data() {
return {
mappingShow: false,
routeRow:{},
contrastId: this.currentTreeData.id, // 点击树id

pointList: [],
count: 0,
allConnections: [],
relationship: [],


}
},
watch(){

},
created() {

this.init3();

},
mounted(){

},
methods:{

openFileMappingDialog(row){
console.log('选择数据 row :', row )
this.routeRow = row ;
this.mappingShow = true ;
if( this.leftTab.length > 0 && this.rightTab.length > 0 ){
this.initJsPlumb() ;
}
},
closeFileMappingDialog(){
instance.reset()
this.mappingShow = false ;
},
initJsPlumb(){
let that = this ;
that.$nextTick(()=> {
instance.ready(function () {

setTimeout(()=>{
// console.log(' /////// initJsPlumb ///////////////' )

instance.setContainer('jsplumbContainer');
// 初始化jsPlumb 创建jsPlumb实例
// that.init3();
// 设置可以为连线起点和连线终点的元素
that.setContainer();
// 绑定事件监听
that.setEvent();
// 设置默认连线
that.setConnect( );
// 连线前的判断
// that.beforeDrop3();

},1000)

});
})
},
init3() {
// 清除端点、连接
// instance.reset();
// this.pointList = new Map();
// this.$forceUpdate();
instance = $jsPlumb.getInstance({
//父级元素id;假如页面元素所在上层不同,最外层父级一定要设置
Container: "jsplumbContainer",
// DragOptions : { cursor: "pointer", zIndex:2000 },//拖动的时候
PaintStyle: { //连接线样式
stroke: '#BCBCBC',
strokeWidth: 5,
},
HoverPaintStyle: {
stroke: '#1E90FF'
},
EndpointStyle: {
fill: '#BCBCBC',
radius: 6
},
EndpointHoverStyle: {
fill: '#1E90FF',
radius: 8
}, // 端点悬停样式
Rectangle: {

},
ConnectionsDetachable: false, //连线是否可用鼠标分离
ReattachConnections: false, //是否重新连接使用鼠标分离的线
});

},
// 截取元素类名中的id
interceptId(className){
return className.slice(className.indexOf('-') + 1);
},
// 设置可以连线的元素
setContainer(){
// console.log(' /////// 设置可以连线的元素 ///////////////' )
const leftElList = document.querySelectorAll('.leftRow'); // 左侧行元素集合
const rightElList = document.querySelectorAll('.rightRow'); // 右侧行元素集合
// 将dom元素设置为连线的起点或者终点 设置了起点的元素才能开始连线 设置为终点的元素才能为连线终点
// console.log('leftElList ==>', leftElList )
instance.batch(function () {
[leftElList, rightElList].forEach((trList, index) => {
trList.forEach((tr) => {
// const id = that.interceptId(tr.classList[2]);
instance.setDraggable(tr, false); // 是否支持拖拽
if (index === 0) {
// const item = that.leftTab.find(i => i.id == id);
// 判断是否有子项,若没有则设置为起点
// !item?.hasChild && instance.makeSource(tr, {
instance.makeSource(tr, {
anchor: ["Right"], // 设置端点位置
// anchor: [1, 0.5, 0, 0], // 左 上 右 下
allowLoopback: true, //允许回连
maxConnections: -1, //最大连接数(-1表示不限制)
endpoint: "Dot"
})
}
else {
// const item = that.rightTab.find(i => i.id == id);
// 判断是否有子项,若没有则设置为终点
// !item?.hasChild && instance.makeTarget(tr, {
instance.makeTarget(tr, {
anchor: ["Left"], // 设置端点位置
// anchor: [0, 0.5, 0, 0], // 左 上 右 下
allowLoopback: true, //允许回连
maxConnections: -1, //最大连接数(-1表示不限制)
});
}
});
});
});

},
// 设置默认连线
setConnect(relationship) {
listall(this.routeRow.id).then((res) => {
console.log('获取连线 res ==>', res )
if( res.data.success ){
this.relationship = res.data.data ;
}
});
setTimeout(() => {
this.relationship.forEach(function (data) {
// source是连线起点元素id target是连线终点元素id
instance.connect({
source: document.querySelector(`.leftId-${data.vcode}`),
target: document.querySelector(`.rightId-${data.tvcode}`)
});
});
},1500)
},
// 绑定事件监听
setEvent() {
let that = this ;
// 连线事件
instance.bind("connection", function (connInfo, originalEvent) {
// connInfo是jsPlumb对象 可以打印出来康康有哪些东西 source
// console.log('连线事件 connInfo :', connInfo, )
let sourceid = that.interceptId(connInfo.source.classList[1]);
let targetid = that.interceptId(connInfo.target.classList[2]);
console.log('连线事件 :', sourceid, targetid, connInfo )

that.pointList.push({
sourceId: sourceid,
targetId: targetid ,
pointIds: sourceid + "-" + targetid
})
that.pointList = that.unique(that.pointList)
// console.log('连线事件 pointList :', that.pointList, )

connInfo.pointIds = sourceid + "-" + targetid ;
that.allConnections.push(connInfo)
that.allConnections = that.unique(that.allConnections)


});
// 点击连接线删除该条线
instance.bind('click', function (connection, originalEvent) {
let sourceid = that.interceptId(connection.source.classList[1]);
let targetid = that.interceptId(connection.target.classList[2]);
console.log('删除事件 :', sourceid, targetid , connection, )

that.$confirm("确认删除映射么?", "提示", {
confirmButtonText: "确定",
cancelButtonText: "取消",
closeOnClickModal: false,
type: "warning",
})
.then(() => {
instance.deleteConnection(connection);
for(let i = 0; i < that.pointList.length; i++) {
let item = that.pointList[i];
if ( item.sourceId == sourceid && item.targetId == targetid ) {
that.pointList.splice(i, 1);
}
}
for(let i = 0; i < that.allConnections.length; i++) {
let item = that.allConnections[i];
if ( item.pointIds == sourceid + "-" + targetid ) {
that.allConnections.splice(i, 1);
}
}

})
.catch(() => {});

// console.log('删除事件 pointList :', that.pointList, )

})

},
unique(arr) {
const res = new Map();
return arr.filter((arr) => !res.has(arr.pointIds) && res.set(arr.pointIds, 1));
},
// 连线重绘时错位,通常都是父容器设置了relative定位,而且出现了scroll不可视区域,
// 通过调试找到连线 jtk-connector 和连接点 jtk-endpoint,
// 使用父容器的 scrollLeft 进行修正即可,用在画线结束后面
fix_jsPlumb_offset(left) {
var lines = document.getElementsByClassName("jtk-connector");
var dots = document.getElementsByClassName("jtk-endpoint");
this._fix_left(lines, left);
this._fix_left(dots, left);
},
_fix_left(arr, left) {
for (var i = 0; i < arr.length; i++) {
var obj = arr[i];
var origin_left = obj.style.top.replace(/px/, "");
obj.style.top = (parseInt(origin_left) + parseInt(left)) + 'px';
}
},
// 页面滚动,连线跟随变化
connect(e) {
// console.log('滚动 scrollTop: ', e.target.scrollTop )

this.count++;
if (this.count >= 1) {
let connections = instance.getAllConnections();
// console.log('滚动 connections =>', connections )
let linePoints = [];
for (let i = connections.length - 1; i >= 0; i--) {
linePoints.push([connections[i].sourceId, connections[i].targetId]);
instance.deleteConnection(connections[i]);
}
for (let i = 0; i < linePoints.length; i++) {
instance.connect({
source: linePoints[i][0],
target: linePoints[i][1]
});
}
this.count = 0;
}

this.$nextTick(()=>{
// 获取滑动距离,修改锚点、连线位置
this.fix_jsPlumb_offset(e.target.scrollTop)
})

},
getLeftExpand( row, expandedRows ){
// console.log('展开或者关闭:', row, expandedRows )
// console.log('展开或者关闭 allConnections :', this.allConnections )

let that = this ;
let connections = instance.getAllConnections();
let linePoints = [];
let children = row.children ;

// console.log('展开或者关闭 connections :', connections )

// 展开:
if( expandedRows ){

if( children ){
that.allConnections = that.unique(that.allConnections)

children.map((item,index)=>{
for (let i = that.allConnections.length - 1; i >= 0; i--) {
if( item.code == that.interceptId(that.allConnections[i].source.classList[1]) ){
instance.connect({
source: that.allConnections[i].sourceId,
target: that.allConnections[i].targetId
});
}
}
})

}

}
// 合闭:
else{

if( children ){
children.map((item,index)=>{
for (let i = connections.length - 1; i >= 0; i--) {
// linePoints.push(connections[i]);
if( item.code == that.interceptId(connections[i].source.classList[1]) ){
instance.deleteConnection(connections[i]);
}
}
})

}

}


this.$nextTick(()=>{
// 展开后连线位置错位,重新绘制:
for (let i = connections.length - 1; i >= 0; i--) {
linePoints.push([connections[i].sourceId, connections[i].targetId]);
instance.deleteConnection(connections[i]);
}
for (let i = 0; i < linePoints.length; i++) {
instance.connect({
source: linePoints[i][0],
target: linePoints[i][1]
});
}

})


},

// 连线前的判断
beforeDrop3 () {
let that = this ;
// 连线前规则,返回true符合规则,不返回或者返回false,不符合规则
instance.bind('beforeDrop', (info) => {
// info是该线段的基本信息 sourceId是线头节点id,targetId是线尾节点id
if (info.sourceId == info.targetId) { // 判断是否是同一节点
return false;
}
// // 必须是右边连接左边
// if (info.targetId.indexOf('left') === -1) {
// return false;
// }
// // 左边不可以连接右边
// if (info.sourceId.indexOf('right') === -1) {
// return false;
// }
// console.log('info ==>', info )
// let sourceId = info.sourceId; // 起点
// let targetId = info.targetId // 目标点
// let sourceKey = info.connection['endpoints'][0].anchor.type // 连接的位置获取
// let targetKey = info.dropEndpoint.anchor.type // 连接的位置获取
// let pointList = JSON.parse(JSON.stringify(that.pointList));
// // console.log(pointList);
// for(let i = 0; i < pointList.length; i++) {
// let item = pointList[i];
// if (('right' + item.sourceId) === sourceId && ('left' + item.targetId) === targetId) {
// return false;
// }
// }
// pointList.push({
// sourceId: Number(sourceId.replace('right', '')),
// targetId: Number(targetId.replace('left', '')),
// });
// that.pointList = pointList;
// console.log('pointList', that.pointList);
// return true;

});
},

confirmFileMapping(){
let list = [] ;
let connections = instance.getAllConnections();
// console.log('保存 connections =>', connections )
for(let i = 0; i < connections.length; i++) {
list.push({
sid: this.routeRow.sid ,
vcode: this.interceptId(connections[i].source.classList[1]) , //来源字典code
tvcode: this.interceptId(connections[i].target.classList[2]) , //目标字典code
})
}
console.log('保存 list =>', list )
submitlist(this.routeRow.id, list).then((res) => {
// console.log('res ==>', res )
if( res.data.success ){
this.$message.success(res.data.msg)
}
else{
this.$message.warning(res.data.msg)
}
});
// this.closeFileMappingDialog()
},



}
}
</script>

<style lang="scss" scoped>
.mapppingDialog{
/deep/.el-dialog{
min-width: 1100px;
//max-width: 80%;
}
/deep/.el-dialog__body{
padding: 1px 20px 15px 20px;
}
}
#jsplumbContainer{
height: 75vh;
overflow-y: auto;
position: relative; /*一定加上这句,否则连线位置发生错乱*/
padding-right: 10px;
}
.el-table /deep/.el-table__cell {
padding: 5px 0;
}
.el-table /deep/.cell{
padding-right: 0 !important;
}
.dialog_foot{
text-align: center;
margin-top: 20px;
}

</style>
posted @ 2023-08-30 16:15  昵称已被使用。  阅读(319)  评论(0编辑  收藏  举报