vue写一个自定义日历组件

因为最近需求需要,写一个自定义日历。

废话少说直接上效果图, 日历返回的起始时间

 

 

 

代码实现

首先根据当前月时间 组建日历

 

 构建日历  

createTime(){
                let t = this;
                let Timesr = getTime();
                t.Timesr = Timesr;
                t.$nextTick(()=>{
                    this.optTime(Timesr)
                })
            },
            // 到时候需要什么数据改这个函数
            optTime(Timesr){
                let t = this;
                let lastDay= new Date(Timesr.y,Timesr.month,0).getDate();
                this.weekey =  new Date(`${Timesr.y}-${Timesr.month}-01`).getDay();
                let arr = []
                 arr[t.monthIndex] = {Yname:`${Timesr.y}年${Timesr.month}月`,chlid:[]}
                for(let i = 1; i<=lastDay; i++){
                    let _o = {
                        day:i,
                        about:Timesr.d > i?1:0,
                        Reducible:Timesr.d >i?1:0,
                        price:i==10?100:0,
                        m:Timesr.month,
                        y:Timesr.y,
                        dayText:`${Timesr.y}-${Timesr.month<=9?'0'+Timesr.month:Timesr.month}-${i<=9?'0'+i:i}` 
                    }
                    arr[t.monthIndex].chlid.push(_o)
                }
                t.dayList = arr
                
            },

完整代码 

<template>
    <view class="day_conter" v-if="isModal" >
        <view class="day_head">
            <view @click="rePath('upper')">上一月</view>
            <view class="day_tille" >{{dayList[monthIndex].Yname}}</view>
            <view @click="rePath('next')" >下一月</view>
        </view>
        <view class="day-wrap">
            <view class="day-tit">
                <view class="day-tit-cell" v-for="(item,index) in week" :key="index">{{item}}</view>
            </view>
            <view class="day-table">
                    <view class="day-list-cell" v-for="(item,index) in weekey" :key="index"></view>
                    <view class="day-list-cell"  v-for="(item,index) in dayList[monthIndex].chlid" 
                    :key="index" 
                    :class="[item.about>0?'white':'',(item.dayText &&  selectDay.includes(item.dayText)  )?'act':'']" @click="selectDate(item.about>0?item:'',index)"
                    >
                        <text class="day_about" v-if="!selectDay.includes(item.dayText)" :class="!item.about?'':'day_yabout'">{{!item.about?'已约满':'可预约'}} </text>
                        <tex class="day_about" v-if="mode==true&&selectDay.length>0">{{selectDay[0]==item.dayText?'入住':selectDay[selectDay.length-1]==item.dayText?'离店':selectDay[index]==item.dayText?'选中':''}}</tex>
                        <text class="day-list-cell-day">{{item.day}}</text>
                        <text class="day-list-cell-price" v-if="item.about&&item.price">补差¥{{item.price}}</text>
                    </view>
            </view>
        </view>
    </view>
</template>
<script>
    import { getTime } from '../../untils/index.js'
    export default{
        props:{
            isModal:{
                type:Boolean,
                default:false
            },
            mode:{ //单多选
                type:Boolean,
                default:true
            }
        },
        data(){
            return{
                week:['','','','','','',''],
                weekey:0,
                dayList:[],
                monthIndex:0,
                Timesr:'',
                opt:[],
                selectDay:[], //选中的
            }
        },
        created(){
            this.createTime()
        },
        watch:{
            Timesr:{
                deep:true,
                handler(val){
                    this.optTime(val)
                }
            }
        },
        methods:{
            
            init(){
                let t  = this;
                t.createTime()
            },
            // 初始化日历根据当前月组建日历 
            createTime(){
                let t = this;
                let Timesr = getTime();
                t.Timesr = Timesr;
                t.$nextTick(()=>{
                    this.optTime(Timesr)
                })
            },
            // 到时候需要什么数据改这个函数
            optTime(Timesr){
                let t = this;
                let lastDay= new Date(Timesr.y,Timesr.month,0).getDate();
                this.weekey =  new Date(`${Timesr.y}-${Timesr.month}-01`).getDay();
                let arr = []
                 arr[t.monthIndex] = {Yname:`${Timesr.y}年${Timesr.month}月`,chlid:[]}
                for(let i = 1; i<=lastDay; i++){
                    let _o = {
                        day:i,
                        about:Timesr.d > i?1:0,
                        Reducible:Timesr.d >i?1:0,
                        price:i==10?100:0,
                        m:Timesr.month,
                        y:Timesr.y,
                        dayText:`${Timesr.y}-${Timesr.month<=9?'0'+Timesr.month:Timesr.month}-${i<=9?'0'+i:i}` 
                    }
                    arr[t.monthIndex].chlid.push(_o)
                }
                t.dayList = arr
                
            },
            //上下一个月
            rePath(o){
                let t = this;
                let opt = t.Timesr
                t.selectDay = []
                t.opt = []
                if(o == 'upper'){
                     opt.month--
                     if( opt.month==0 ){
                         opt.month = 12
                         opt.y--
                     }
                }else{
                        opt.month++
                    if( opt.month>12 ){
                         opt.month = 1
                         opt.y++
                    }
                }
            },
            //随便乱选
            selectDate(Node){
                let opt = this.opt;
                let arr = this.selectDay;
                let t = this;
                 if(Node){
                     if(!this.mode){ //单选
                        t.selectDay = [Node.dayText]
                        t.$emit('select',Node)
                     }else{
                         //开始
                         if(arr.length>0&&arr.includes(Node.dayText)){
                            if(arr.length>1){
                                arr.map((item,indexs)=>{
                                    if(item == Node.dayText ){
                                         opt[1] = {... Node} 
                                    }
                                })
                            }else{
                                arr = arr.filter(item=>{
                                    return item !== Node.dayText
                                })
                                opt = []
                                t.opt = []
                            }
                         }
                         else{
                             arr.push(Node.dayText);
                             if( arr.length==1 ){
                                 opt[0] = {...Node }
                             }else if(arr.length>1){
                                 opt[1] = {...Node}
                             }
                         }
                         t.selectDay = arr
                        if(opt.length == 2){
                            t.FnTime(opt,arr)
                        }
                     }
                 }
            },
            // 多选特效
            FnTime(Node,list){
                let t = this;
                let arr = [];
                let num = 0;
                let isNum=false
                if(Node[1].day>Node[0].day ){
                    num = Node[1].day-Node[0].day;
                    isNum=true
                }else{
                    num = Node[0].day-Node[1].day;
                    isNum=false
                }
                let o = new Array(num);
                for( let i =0; i <= o.length;i++){
                    arr.push( `${isNum?Node[0].y:Node[1].y}-${isNum?Node[0].m<=9?'0'+Node[0].m:Node[0].m:Node[1].m<=9?'0'+Node[1].m:Node[1]}-${isNum?(Node[0].day+i)<=9?'0'+(Node[0].day+i):(Node[0].day+i):(Node[1].day+i)<=9?'0'+(Node[1].day+i):(Node[1].day+i)}` )
                }
                t.selectDay = arr
                if(!isNum){
                     Node.reverse() 
                }
                t.$emit('select',Node)   //返回 选中起始时间
            }
        }
        
    }
