• 基于element ui的el-date-picker 日、周、月粒度切换时间选择器


    先上效果图

     需求

    • 粒度—时间选择器联动
    • 时间周期不能大于今天。(所以今天以后的时间都不能选)
      • 周粒度——因为一周没过完,所以不能选当前周
      • 月粒度——因为本月没结束,不能选当前月
    • 切换粒度的时候自动选择最近符合的时间。
    • 侧边有快捷选择。

    根据需求还有个隐藏bug 周需要特殊处理选择的日期还有样式

    周粒度是一周一周选择,所以需要特殊处理

    上代码

    父组件使用

    <lidu-picker ref="liduPicker" @changeDate="changeDate"></lidu-picker>

    import liduPicker from './components/liduPicker'
    monted(){
      // 默认日粒度 可以父组件调用初始化也可以直接在子组件初始化
      // this.$refs['liduPicker'].changeSize(1)
    }

    组件liduPicker 周粒度的时候需要增加class="is-week-mode"

    date-picker的 value-format="yyyy-MM-dd",其他的未测试是否有影响

    组件内在最后使用了dateFormat处理时间。没有的请修改

    <template>
        <el-form inline size="medium">
            <el-form-item>
                <el-select v-model="lidu" placeholder="请选择" @change="changeSize">
                    <el-option label="日粒度" :value="1"></el-option>
                    <el-option label="周粒度" :value="2"></el-option>
                    <el-option label="月粒度" :value="3"></el-option>
                </el-select>
            </el-form-item>
            <el-form-item>
                <el-date-picker
                    style="300px"
                    v-model="datePicker"
                    :type="lidu == 3 ? 'monthrange' : 'daterange'"
                    align="left"
                    unlink-panels
                    range-separator="至"
                    start-placeholder="开始时间"
                    end-placeholder="结束时间"
                    :picker-options="pickerOptions"
                    value-format="yyyy-MM-dd"
                    @change="changeDate"
                    @focus="setWeekClass"
                ></el-date-picker>
            </el-form-item>
        </el-form>
    </template>
    
    <script>
    import { dateFormat } from '@/helpers/utils'
    
    export default {
        data() {
            return {
                // 粒度 1:日,2:周,3:月
                lidu: 1,
                // 时间区间选择
                datePicker: [],
                pickerOptions: {
                    firstDayOfWeek: 1,
                    shortcuts: [],
                },
            }
        },
        methods: {
            // 切换粒度
            changeSize(val) {
                this.datePicker = []
                let shortcuts = []
                // 一天时间
                const day = 3600 * 1000 * 24
                const date = new Date()
                const end = date - day
                // 日粒度
                if (val == 1) {
                    //   初始化时间 默认最近7天
                    this.changeDate([date - day * 7, date - day])
                    //   昨日
                    const latelyDay = this.setShortcut('昨日', end, end)
                    //   上周
                    const curDay = date.getDay()
                    const lastWeek = this.setShortcut('上周', date - day * (7 + curDay), date - day * (1 + curDay))
                    //   本月
                    const curMonth = this.setShortcut('本月', new Date().setDate(1), end)
                    //   上月  上个月第一天 ~ 上个月最后一天
                    const lastMonth = this.setShortcut('上月', new Date(date.getFullYear(), date.getMonth(), 0).setDate(1), new Date().setDate(0))
                    //   最近一周
                    const latelyWeek = this.setShortcut('最近7天', date - day * 7, end)
                    //   最近15天
                    const latelyHalfMonth = this.setShortcut('最近15天', date - day * 15, end)
                    //   最近30天
                    const latelyMonth = this.setShortcut('最近30天', date - day * 31, end)
                    //   最近90天
                    const lately3Month = this.setShortcut('最近90天', date - day * 91, end)
                    shortcuts.push(latelyDay, lastWeek, curMonth, lastMonth, latelyWeek, latelyHalfMonth, latelyMonth, lately3Month)
                    // 选择限制 不能选今天以后
                    this.pickerOptions.disabledDate = time => {
                        return time.getTime() + 86400000 >= Date.now()
                    }
                }
                // 周粒度
                if (val == 2) {
                    //   初始化时间 默认最近7天
                    this.changeDate([date - day * 7, date - day])
                    //   最近7天
                    const latelyWeek = this.setShortcut('最近7天', date - day * 7, end)
                    // 最近30天
                    const latelyMonth = this.setShortcut('最近30天', date - day * 31, end)
                    // 最近90天
                    const lately3Month = this.setShortcut('最近90天', date - day * 91, end)
                    shortcuts.push(latelyWeek, latelyMonth, lately3Month)
                    // 选择限制 不能选今天以后
                    this.pickerOptions.disabledDate = time => {
                        return time.getTime() + 86400000 >= Date.now()
                    }
                }
                // 月粒度 都是到上个月的最后一天
                if (val == 3) {
                    const lastMonth1 = new Date(date.getFullYear(), date.getMonth(), 0).setDate(1)
                    // 初始化时间 默认上月
                    this.changeDate([lastMonth1, lastMonth1])
                    // 上月
                    const last1M = this.setShortcut('上月', lastMonth1, lastMonth1)
                    // 今年
                    const curYear = this.setShortcut('今年', new Date(date.getFullYear(), 0), lastMonth1)
                    // 最近三个月
                    const last3M = this.setShortcut('最近三个月', new Date(date.getFullYear(), date.getMonth() - 3), lastMonth1)
                    // 最近六个月
                    const last6M = this.setShortcut('最近六个月', new Date(date.getFullYear(), date.getMonth() - 6), lastMonth1)
                    shortcuts.push(last1M, curYear, last3M, last6M)
                    // 选择限制 不能选上个月最后一天之后
                    this.pickerOptions.disabledDate = time => {
                        return time.getTime() + 86400000 >= new Date().setDate(0)
                    }
                }
                // console.log('快捷设置:', shortcuts)
                this.pickerOptions.shortcuts = shortcuts
            },
            setShortcut(text, start, end) {
                return {
                    text,
                    onClick(picker) {
                        picker.$emit('pick', [dateFormat(new Date(start), 'YYYY-MM-dd'), dateFormat(new Date(end), 'YYYY-MM-dd')])
                    },
                }
            },
            // 所选时间
            changeDate(date) {
                if (!date) return
                // 日粒度
                if (this.lidu == 1) {
                    date = [dateFormat(new Date(date[0]), 'YYYY-MM-dd'), dateFormat(new Date(date[1]), 'YYYY-MM-dd')]
                    this.datePicker = this.datePicker.length ? this.datePicker : date
                }
                // 周粒度
                if (this.lidu == 2) {
                    // 取出开始时间和结束时间分别是周几
                    const day = 3600 * 1000 * 24
                    const yesterday = new Date() - day
                    const start = new Date(date[0])
                    const end = new Date(date[1])
                    // 开始时间是距离周一天数
                    const startDay = start.getDay() == 0 ? 6 : start.getDay() - 1
                    // 结束时间是距离周日天数
                    const endDay = end.getDay() == 0 ? 6 : end.getDay() - 1
                    // 距离上周一天数
                    const monDay = 13 - new Date().getDay()
                    const lastMonday = new Date() - day * monDay
                    // 距离上周日天数
                    const sunDay = new Date().getDay() == 0 ? 7 : new Date().getDay()
                    const lastSunday = new Date() - day * sunDay
                    const res = []
                    // 计算所选开始时间的周一  (判断当前所选日期的周一是否 > 上周一)
                    res[0] = Number(start) - day * startDay > Number(lastMonday) ? Number(lastMonday) : Number(start) - day * startDay
                    // 计算所选结束时间的周日   (判断当前所选日期的周日是否 > 上周日)
                    res[1] = Number(end) + day * (6 - endDay) > Number(lastSunday) ? Number(lastSunday) : Number(end) + day * (6 - endDay)
                    this.datePicker = [dateFormat(new Date(res[0]), 'YYYY-MM-dd'), dateFormat(new Date(res[1]), 'YYYY-MM-dd')]
                }
                // 月粒度
                if (this.lidu == 3) {
                    const endTime = new Date(date[1])
                    endTime.setMonth(endTime.getMonth() + 1)
                    const endDay = endTime.setDate(0)
                    // console.log('结束时间的月底', dateFormat(new Date(endDay), 'YYYY-MM-dd'))
                    this.datePicker = [dateFormat(new Date(date[0]), 'YYYY-MM-dd'), dateFormat(new Date(endDay), 'YYYY-MM-dd')]
                }
                // console.log('this.datePicker',this.datePicker)
                this.$emit('changeDate', this.lidu, this.datePicker)
            },
            // 如果是周粒度的时候 首次进入需要绑定样式 is-week-mode
            setWeekClass(event) {
                if (this.lidu == 2 && event.picker && event.picker.$children[0].$el.className != 'el-date-table is-week-mode') {
                    // console.log(event.picker)
                    event.picker.$children.forEach(r => {
                        //   console.log(r.$el)
                        r.$el.className = `el-date-table is-week-mode`
                    })
                } else if (this.lidu != 2 && event.picker && event.picker.$children[0].$el.className == 'el-date-table is-week-mode') {
                    event.picker.$children.forEach(r => {
                        //   console.log(r.$el)
                        r.$el.className = `el-date-table`
                    })
                }
            },
        },
        mounted() {
            // 默认日粒度
            this.changeSize(1)
        },
    }
    </script>
    
    <style></style>
    <template>
        <el-form inline size="medium">
            <el-form-item>
                <el-select v-model="lidu" placeholder="请选择" @change="changeSize">
                    <el-option label="日粒度" :value="1"></el-option>
                    <el-option label="周粒度" :value="2"></el-option>
                    <el-option label="月粒度" :value="3"></el-option>
                </el-select>
            </el-form-item>
            <el-form-item>
                <el-date-picker
                    style="300px"
                    v-model="datePicker"
                    :type="lidu == 3 ? 'monthrange' : 'daterange'"
                    align="left"
                    unlink-panels
                    range-separator=""
                    start-placeholder="开始时间"
                    end-placeholder="结束时间"
                    :picker-options="pickerOptions"
                    value-format="yyyy-MM-dd"
                    @change="changeDate"
                    @focus="setWeekClass"
                ></el-date-picker>
            </el-form-item>
        </el-form>
    </template>

    <script>
    import { dateFormat } from '@/helpers/utils'

    export default {
        data() {
            return {
                // 粒度 1:日,2:周,3:月
                lidu: 1,
                // 时间区间选择
                datePicker: [],
                pickerOptions: {
                    firstDayOfWeek: 1,
                    shortcuts: [],
                },
            }
        },
        methods: {
            // 切换粒度
            changeSize(val) {
                this.datePicker = []
                let shortcuts = []
                // 一天时间
                const day = 3600 * 1000 * 24
                const date = new Date()
                const end = date - day
                // 日粒度
                if (val == 1) {
                    //   初始化时间 默认最近7天
                    this.changeDate([date - day * 7, date - day])
                    //   昨日
                    const latelyDay = this.setShortcut('昨日', end, end)
                    //   上周
                    const curDay = date.getDay()
                    const lastWeek = this.setShortcut('上周', date - day * (7 + curDay), date - day * (1 + curDay))
                    //   本月
                    const curMonth = this.setShortcut('本月', new Date().setDate(1), end)
                    //   上月  上个月第一天 ~ 上个月最后一天
                    const lastMonth = this.setShortcut('上月', new Date(date.getFullYear(), date.getMonth(), 0).setDate(1), new Date().setDate(0))
                    //   最近一周
                    const latelyWeek = this.setShortcut('最近7天', date - day * 7, end)
                    //   最近15天
                    const latelyHalfMonth = this.setShortcut('最近15天', date - day * 15, end)
                    //   最近30天
                    const latelyMonth = this.setShortcut('最近30天', date - day * 31, end)
                    //   最近90天
                    const lately3Month = this.setShortcut('最近90天', date - day * 91, end)
                    shortcuts.push(latelyDay, lastWeek, curMonth, lastMonth, latelyWeek, latelyHalfMonth, latelyMonth, lately3Month)
                    // 选择限制 不能选今天以后
                    this.pickerOptions.disabledDate = time => {
                        return time.getTime() + 86400000 >= Date.now()
                    }
                }
                // 周粒度
                if (val == 2) {
                    //   初始化时间 默认最近7天
                    this.changeDate([date - day * 7, date - day])
                    //   最近7天
                    const latelyWeek = this.setShortcut('最近7天', date - day * 7, end)
                    // 最近30天
                    const latelyMonth = this.setShortcut('最近30天', date - day * 31, end)
                    // 最近90天
                    const lately3Month = this.setShortcut('最近90天', date - day * 91, end)
                    shortcuts.push(latelyWeek, latelyMonth, lately3Month)
                    // 选择限制 不能选今天以后
                    this.pickerOptions.disabledDate = time => {
                        return time.getTime() + 86400000 >= Date.now()
                    }
                }
                // 月粒度 都是到上个月的最后一天
                if (val == 3) {
                    const lastMonth1 = new Date(date.getFullYear(), date.getMonth(), 0).setDate(1)
                    // 初始化时间 默认上月
                    this.changeDate([lastMonth1, lastMonth1])
                    // 上月
                    const last1M = this.setShortcut('上月', lastMonth1, lastMonth1)
                    // 今年
                    const curYear = this.setShortcut('今年', new Date(date.getFullYear(), 0), lastMonth1)
                    // 最近三个月
                    const last3M = this.setShortcut('最近三个月', new Date(date.getFullYear(), date.getMonth() - 3), lastMonth1)
                    // 最近六个月
                    const last6M = this.setShortcut('最近六个月', new Date(date.getFullYear(), date.getMonth() - 6), lastMonth1)
                    shortcuts.push(last1M, curYear, last3M, last6M)
                    // 选择限制 不能选上个月最后一天之后
                    this.pickerOptions.disabledDate = time => {
                        return time.getTime() + 86400000 >= new Date().setDate(0)
                    }
                }
                // console.log('快捷设置:', shortcuts)
                this.pickerOptions.shortcuts = shortcuts
            },
            setShortcut(text, start, end) {
                return {
                    text,
                    onClick(picker) {
                        picker.$emit('pick', [dateFormat(new Date(start), 'YYYY-MM-dd'), dateFormat(new Date(end), 'YYYY-MM-dd')])
                    },
                }
            },
            // 所选时间
            changeDate(date) {
                if (!date) return
                if (this.lidu == 1) {
                    date = [dateFormat(new Date(date[0]), 'YYYY-MM-dd'), dateFormat(new Date(date[1]), 'YYYY-MM-dd')]
                    this.datePicker = this.datePicker.length ? this.datePicker : date
                }
                if (this.lidu == 2) {
                    // 取出开始时间和结束时间分别是周几
                    const day = 3600 * 1000 * 24
                    const yesterday = new Date() - day
                    const start = new Date(date[0])
                    const end = new Date(date[1])
                    // 开始时间是距离周一天数
                    const startDay = start.getDay() == 0 ? 6 : start.getDay() - 1
                    // 结束时间是距离周日天数
                    const endDay = end.getDay() == 0 ? 6 : end.getDay() - 1
                    // 距离上周一天数
                    const monDay = 13 - new Date().getDay()
                    const lastMonday = new Date() - day * monDay
                    // 距离上周日天数
                    const sunDay = new Date().getDay() == 0 ? 7 : new Date().getDay()
                    const lastSunday = new Date() - day * sunDay
                    const res = []
                    // 计算所选开始时间的周一  (判断当前所选日期的周一是否 > 上周一)
                    res[0] = Number(start) - day * startDay > Number(lastMonday) ? Number(lastMonday) : Number(start) - day * startDay
                    // 计算所选结束时间的周日   (判断当前所选日期的周日是否 > 上周日)
                    res[1] = Number(end) + day * (6 - endDay) > Number(lastSunday) ? Number(lastSunday) : Number(end) + day * (6 - endDay)
                    this.datePicker = [dateFormat(new Date(res[0]), 'YYYY-MM-dd'), dateFormat(new Date(res[1]), 'YYYY-MM-dd')]
                }
                if (this.lidu == 3) {
                    const endTime = new Date(date[1])
                    endTime.setMonth(endTime.getMonth() + 1)
                    const endDay = endTime.setDate(0)
                    // console.log('结束时间的月底', dateFormat(new Date(endDay), 'YYYY-MM-dd'))
                    this.datePicker = [dateFormat(new Date(date[0]), 'YYYY-MM-dd'), dateFormat(new Date(endDay), 'YYYY-MM-dd')]
                }
                // console.log('this.datePicker',this.datePicker)
                this.$emit('changeDate', this.lidu, this.datePicker)
            },
            // 如果是周粒度的时候 首次进入需要绑定样式 is-week-mode
            setWeekClass(event) {
                if (this.lidu == 2 && event.picker && event.picker.$children[0].$el.className != 'el-date-table is-week-mode') {
                    // console.log(event.picker)
                    event.picker.$children.forEach(r => {
                        //   console.log(r.$el)
                        r.$el.className = `el-date-table is-week-mode`
                    })
                } else if (this.lidu != 2 && event.picker && event.picker.$children[0].$el.className == 'el-date-table is-week-mode') {
                    event.picker.$children.forEach(r => {
                        //   console.log(r.$el)
                        r.$el.className = `el-date-table`
                    })
                }
            },
        },
        mounted() {
            // 默认日粒度
            this.changeSize(1)
        },
    }
    </script>

    <style></style>
  • 相关阅读:
    实现 ajax 多项选择框
    Ajax 文件上传之PHP心得
    php tree生成树分享
    基于JQuery框架的AJAX
    jQuery Ajax 全解析
    asp 下载函数
    10元奥运纪念钞明发行 与人民币等值流通
    jQuery(Ajax)/PHP/MySQL实现搜索自动提示功能
    隔行扫描和逐行扫描(interlace and progressive )
    VGA 输出调试
  • 原文地址:https://www.cnblogs.com/HDWdemo/p/14682167.html
Copyright © 2020-2023  润新知