relation-graph——数据组装+鼠标移入后的详情(自定义插槽的用法)——js技能提升

最近在写后台管理系统的时候,遇到一个需求,就是给我一些节点,让我渲染到页面上,效果图如下:

之前写过一篇文章关于relation-graph关系图组件http://t.csdnimg.cn/7BGYm的用法

还有一篇关于relation-graph——实现右击节点显示详情+点击展开折叠操作——技能提升http://t.csdnimg.cn/K3rzf
在这里插入图片描述
关于插件的安装和使用,在此不再赘述。可以参照上面的两个链接。
在这里插入图片描述
下面给我的数据结构及想要的效果:
在这里插入图片描述

原始数据结构

this.taskRecords = {
    "nodes": [
        {
            "taskName": "完善客诉",
            "taskNodeName": "WanShanKeSu"
        },
        {
            "taskName": "PCB判责",
            "taskNodeName": "PCBPanZe"
        },
        {
            "taskName": "PCBA判责",
            "taskNodeName": "PCBAPanZe"
        },
        {
            "taskName": "方案确定并处理",
            "taskNodeName": "FangAnQuDingBingChuLi"
        }
    ],
    "connections": [
        {
            "from": "",
            "to": "WanShanKeSu",
            "depth": null
        },
        {
            "from": "",
            "to": "PCBPanZe",
            "depth": null
        },
        {
            "from": "",
            "to": "PCBAPanZe",
            "depth": null
        },
        {
            "from": "WanShanKeSu",
            "to": "PCBPanZe",
            "depth": null
        },
        {
            "from": "WanShanKeSu",
            "to": "PCBAPanZe",
            "depth": null
        },
        {
            "from": "PCBPanZe",
            "to": "FangAnQuDingBingChuLi",
            "depth": null
        },
        {
            "from": "PCBAPanZe",
            "to": "FangAnQuDingBingChuLi",
            "depth": null
        }
    ]
}

可以看出提供的节点有4个
完善客诉 PCB判责 PCBA判责 方案确定并处理
给出的连线有:

1.空 ——> 完善客诉
2.空 ——> PCB判责
3.空 ——> PCBA判责
4.完善客诉 ——> PCB判责
5.完善客诉 ——> PCBA判责
6.PCB判责 ——> 方案确定并处理
7.PCBA判责 ——> 方案确定并处理

如果不进行任何的处理,直接通过 渲染,则会出现下面的情况
在这里插入图片描述
上图乍一看,没啥问题,但是通过拖动【完善客诉】节点,就会发现问题了,就是【完善客诉】指向【PCBA判责】与【完善客诉】指向【PCB判责】的连线重合了,就会有【完善客诉】指向【PCB判责】再指向【PCBA判责】的错觉。这样的效果不是我们想要的。
在这里插入图片描述
想要实现【完善客诉】在【PCBA判责】与【PCB判责】节点中间,则需要指定排列的顺序。

比如上面的nodes节点更改顺序如下:

"nodes": [
		{
            "taskName": "PCB判责",
            "taskNodeName": "PCBPanZe"
        },
        {
            "taskName": "完善客诉",
            "taskNodeName": "WanShanKeSu"
        },
        {
            "taskName": "PCBA判责",
            "taskNodeName": "PCBAPanZe"
        },
        {
            "taskName": "方案确定并处理",
            "taskNodeName": "FangAnQuDingBingChuLi"
        }
    ],

这样就是我们想要的效果了
考虑到还有多层路径的情况,所以要通过递归来排列节点的顺序

我的思路

根据connections将空的节点填充为start开始节点,然后将没有任何from引申的节点,通通相当于指向end结束节点

1.开始 ——> 完善客诉
2.开始 ——> PCB判责
3.开始 ——> PCBA判责
4.完善客诉 ——> PCB判责
5.完善客诉 ——> PCBA判责
6.PCB判责 ——> 方案确定并处理
7.PCBA判责 ——> 方案确定并处理
8.方案确定并处理 ——> 结束

1.给from为空的节点赋值为start

let endArr = [];
let nodeObj = {};
let nodeArr = [];
this.taskRecords.connections.forEach((item) => {
  if (!item.from) {
    item.from = 'start';
  }
  endArr.push(item.from);
});

上面的endArr就是所有连线的开始节点,比如现在的endArr=['完善客诉','PCB判责','PCBA判责']

所有节点的集合:

this.taskRecords.nodes &&this.taskRecords.nodes.forEach((item) => {
  nodeArr.push(item.taskNodeName);
  nodeObj[item.taskNodeName] = [];
});