</script>
<style lang="scss">
    @import "./index.scss"
</style>

 css 如下

.day_conter {
  max-height: 75vh;
  overflow-y: auto;
  //background: #FCFCFC;
  padding-bottom: calc(116rpx + env(safe-area-inset-bottom));
  position: relative;
  width: 750rpx;
  border-radius: 24rpx 24rpx 0 0;
  padding: 20rpx 0 300rpx 0;
  margin-top: 20rpx;

  .day_head {
    display: flex;
    height: 82rpx;
    justify-content: center;
    line-height: 82rpx;
    background: #FFFFFF;
    border-bottom: 1rpx solid #EEEEEE;

    .day_tille {
      padding: 0 20rpx;
    }
  }

  .day-wrap {
    //padding-bottom: 16rpx;
    background: #FFFFFF;
    width: 100%;
    position: relative;

    .day-tit {
      display: flex;
      justify-content: flex-start;

      .day-tit-cell {
        width: 14.25%;
        box-sizing: border-box;
        height: 82rpx;
        background-color: #FFFFFF;
        font-size: 24rpx;
        font-family: Microsoft YaHei;
        font-weight: 400;
        text-align: center;
        color: #333333;
        display: flex;
        justify-content: center;
        flex-flow: column;
      }

      .day-tit-cell:nth-of-type(1) {
        color: #FF7920;
      }
    }

    .day-table {
      display: flex;
      justify-content: flex-start;
      flex: 1;
      flex-direction: row;
      flex-wrap: wrap;
      font-size: 18rpx;

      .day-list-cell {
        width: 14.26%;
        height: 120rpx;
        box-sizing: border-box;
        border-top: 2rpx solid #F6F6F6;
        border-bottom: 2rpx solid #F6F6F6;
        display: flex;
        justify-content: flex-start;
        flex-flow: column;
        padding-top: 12rpx;
        background: #F9F9F9;
        border-right: 1rpx solid #FFFFFF;

        .day_about {
          text-align: center;
          font-weight: bold;
          display: block;
          font-size: 20rpx;
        }

        .day-Reducible {
          text-align: center;
        }

        .day-list-cell-day {
          text-align: center;
          font-size: 28rpx;
          font-family: PingFang SC;
          font-weight: 400;
          line-height: 43rpx;
          color: #333333;
        }

        .day-list-cell-price {
          text-align: center;
          font-size: 16rpx;
          font-family: PingFang SC;
          font-weight: bold;
          line-height: 20rpx;
          color: #FF7920;
        }
      }

      .day-list-cell.white {
        background: #FFFFFF;
      }

      .day_yabout {
        // 可预约
        color: #9BD588;
      }

      .day_man {
        color: #999;
      }

      .day_less {
        // 紧张
        color: #FF7920;
      }

      .day-list-cell.act {
        background: #3685FC;
        border-radius: 16rpx 0rpx 0rpx 16rpx;

        .day-list-cell-day {
          color: #FFFFFF;
        }

        .day_about {
          color: #fff;
        }

        .day-list-cell-price {
          color: #FFFFFF;
        }
      }

      .day-list-cell.acts {
        background: #3685FC;
        border-radius: 0rpx 16rpx 16rpx 0rpx;

        .day-list-cell-day {
          color: #FFFFFF;
        }

        .day_about {
          color: #fff;
        }

        .day-list-cell-price {
          color: #FFFFFF;
        }
      }

      .day-list-cell.actdan {
        background: #EAF1FE;

        .day-list-cell-day {
          color: #A5CEFF;
        }

        .day_about {
          color: #A5CEFF;
        }

        .day-list-cell-price {
          color: #A5CEFF;
        }
      }

      .day-list-cell.actives {
        background: #3685FC;
        border-radius: 16rpx;

        .day-list-cell-day {
          color: #FFFFFF;
        }

        .day_about {
          color: #fff;
        }

        .day-list-cell-price {
          color: #FFFFFF;
        }
      }
    }
  }
}

 

posted @ 2022-03-25 10:11  落魄的程序员  阅读(1375)  评论(5编辑  收藏  举报