组件
<template>
<div class="context">
<div class="top">
<div class="label-context">
<div class="label" v-for="(item, index) in value" :key="index">
<div class="label-text" v-if="index % 2 === 0">
{{ item.label }}
</div>
<div class="connect-line-box" v-if="index % 2 === 0">
<div class="connect-line"><i class="center-line-icon"></i></div>
</div>
</div>
</div>
</div>
<div class="center-line">
<div class="icon-box" v-for="(item, index) in value" :key="index">
<i class="center-line-icon"></i>
</div>
</div>
<div class="bottom">
<div class="label-context">
<div class="label" v-for="(item, index) in value" :key="index">
<div class="connect-line-box" v-if="index % 2 === 1">
<div class="connect-line"></div>
</div>
<div class="label-text" v-if="index % 2 === 1">
{{ item.label }}
</div>
</div>
</div>
</div>
</div>
</template>
<script>
export default {
name: 'FishBoneComponent',
props: {
value: {
type: Array,
default: () => [
{
time: '2024-06-13 15:27:30',
label: ''
},
{
time: '2024-06-12 15:27:30',
label: ''
},
{
time: '2024-06-12 15:27:30',
label: ''
},
{
time: '2024-06-12 15:27:30',
label: ''
},
{
time: '2024-06-12 15:27:30',
label: ''
},
{
time: '2024-06-12 15:27:30',
label: ''
},
{
time: '2024-06-12 15:27:30',
label: ''
},
{
time: '2024-06-12 15:27:30',
label: ''
},
{
time: '2024-06-12 15:27:30',
label: ''
},
{
time: '2024-06-12 15:27:30',
label: ''
},
]
}
},
mounted() {
this.value = this.value.sort((a, b) => {
return new Date(a.time) - new Date(b.time);
});
console.log(this.value)
}
}
</script>
<style lang="scss" scoped>
$center-color: #1890ff;
$text-box-width: 200px;
$text-margin-left: 10px;
$line-height: 40px;
$add-width: 0px;
$line-icon-size: 13px;
.context {
width: 100%;
padding: 0.5%;
height: 100%;
}
.center-line {
position: absolute;
height: 2px;
background-color: $center-color;
width: 98%;
display: flex;
align-items: center;
justify-content: left;
}
.center-line::after {
content: '';
position: absolute;
top: 50%;
right: -10px;
width: 0;
height: 0;
border-top: 5px solid transparent;
border-bottom: 5px solid transparent;
border-left: 10px solid $center-color;
transform: translateY(-50%);
}
.center-line .icon-box:first-child {
margin-left: $text-margin-left;
width: $text-box-width/2 + $line-icon-size/2;
flex-shrink: 0;
i {
float: right;
width: $line-icon-size;
height: $line-icon-size;
flex-shrink: 0;
}
}
.center-line .icon-box:not(:first-child) {
margin-left: $text-margin-left - $line-icon-size/2;
width: $text-box-width/2 + $line-icon-size/2;
flex-shrink: 0;
i {
float: right;
width: $line-icon-size;
height: $line-icon-size;
flex-shrink: 0;
}
}
.center-line-icon {
width: $line-icon-size;
height: $line-icon-size;
background-color: $center-color;
border-radius: 50%;
}
.top .label-context {
display: flex;
flex-direction: row;
justify-content: normal;
}
.connect-line-box {
display: flex;
flex-direction: row;
text-align: center;
justify-content: center;
}
.connect-line {
width: 2px;
height: $line-height;
background-color: #1d71fa;
}
.top .label {
display: flex;
flex-direction: column;
justify-content: flex-end;
margin-left: $text-margin-left;
}
.label > div {
width: $text-box-width;
margin-left: $add-width;
white-space: normal;
}
.bottom .label-context {
display: flex;
flex-direction: row;
justify-content: normal;
margin-left: $text-box-width/2;
}
.bottom .label {
display: flex;
flex-direction: column;
justify-content: flex-start;
margin-left: $text-margin-left;
}
.label-text {
padding: 6px;
background-color: rgb($center-color, 0.08);
border-radius: 3px;
color: black;
font-size: 15px;
}
</style>
测试案例
<template>
<div class="card">
<div class="title-box">
<span class="title">
大事记
</span>
<div style="float: right;">
<el-button type="primary" icon="el-icon-edit" size="mini">更多</el-button>
</div>
</div>
<FishBoneComponent :value="data"></FishBoneComponent>
</div>
</template>
<script>
import FishBoneComponent from "@/views/FishBoneComponent";
export default {
name: "FishBone",
components: {FishBoneComponent},
data(){
return{
data: [
{
time: '2024-06-13 15:27:30',
label: '测试测试测试测试测试测试测试测试测试测试测试测试测试测试11'
},
{
time: '2024-06-12 15:27:30',
label: '测试测试测试测试测试测试测试测试测试测试测试测试测试测试22'
},
{
time: '2024-06-12 15:27:30',
label: '测试测试测试测试测试测试测试测试测试测试测试测试测试测试33'
},
{
time: '2024-06-12 15:27:30',
label: '测试测试测试测试测试测试测试测试测试测试测试测试测试测试44'
},
{
time: '2024-06-12 15:27:30',
label: '55'
},
{
time: '2024-06-12 15:27:30',
label: '测试测试测试测试测试测试测试测试测试测试测试测试测试测试66'
},
{
time: '2024-06-12 15:27:30',
label: '测试测试测试测试测试测试测试测试测试测试测试测试测试测试77'
},
{
time: '2024-06-12 15:27:30',
label: '测试测试测试测试测试测试测试测试测试测试测试测试测试测试'
},
{
time: '2024-06-12 15:27:30',
label: '测试测试测试测试测试测试测试测试测试测试测试测试测试测试'
},
{
time: '2024-06-12 15:27:30',
label: '测试测试测试测试测试测试测试测试测试测试测试测试测试测试'
},
]
}
}
}
</script>
<style scoped>
.card{
padding: 8px;
}
.title-box{
margin-bottom: 8px;
}
.title{
font-size: 18px;
font-weight: bold;
color: #1890ff;
}
</style>
预览图