?
疯狂撸码中ing
实现组件效果?
?src/components/sgTopo.vue
<template>
<!-- 强哥的拓扑图2021.08.21 -->
<div
class="sg-topo tree-body"
v-if="data"
:arrow-right="data.body.arrowRight"
:style="data.body.style || {}"
>
<div class="topo-title" :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 :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
:style="child.title.style || {}"
class="topo-title"
gray
>{{ child.title.text }}</span
>
<ul class="topo-container">
<!-- 三级节点 -->
<li
v-for="(childNode, $i) in child.data"
:key="$i"
class="node-title"
border
>
{{ childNode.text }}
</li>
</ul>
</div>
</div>
</div>
</div>
<!-- 拓扑图类型:2 ------------------------------------------>
<div v-if="a.type == 2" :type="a.type">
<span :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 :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
: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 {
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;
}
}
.topo-container {
margin-top: 15px;
.node-title {
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;
}
}
[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] {
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;
}
}
}
.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 {
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;
}
&::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>
引用组件示例demo
<template>
<div class="sg-body">
<div style="padding: 30px; display: flex">
<sg-topo :data="data1" style="margin-right: 25px" />
<sg-topo :data="data2" style="margin-right: 25px" />
<sg-topo :data="data3" style="margin-right: 25px" />
<sg-topo :data="data4" style="margin-right: 25px" />
<sg-topo :data="data5" style="margin-right: 25px" />
</div>
</div>
</template>
<script>
import sgTopo from "../components/sgTopo";
export default {
components: {
sgTopo,
},
data() {
return {
// 数据使用
data1: {
body: {
arrowRight: true,
title: {
text: "一级内容",
style: {
width: "100px",
background: "#002766",
},
},
style: {
width: "300px",
},
data: [
{
type: 1,
title: {
text: "二级内容",
},
},
{
type: 1,
title: {
text: "二级内容",
},
},
{
type: 1,
title: {
text: "二级内容",
},
},
{
type: 1,
title: {
text: "二级内容",
},
children: [
{
title: {
text: "三级标题",
},
data: [
{
text: "三级内容",
},
{
text: "三级内容",
},
{
text: "三级内容",
},
{
text: "三级内容",
},
],
},
{
title: {
text: "三级标题",
},
data: [
{
text: "三级内容",
},
{
text: "三级内容",
},
{
text: "三级内容",
},
{
text: "三级内容",
},
],
},
],
},
],
},
},
data2: {
body: {
arrowRight: true,
title: {
text: "一级内容",
style: {
width: "100px",
background: "#002766",
},
},
style: {
width: "230px",
},
data: [
{
type: 1,
title: {
text: "二级内容",
},
},
{
type: 1,
title: {
text: "二级内容",
style: {
background: "#0050B3",
},
},
},
{
type: 1,
title: {
text: "二级内容",
},
},
{
type: 1,
title: {
text: "二级内容",
style: {
background: "#0050B3",
},
},
},
{
type: 1,
title: {
text: "二级内容",
},
},
{
type: 1,
title: {
text: "二级内容",
},
},
],
},
},
data3: {
body: {
arrowRight: true,
title: {
text: "一级内容",
style: {
width: "100px",
background: "#002766",
},
},
style: {
width: "230px",
},
data: [
{
type: 2,
title: {
text: "二级内容",
},
children: [
{
title: {
text: "三级内容",
},
/* children: [
{
title: {
text: "三级内容",
},
},
{
title: {
text: "三级内容",
},
},
{
title: {
text: "三级内容",
},
},
], */
},
{
title: {
text: "三级内容",
},
data: [
{
title: {
text: "三级内容",
},
},
{
title: {
text: "三级内容",
},
},
{
title: {
text: "三级内容",
},
},
],
},
{
title: {
text: "三级内容",
},
},
],
},
{
type: 2,
title: {
text: "二级内容",
},
children: [
{
title: {
text: "三级内容",
},
/* children: [
{
title: {
text: "三级内容",
},
},
{
title: {
text: "三级内容",
},
},
{
title: {
text: "三级内容",
},
},
], */
},
{
title: {
text: "三级内容",
},
data: [
{
title: {
text: "三级内容",
},
},
{
title: {
text: "三级内容",
},
},
{
title: {
text: "三级内容",
},
},
],
},
{
title: {
text: "三级内容",
},
},
],
},
],
},
},
data4: {
body: {
arrowRight: true,
title: {
text: "一级内容",
style: {
width: "100px",
background: "#002766",
},
},
style: {
width: "280px",
},
container: {
style: {
display: "flex",
"flex-wrap": "wrap",
"justify-content": "space-between",
},
},
data: [
{
type: 2,
title: {
text: "二级内容",
},
children: [
{
title: {
text: "三级内容",
},
children: [
{
title: {
text: "三级内容",
},
},
{
title: {
text: "三级内容",
},
},
{
title: {
text: "三级内容",
},
},
],
},
{
title: {
text: "三级内容",
},
data: [
{
title: {
text: "三级内容",
},
},
{
title: {
text: "三级内容",
},
},
{
title: {
text: "三级内容",
},
},
],
},
{
title: {
text: "三级内容",
},
},
],
},
{
type: 2,
title: {
text: "二级内容",
},
children: [
{
title: {
text: "三级内容",
},
/* children: [
{
title: {
text: "三级内容",
},
},
{
title: {
text: "三级内容",
},
},
{
title: {
text: "三级内容",
},
},
], */
},
{
title: {
text: "三级内容",
},
data: [
{
title: {
text: "三级内容",
},
},
{
title: {
text: "三级内容",
},
},
{
title: {
text: "三级内容",
},
},
],
},
{
title: {
text: "三级内容",
},
},
],
},
],
},
},
data5: {
body: {
arrowRight: true,
title: {
text: "一级内容",
style: {
width: "100px",
color: "#002766",
background: "#f0f2f5",
},
},
style: {
width: "250px",
},
container: {
style: {
display: "flex",
"flex-wrap": "wrap",
},
},
data: [
{
type: 2,
title: {
text: "标签",
style: {
"margin-right": "10px",
},
},
},
{
type: 2,
title: {
text: "标签",
style: {
"margin-right": "10px",
background: "#0050b3",
},
},
},
{
type: 2,
title: {
text: "标签",
style: {
"margin-right": "10px",
background: "#0050b3",
},
},
},
{
type: 2,
title: {
text: "标签1234567",
style: {
"margin-right": "10px",
background: "#0050b3",
},
},
},
{
type: 2,
title: {
text: "标签1237",
style: {
"margin-right": "10px",
},
},
},
{
type: 2,
title: {
text: "标签127",
style: {
"margin-right": "10px",
},
},
},
{
type: 2,
title: {
text: "标签12347",
style: {
"margin-right": "10px",
},
},
},
{
type: 2,
title: {
text: "标签67",
style: {
"margin-right": "10px",
},
},
},
{
type: 2,
title: {
text: "标签1247",
style: {
"margin-right": "10px",
background: "#0050b3",
},
},
},
{
type: 2,
title: {
text: "标签1234567",
style: {
"margin-right": "10px",
},
},
},
{
type: 2,
title: {
text: "标签7",
style: {
"margin-right": "10px",
},
},
},
{
type: 2,
title: {
text: "标签147",
style: {
"margin-right": "10px",
},
},
},
{
type: 2,
title: {
text: "标签1567",
style: {
"margin-right": "10px",
background: "#0050b3",
},
},
},
],
},
},
};
},
};
</script>
|