前面 用Echarts 制作一个数据库表的关联关系图(一) 中提到了几个问题,接下来一个一个解决。
1、添加节点
目前项目背景为:左边是展示数据库表的 ztree 树,树的上面是一些对ztree 树进行操作的一些按钮,我的思路是在左边按钮区域添加一个按钮,选中树节点后(可支持多选),点击按钮后做添加操作。
let [ ...temp ] = this.gData; // 节点的数据存在vuex state中
temp.push({ // 保存节点的名字和ID
name: nodes[0].name,
value:nodes[0].tableId,
x: 0,
y: 0
});
这样数据就保存起来了。
2、节点坐标
当节点变化时,在 commit 后,先计算节点个数,再计算每个点的坐标,计算坐标的核心代码如下:
// 表格关联关系 节点坐标计算
export function getXYbyCount(count,width,height){
let w = width | 500;
let h= height | 400;
let centerX=(w-100)/2;
let centerY =(h-100)/2;
let r = centerX < centerY ? centerX:centerY;
let pointX = 100+centerY;
let pointY = 100+centerY;
let point = [];
for(let i=0;i<count;i++){
point.push(
{
x:pointX-r*Math.cos(i*2*Math.PI/count),
y:pointY-r*Math.sin(i*2*Math.PI/count)
}
);
}
return point;
}
不多说了,学过数学的都能看懂。
3、触发Echarts 刷新
vue 中双向绑定必须绑定到 html 元素,才能用 watch 监控直接改变的 state ,如下所示:
watch:{
// 鉴定节点的变化 重新加载图表
gData:function (val) {
this.initGraph();
}
},
4、连接线如何连接
echarts 点击节点时,可以捕捉到点击事件,于是就可以设置个超时时间,把点击的节点记录下来,做连线,
// 点击事件
handleClick(handler) {
// 判断是节点 还是 连线
if(handler.dataType === 'node'){
if(this.tableSchemas[handler.value] === undefined){
this.getTableSchemaByid(handler.value);
}
// 判断是否已经存在节点
if(_.indexOf(this.nodeArr,handler.name+"#"+handler.value) === -1){
this.nodeArr.push(handler.name+"#"+handler.value);
}
// console.log(this.nodeArr);
// 点击超时 清空
setTimeout(()=>{
this.nodeArr=[];
},2000);
// 点击了两个节点
if(this.nodeArr.length >= 2){
// 判断重复使用 两种组合方式 有连线了就不再连接了
let lineValue1 = ''; // 该行和以下非真实代码
let lineValue2 = '';
let tmp = {
source: sourceNode,
target: targetNode,
lineStyle: {
normal: {
width: 5,
curveness: 0.2
}
},
value:lineValue1
};
// 控制重复连线
if( (_.indexOf(this.optionLinks,lineValue1) === -1) &&
(_.indexOf(this.optionLinks,lineValue2) === -1) ){
this.optionLinks.push(lineValue1);
// 设置连线
this.option.series[0].links.push(tmp);
}
this.myChart.setOption(this.option);
this.nodeArr=[];
}
}
else{
if(this.allCondition[handler.value]){
// 已经保存过条件处理逻辑
}
else {
// 重新初始化 为了防止值重复 { 一些处理代码}
// some code
}
}
}
5、请求节点字段信息
当点击节点时候去请求并记录节点的信息。在本地保存临时变量,如果已存在该表格信息,就不再请求服务器。
6、连接条件框
用一个条件框,切换节点或者连线的时候做更新,效果
如图所示:
7、添加删除修改条件逻辑
上图所示的弹出层,我们只需要一个,vue是数据驱动的,当连线切换时候,我们去更新数据就行,
// 选择的所有关联条件
allCondition:{},
// 存放表的字段信息 key :tavleId value:schemas
tableSchemas:{},
// 选中表格1 的字段
tableFirst:[],
// 选中表格2 的字段
tableSecond:[],
// 当前连线的的信息
currentItem:
{
count:1,
// 起始表格名字
tableSource:'',
// 目标表格名字
tableTarget:'',
tableIds:'',
// 表格直接的关联方式
tableConnector:'INNER',
data:[
{
itemId:1,
tableFirstId:'tableFirstId1',
tableRightId:'tableRightI1',
},
]
},
// 弹出框是否显示
modalRelation:false,
// 连接线
optionLinks:[],
// 当前图表
myChart: {},
相信一看到这些数据结构及定义,就懂了。
8、最终条件的保存
用上个步骤的 allCondition 即可。保存到后端时,转换成相应的数据结构,前端需要再次展示的时候,还原回来即可。
总结
这就是开发表关联的一个思路和大部分代码,做的时候不要急,也不能乱,一个个小功能拆分出来,向上累积,最终就会达到我们想要的效果。