疯狂撸码中ing
实现组件效果
src/components/sgTopo.vue
<template> <!-- 强哥的拓扑图2021.09.14 --> <div class="sg-topo tree-body" v-if="data" :arrow-right="data.body.arrowRight" :style="data.body.style || {}" > <div class="topo-title main-node" :active="data.body.title.active" :style="data.body.title.style || {}" > {{ data.body.title.text }} </div> <ul class="topo-container" :style="data.body.container ? data.body.container.style || {} : {}" > <li class="tree-level" v-for="(a, $i) in data.body.data" :key="$i"> <!-- 拓扑图类型:1 ------------------------------------------> <div v-if="a.type == 1" :type="a.type"> <span :active="a.title.active" :style="a.title.style || {}" class="node-title" >{{ a.title.text }}</span > <!-- 二级树 --> <div v-if="a.children" class="topo-childrens"> <div class="tree-body" gray v-for="(child, $i) in a.children" :key="$i" > <div class="tree-level"> <span :active="child.title.active" :style="child.title.style || {}" class="topo-title" gray >{{ child.title.text }}</span > <ul class="topo-container"> <!-- 三级节点 --> <li :active="childNode.title.active" :style="childNode.title.style || {}" v-for="(childNode, $i) in child.data" :key="$i" class="node-title" border > {{ childNode.title.text }} </li> </ul> </div> </div> </div> </div> <!-- 拓扑图类型:2 ------------------------------------------> <div v-if="a.type == 2" :type="a.type"> <span :active="a.title.active" :style="a.title.style || {}" class="node-title" >{{ a.title.text }}</span > <!-- 二级树 --> <ul v-if="a.children" class="topo-childrens"> <li class="tree-level" v-for="(child, $i) in a.children" :key="$i"> <span :active="child.title.active" :style="child.title.style || {}" class="topo-title" >{{ child.title.text }}</span > <ul v-if="child.children" class="topo-childrens"> <!-- 三级节点 --> <li v-for="(childNode, $i) in child.children" :key="$i" class="tree-level" > <span :active="childNode.title.active" :style="childNode.title.style || {}" class="topo-title" >{{ childNode.title.text }}</span > </li> </ul> </li> </ul> </div> <!-- 拓扑图类型:3 ------------------------------------------> <!-- 这个类型太没规律了,担心设计师的脑回路有一定问题 --> </li> </ul> </div> </template> <script> export default { props: ["data"], }; </script> <style lang="scss" scoped> @import "~@/css/sg"; .tree-body { height: min-content; position: relative; display: inline-block; background: #ffffff; border-radius: 4px; border: 1px dashed #0050b3; box-sizing: border-box; padding: 10px; &[gray] { background: #ffffff; border-radius: 4px; border: 1px dashed #dddddd; box-sizing: border-box; padding: 10px; display: inline-block; font-size: 12px; width: min-content; flex-shrink: 0; } &[arrow-right]::after { content: url(~@/assets/softwareIndustryBigBrain/common/tree-body/tree-body-arrow.jpg); //右上角的向右箭头图片 position: absolute; right: -22px; top: -10px; } .topo-title { transition: 0.618s ease; pointer-events: none; cursor: pointer; box-sizing: border-box; text-align: center; width: calc(100% - 40px); height: 30px; line-height: 26px; padding: 0 20px; margin: 0 auto; margin-top: -25px; background: #002766; border-radius: 4px; font-size: 16px; font-family: PingFangSC-Regular, PingFang SC; font-weight: 400; color: #ffffff; &[gray] { padding: 0 10px; height: 22px; background: #f0f2f5; border-radius: 11px; font-size: 12px; font-weight: 400; color: #999999; line-height: 22px; display: inline-block; width: min-content; white-space: nowrap; display: block; margin-top: -20px; } &.main-node[active] { pointer-events: auto; &:hover { background: #0050b3!important; } } } .topo-container { margin-top: 15px; .node-title { pointer-events: none; display: inline-block; height: 30px; padding: 0 20px; background: #40a9ff; border-radius: 4px; font-size: 14px; font-family: PingFangSC-Regular, PingFang SC; font-weight: 400; color: #ffffff; line-height: 26px; display: inline-block; width: min-content; white-space: nowrap; cursor: pointer; transition: 0.618s ease; &:hover { background: #0050b3; } &[active] { pointer-events: auto; background: #0050b3; &:hover { background: #0050b3cc; } } } [type="1"] { text-align: center; .topo-childrens { display: flex; justify-content: space-evenly; margin-top: 40px; position: relative; &::before { content: ""; width: 1px; height: 16px; background: #40a9ff; position: absolute; top: -42px; } &::after { content: ""; width: 50px; //二级横线宽度 height: 1px; background: #40a9ff; position: absolute; top: -26px; } > * { position: relative; // 默认的节点⊥ &::before { position: absolute; content: ""; // width: 100%; width: 0; height: 16px; // border-radius: 4px; box-sizing: border-box; border-right: 1px solid #40a9ff; top: -27px; } //第一个节点顶部的曲线╭ &:first-of-type { &::before { border: 1px solid #40a9ff; border-top-left-radius: 4px; border-right: none; left: 50%; width: 50%; border-bottom: none; } } //最后一个节点顶部的曲线╮ &:last-of-type { &::before { border: 1px solid #40a9ff; border-top-right-radius: 4px; border-left: none; right: 50%; width: 50%; border-bottom: none; } } } } .node-title[border] { pointer-events: none; background: #ffffff; border: 1px solid #40a9ff; color: #40a9ff; margin-bottom: 10px; &:last-of-type { margin-right: 0; margin-bottom: 0; } cursor: pointer; transition: 0.618s ease; &:hover { color: #0050b3; border-color: #0050b3; } &[active] { pointer-events: auto; color: #0050b3; border-color: #0050b3; &:hover { background: #40a9ff33; } } } } .tree-level { margin-bottom: 10px; &:last-of-type { margin-right: 0; margin-bottom: 0; } } } } // ---------------------------------------- [type="2"] { width: min-content; margin: 0 auto; .tree-level { margin-top: -5px; width: min-content; margin-left: 20px; //二级元素 第一个节点的左侧线条└ &:first-of-type .topo-title::before { height: 25px; top: -11px; } } .topo-title { pointer-events: none; margin-top: 15px; background: #ffffff; border: 1px solid #40a9ff; color: #40a9ff; font-size: 14px; height: 30px; line-height: 26px; display: block; width: min-content; white-space: nowrap; box-sizing: border-box; position: relative; cursor: pointer; transition: 0.618s ease; + .topo-childrens { margin-top: 10px; .tree-level { .topo-title { margin-right: -30px; margin-top: 15px; //二级元素 常规点的左侧线条└ &::before { height: 40px; top: -26px; } //二级元素延长线| &::after { content: ""; position: absolute; top: -25px; left: -36px; height: 40px; width: 1px; background: #40a9ff; } } //三级元素 第一个节点的左侧线条└ &:first-of-type .topo-title::before { height: 25px; top: -11px; } } } &:hover { color: #0050b3; border-color: #0050b3; } /* &[active] { &:hover { color: #0044b1; border-color: #0044b1; } } */ &[active] { pointer-events: auto; color: #0050b3; border-color: #0050b3; &:hover { background: #40a9ff33; } } &::before { content: ""; position: absolute; left: -16px; top: -25px; width: 16px; height: 40px; box-sizing: border-box; border: 1px solid #40a9ff; border-top: 0; border-right: 0; } } > .topo-childrens { display: flex; flex-wrap: wrap; margin-top: 0px; > .tree-level { margin-top: -5px; margin-bottom: 0; } } .topo-childrens { flex-direction: column; .tree-level:last-of-type { position: relative; // 用于隐藏二级元素左侧最后多余的延长线| &::after { content: ""; position: absolute; top: 30px; left: -15px; width: 1px; height: calc(100% - 40px); background: white; } // 最后一个节点元素左侧线条╰ > .topo-title:last-of-type { &::before { border-bottom-left-radius: 4px; } } } } } </style>
【sgTopo】强哥古法炮制、纯手工打造简单拓扑图、流程图、思维导图组件(完善中ing)(二)https://developer.aliyun.com/article/1476837