基于Vue实现动态组织结构图

news/2024/12/26 0:50:58/文章来源:https://www.cnblogs.com/haonanZhang/p/18424465
最近一个项目里有个前端绘制家谱图的需求,大概是下面这个样子:

组件源码如下

<template><table v-if="treeData.name"><tr><td :colspan="Array.isArray(treeData.children) ? treeData.children.length * 2 : 1":class="{parentLevel: Array.isArray(treeData.children) && treeData.children.length, extend: Array.isArray(treeData.children) && treeData.children.length && treeData.extend}"><div :class="{node: true, hasMate: treeData.mate}"><div class="person" :class="Array.isArray(treeData.class) ? treeData.class : []"@click="$emit('click-node', treeData)"><div class="avat"><img v-if="treeData.image_url" :src="treeData.image_url" /><img v-else src="/static/user_default.png" /></div><div class="name">{{ treeData.name }}</div><div class="sub_name" v-if="treeData.subName">{{ treeData.subName }}</div></div><template v-if="Array.isArray(treeData.mate) && treeData.mate.length"><div class="person" v-for="(mate, mateIndex) in treeData.mate" :key="treeData.name+mateIndex":class="Array.isArray(mate.class) ? mate.class : []" @click="$emit('click-node', mate)"><div class="avat"><img :src="mate.image_url" /></div><div class="name">{{mate.name}}</div></div></template></div><div class="extend_handle" v-if="Array.isArray(treeData.children) && treeData.children.length"@click="toggleExtend(treeData)"></div></td></tr><tr v-if="Array.isArray(treeData.children) && treeData.children.length && treeData.extend"><td v-for="(children, index) in treeData.children" :key="index" colspan="2" class="childLevel"><TreeChart :json="children" @click-node="$emit('click-node', $event)" /></td></tr></table>
</template><script>export default {name: "TreeChart",props: ["json"],data() {return {treeData: {}}},watch: {json: {handler: function(Props) {let extendKey = function(jsonData) {jsonData.extend = (jsonData.extend === void 0 ? true : !!jsonData.extend);if (Array.isArray(jsonData.children)) {jsonData.children.forEach(c => {extendKey(c)})}return jsonData;}if (Props) {this.treeData = extendKey(Props);}},immediate: true}},methods: {toggleExtend: function(treeData) {treeData.extend = !treeData.extend;this.$forceUpdate();}}}
</script><style scoped>table {border-collapse: separate !important;border-spacing: 0 !important;width: 100%}td {position: relative;vertical-align: top;padding: 0 0 50px 0;text-align: center;}.extend_handle {position: absolute;left: 50%;bottom: 30px;width: 10px;height: 10px;padding: 10px;transform: translate3d(-15px, 0, 0);cursor: pointer;}.extend_handle:before {content: "";display: block;width: 100%;height: 100%;box-sizing: border-box;border: 2px solid;border-color: #ccc #ccc transparent transparent;transform: rotateZ(135deg);transform-origin: 50% 50% 0;transition: transform ease 300ms;}.extend_handle:hover:before {border-color: #333 #333 transparent transparent;}.extend .extend_handle:before {transform: rotateZ(-45deg);}.extend::after {content: "";position: absolute;left: 50%;bottom: 15px;height: 15px;border-left: 2px solid #ccc;transform: translate3d(-1px, 0, 0)}.childLevel::before {content: "";position: absolute;left: 50%;bottom: 100%;height: 15px;border-left: 2px solid #ccc;transform: translate3d(-1px, 0, 0)}.childLevel::after {content: "";position: absolute;left: 0;right: 0;top: -15px;border-top: 2px solid #ccc;}.childLevel:first-child:before,.childLevel:last-child:before {display: none;}.childLevel:first-child:after {left: 50%;height: 15px;border: 2px solid;border-color: #ccc transparent transparent #ccc;border-radius: 6px 0 0 0;transform: translate3d(1px, 0, 0)}.childLevel:last-child:after {right: 50%;height: 15px;border: 2px solid;border-color: #ccc #ccc transparent transparent;border-radius: 0 6px 0 0;transform: translate3d(-1px, 0, 0)}.childLevel:first-child.childLevel:last-child::after {left: auto;border-radius: 0;border-color: transparent #ccc transparent transparent;transform: translate3d(1px, 0, 0)}.node {position: relative;display: inline-block;margin: 0 1em;box-sizing: border-box;text-align: center;cursor: pointer;}.node .person {position: relative;display: inline-block;z-index: 2;width: 6em;overflow: hidden;}.node .person .avat {display: block;width: 4em;height: 4em;margin: auto;overflow: hidden;background: #fff;
/*        border: 1px solid #ccc;*/border-radius: 50%;box-sizing: border-box;}.node .person .avat img {width: 100%;height: 100%;}.node .person .name {height: 2em;line-height: 2em;overflow: hidden;width: 100%;}.sub_name{}.node.hasMate::after {content: "";position: absolute;left: 2em;right: 2em;top: 2em;border-top: 2px solid #ccc;z-index: 1;}/* 横板 */.landscape {transform: translate(-100%, 0) rotate(-90deg);transform-origin: 100% 0;}.landscape .node {text-align: left;height: 8em;width: 8em;}.landscape .person {position: relative;transform: rotate(90deg);padding-left: 4.5em;height: 4em;top: 4em;left: -1em;}.landscape .person .avat {position: absolute;left: 0;}.landscape .person .name {height: 4em;line-height: 4em;}.landscape .hasMate {position: relative;}.landscape .hasMate .person {position: absolute;}.landscape .hasMate .person:first-child {left: auto;right: -4em;}.landscape .hasMate .person:last-child {left: -4em;margin-left: 0;}
</style>

使用

<TreeChart :json="treeData" @click-node="clickNode" />

数据如下

treeData:  {name: '保密中心',subName: '张三',image_url: "",class: ["rootNode"],children: [{name: '综合科室',subName: '张三',image_url: ""},{name: '保密科室',subName: '王五',image_url: "",// mate: [{//       name: 'mate',//       image_url: "https://static.refined-x.com/avat3.jpg"// }],
                            children: [{name: '保密局一',subName: '张三',image_url: ""},{name: '保密局二',subName: '张三',image_url: ""},{name: '保密局三',subName: '李四',image_url: ""}]},{name: '销毁科室',subName: '王麻子',image_url: "",}]}

 

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

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

中国能源发展报告2022

中国能源发展与未来中国能源发展报告2022林伯强高耗能产业的出路CCUS(Carbon Capture,Utilization and Storage,即碳捕获、利用与封存技术)高耗能产业布局:08 年,东高西低 >> 08 年之后,西高东低,自南向北移动,东减西增; 转移趋势北部沿海城市-河北,山东,201…

Qt表格入门

这篇博客详细介绍了Qt表格的基础知识,包括如何使用QTableWidget和QTableView来显示数据,以及如何使用QStyledItemDelegate和QSortFilterProxyModel进行数据代理、过滤和排序。此外,博客还提供了完整的代码示例,用于演示如何在Qt中创建和定制表格视图。这些内容对于Qt初学者…

王悦帆的第一次作业

这个作业属于哪个课程 https://edu.cnblogs.com/campus/zjlg/rjjc这个作业的目标 熟悉如何运用博客,展示自己姓名-学号 王悦帆 2022329301024一、自我介绍 (一)基本情况 大家好,我叫王悦帆,来自河南长垣,是自动化一班的成员,兴趣爱好是踢足球,看足球比赛。曾经去过现场…

day5[LangGPT结构化提示词编写实践]

任务要求:利用LangGPT优化提示词,使LLM输出正确结果。

Rebound-hackthebox

端口扫描smb探测 crackmapexec smb 10.10.11.231 -u anonymous -p "" --sharesRID 枚举 使用 CME 工具对指定主机的 SMB 服务进行扫描,并尝试使用 RID 枚举技术获取主机上的用户和组信息。RID 枚举(Relative Identifier enumeration)是一种用于获取 Windows 主机上…

CSP-J 2024 入门组初赛第一轮初赛试题及答案解析

CSP-J 2024 入门组初赛第一轮初赛试题及答案解析 一、 单项选择题(共15题,每题2分,共计30分:每题有且仅有一个正确选项) 1 32 位 int 类型的存储范围是( ) A -2147483647 ~ +2147483647 B -2147483647 ~ +2147483648 C -2147483648 ~ +2147483647 D -2147483648 ~ +…

数字产品护照 (DPP) 解决方案:利用 Blazor 和区块链实现产品全生命周期追踪

数字产品护照 (DPP) 解决方案:利用 Blazor 和区块链实现产品全生命周期追踪 随着全球对可持续发展和产品透明度的关注日益增加,企业需要一种可靠的方法来跟踪和管理产品生命周期中的关键数据。我们的数字产品护照(Digital Product Passport,DPP)系统正是为此而生,提供了一…

四种常用的IO模型

不管是做C端还是做B端,都要接触网络。文件操作,rpc,网上冲浪等,都与网络相关。网络又离不开IO。用的最多的IO操作就是读取和写入了。在Linux系统中,用read系统调用来发起读取操作,用write系统调用来发起写入操作。虽然在开发中,很少接触到底层的原理。但是学习后可以让我…

java学习9.21

今天回炉mybatis的用法,由于之前只是跟着教程走能成功配置数据库,但是一旦出现细小的区别就会产生自己改不了的bug,因此熟悉mybaits和其他技术的内容。知道问题出在哪里,以及怎么改。 mybatis配置 1.导入操作 (1)官网下载jar包并导入 (2)maven直接导入依赖 2.导入完之后创建…

龙祖维的第一次作业

这个作业属于哪个课程 https://edu.cnblogs.com/campus/zjlg/rjjc这个作业的目标 熟悉博客、向老师介绍自己姓名-学号 龙祖维 2022329301084一、自我介绍 基本信息 我叫龙祖维,来自湖南郴州,是22电气工程及其自动化2班的一名学生 兴趣爱好 我喜欢运动,篮球、足球、乒乓及羽毛…

企业如何快速拥有专属的Agent平台?

LinkAI3.0基于企业场景全新打造的Agen3.0平台,既聚焦业务,带来了新的业务型功能,也基于管理需求,增加了通用的管理型功能:全新「客户管理」支持AI生成客户标签及画像;工作流自定义变量拓展个性化的使用场景;支持精细化管控成员角色权限的「企业空间」;「企业专属智能体…

docker阶段04 Docker仓库管理(Harbor), Docker 的资源限制

Docker 仓库管理 上传docker hub官方镜像仓库#1.给本地镜像打标签 上传本地镜像前必须先给上传的镜像用docker tag 命令打标签 标签格式: docker.io/用户帐号/镜像名:TAG #范例: [root@ubuntu1804 ~]#docker tag alpine:3.11 docker.io/wangxiaochun/alpine:3.11-v1#2.登录 do…