目前nodeArr=['完善客诉','PCB判责','PCBA判责','方案确定并处理']

this.taskRecords.connections &&this.taskRecords.connections.forEach((item) => {
  nodeObj[item.from].push(item.to);
});

经过上面的处理,nodeObj内容如下:

nodeObj = {
	'开始':['完善客诉','PCB判责','PCBA判责'],
	'完善客诉':['PCB判责','PCBA判责',],
	'PCB判责':['方案确定并处理'],
	'PCBA判责':['方案确定并处理'],
	'方案确定并处理':[],
	'结束':[]
}

我的思路是:遍历nodeObj,如果节点对应的数组长度大于1,则表示有好几个分支,则分支的排序尤为重要。比如【开始】节点,指向三个节点,我需要再次遍历,每一个子节点是否有好几个分支,如果有,则需要将该节点,位置安排在分支中间。

比如【完善客诉】的子节点【PCB判责】【PCBA判责】,则【完善客诉】位置应该是位于【PCB判责】和【PCBA判责】中间。

下面的代码可以实现这一操作:

for (let key in nodeObj) {
  if (nodeObj[key].length) {
    nodeObj[key].forEach((item) => {
      if (nodeObj[item].length > 1) {
        let arr = nodeObj[item].filter(
          (n) => nodeObj[key].indexOf(n) > -1
        );
        let len = Math.floor(arr.length / 2);
        let centerIndex = this.taskRecords.connections.findIndex(
          (no) => no.from == key && no.to == item
        );
        let currentObj = this.taskRecords.connections[centerIndex];
        this.taskRecords.connections.splice(centerIndex, 1);
        this.taskRecords.connections.splice(len, 0, currentObj);
      }
    });
  }
}

经过上面的操作:
endArr=['完善客诉','PCB判责','PCBA判责']
nodeArr=['完善客诉','PCB判责','PCBA判责','方案确定并处理']
所以存在于nodeArr中,但是不存在于endArr中的【方案确定并处理】应该有一条线是指向【结束】的

 nodeArr && nodeArr.forEach((item) => {
  if (endArr.indexOf(item) == -1) {
    this.taskRecords.connections.push({
      from: item,
      to: 'end',
    });
  }
});

重新组装nodes节点数据:

let nodes = [
  {
    text: '开始',
    id: 'start',
    color: this.info.taskList.length ? '#f90' : null,
  },
];
this.taskRecords.nodes &&
  this.taskRecords.nodes.forEach((item) => {
    nodes.push({
      id: item.taskNodeName,
      text: item.taskName,
      color: item.color,
      ...item,
    });
  });
nodes.push({
  text: '结束',
  id: 'end',
});

上面的步骤基本能实现想要的效果了。

//需要指定 节点参数和连接线的参数
this.graph_json_data = {
  rootId: 'start',
  nodes: nodes,
  lines: this.taskRecords.connections,
};
this.$refs.seeksRelationGraph.setJsonData(
  this.graph_json_data,
  (seeksRGGraph) => {}
);

我的效果图中,还有节点变亮,以及变亮节点中间的连线也是变亮的。这个就是给对应的节点和连线中添加color即可。

自定义插槽

下面要讲的是自定义插槽:
鼠标移入到节点上时,可以i显示其他的内容,此时需要使用插槽了。
在这里插入图片描述

<RelationGraph
          ref="seeksRelationGraph"
          style="
            height: 300px;
            width: 80%;
            margin: 0 auto;
            border: 1px solid #666;
          "
          :options="graphOptions"
        >
          <template #node="{ node }">
            <div class="my-node">
              <div class="my-node-text">{{ node.text }}</div>
              <div
                class="my-node-detail"
                v-if="node.data && node.data.creatorName"
              >
                <div @dblclick="handleCopy(node.data)">
                  {{ node.data.taskOwnerName || node.data.creatorName }}{{
                    (node.data.completedTime || node.data.creationTime) | moment
                  }}
                </div>
              </div>
            </div>
          </template>
        </RelationGraph>

上面中的graphOptions就是一些普通的配置项,具体的可以在https://relation-graph.com/#/options-tools链接中在线配置好后,拷贝到本地使用。

在这里插入图片描述
自定义插槽,一定要注意:node中识别内容只有id``text``data,其中的data可以是个对象,一开始我使用的是detail对象,则没有显示出来。改成data就可以了。

