基于VUE2实现一个简单的会员预约日历

由于是老项目,所以组件是基于vue2.0开发的,没有引入部分ele组件,先看图:
在这里插入图片描述
Canledar.vue 代码部分:

<template id="custom-calendar">
    <div class="custom-calendar">
        <div class="calendar-wrapper">
            <div class="calendar-header">
                <div class="calendar-current-date">
                    {{`${currYear}年${currMonth}月`}}
                </div>
                <div class="calendar-month-control">
                    <button class="button--default button--mini" type="button" @click="handleMonthChange(-1)">上一月</button>
                    <button class="button--default button--mini" type="button" @click="handleMonthChange(1)">下一月</button>
                </div>
            </div>
            <div class="calendar-week">
                <div class="calendar-week-list">
                    <div v-for="(item, index) of weekly" :key="index" class="calendar-week-list__item">
                        {{ item }}
                    </div>
                </div>
            </div>
            <div class="calendar-date-wrapper">
                <div class="calendar-date-list">
                    <div 
                        :class="{
                            'calendar-date-list__item': true, 
                            'is-current-month': item.currMonth, 
                            'is-current-day': item.currDay, 
                            'is-actived': item.actived,
                            'disabled': item.disabled
                        }" 
                        v-for="(item, index) of dateList" 
                        :key="index"
                        @click="handleActived(index, item.date)">
                        <span>{{ item.day }}</span>
                        <span class="lunar">{{ 
                            item.lunar.lunarFestival ? 
                                item.lunar.lunarFestival :
                                item.lunar.isTerm ? 
                                    item.lunar.Term : 
                                    item.lunar.IDayCn 
                        }}</span>
                        <span class="date-status" v-if="showStatusLabel && !item.disabled">
                            {{statusArr[+!item.disabled].label}}
                        </span>
                    </div>
                </div>
            </div>
            <div class="calendar-footer">
                <button 
                    type="button" 
                    class="button--default button--small" 
                    v-show="showResetButton"
                    @click="handleResetCalendar">
                    重置
                </button>
                <button    
                    type="button" 
                    class="button--default button--primary button--small"
                    @click="handleConfirmCalendar"
                    v-show="showConfirmButton">
                    确认
                </button>
            </div>
        </div>
    </div>
</template>

js部分

