Fullcalendar日历插件+vue 实现指定时间内进行预约功能,指定时间外禁止创建预约 最全说明+实例

首先吐槽这个Fullcalendar这个插件的沙雕文档,都是英文,谷歌翻译又翻译得很笨,查看了很多文档和博客,很都是复制粘贴党.浪费大家时间.

/***/在项目中需要加一个预约功能,后端传给我一个类似下图这样的数据结构,这个就是限制预约时间段,比如data数组中第一项data[0] = [15] 意思是周日 只有15点到16点可以预约.data[1]=[6,“8,12”] 就是周一的6点到7点,8点到下午三点可以预约,如图
在这里插入图片描述

在这里插入图片描述

1.首先需要下载Fullcalendar以及相关配置

npm install @fullcalendar/core @fullcalendar/daygrid @fullcalendar/timegrid @fullcalendar/moment @fullcalendar/interaction在这里插入图片描述
这个是相关配置代码,其中比较关键的是有个点击事件和select事件重复,最后我选择了select事件,因为这个事件可以被限制范围,

下面列一些花很大精力查到的,用处很大的属性
columnHeaderFormat="ddd"  // 格式化表头,成周一周二...默认为11/19周二,11/20周三...
:first-day="nowDay"  //此处创建一个nowDay方法使当前日期始终在第一列,后面则为当前时期后六天
:business-hours="businessHours" //此处创建一个businessHours数组数据结构类似于[{startTime:"6:00",endTime:"8:00",daysOfWeek:[0]}]  ,daysOfWeek:[0]表示周日,daysOfWeek:[1]表示周一以此类推
:select-allow="handlerAllow"  //此处设置一个handlerAllow方法限制select拉取的范围
min-time="00:00:00" max-time="24:00:00" slot-duration="01:00:00" //此处设置每天时间从什么时候开始结束,以及每段时间的间隔为多少
:eventConstraint="businessHours"   //当事件拖动时,限制拖动到灰色区域
aspectRatio="1.5"   //设置日历的宽高比率 ,发现有超出部分可以适当调整
:editable="true" :eventDurationEditable="false"  //事件可以被拖动,禁止事件下拉(因为项目需要固定只能预约一个小时,下拉会导致时间增加)
:selectConstraint="businessHours"   //这个属性找了两天,贼鸡儿难受,此处限制灰色区域创建预约,就是灰色部分不能被点击,eventConstraint这个只是事件拖动时不会被拖到灰色区域
:event-overlap="false"  //阻止两次预约拖动时重叠
<template>
    <div>
        <div class="calendar">
            <FullCalendar :plugins="calendarPlugins" :all-day-slot="false" :header="{ // 头部样式
                left: 'today',
                right:'next'
            }" :button-text="{ //头部按钮样式
                today: '今天'
            }" :event-overlap="false" :events="event" columnHeaderFormat="ddd" :select-overlap="false"
                :first-day="nowDay" :business-hours="businessHours" :select-allow="handlerAllow" :select-mirror="true"
                selectable="true" min-time="00:00:00" max-time="24:00:00" slot-duration="01:00:00"
                slot-label-format="HH:mm" default-view="timeGridWeek" locale="zh-cn" @eventClick="handleEventClick"
                @eventDrop="handDrop" :eventConstraint="businessHours" @select="handleSelect" aspectRatio="1.5"
                :editable="true" :eventDurationEditable="false" :resourceIds="businessHours"
                :selectConstraint="businessHours" :valid-range="visibleRange" />
        </div>
    </div>
</template>

<script>

import FullCalendar from '@fullcalendar/vue'
import dayGridPlugin from '@fullcalendar/daygrid'
import interactionPlugin from '@fullcalendar/interaction'
import momentPlugin from '@fullcalendar/moment'
import '@fullcalendar/core/locales/zh-cn'
import timeGridPlulgin from '@fullcalendar/timegrid'


