vue封装个日历,样式参考vant

vue封装个日历,样式参考vant
结果展示
在这里插入图片描述


<template>
    <div class="report">
      <Header title="工作日历"  :isShowLeft="true" @onClickBack="goBack" />
      <div class="report-content">
        <van-icon name="arrow-left" class="img3" size="13"  @click="prevYear()" />
        <van-icon name="arrow-left" class="img1" size="13"  @click="prevMonth()" />
        <van-icon name="arrow"  class="img2" size="13"  @click="nextMonth()" />
        <van-icon name="arrow"  class="img4" size="13"  @click="nextYear()" />
          <div class="calendar">
          <div class="header">
            <span>{{ year }}{{ month }}</span>
          </div>
          <div class="box">
              <div class="box-top">
              <div class="box-top-content">
                  <div class="week-box"></div>
                  <div class="week-box"></div>
                  <div class="week-box"></div>
                  <div class="week-box"></div>
                  <div class="week-box"></div>
                  <div class="week-box"></div>
                  <div class="week-box"></div>
              </div>
              </div>
              <div class="box-bottom">
              <div class="box-mark">{{ month }}</div>
              <div class="box-bottom-content" v-for="(week, index) in weeks" :key="index">
                  <div class="box-bottom-content-box" v-for="(day, i) in week" :key="i" :class="{ today: day.today, selected: day.selected }" @click="selectDay(day)">
                  {{ day.date && day.date.getDate() }}
                  </div>
              </div>
              </div>
          </div>
          </div>
      </div>
      <FloatIcons :padding="'10 10 60 10'" class="icons-warp">
        <div @click="backToday">
          <div class="float-icon-item">
            <span style="font-size: 15px;"></span>
          </div>
        </div>
      </FloatIcons>
    </div>
    
  </template>
  
  <script>
  import Header from "@/components/header/Header.vue";
  import { useRouter } from 'vue-router'
  import FloatIcons from "@/components/s-icons";
  export default {
    components:{
        Header,
        FloatIcons
    },
    data() {
      return {
        router: useRouter(),
        year: new Date().getFullYear(),
				month: new Date().getMonth() + 1 ,
        selectedDate: null,
      };
    },
    computed: {
      weeks() {
        const weeks = [];
        const firstDayOfMonth = new Date(this.year, this.month - 1, 1);
        const lastDayOfMonth = new Date(this.year, this.month, 0);
        const daysInMonth = lastDayOfMonth.getDate();
        let dayOfWeek = firstDayOfMonth.getDay();
        let date = 1;
  
        for (let i = 0; i < 6; i++) {
          const week = [];
  
          for (let j = 0; j < 7; j++) {
            if (i === 0 && j < dayOfWeek) {
              week.push({ date: null });
            } else if (date > daysInMonth) {
              week.push({ date: null });
            } else {
              const today = new Date();
              const selected = this.selectedDate && this.selectedDate.getTime() === new Date(this.year, this.month - 1, date).getTime();
              week.push({ date: new Date(this.year, this.month - 1, date), today: today.getTime() === new Date(this.year, this.month - 1, date).getTime(), selected });
              date++;
            }
          }
  
          weeks.push(week);
        }
        return weeks.filter((e, i) => i === 5 ? !!e[0].date : true);
      },
    },
    mounted(){
      this.setSelectDate()
    },
    methods: {
      setSelectDate(){
        this.selectedDate = new Date(this.year, this.month - 1, this.selectedDate?.getDate() || new Date().getDate())
      },
      prevMonth() {
        if (this.month === 1) {
          this.year--;
          this.month = 12;
        } else {
          this.month--;
        }
        this.setSelectDate()
      },
      prevYear(){
        this.year--;
        this.setSelectDate()
      },
      nextMonth() {
        if (this.month === 12) {
          this.year++;
          this.month = 1;
        } else {
          this.month++;
        }
        this.setSelectDate()
      },
      nextYear(){
        this.year++;
        this.setSelectDate()
      },
      selectDay(day) {
        if (day.date) {
          this.selectedDate = day.date;
        }
      },
      /** 返回 */
      goBack(){
          this.router.go(-1)
      },
      /** 返回今天 */
      backToday(){
        this.year = new Date().getFullYear()
				this.month = new Date().getMonth() + 1 
        this.selectedDate = new Date(this.year, this.month - 1, new Date().getDate())
      
      },
    },
  };
  </script>
  
<style  scoped lang="less">
.report{
    height: 100%;
    width: 100%;
    /* background: #F3F8FC; */
    .report-content{
        height: calc(~'100% - 46px');
        width: 100%;
        position: relative;
        // overflow: scroll;
        .calendar {
            font-family: Arial, sans-serif;
            /* width: 238px; */
            background: #fff;
            margin: 0 auto;
            .header {
                display: flex;
                justify-content: center;
                align-items: center;
                margin-bottom: 10px;
                height: 34px;
            }
            .header span {
                background-color: transparent;
                font-size: 18px;
            }
            .box {
                width: 100%;
                border-collapse: collapse;
                padding: 0;
            }
            .box-top{
              box-shadow:  0 2px 10px rgba(125, 126, 128, .16);;
            }
            .box-top-content {
                display: flex;
                justify-content: space-between;
            }
            .box-top-content > div {
                width: 34px;
                height: 34px;
                display: flex;
                justify-content: center;
                align-items: center;
            }
            .box-mark{
              position: absolute;
              top: 164px;
              left: 50%;
              z-index: 0;
              color: red;
              font-size: 160px;
              transform: translate(-50%,-50%);
              pointer-events: none;
            }
            .box-bottom {
                display: flex;
                flex-direction: column;
            }
            .box-bottom-content {
                display: flex;
                justify-content: space-between;
            }
            .box-bottom-content-box {
                width: 34px;
                height: 34px;
                display: flex;
                justify-content: center;
                align-items: center;

                position: relative;
    
                font-size: 14px;
                font-family: PingFangSC, PingFangSC-Regular;
                font-weight: 400;
                text-align: center;
                // line-height: 34px;
            }
            
            .today {
                background-color: #eee;
            }
            
            .selected {
                background-color: #007bff;
                color: #fff;
                border-radius: 50%;
            }
        }
    }
}
.week-box{
    opacity: 0.65;
    font-size: 14px;
    font-family: PingFangSC, PingFangSC-Medium;
    font-weight: 500;
    color: #666666;
}
.img1,
	.img2,
    .img3,
    .img4 {
		width: 22px;
		height: 22px;
    line-height: 22px;
    position: absolute;
		top: 8px;
		background: #f2f2f2;
		border-radius: 6px;
	}

	.img1 {
		left: 85px;
	}

	.img2 {
		right: 85px;
	}
    .img3 {
		left: 45px;
	}

	.img4 {
		right: 45px;
	}
  
  .icons-warp {
  border-radius: 20px;
  background-color: #99a9bf;
  z-index: 99999;
  height: 35px;
  line-height: 35px;
  width: 35px;
  border-radius: 50%;
}
  
  
</style>
  
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值