// calendarFormatter.js 是网上开源的一个日历转换js
<script type="text/javascript" src="./js/calendarFormatter.js"></script>
<script>
    Vue.component('calendar', {
        name: 'calendar',
    	template: '#custom-calendar',
        props: {
            data: Object,             // 已选日期
            maxDays: {
                type: Number,
                default: 7            // 最多可选n天内, -1 表示不限制
            },
            showResetButton: {        // 显示重置按钮
                type: Boolean,
                default: true
            },
            showConfirmButton: {      // 显示确定按钮
                type: Boolean,
                default: true
            },
            showStatusLabel: {        // 显示状态文字
                type: Boolean,
                default: true
            }
        },
        watch: {
            "data": {
                immediate: false,
                handler: function(val, oldVal) {
                    if (val) {
                        this.activedDate = { ...val }
                    }
                }
            }
        },
        data() {
            return {
                weekly: ['日', '一', '二', '三', '四', '五', '六'],  // 星期
                dateList: [],         // 当前日期集合
                length: 42,           // 日期框长度
                currYear: null,       // 当前年份
                currMonth: null,      // 当前月份
                currDate: null,       // 当天日期
                activedDate: {},      // 已选日期
                statusArr: [          // 状态
                    { label: '不可预定', value: 0 },
                    { label: '可预定', value: 1 }
                ]
            }
        },
        computed: {
            getDiffDate() {
                if (this.maxDays === null || +this.maxDays === -1) return false
                const date = new Date(this.currDate)
                date.setDate(date.getDate() + this.maxDays - 1)
                date.setHours(0, 0, 0, 0)
                return +date
            }
        },
        methods: {
            // 初始化日历
            initCalendar() {
                this.currDate = this.dateFormatter(new Date(), "YYYY-MM-DD")
                this.handleMonthChange()
            },
            // 月份切换
            handleMonthChange(diff = 0) {
                let date = new Date()
                if (diff !== 0) {
                    date = new Date(`${this.currYear}/${this.currMonth}`)
                    date.setMonth(date.getMonth() + diff)
                }
                this.currYear = date.getFullYear()
                this.currMonth = date.getMonth() + 1
                this.initDateList(this.currYear, this.currMonth - 1)
            },
            // 根据指定年、月份生成日期数组
            initDateList(year, month) { 
                const firstDate = new Date(year, month, 1)      // 当前月第一天
                const firstDayWeek = firstDate.getDay()         // 当前月第一天为星期几
                const lastDate = new Date(year, month + 1, 0)   // 当前月最后一天
                const lastDayWeek = lastDate.getDay()           // 当前月最后一天为星期几
                const maxDay = lastDate.getDate()               // 当前月最大天数
				
				/*
				* 下面分步获取日历的方式也可改为,先算出日历面板上第一个日期的节点,然后在逐步遍历 this.length 次
				*/
                // 当月日期
                let dateList = this.getDateList(firstDate, maxDay, true) 

                // 补充上月部分日期
                firstDate.setDate(-firstDayWeek + 1)
                dateList = [
                    ...this.getDateList(firstDate, firstDayWeek),
                    ...dateList
                ]

                // 补充下月部分日期
                lastDate.setDate(maxDay + 1)
                dateList = [
                    ...dateList,
                    ...this.getDateList(lastDate, this.length - dateList.length)
                ]
                this.dateList = dateList
            },
            // 获取日期数组
            getDateList(date, maxDay, currMonth = false) {
                const dateList = []
                for (let i = 0; i < maxDay; i++) {
                    if (i > 0) date.setDate(date.getDate() + 1)
                    const dateDay = this.dateFormatter(date, "YYYY-MM-DD")
                    const activatedDay = this.activedDate[dateDay]
                    dateList.push({
                        date: dateDay,
                        day: date.getDate(),
                        currMonth,
                        currDay: dateDay === this.currDate ? true : false,
                        disabled: this.disabledDate(date),
                        actived: activatedDay?.actived || false,
                        qty: activatedDay?.qty || 0,
                        lunar: this.solar2lunar(date)
                    })
                }
                return dateList
            },
            // 日期选中、取消
            handleActived(index, val) {
                const dateList = this.dateList
                if (!dateList[index].disabled) {
                    if (dateList[index].actived) {
                        alert('确定取消?')
                        this.$set(dateList[index], 'actived', false)
                        delete this.activedDate[val]
                    } else {
                        this.$set(dateList[index], 'actived', true)
                        this.activedDate[val] = dateList[index]
                    }
                }
            },
            // 禁用日期
            disabledDate(time) {
                const date = new Date(`${this.currDate}`).setHours(0, 0, 0, 0)
                return +time < +date || this.getDiffDate && +time > this.getDiffDate
            },
            dateFormatter(date, formatter = 'YYYY-MM-DD HH:mm:ss') {
                date = (date ? new Date(date) : new Date())
                const Y = date.getFullYear() + '',
                    M = date.getMonth() + 1,
                    D = date.getDate(),
                    H = date.getHours(),
                    m = date.getMinutes(),
                    s = date.getSeconds()
                return formatter.replace(/YYYY|yyyy/g, Y)
                    .replace(/YY|yy/g, Y.substr(2, 2))
                    .replace(/MM/g, (M < 10 ? '0' : '') + M)
                    .replace(/DD/g, (D < 10 ? '0' : '') + D)
                    .replace(/HH|hh/g, (H < 10 ? '0' : '') + H)
                    .replace(/mm/g, (m < 10 ? '0' : '') + m)
                    .replace(/ss/g, (s < 10 ? '0' : '') + s)
            },
            // 阳历转农历
            solar2lunar(date) {
                return calendarFormatter.solar2lunar(
                    date.getFullYear(), 
                    date.getMonth() + 1, 
                    date.getDate()
                )
            },
            // 重置日历
            handleResetCalendar() {
                this.activedDate = {}
                this.handleMonthChange()
            },
            // 日历点击确定
            handleConfirmCalendar() {
                this.$emit("update", this.activedDate)
            }
        },
        created() {
            this.initCalendar()
        }
    })
</script>

css 部分

