需求:
縱坐標為日期 橫坐標為 時間點 且 橫坐標有分支(前提事件)
縱坐標是用elementUi里的事件軸實現。

實現:
<template>
<div class="processInfo" v-loading="openAccountProcessLoading">
<common-title title=”時間軸"></common-title>
<!-- <div style="display:flex; width:900px;margin:100px auto;"> -->
<div class="timeLineTitle" >
<div class="timeLineItem">
<div class="finish timeLineStatus"></div>
<div>已完成</div>
</div>
<div class="timeLineItem">
<div class="being timeLineStatus"></div>
<div>進行中</div>
</div>
<div class="timeLineItem">
<div class="wating timeLineStatus"></div>
<div>待開始</div>
</div>
<div class="timeLineItem">
<div class="timeOut timeLineStatus"></div>
<div>超時警告</div>
</div>
</div>
<el-timeline style="margin-left: 100px; margin-top: 10px;" id="timeLineDate">
<el-timeline-item
v-for="(activity, index) in activities"
:key="index"
icon="el-icon-timer"
type="primary"
size="large"
:timestamp="activity.timestamp"
placement="top"
>
<!-- <div>1111</div> -->
<div style="display:flex;">
<timeLine :timeLineList="activity.timeLineList"></timeLine>
</div>
</el-timeline-item>
</el-timeline>
</div>
</template>
<script>
import { businessProcess } from '@/api/dataGovern'
import CommonTitle from '@/components/dataGovern/common/commonTitle'
import timeLine from './timeLine' export default { components: { CommonTitle, timeLine }, data() { return { openAccountProcessLoading:true, activities: [ { timestamp: '4月1日', timeLineList: [ { status: '', timestamp: '10:00', info: 'BOSS賬單', timeLineBranch: [ { timestamp: '10:00', status: 'being', info: 'BOSS賬單' }, { timestamp: '12:00', status: 'wating', info: 'CB用戶資料下載' }, { timestamp: '4月30日 12:00', status: 'wating', info: 'CB用戶資料下載' }, ], }, { status: 'wating', timestamp: '12:00', info: '入會', }, { status: 'finish', timestamp: '13:00', info: 'BOSS收入划撥', }, { status: 'wating', timestamp: '12:00', info: '入會', }, { status: 'finish', timestamp: '13:00', info: 'BOSS收入划撥', }, ], }, { timestamp: '4月3日', timeLineList: [ { status: 'finish', timestamp: '13:00', info: '工作室更名為:西安拓美網絡科技有限公司3', }, { status: 'finish', timestamp: '14:00', info: '工作室更名為:西安拓美網絡科技有限公司4', timeLineBranch: [ { timestamp: '4月1日', status: 'timeOut', info: '佣金結算' }, { timestamp: '4月1日', status: 'timeOut', info: 'z端用戶結算' }, { timestamp: '10:00', status: 'being', info: 'BOSS賬單' }, { timestamp: '12:00', status: 'wating', info: 'CB用戶資料下載' }, { timestamp: '4月30日 12:00', status: 'wating', info: 'CB用戶資料下載' }, ], }, { status: 'finish', timestamp: '16:00', info: '工作室更名為:西安拓美網絡科技有限公司5', }, { status: 'finish', timestamp: '18:00', info: '工作室更名為:西安拓美網絡科技有限公司6', }, { status: 'finish', timestamp: '16:00', info: '工作室更名為:西安拓美網絡科技有限公司5', }, { status: 'finish', timestamp: '18:00', info: '工作室更名為:西安拓美網絡科技有限公司6', }, ], }, { timestamp: '4月5日', timeLineList: [ { status: 'finish', timestamp: '16:00', info: '工作室更名為:西安拓美網絡科技有限公司5', }, { status: 'finish', timestamp: '18:00', info: '工作室更名為:西安拓美網絡科技有限公司6', }, ], }, { timestamp: '4月6日', timeLineList: [ { status: 'finish', timestamp: '20:00', info: '工作室更名為:西安拓美網絡科技有限公司03', }, { status: 'finish', timestamp: '22:00', info: '工作室更名為:西安拓美網絡科技有限公司02', }, { status: 'finish', timestamp: '2016-10-6', info: '工作室更名為:西安拓美網絡科技有限公司01', timeLineBranch: [ { timestamp: '4月1日', status: 'timeOut', info: 'z端用戶結算' }, { timestamp: '10:00', status: 'being', info: 'BOSS賬單' }, { timestamp: '12:00', status: 'wating', info: 'CB用戶資料下載' }, { timestamp: '4月30日 12:00', status: 'wating', info: 'CB用戶資料下載' }, ], }, { status: 'being', timestamp: '20:00', info: '工作室更名為:西安拓美網絡科技有限公司03', }, { status: 'finish', timestamp: '22:00', info: '工作室更名為:西安拓美網絡科技有限公司02', }, { status: 'finish', timestamp: '2016-10-6', info: '工作室更名為:西安拓美網絡科技有限公司01', }, { status: 'finish', timestamp: '20:00', info: '工作室更名為:西安拓美網絡科技有限公司03', }, { status: 'finish', timestamp: '20:00', info: '工作室更名為:西安拓美網絡科技有限公司03', }, ], }, ], } }, created() { this.getbusinessProcess() }, methods: { } } </script> <style scoped lang="scss"> h1, h2 { font-weight: normal; } ul { list-style-type: none; padding: 0; } li { display: inline-block; margin: 0 10px; width: 100%; } a { color: #42b983; } // .main-wrapper{ // background-color: #fff; // } .processInfo { background-color: #fff; } .timeLineTitle { display: flex; justify-content: center; /* 水平居中 */ align-items: center; /* 垂直居中 */ .timeLineItem { display: flex; padding: 20px; font-size: 12px; justify-content: center; /* 水平居中 */ align-items: center; /* 垂直居中 */ } .timeLineStatus { width: 12px; height: 10px; margin: 10px; border-radius: 2px; } .finish { background-color: #65bdaf; } .being { background-color: #eabd60; } .wating { background-color: #e2e9f9; } .timeOut { background-color: #ce3820; } } </style> <style lang="scss"> .processInfo { overflow: auto; height: 100%; .el-timeline-item { padding-bottom: 120px; } .el-timeline-item__timestamp.is-top { position: absolute; left: -50px; color: #205081; /* font-weight: bold; */ font-family: zcool-gdh; font-size: 12px; } .el-timeline-item__wrapper { padding: 0px 15px; } // .timeLineDate .el-timeline-item:last-child .el-timeline-item__tail{ // display: none; // } } </style>
timeLine:
<template>
<!--時間線-->
<div style="display:flex; width:95%" class="timeLineClass">
<!-- 當日志記錄不超過9個,全排列 -->
<div class="container" v-if="timeLineList.length<6">
<div style="display:flex;">
<div
v-for="(item,index) in timeLineList"
:key="index"
v-if="index>=0 && index<timeLineList.length-1"
style="flex:1;display:flex;flex-direction:column;"
>
<div style="display:flex">
<div class="item"></div>
<div
class="dot"
@mouseover="changeActive(index)"
:class="{active: index === timeIndex}"
></div>
<div class="item"></div>
</div>
<div class="item_top">
<span v-if="timeLineList[index].timestamp">{{timeLineList[index].timestamp}}</span>
</div>
<el-tooltip effect="light" placement="top">
<div slot="content">{{timeLineList[index].info}}</div>
<div class="item_bottom">
<div
class="itemBot_list"
:style="{backgroundColor:(timeLineList[index].status =='finish' ? '#65bdaf' :(timeLineList[index].status =='being'?'#eabd60':(timeLineList[index].status =='wating'?'#e2e9f9':(timeLineList[index].status =='timeOut'?'#ce3820':''))))}"
>{{timeLineList[index].info}}</div>
</div>
</el-tooltip>
<!-- 橫時間軸分支 -->
<div
class="timeLineBranch"
v-if="timeLineList[index].timeLineBranch && timeLineList[index].timeLineBranch.length>0"
>
<el-timeline>
<el-timeline-item
v-for="(itemBranch,indexBranch) in timeLineList[index].timeLineBranch"
:key="indexBranch"
:timestamp="itemBranch.timestamp"
>
<!-- {{itemBranch.info}} -->
<div :style="{color:(itemBranch.status =='finish' ? '#65bdaf' :(itemBranch.status =='being'?'#eabd60':(itemBranch.status =='wating'?'#e2e9f9':(itemBranch.status =='timeOut'?'#ce3820':''))))}">{{itemBranch.info}}</div>
</el-timeline-item>
</el-timeline>
</div>
</div>
<div style="flex:1;display:flex;flex-direction:column;">
<div style="display:flex">
<div class="item"></div>
<div
class="dot"
@mouseover="changeActive(timeLineList.length-1)"
:class="{active: timeLineList.length-1 === timeIndex}"
></div>
<div style="flex:1;"></div>
</div>
<div class="item_top">
<span>{{timeLineList[timeLineList.length-1].timestamp}}</span>
</div>
<el-tooltip effect="light" placement="top">
<div slot="content">{{timeLineList[timeLineList.length-1].info}}</div>
<div class="item_bottom">
<div
class="itemBot_list"
:style="{backgroundColor:(timeLineList[timeLineList.length-1].status =='finish' ? '#65bdaf' :(timeLineList[timeLineList.length-1].status =='being'?'#eabd60':(timeLineList[timeLineList.length-1].status =='wating'?'#e2e9f9':(timeLineList[timeLineList.length-1].status =='timeOut'?'#ce3820':''))))}"
>{{timeLineList[timeLineList.length-1].info}}</div>
</div>
</el-tooltip>
<!-- 橫時間軸分支 -->
<div
class="timeLineBranch"
v-if="timeLineList[timeLineList.length-1].timeLineBranch && timeLineList[timeLineList.length-1].timeLineBranch.length>0"
>
<el-timeline>
<el-timeline-item
v-for="(itemBranch,indexBranch) in timeLineList[timeLineList.length-1].timeLineBranch"
:key="indexBranch"
:timestamp="itemBranch.timestamp"
>
<div :style="{color:(itemBranch.status =='finish' ? '#65bdaf' :(itemBranch.status =='being'?'#eabd60':(itemBranch.status =='wating'?'#e2e9f9':(itemBranch.status =='timeOut'?'#ce3820':''))))}">{{itemBranch.info}}</div>
</el-timeline-item>
<!-- <el-timeline-item timestamp="2018/4/12"></el-timeline-item> -->
</el-timeline>
</div>
</div>
</div>
</div>
<!-- 當日志記錄超過8個,可以左右滑動 -->
<div class="container" v-else>
<div style="display:flex;">
<div style="flex:1;display:flex;flex-direction:column">
<!-- <div style="flex:1;display:flex;"> -->
<div style="display:flex;">
<!-- <div style="flex:1;"></div> -->
<div class="item"></div>
<div
class="move-button el-icon-arrow-left"
v-bind:class="{active: left_button_active}"
:disabled="left_button_disabled"
@click="moveLeft()"
></div>
<div class="item"></div>
</div>
<div class="item_top">
<span style="color:#000;">左</span>
</div>
<!-- <div class="item_bottom">
<div class="itemBot_end"></div>
</div>-->
</div>
<div
v-for="(item,index) in timeLineList"
:key="index"
v-if="index >= point && index <= point_end"
style="flex:1;display:flex;flex-direction:column;"
>
<div style="display:flex">
<div class="item"></div>
<div
class="dot"
@mouseover="changeActive(index)"
:class="{active: index === timeIndex}"
></div>
<div class="item"></div>
</div>
<div class="item_top">
<span>{{timeLineList[index].timestamp}}</span>
</div>
<el-tooltip effect="light" placement="top">
<div slot="content">{{timeLineList[index].info}}</div>
<div class="item_bottom">
<div
class="itemBot_list"
:style="{backgroundColor:(timeLineList[index].status =='finish' ? '#65bdaf' :(timeLineList[index].status =='being'?'#eabd60':(timeLineList[index].status =='wating'?'#e2e9f9':(timeLineList[index].status =='timeOut'?'#ce3820':''))))}"
>{{timeLineList[index].info}}</div>
</div>
</el-tooltip>
<!-- 橫時間軸分支 -->
<div
class="timeLineBranch"
v-if="timeLineList[index].timeLineBranch && timeLineList[index].timeLineBranch.length>0"
>
<el-timeline>
<el-timeline-item
v-for="(itemBranch,indexBranch) in timeLineList[index].timeLineBranch"
:key="indexBranch"
:timestamp="itemBranch.timestamp"
>
<div :style="{color:(itemBranch.status =='finish' ? '#65bdaf' :(itemBranch.status =='being'?'#eabd60':(itemBranch.status =='wating'?'#e2e9f9':(itemBranch.status =='timeOut'?'#ce3820':''))))}">{{itemBranch.info}}</div>
</el-timeline-item>
</el-timeline>
</div>
</div>
<div style="flex:1;display:flex;flex-direction:column;">
<div style="display:flex">
<div class="item"></div>
<div
class="move-button el-icon-arrow-right"
v-bind:class="{active: right_button_active}"
:disabled="right_button_disabled"
@click="moveRight()"
></div>
<div style="flex:1;"></div>
</div>
<div class="item_top">
<span style="color:#000;">右</span>
</div>
<!-- <div class="item_bottom">
<div class="itemBot_end"></div>
</div>-->
</div>
</div>
</div>
</div>
</template>
<script>
export default {
name: 'timeLine',
props: ['timeLineList'],
data() {
return {
timeIndex: this.timeLineList.length - 1, //默認當前選擇的為最近的時間點
point: this.timeLineList.length -5, //時間軸只展示5個,初始為最后5個
point_end: this.timeLineList.length - 1,
right_button_active: false,
left_button_active: true,
left_button_disabled: false,
right_button_disabled: true,
}
},
methods: {
changeActive(index) {
this.timeIndex = index
console.log('懸浮選擇的時間點:', this.timeIndex)
},
moveLeft() {
if (this.point > 0) {
this.point -= 1
this.point_end -= 1
this.timeIndex -= 1
this.right_button_disabled = false
this.right_button_active = true
if (this.point === 0) {
//如果移到第一個時間點,設置左按鈕不可點擊
this.left_button_disabled = true
this.left_button_active = false
}
}
},
moveRight() {
if (this.point_end < this.timeLineList.length - 1) {
this.point += 1
this.point_end += 1
this.timeIndex += 1
this.left_button_disabled = false
this.left_button_active = true
console.log('————————————', this.timeIndex)
if (this.point_end === this.timeLineList.length - 1) {
//如果移到最后一個時間點,設置右按鈕不可點擊
this.right_button_disabled = true
this.right_button_active = false
}
}
},
},
}
</script>
<style scoped lang='scss'>
ul {
list-style-type: none;
padding: 0;
}
li {
display: inline-block;
margin: 0 10px;
width: 100%;
}
.container {
width: 100%;
height: 30px;
margin-left: 0px;
padding-left: 0px;
margin-bottom: 5px;
}
.dot {
border: 2px solid #dcdfe6;
width: 15px;
height: 15px;
border-radius: 15px;
// background: white;
background: #499cf0;
margin: 2px 0px;
box-sizing: border-box;
}
.item {
flex: 1;
border-bottom: 1px solid #dcdfe6;
margin-bottom: 9px;
box-sizing: border-box;
min-width: 100px;
}
.item_top {
// flex: 1;
text-align: center;
height: 15px;
margin-top: -40px;
font-size: 14px;
}
.item_bottom {
flex: 1;
text-align: center;
height: 15px;
margin-top: 24px;
font-size: 12px;
.itemBot_list {
padding: 4px 8px;
border-radius: 5px;
background-color: #6bb9ba;
height: 26px;
width: 100px;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
display: inline-block;
vertical-align: middle;
}
.itemBot_end {
height: 26px;
visibility: hidden;
}
}
.move-button {
border: 2px solid #dcdfe6;
width: 40px;
height: 19px;
border-radius: 19px;
background: white;
text-align: center;
box-sizing: border-box;
}
.active {
background-color: #fff !important;
// border: 3px solid #67c23a;
border: 3px solid #499cf0;
}
</style>
<style lang="scss">
.timeLineClass {
.timeLineBranch {
// display: flex;
// justify-content: center;
position: relative;
// min-height: 45px;
height: 90px;
overflow-y: auto;
overflow-x:hidden;
.el-timeline {
// width: 30px; //和 itemBot_list的width一樣寬
position: absolute;
left: 50%;
/* padding-top: 1px; */
/* height: 100%; */
margin-left: -12px;
}
.el-timeline-item {
padding-bottom: 10px;
}
}
//橫軸時間軸 分支左邊時間
.el-timeline-item__timestamp.is-bottom {
font-size: 12px;
// white-space: nowrap;
margin-top: 3px;
position: absolute;
left: -100px;
top: 0px;
text-align: right;
min-width: 100px;
padding: 0 5px;
// margin-left: -60px;
// float: left;
}
//橫軸時間軸 分支右邊內容
.el-timeline-item__content {
font-size: 12px;
margin-top: 1px;
// white-space: nowrap;
// float: right;
// margin-right: -40px;
}
.el-timeline .el-timeline-item .el-timeline-item__tail {
position: absolute;
left: 4px;
height: 100%;
border-left: 2px solid #e4e7ed;
display: block;
}
.el-timeline .el-timeline-item:last-child .el-timeline-item__tail {
display: none;
}
}
</style>
橫坐標時間軸 借鑒原文git 地址:https://github.com/FareDream/timeLineCase
