日历插件

适用于vue、uniapp、微信小程序的日历插件(代码片段)

说明:

适用于vue、uniapp。可运行再pc、手机浏览器、手机微信浏览器、手机app。

插件说明:

最近公司开发约课系统,要求日历上能展示还剩多少人可预约。我想着百度一搜一大把啊,于是我找了一上午没找到合适的,于是我结合百度的和自己的需求写了一个。

先看看效果吧

日历插件插图

样式啥的,完全可控,还能增加状态

开始吧

首先来段HTML代码:

<div class="calendar">
    <div class='tit flex_c_c'>
        <div class='pre flex_c_c' @click='gotoPreMonth()'> < </div>
        <div class='current flex_c_c'>{{currentYear}}年{{currentMonth}}月</div>
        <div class='next flex_c_c' @click='gotoNextMonth()'> > </div>
    </div>
    <div class='content1'>
        <div class="head">
            <div class="list">日</div>
            <div class="list">一</div>
            <div class="list">二</div>
            <div class="list">三</div>
            <div class="list">四</div>
            <div class="list">五</div>
            <div class="list">六</div>
        </div>
        <div class="list" v-for="(item,index) in allArr" :key="index">
            <div
                v-if="item.state==1"
                class="box succese"
            >
                <div>{{item.date}}</div>
                <div class="t24">剩{{item.num}}人</div>
            </div>
            <div
                v-else-if="item.num>0"
                :class="'box have ' + (clickDate==item.date?'clickDate':'')"
                @click="rlChange(item.date)"
            >
                <div>{{item.date}}</div>
                <div class="t24">剩{{item.num}}人</div>
            </div>
            <div
                v-else-if="item.num==0"
                class="box nothing"
            >
                <div>{{item.date}}</div>
                <div class="t24">剩{{item.num}}人</div>
            </div>
            <div
                v-else
                class="box gray"
            >
                <div>{{item.date}}</div>
            </div>
        </div>
    </div>
</div>

html根据需求还需要修改,后面细说怎么根据需求修改

再来段css代码:

// 日历less写法
.calendar{
    width: 100%;
    background: #fff;
    border-radius: 8rpx;
    box-shadow: 0 0 2px rgb(0 0 0 / 10%);
    .tit{
        font-size: 34rpx;
        color: #2A2A2A;
        padding: 25rpx 0;
        border-bottom: 1px solid #c8c7cc;
        .current{
            margin: 0 25rpx;
            line-height: 1;
        }
        .next{
            line-height: 1;
        }
        .pre{
            line-height: 1;
            transform:rotate(180deg);
            -ms-transform:rotate(180deg);   /* IE 9 */
            -moz-transform:rotate(180deg);  /* Firefox */
            -webkit-transform:rotate(180deg); /* Safari 和 Chrome */
            -o-transform:rotate(180deg);    /* Opera */
        }
    }
    .content1{
        display: flex;
        flex-wrap: wrap;
        box-sizing: border-box;
        .head{
            width: 100%;
            display: flex;
            flex-wrap: wrap;
            border-bottom: 1px solid #F5F5F5;
            .list{
                background: #fff;
            }
        }
        .list{
            width: calc(14.285% - 4px);
            background: #f6f6f6;
            height: 80rpx;
            line-height: 1.2;
            display: flex;
            flex-direction: column;
            justify-content: center;
            align-items: center;
            text-align: center;
            flex-shrink: 0;
            font-size: 32rpx;
            /* background: rgb(224, 199, 199); */
            margin: 2px;
            .box{
                font-size: 28rpx;
                width: 100%;
                height: 100%;
                display: flex;
                flex-direction: column;
                justify-content: center;
                align-items: center;
                text-align: center;
            }
            .have{
                background: #fff;
            }
            .succese{
                background: #0acf63;
            }
            .nothing{
                opacity: 0.6;
            }
            .t24{
                color: #f67a47;
            }
            .clickDate{
                background: #007aff;
                color: #fff;
            }
        }
        .gray{
            color: rgba(0,0,0,0.4);
        }
    }
}

先上一段不需要修改的js吧,这段代码我是用mixin导入到页面,当然也可以写成组件,这里我只讨论方法

