本例实现的功能有
- 一天按照0-24小时竖向显示
- 可显示每个小时段的任务/内容
- 当前的时刻可以明确的在页面中显示
- 鼠标在任务/内容滑动过程中平缓过度
- 第一步,计算一天的时间
computed: {
hours() {
let result = [], hour
for (let i = 0; i < 24; i++) {
if (i < 10) {
hour = '0' + i + ':00'
} else {
hour = i + ':00'
}
result.push({ hour })
}
return result
},
},
- 第二步,根据接口回来的数据和时间进行关联
async getList(){//获取数据
this.queryParams = {
beginPlanExecuteTime: this.beginPlanExecuteTime,
endPlanExecuteTime: this.endPlanExecuteTime,
pageSize:9999,
pageNo:1
}
let {data} = await getTaskCalendar(this.queryParams)
this.list = data.map(item=>({
...item,
planExecuteTime: moment(item.planExecuteTime).format('HH:mm'),
hour: moment(item.planExecuteTime).format('HH:00')
}))
this.taskList = this.hours.map(item=>{
let result = this.list.filter(it=>it.hour === item.hour)
return { ...item, tasks: result }
})
},
- 第三步,对在当前时间的时分有明确的标志,每秒获取一次时间,组件销毁的时候别忘了清除定时器哦~
getCurrentTime(){
this.timer = setInterval(()=>{
let hour = new Date().getHours() < 10 ? `0${new Date().getHours()}` : new Date().getHours()
let minute = new Date().getMinutes() < 10 ? `0${new Date().getMinutes()}` : new Date().getMinutes()
this.currentTime = hour + ':' + minute
this.currentPosition = (new Date().getHours()) * 54 + (new Date().getMinutes()/60) * 54 + 'px'
}, 1000)
},
- 视图部分
<el-scrollbar>
<div class="time-calendar-wrap">
<div class="current-time" :style="{top: currentPosition}">
<span class="text">{{ currentTime }}</span>
</div>
<ul>
<li v-for="item in taskList" class="time-calendar-box">
<span class="time">{{ item.hour }}</span>
<!--任务-->
<div class="task-wrap">
<!-- // 1完成,2超期,3终止,4,正在执行,5等待执行-->
<div v-for= "task in item.tasks"
:key="task.id"
@click="handleSelectTask(task)"
:class="['task-grid',
{'finish': task.executeState==1 },
{'out-time':task.executeState ==2},
{'stop': task.executeState ==3},
{'ing': task.executeState==4 },
{'wait': task.executeState==5},
{'focus': taskId === task.id}
]"
>
<p>
{{task.taskName}}
</p>
<p>
{{task.planExecuteTime}}
</p>
</div>
</div>
</li>
</ul>
</div>
</el-scrollbar>
- 页面样式部分
.time-calendar-wrap {
padding-left: 20px;
margin-top: 20px;
position: relative;
padding-top:4px;
height: calc(100vh - 280px);
ul{
padding-left: 40px;
}
.current-time{
position: relative;
left: 40px;
height: 2px;
background-color: rgba(255,255,255,0.5);
.text{
position: absolute;
left: -40px;
top:-10px
}
&::after{
content: '';
background-color: rgba(255,255,255,0.5);
height: 10px;
width: 10px;
border-radius: 50%;
display: block;
position: absolute;
left:-10px;
top:-4px
}
}
}
.task-wrap{
display: flex;
.task-grid{
position: relative;
background-image: linear-gradient(to right, rgb(244 114 38 / 25%) 0%,rgb(0 0 0 / 0%) 100%);
border-top: 1px solid transparent;
border-bottom: 1px solid transparent;
cursor: pointer;
transition: all 0.55s ease-in-out 0s;
height: 54px;
display: flex;
flex-direction: column;
justify-content: center;
padding-left: 10px;
text-overflow: ellipsis;
overflow: hidden;
width: 100%;
white-space: nowrap;
flex:1;
&:after,&:before{
position: absolute;
height: 1px;
width: 100%;
content: '';
background-color: transparent;
left: 0;
}
&:after{
bottom: 0;
}
&:before{
top: 0;
}
p{
text-overflow: ellipsis;
overflow: hidden;
}
&:hover{
flex: 24;
}
.large{
}
&.out-time{
background-image: linear-gradient(to right, rgb(244 114 38 / 25%) 0%,rgb(0 0 0 / 0%) 100%);
border-left: 4px solid rgb(244 114 38);
&.focus{
&:after,&:before{
background-image: linear-gradient(to right, rgb(244 114 38 / 90%) 0%,rgb(0 0 0 / 0%) 100%);
}
}
}
&.finish{
background-image: linear-gradient(to right, rgb(7 160 88 / 25%) 0%,rgb(0 0 0 / 0%) 100%);
border-left: 4px solid rgb(7 160 88);
&.focus{
&:after,&:before{
background-image: linear-gradient(to right, rgb(7 160 88 / 90%) 0%,rgb(0 0 0 / 0%) 100%);
}
}
}
&.wait{
background-image: linear-gradient(to right, rgb(192 125 255 / 25%) 0%,rgb(0 0 0 / 0%) 100%);
border-left: 4px solid rgb(192 125 255);
&.focus{
&:after,&:before{
background-image: linear-gradient(to right, rgb(192 125 255 / 90%) 0%,rgb(0 0 0 / 0%) 100%);
}
}
}
&.ing{
background-image: linear-gradient(to right, rgb(35 150 255 / 25%) 0%,rgb(0 0 0 / 0%) 100%);
border-left: 4px solid rgb(35 150 255 );
&.focus{
&:after,&:before{
background-image: linear-gradient(to right, rgb(35 150 255 / 90%) 0%,rgb(0 0 0 / 0%) 100%);
}
}
}
&.stop{
background-image: linear-gradient(to right, rgb(237 27 27 / 25%) 0%,rgb(0 0 0 / 0%) 100%);
border-left: 4px solid rgb(237 27 27 );
&.focus{
&:after,&:before{
background-image: linear-gradient(to right, rgb(237 27 27 / 90%) 0%,rgb(0 0 0 / 0%) 100%);
}
}
}
}
}