.my-node {
  height: 100%;
  display: flex;
  justify-content: center;
  align-items: center;
  position: relative;
  .my-node-detail {
    display: none;
  }
  &:hover {
    .my-node-detail {
      display: block;
      position: absolute;
      left: 50%;
      transform: translateX(-50%);
      top: -50%;
      width: 250px;
      height: auto;
      min-height: 60px;
      line-height: 30px;
      background: #fff;
      padding: 10px 0;
      border: 3px solid #f90;
      color: #000;
      z-index: 1;
      font-size: 18px;
      user-select: all;
    }
  }
}

监听全屏/取消全屏——保证关系图在页面中间

我的思路就是,全屏/取消全屏时,重新渲染

监听页面的全屏操作

mounted() {
  // 添加全屏变化的事件监听器
  document.addEventListener('fullscreenchange', this.onFullScreenChange);
},

方法:

onFullScreenChange() {
  this.$refs.seeksRelationGraph.setJsonData(
    this.graph_json_data,
    (seeksRGGraph) => {}
  );
},

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mfbz.cn/a/767369.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Python 编程快速上手——让繁琐工作自动化(第2版)读书笔记01 Python基础快速过关

Python 编程快速上手——让繁琐工作自动化&#xff08;第2版&#xff09;读书笔记01 Python基础快速过关 1 python基础概念 Python提供了高效的高级数据结构&#xff0c;还能简单有效地面向对象编程。 python运算符顺序 **——%——//——/——*——-——python中常见的数据…

【085】基于SpringBoot实现的网上音乐商城平台

系统介绍 视频演示 点击查看演示视频 基于SpringBoot实现的网上音乐商城平台分为管理员、用户两个角色&#xff0c;系统实现了用户注册和登陆、用户信息管理、用户加购、下单商品、购物车管理、订单管理、音乐分类、音乐商品管理、退出系统等功能 技术选型 开发工具&#…

大数据基础知识【大数据导论】

各位大佬好 &#xff0c;这里是阿川的博客&#xff0c;祝您变得更强 个人主页&#xff1a;在线OJ的阿川 大佬的支持和鼓励&#xff0c;将是我成长路上最大的动力 阿川水平有限&#xff0c;如有错误&#xff0c;欢迎大佬指正 大数据基础知识前 必看 【大数据导论】—大数据序言…

旅游管理系统16021

摘 要 本文旨在设计和实现一个基于Spring Boot框架的旅游管理系统。该系统通过利用Spring Boot的快速开发特性和丰富的生态系统&#xff0c;提供了一个高效、可靠和灵活的解决方案。系统将实现旅游景点信息的管理、线路规划、跟团游玩、旅游攻略、酒店信息管理、订单管理和用户…

【C语言】inline 关键字

在C语言中&#xff0c;inline关键字用于建议编译器对函数进行内联展开&#xff0c;而不是像普通函数一样调用。内联函数的目的是减少函数调用的开销&#xff0c;特别是对于简单的、频繁调用的函数。 内联函数的定义和使用 定义内联函数 要定义一个内联函数&#xff0c;需要在…

PyTorch之nn.Module、nn.Sequential、nn.ModuleList使用详解

文章目录 1. nn.Module1.1 基本使用1.2 常用函数1.2.1 核心函数1.2.2 查看函数1.2.3 设置函数1.2.4 注册函数1.2.5 转换函数1.2.6 加载函数 2. nn.Sequential()2.1 基本定义2.2 Sequential类不同的实现2.3 nn.Sequential()的本质作用 3. nn.ModuleList参考资料 本篇文章主要介绍…

应用密码学—(扩展)欧几里得、DES、RSA、SHA-1算法

1. 欧几里得算法 1.1 分析算法的实现原理 欧几里德&#xff08;Euclid&#xff09;算法&#xff0c;也既常说的“辗转相除法”&#xff0c;公式为gcd(m, n) { return gcd(n, m%n); }&#xff0c;对于任意两个正整数m、n&#xff0c;每次求的一个数字r m % n&#xff0c;然后把…

sideloadly 苹果自签和sidestore手机续签ipa记录

sideloadly 地址&#xff1a;https://sideloadly.io/#download 直接安装对应系统软件&#xff0c;然后吧ipa 拖到里面续签&#xff0c;缺点每7天需要电脑续签 如果续签保留数据需要对应的位置开启 enable file sharing 勾选 和 bundle id 修改 注意的地方需要电脑和手机appi…

无人机热成像分析图谱原理

一、热成像原理 热成像&#xff0c;也称为红外热成像或红外成像&#xff0c;是一种利用红外辐射&#xff08;通常指的是热辐射&#xff09;来获取物体表面温度分布信息的成像技术。在无人机上集成热成像传感器&#xff0c;可以远程捕获并分析目标物体的热特征&#xff0c;不受…