export default {
    components: {
        FullCalendar
    },
    data () {
        return {
            calendarPlugins: [dayGridPlugin, timeGridPlulgin, momentPlugin, interactionPlugin],
            event: [
                // {
                //     start: '2019-11-20 14:00:00',
                //     end: '2019-11-20 15:00:00',

                // },
                // {
                //     start: '2019-11-22 12:00:00',
                //     end: '2019-11-22 13:00:00'
                // }
            ],
            data: [
                [15], //周日 0
                [6, "8,12"], //周一 1
                ["10,17", 20], //周二 2
                [], //周三 3
                ["9,15"],//周四 4
                [],//周五 5
                ["15,24"],//周六 6
            ],
            arr: [],
            businessHours: []
        }
    },
    computed: {
        nowDay () { //使得日历是当前时间的后七天
            return new Date().getDay()
        },
        visibleRange () { //限制日期时间,因为是预约功能,需要设置当前时间之后的多少天内可以预约,超过时间则不能预约
            let nowDate = new Date()
            return {
                start: nowDate,
                end: this.getDateStr(this.day) //后面写了一个方法转化
            }
        },
    },
    created () {
        this.init()
    },
    methods: {
        startFormatTime (t) {
            let a = new Date(t).toJSON()
            let b = new Date(+new Date(a) + 8 * 3600 * 1000)
            let c = b.toISOString()
            let d = c.replace(/T/g, ' ').replace(/\.[\d]{3}Z/, '');
            return d
        },
        getDateStr (t) {
            var dd = new Date();
            dd.setDate(dd.getDate() + t);
            var y = dd.getFullYear();
            var m = (dd.getMonth() + 1) < 10 ? "0" + (dd.getMonth() + 1) : (dd.getMonth() + 1);//获取当前月份的日期,不足10补0
            var d = dd.getDate() < 10 ? "0" + dd.getDate() : dd.getDate();//获取当前几号,不足10补0
            return y + "-" + m + "-" + d;
        },
        transform (val, k) { 
            if (typeof (val) == 'string') {
                let a = val.split(",")
                let b = {
                    startTime: `${a[0]}:00`,
                    endTime: `${a[1]}:00`,
                    daysOfWeek: [k]
                }
                this.arr.push(b)
            } else if (typeof (val) == 'number') {
                let c = {
                    startTime: `${val}:00`,
                    endTime: `${val + 1}:00`,
                    daysOfWeek: [k]
                }
                this.arr.push(c)
            }
            this.businessHours = this.arr
        },
        init () {
            this.data.map((item, index) => {
                item.map(j => {
                    this.transform(j, index)
                })
            })
        },
        handlerAllow: info => { 
        //这个是限制过去时间不能点击,并且限制每次点击只能预约一个小时,不能水平拉动
            let a = info.start.getHours()
            let b = info.end.getHours()
            let c = info.start.getDay()
            let d = info.end.getDay()
            const currentDate = new Date()
            const start = info.start
            const end = info.end
            return (start <= end && start >= currentDate && b - a == 1 && c == d)
        },
        handleSelect (info) {
            this.$confirm('是否选择该时间为预约时间?', '提示', {
                confirmButtonText: '确定',
                cancelButtonText: '取消',
                type: 'warning'
            }).then(() => {
                let a = {
                    start: this.startFormatTime(info.startStr),
                    end: this.startFormatTime(info.endStr),
                }
                if (this.event.length < 5) {
                    this.event = this.event.concat(a)
                    this.$message({
                        type: 'success',
                        message: '操作成功!'
                    });
                } else {
                    this.$message({
                        type: 'warning',
                        message: '一周最多只能预约3次!'
                    });
                }
            }).catch(() => { });
        },
        handleEventClick (val) {
            console.log(1111, val)
        },
        handDrop (val) {
            console.log(1, val)
        }
    }
}

</script>

<style lang="scss" scoped>
@import '~@fullcalendar/core/main.css';
@import '~@fullcalendar/daygrid/main.css';
@import '~@fullcalendar/timegrid/main.css';
</style>

其他部分没什么好说的,自己瞅吧,这沙雕插件就是属性难搞,找了好几天.希望大家以后发点干货,别瞎鸡儿转载转载,搜了都是一堆一模一样的东西

  • 17
    点赞
  • 40
    收藏
    觉得还不错? 一键收藏
  • 15
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值