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

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

/***/在项目中需要加一个预约功能,后端传给我一个类似下图这样的数据结构,这个就是限制预约时间段,比如data数组中第一项data[0] = [15] 意思是周日 只有15点到16点可以预约.data[1]=[6,“8,12”] 就是周一的6点到7点,8点到下午三点可以预约,如图
Fullcalendar日历插件+vue 实现指定时间内进行预约功能,指定时间外禁止创建预约 最全说明+实例_第1张图片

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

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

npm install @fullcalendar/core @fullcalendar/daygrid @fullcalendar/timegrid @fullcalendar/moment @fullcalendar/interactionFullcalendar日历插件+vue 实现指定时间内进行预约功能,指定时间外禁止创建预约 最全说明+实例_第3张图片
这个是相关配置代码,其中比较关键的是有个点击事件和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>

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

你可能感兴趣的:(前端,vue,Fullcalendar,日历组件)