手动实现一天的日历

164 阅读3分钟

本例实现的功能有

  • 一天按照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%);
        }
      }
    }
  }
}