卸载node,下载nvm,下载node过程步骤及错误记录

网上有很多步骤&#xff0c;先跟着网上的步骤来&#xff1a; 卸载node和下载nvm步骤&#xff1a; window下安装并使用nvm&#xff08;含卸载node、卸载nvm、全局安装npm&#xff09;-CSDN博客 使用NVM下载和安装NodeJS教程-CSDN博客 出现的问题&#xff1a; 1.nvm配置sett…

ENVI5.6使用笔记

目录 1. ENVI安装扩展2. ENVI绘制高光谱3D数据立体图3. 对本次工作存档&#xff0c;下次打开软件可直接续档 1. ENVI安装扩展 从ENVI App Store下载商店envi_app_store.zip&#xff0c;解压得到ENVI_App_Store.sav&#xff0c;将其复制到ENVI的扩展文件夹下&#xff08;例如E:…

中国桥梁空间分布数据

2020年中国桥梁空间分布数据&#xff0c;共包含102000余条数据。 数据属性表包括&#xff1a;地级市名、区县名、桥梁名称和经纬度。有shp和EXCEl两种格式数据。目前暂没有广西、广东和台湾三个省份数据。

【js】数组元素拼接、数组元素类型转换

一、数组元素拼接 二、数组元素类型转换 1、字符串数组 转换成 数字型数组 [1, 2, 3].map(Number) // [1,2,3] 2、数字型数组 转换成 字符串数组 [1, 2, 3].map(String) // [1, 2, 3]

干货:js解析url参数的作用、场景、方法和安全策略。

涉及到Web3D开发&#xff0c;Three.js和Babylon.js是两个备受推崇的引擎。它们都是基于WebGL的开源3D引擎&#xff0c;用于创建交互式的3D图形应用程序&#xff0c;但要细论起来&#xff0c;three.js普及度远超Babylon .js. 一、二者的介绍 Three.js&#xff1a; Three.js 是…

GitCode见证:华为云DevUI如何定义下一代前端开发

在当今快速发展的数字时代&#xff0c;前端开发已成为企业数字化转型的关键一环。随着用户对交互体验的期待不断增长&#xff0c;拥有一个强大、灵活且易于使用的前端解决方案变得至关重要。 DevUI的诞生&#xff0c;源于华为对研发工具的深入理解和长期积累&#xff0c;作为一…

【C++】开源:量化金融计算库QuantLib配置与使用

&#x1f60f;★,:.☆(&#xffe3;▽&#xffe3;)/$:.★ &#x1f60f; 这篇文章主要介绍量化交易库QuantLib配置与使用。 无专精则不能成&#xff0c;无涉猎则不能通。——梁启超 欢迎来到我的博客&#xff0c;一起学习&#xff0c;共同进步。 喜欢的朋友可以关注一下&#…

linux模拟aix盘19c单机asm安装补丁

linux模拟盘aix盘vi /etc/rc.d/rc.local/bin/ln /dev/sda /dev/rhdisk2/bin/ln /dev/sdb /dev/rhdisk3 /bin/chown grid:oinstall /dev/rhdisk*chmod 660 /dev/rhdisk* 一、19c安装GI&#xff08;Standalone Oracle Restart&#xff09; su - grid配置环境变量vi .profileex…

红酒与摄影:捕捉酒香与光影的交融

在摄影的世界里&#xff0c;每一个画面都是一段故事&#xff0c;每一束光线都是情感的载体。当红酒遇上摄影&#xff0c;两者之间的交融&#xff0c;仿佛开启了一场关于色彩、光影与情感的视觉盛宴。今天&#xff0c;就让我们一起探索红酒与摄影的奇妙结合&#xff0c;感受雷盛…

为什么我感觉 C 语言在 Linux 下执行效率比 Windows 快得多?

在开始前刚好我有一些资料&#xff0c;是我根据网友给的问题精心整理了一份「Linux的资料从专业入门到高级教程」&#xff0c; 点个关注在评论区回复“888”之后私信回复“888”&#xff0c;全部无偿共享给大家&#xff01;&#xff01;&#xff01;Windows的终端或者叫控制台…

反射--通俗易懂

一、反射(Reflection) 反射就是:加载类&#xff0c;并允许以编程的方式解剖类中的各种成分(成员变量、方法、构造器等) 动态语言&#xff0c;是一类在运行时可以改变其结构的语言&#xff1a;例如新的函数、对象、甚至代码可以被引进&#xff0c;已有的函数可以被删除或是其他…