• 小程序自定义日历组件


    根据项目需求自己封装的calendar组件

    <template>
        <div class="calendar-wrapper">
            <div class="header transition" v-if="HeaderBar">
                <div class="pre" @click="changeMonth('pre')">
                    <image src="/static/img/icons/icon-arrow-left.png" />
                </div>
                <div>{{ y + '年' + formatNum(m) + '月' }}</div>
                <div class="next" @click="changeMonth('next')">
                    <image src="/static/img/icons/icon-arrow-right.png" />
                </div>
            </div>
            <div class="day">
                <div class="week-day" :class="{ 'text-ccc': !HeaderBar }" v-for="(item, index) in weekDay" :key="index">
                    {{ item }}
                </div>
            </div>
            <div :class="{ hide: !monthOpen }" class="content" :style="{ height: height }">
                <div class="days transition" :style="{ top: positionTop + 'rpx' }">
                    <div
                        class="item"
                        :class="{ week: Open && hasWeek(item), weekStart: isWeekStart(item), weekEnd: isWeekEnd(item) }"
                        v-for="(item, index) in dates"
                        :key="index"
                    >
                        <div
                            class="day"
                            :class="{
                                choose: choose == `${item.year}-${item.month}-${item.date}` && item.isCurM,
                                nolm: !item.isCurM,
                                today: isToday(item.year, item.month, item.date)
                            }"
                            @click="item.isCurM && selectOne(item, $event)"
                        >
                            {{ Number(item.date) }}
                        </div>
                        <div class="markDay" v-if="isMarkDay(item.year, item.month, item.date) && item.isCurM"></div>
                    </div>
                </div>
            </div>
            <!-- <image src="/static/img/icons/logo.png" mode="scaleToFill" v-if="collapsible" @click="toggle" class="weektoggle" :class="{ down: monthOpen }"></image> -->
        </div>
    </template>
    
    <script>
    import { getWeek } from '@/static/js/getWeek'
    
    export default {
        name: 'calendar',
        props: {
            defaultTime: {
                type: String,
                default: ''
            },
            // 星期几为第一天(0为星期日)
            weekstart: {
                type: Number,
                default: 1
            },
            // 标记的日期
            markDays: {
                type: Array,
                default: () => {
                    return []
                }
            },
            //是否展示月份切换按钮
            headerBar: {
                type: Boolean,
                default: false
            },
            // 是否展开
            open: {
                type: Boolean,
                default: false
            },
            //是否可收缩
            collapsible: {
                type: Boolean,
                default: false
            },
            //未来日期是否不可点击
            disabledAfter: {
                type: Boolean,
                default: false
            }
        },
        data() {
            return {
                HeaderBar: false,
                Open: false,
                weektext: ['', '', '', '', '', '', ''],
                y: new Date().getFullYear(), //
                m: new Date().getMonth() + 1, //
                date: '',
                dates: [], // 当前月的日期数据
                positionTop: 0,
                monthOpen: true,
                choose: '',
                week: '',
                startDate: '',
                endDate: ''
            }
        },
        watch: {
            headerBar(val) {
                this.HeaderBar = val
            },
            open(val) {
                this.Open = val
                this.toggle()
            }
        },
        created() {
            this.date = this.getToday().date
            this.choose = this.defaultTime ? this.defaultTime : this.date
            this.HeaderBar = this.open
            this.Open = this.open
            this.dates = this.monthDay(this.y, this.m)
            !this.Open && this.toggle()
        },
        computed: {
            // 顶部星期栏
            weekDay() {
                return this.weektext.slice(this.weekstart).concat(this.weektext.slice(0, this.weekstart))
            },
            height() {
                return (this.dates.length / 7) * 80 + 'rpx'
            }
        },
        methods: {
            formatNum(num) {
                let res = Number(num)
                return res < 10 ? '0' + res : res
            },
            getToday() {
                let date = new Date()
                let y = date.getFullYear()
                let m = date.getMonth()
                let d = date.getDate()
                let day = new Date().getDay()
                let _day = day ? day : 7
                let week = Math.ceil((d + 6 - _day) / 7)
                this.week = week
                let weekText = ['', '', '', '', '', '', '']
                let formatWeek = '星期' + weekText[day]
                let today = {
                    date: y + '-' + this.formatNum(m + 1) + '-' + this.formatNum(d),
                    day: formatWeek
                }
                return today
            },
            // 获取当前月份数据
            monthDay(y, month) {
                let dates = []
                let m = Number(month)
                let firstDayOfMonth = new Date(y, m - 1, 1).getDay() || 7 // 当月第一天星期几
                let lastDateOfMonth = new Date(y, m, 0).getDate() // 当月最后一天
                let lastDayOfLastMonth = new Date(y, m - 2, 0).getDate() // 上一月的最后一天
                let weekstart = this.weekstart === 7 ? 0 : this.weekstart
                let startDay = (() => {
                    // 周初有几天是上个月的
                    if (firstDayOfMonth == weekstart) {
                        return 0
                    } else if (firstDayOfMonth > weekstart) {
                        return firstDayOfMonth - weekstart
                    } else {
                        return 7 - weekstart + firstDayOfMonth
                    }
                })()
                let endDay = 7 - ((startDay + lastDateOfMonth) % 7) // 结束还有几天是下个月的
                for (let i = 1; i <= startDay; i++) {
                    dates.push({
                        date: this.formatNum(lastDayOfLastMonth - startDay + i),
                        day: weekstart + i - 1 || 7,
                        month: m - 1 >= 0 ? this.formatNum(m - 1) : 12,
                        year: m - 1 >= 0 ? y : y - 1
                    })
                }
                for (let j = 1; j <= lastDateOfMonth; j++) {
                    dates.push({
                        date: this.formatNum(j),
                        day: (j - 1 + firstDayOfMonth) % 7 || 7,
                        month: this.formatNum(m),
                        year: y,
                        isCurM: true //是否当前月份
                    })
                }
                for (let k = 1; k <= endDay; k++) {
                    dates.push({
                        date: this.formatNum(k),
                        day: (lastDateOfMonth + startDay + weekstart + k - 1) % 7 || 7,
                        month: m + 1 <= 11 ? this.formatNum(m + 1) : 0,
                        year: m + 1 <= 11 ? y : y + 1
                    })
                }
                return dates
            },
            // isWorkDay(y, m, d) {
            //     //是否工作日
            //     let ymd = `${y}/${m}/${d}`
            //     let formatDY = new Date(ymd.replace(/-/g, '/'))
            //     let day = formatDY.getDay()
            //     if (day == 0 || day == 6) {
            //         return false
            //     } else {
            //         return true
            //     }
            // },
            hasWeek(i) {
                const month = this.choose.split('-')[1]
                if (month === i.month) {
                    let date = parseInt(i.date)
                    let day = i.day
                    let _day = day ? day : 7
                    let week = Math.ceil((date + 6 - _day) / 7)
                    Math.ceil((date + 6 - _day) / 7)
                    return this.week === week
                }
            },
            isWeekStart(item) {
                const time = `${item.year}-${item.month}-${item.date}`
                return time === getWeek(this.choose).startDate
            },
            isWeekEnd(item) {
                const time = `${item.year}-${item.month}-${item.date}`
                return time === getWeek(this.choose).endDate
            },
            isFutureDay(y, m, d) {
                //是否未来日期
                let ymd = `${y}/${m}/${d}`
                let formatDY = new Date(ymd.replace(/-/g, '/'))
                let showTime = formatDY.getTime()
                let curTime = new Date().getTime()
                if (showTime > curTime) {
                    return true
                } else {
                    return false
                }
            },
            // 标记日期
            isMarkDay(y, m, d) {
                let flag = false
                for (let i = 0; i < this.markDays.length; i++) {
                    let dy = `${y}-${m}-${d}`
                    if (this.markDays[i] == dy) {
                        flag = true
                        break
                    }
                }
                return flag
            },
            isToday(y, m, d) {
                let checkD = y + '-' + m + '-' + d
                let today = this.date
                if (checkD == today) {
                    return true
                } else {
                    return false
                }
            },
            // 展开收起
            toggle() {
                this.monthOpen = !this.monthOpen
                if (this.monthOpen) {
                    this.positionTop = 0
                } else {
                    let index = -1
                    this.dates.forEach((i, x) => {
                        this.isToday(i.year, i.month, i.date) && (index = x)
                    })
                    this.positionTop = -((Math.ceil((index + 1) / 7) || 1) - 1) * 80
                }
            },
            // 点击回调
            selectOne(i) {
                let time = `${i.year}-${i.month}-${i.date}`
                let selectD = new Date(time).getTime()
                let curTime = new Date().getTime()
                let day = new Date(time).getDay()
                let date = new Date(time).getDate()
                let _day = day ? day : 7
                this.week = Math.ceil((date + 6 - _day) / 7)
                let weekText = ['', '', '', '', '', '', '']
                let formatWeek = '星期' + weekText[day]
                let response = {
                    date: time,
                    day: formatWeek
                }
                if (!i.isCurM) {
                    // console.log('不在当前月范围内');
                    return false
                }
                if (selectD > curTime) {
                    if (this.disabledAfter) {
                        // console.log('未来日期不可选')
                        return false
                    } else {
                        this.choose = time
                        this.$emit('onDayClick', response)
                    }
                } else {
                    this.choose = time
                    this.$emit('onDayClick', response)
                }
                // console.log(response);
            },
            //改变年月
            changYearMonth(y, m) {
                this.dates = this.monthDay(y, m)
                this.y = y
                this.m = m
            },
            changeMonth(type) {
                if (type == 'pre') {
                    if (this.m + 1 == 2) {
                        this.m = 12
                        this.y = this.y - 1
                    } else {
                        this.m = this.m - 1
                    }
                } else {
                    if (this.m + 1 == 13) {
                        this.m = 1
                        this.y = this.y + 1
                    } else {
                        this.m = this.m + 1
                    }
                }
                this.dates = this.monthDay(this.y, this.m)
            }
        }
    }
    </script>
    
    <style lang="scss" scoped>
    .calendar-wrapper {
        color: #42464a;
        font-size: 28rpx;
        text-align: center;
        background-color: #fff;
        padding-bottom: 20rpx;
    
        .header {
            display: flex;
            align-items: center;
            justify-content: center;
            height: 80rpx;
            color: #42464a;
            font-size: 32rpx;
            font-weight: bold;
            .pre,
            .next {
                font-size: 28rpx;
                font-weight: normal;
                padding: 8rpx 15rpx;
                image {
                    width: 6px;
                    height: 10px;
                }
            }
            .pre {
                margin-right: 30rpx;
            }
            .next {
                margin-left: 30rpx;
            }
        }
    
        .day {
            display: flex;
            align-items: center;
            height: 70rpx;
            line-height: 70rpx;
            border-bottom: 1rpx solid rgba(255, 255, 255, 0.2);
    
            .week-day {
                flex: 1;
            }
        }
    
        .content {
            position: relative;
            overflow: hidden;
            transition: height 0.4s ease;
    
            .days {
                transition: top 0.3s;
                display: flex;
                align-items: center;
                flex-wrap: wrap;
                position: relative;
    
                .item {
                    position: relative;
                    display: flex;
                    align-items: center;
                    justify-content: center;
                    height: 80rpx;
                    line-height: 80rpx;
                    width: calc(100% / 7);
    
                    .day {
                        font-style: normal;
                        display: inline-block;
                        width: 50rpx;
                        height: 50rpx;
                        line-height: 50rpx;
                        overflow: hidden;
                        border-radius: 50rpx;
    
                        &.choose {
                            background-color: #f5f8fb;
                        }
    
                        &.nolm {
                            color: #666;
                            opacity: 0.3;
                        }
                    }
                    /* .isWorkDay {
                        color: #42464a;
                    } */
                    .today {
                        /* background-color: #e4e4e4; */
                    }
                    .markDay {
                        position: absolute;
                        bottom: 5px;
                        width: 8rpx;
                        height: 8rpx;
                        background: #4d7df9;
                        border-radius: 10rpx;
                        font-style: normal;
                        pointer-events: none;
                    }
                }
                .week {
                    background-color: #f5f8fb;
                }
                .weekStart {
                    border-radius: 20px 0 0 20px;
                }
                .weekEnd {
                    border-radius: 0 20px 20px 0;
                }
            }
        }
    
        .hide {
            height: 80rpx !important;
        }
    
        .weektoggle {
            width: 85rpx;
            height: 32rpx;
            position: relative;
            bottom: -42rpx;
            &.down {
                transform: rotate(180deg);
                bottom: 0;
            }
        }
    }
    </style>

    页面中调用:

    <calendar ref="calendar" :defaultTime="defaultTime" :markDays="markDays" :headerBar="isHeaderBar" :open="isOpen" @onDayClick="onDayClick"></calendar>            

    参考链接:https://github.com/AR1N/uniapp-calendar

  • 相关阅读:
    Actor
    spring mybatis circular reference
    MyBatis实现SaveOrUpdate
    Java SpringMVC实现国际化整合案例分析(i18n) 专题
    Spring Boot MyBatis 通用Mapper插件集成
    Spring Boot Servlet
    Android WebView 开发详解(二)
    Android与设计模式——观察者(Observer)模式
    Android系统设置— android.provider.Settings
    Android PNG渐变背景图片失真问题 getWindow().setFormat(PixelFormat.RGBA_8888);
  • 原文地址:https://www.cnblogs.com/ziyoublog/p/15102423.html
Copyright © 2020-2023  润新知