日历插件

适用于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(文章前面能复制,这里只是说明)

根据需求修改

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

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 215,634评论 6 497
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,951评论 3 391
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 161,427评论 0 351
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,770评论 1 290
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,835评论 6 388
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,799评论 1 294
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,768评论 3 416
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,544评论 0 271
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,979评论 1 308
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,271评论 2 331
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,427评论 1 345
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,121评论 5 340
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,756评论 3 324
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,375评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,579评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,410评论 2 368
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,315评论 2 352

推荐阅读更多精彩内容