基于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="width: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= " width: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 >


免责声明!

本站转载的文章为个人学习借鉴使用,本站对版权不负任何法律责任。如果侵犯了您的隐私权益,请联系本站邮箱yoyou2525@163.com删除。



 
粤ICP备18138465号  © 2018-2025 CODEPRJ.COM