const calendar = {
    data () {
        return {
            clickDate: '',
            currentYear: '',
            currentMonth: '',
            currentMonthDateLen: 0, // 当月天数
            preMonthDateLen: 0, // 当月中,上月多余天数
            allArr:[], // 当月所有数据
        }
    },
    onShow() {
        var date = new Date();
        this.currentYear = date .getFullYear();
        this.currentMonth = date .getMonth()+1;
    },
    methods: {
        // 获取某年某月总共多少天
        getDateLen(year, month) {
            let actualMonth = month - 1;
            let timeDistance = +new Date(year, month) - +new Date(year, actualMonth);
            return timeDistance / (1000 * 60 * 60 * 24);
        },
        // 获取某月1号是周几
        getFirstDateWeek(year, month) {
            return new Date(year, month - 1, 1).getDay()
        },
        // 上月 年、月
        preMonth(year, month) {
            if (month == 1) {
                return {
                    year: --year,
                    month: 12
                }
            } else {
                return {
                    year: year,
                    month: --month
                }
            }
        },
        // 下月 年、月
        nextMonth(year, month) {
            if (month == 12) {
                return {
                    year: ++year,
                    month: 1
                }
            } else {
                return {
                    year: year,
                    month: ++month
                }
            }
        },
        // 获取当月中,上月多余数据,返回数组
        getPreArr(){
            let preMonthDateLen = this.getFirstDateWeek(this.currentYear, this.currentMonth) // 当月1号是周几 == 上月残余天数)
            let preMonthDateArr = [] // 定义空数组
            if (preMonthDateLen > 0) {
                let { year, month } = this.preMonth(this.currentYear, this.currentMonth) // 获取上月 年、月
                let date = this.getDateLen(year, month) // 获取上月天数
                for (let i = 0; i < preMonthDateLen; i++) {
                    preMonthDateArr.unshift({ // 尾部追加
                        month: 'pre', // 只是为了增加标识,区分当、下月
                        date: date
                    })
                    date--
                }
            }
            this.preMonthDateLen=preMonthDateLen
            return preMonthDateArr
        },
        // 获取当月中,下月多余数据,返回数组
        getNextArr() {
            let nextMonthDateLen = 42 - this.preMonthDateLen - this.currentMonthDateLen // 下月多余天数
            let nextMonthDateArr = [] // 定义空数组
            if (nextMonthDateLen > 0) {
                for (let i = 1; i <= nextMonthDateLen; i++) {
                    nextMonthDateArr.push({
                        month: 'next',// 只是为了增加标识,区分当、上月
                        date: i
                    })
                }
            }
            return nextMonthDateArr
        },
        // 整合当月所有数据
        getAllArr(currentMonthDateArr){ 
            let preArr = this.getPreArr()
            let currentArr = currentMonthDateArr
            let nextArr = this.getNextArr()
            let allArr = [...preArr, ...currentArr, ...nextArr]
            this.allArr=allArr
        },
        // 点击 上月
        gotoPreMonth(){
            this.clickDate = ''
            let { year, month } = this.preMonth(this.currentYear, this.currentMonth)
            this.currentYear= year,
            this.currentMonth= month
            this.getCurrentArr()
        },
        // 点击 下月
        gotoNextMonth() {
            this.clickDate = ''
            let { year, month } = this.nextMonth(this.currentYear, this.currentMonth)
            this.currentYear= year
            this.currentMonth= month
            this.getCurrentArr()
        },
    },
}
export default calendar;

好了,接下来就是正题了

// 获取当月数据,返回数组
getCurrentArr(){
    //发起ajax请求
    this.$axios.post(
        '/api/xxxxxxxxxx'
    ).then((response)=>{
        //获取到这样的一个月的数据
        //date:日期,state:日期状态(预约成功、是否可预约等状态),num:剩余数量(根据需求更改)。字段和字段个数可自定义、新增、修改,如有改动字段,HTML需要跟着修改相应字段
        // let data = [
        //     {date:'2021-12-5', state:0, num: 4},
        //     {date:'2021-12-8', state:1, num: 4},
        //     {date:'2021-12-9', state:0, num: 0},
        //     {date:'2021-12-10', state:0, num: 10},
        //     {date:'2021-12-11', state:0, num: 10},
        //     {date:'2021-12-26', state:0, num: 0},
        //     {date:'2021-12-27', state:0, num: 5},
        // ]
    })

    let currentMonthDateLen = this.getDateLen(this.currentYear, this.currentMonth) // 获取当月天数
    //由于后端传来的日期是断断续续的,我们需要当月不间断的数据,所以没办法自己重新循环整合数据,如果后端传的是连续一个月的就不需要整合了
    let currentMonthDateArr = [] // 定义空数组
    if (currentMonthDateLen > 0) {
        for (let i = 1; i <= currentMonthDateLen; i++) {
            currentMonthDateArr.push({
                month: 'current', // 只是为了增加标识,区分上下月
                date: i,
                state: null,
                num: null
            })
            for (let a = 0; a < data.length; a++) {
                const element = data[a];
                if(this.currentYear+'-'+this.currentMonth+'-'+i == data[a].date){
                    currentMonthDateArr[i-1].state = data[a].state
                    currentMonthDateArr[i-1].num = data[a].num
                    continue
                }
            }
        }
    }
    //如果是连续一个月的数据到这里之上的都可以不需要
    this.currentMonthDateLen=currentMonthDateLen
    //参数说明:后端传来的连续数据或自己整合的连续数据
    this.getAllArr(currentMonthDateArr)
},

到这里,就结束了js

下面我们再来看看html

日历插件插图1

根据需求修改

最后,这套代码已经满足我现在的需求了,当然还有很多地方需要完善,欢迎评论区留言,希望能帮助一部分码农

暂无评论

发送评论 编辑评论


				
上一篇
下一篇