<style>
    .custom-calendar {
        width: 100%;
        height: 800px;
        min-height: 200px;
        background-color: #fff;
        margin-bottom: 16px;
        padding: 16px;
        box-sizing: border-box;
    }
    .calendar-wrapper {
        width: 100%;
        height: 100%;
        font-size: 14px;
        box-sizing: border-box;
        display: flex;
        flex-direction: column;
        border: 1px solid #eee;
    }
    .calendar-header, .calendar-week {
        width: 100%;
        height: 52px;
        font-weight: bold;
        border-bottom: 1px solid #eee;
        box-sizing: border-box;
    }
    .calendar-header {
        display: flex;
        justify-content: space-between;
        padding: 0 16px;
    }
    .calendar-week-list, 
    .calendar-date-list {
        display: flex;
        flex-wrap: wrap;
        height: 100%;
    }
    .calendar-header > div,
    .calendar-week-list > div, 
    .calendar-date-list > div {
        display: flex;
        align-items: center;
        justify-content: center;
    }
    .calendar-week-list > div, 
    .calendar-date-list > div {
        height: 100%;
        width: 14.2857%;
    }
    .calendar-date-wrapper {
        width: 100%;
        flex-grow: 1;
    }
    .calendar-date-list {
        width: 100%;
        height: 100%;
        box-sizing: border-box;
    }
    .calendar-date-list .calendar-date-list__item {
        height: auto;
        color: #a0a0a0;
        cursor: pointer;
        border-bottom: 1px solid #eee;
        border-left: 1px solid #eee;
        box-sizing: border-box;
        overflow: hidden;
        display: flex;
        flex-direction: column;
        align-items: center;
        justify-content: center;
        line-height: 1.2;
        transition: all .2s cubic-bezier(.645, .045, .355, 1);
    }
    .calendar-date-list .calendar-date-list__item .date-status {
        margin-top: 6px;
        font-size: 11px;
    }
    .calendar-date-list .calendar-date-list__item:not(.disabled) .date-status {
        color: #67C23A;
        transition: all .2s cubic-bezier(.645, .045, .355, 1);
    }
    .calendar-date-list .calendar-date-list__item:nth-child(7n + 1) {
        border-left-width: 0;
    }
    .calendar-date-list .calendar-date-list__item .lunar {
        font-size: 12px;
    }
    .calendar-date-list .calendar-date-list__item.is-current-month:not(.disabled) {
        color: #000;
    }
    .calendar-date-list .calendar-date-list__item.is-current-month.is-current-day {
        color: rgba(255, 102, 0, 1);
    }
    .calendar-date-list .calendar-date-list__item.is-current-month.is-current-day:not(.disabled):hover,
    .calendar-date-list .calendar-date-list__item.is-current-month.is-current-day.is-actived {
        background: rgba(255, 102, 0, 1);
    }
    .calendar-date-list .calendar-date-list__item.disabled {
        background: rgba(238, 238, 238, .3);
    }
    .calendar-date-list .calendar-date-list__item.is-current-month:not(.disabled):hover,
    .calendar-date-list .calendar-date-list__item.is-current-month.is-actived {
        background: rgba(255, 102, 0, .8);
        color: #fff;
    }
    .calendar-date-list .calendar-date-list__item:not(.disabled):hover .date-status,
    .calendar-date-list .calendar-date-list__item.is-actived .date-status {
        color: #fff;
    }
    .calendar-date-list .calendar-date-list__item:not(.disabled):hover,
    .calendar-date-list .calendar-date-list__item.is-actived {
        background: rgba(255, 102, 0, .5);
        color: #fff;
    }
    .calendar-date-list .calendar-date-list__item.is-current-month.disabled,
    .calendar-date-list .calendar-date-list__item.disabled {
        cursor: not-allowed;
    }
    .calendar-footer {
        width: 100%;
        height: 58px;
        display: flex;
        justify-content: flex-end;
        align-items: center;
        box-sizing: border-box;
        padding: 0 16px;
    }
    button.button--default {
        min-width: 60px;
        height: 38px;
        background: #fff;
        border: 1px solid #ccc;
        border-radius: 2px;
        cursor: pointer;
        line-height: 1;
        padding: 4px 12px;
        transition: all .2s cubic-bezier(.645, .045, .355, 1);
        outline: none;
    }
    button.button--default + button.button--default {
        margin-left: 12px;
    }
    button.button--default.button--small {
        height: 34px;
    }
    button.button--default.button--mini {
        height: 30px;
    }
    button.button--default:hover {
        border-color: #3240FF;
        color: #3240FF;
    }
    button.button--default:active {
        background-color: #3240FF;
        border-color: #3240FF;
        color: #fff;
    }
    button.button--default.button--primary {
        background-color: #3240FF;
        border-color: #3240FF;
        color: #fff;
    }
    button.button--default.button--primary:hover {
        background-color: #5B66FF;
        border-color: #5B66FF;
    }
    button.button--default.button--primary:active {
        background-color: #2833CC;
        border-color: #2833CC;
    }
</style>
  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
好的,下面是一个基于Vue框架实现简单网页项目的步骤: 1. 安装Vue CLI Vue CLI是一个官方提供的脚手架工具,可以快速创建一个Vue项目。在命令行中运行以下命令进行安装: ``` npm install -g @vue/cli ``` 2. 创建一个Vue项目 使用Vue CLI创建一个新项目,运行以下命令: ``` vue create my-project ``` 其中,my-project是你的项目名称。在创建项目的过程中,你可以选择要安装哪些特性和插件。 3. 编写页面组件 在src/components目录下,创建一个名为MyPage.vue的文件,用于编写页面组件。在这个组件中,你可以使用Vue的模板语法、数据绑定、计算属性等功能来编写页面布局和渲染逻辑。 4. 编写路由配置 在src/router目录下,创建一个名为index.js的文件,用于配置页面路由。在这个文件中,你可以使用Vue Router来定义路由规则,并将页面组件与路由关联起来。 5. 编写数据管理逻辑 在src/store目录下,创建一个名为index.js的文件,用于编写应用的数据管理逻辑。在这个文件中,你可以使用Vuex来管理应用的状态、数据、行为等。 6. 运行应用 在命令行中运行以下命令,启动开发服务器: ``` npm run serve ``` 然后在浏览器中访问http://localhost:8080,就可以看到你的网页应用了。 以上就是基于Vue框架实现一个网页项目的简单步骤。当然,具体的实现过程和代码细节还需要根据你的具体需求来进行调整和优化。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值