基于element组件的日期控件

72 阅读3分钟

image.png

日期范围功能测试说明

已实现的功能

1. 默认日期范围

  • ✅ 页面加载时自动设置默认日期范围为:今天往前30天
  • ✅ 使用 getDefaultDateRange() 方法生成默认范围

2. 日期限制规则

  • ✅ 禁用今天之后的日期(不能选择未来日期)
  • ✅ 禁用最早日期之前的日期(基于 minDate 设置)
  • ✅ 最小时间跨度:10天
  • ✅ 最大时间跨度:30天

3. 日期选择器配置

  • ✅ 类型:日期范围选择器 (daterange)
  • ✅ 占位符:开始日期、结束日期
  • ✅ 分隔符:至
  • ✅ 值格式:YYYY-MM-DD

测试用例

测试1:默认值

  1. 刷新页面
  2. 检查日期选择器是否显示默认值(今天往前30天)
  3. 验证开始日期和结束日期的差值是否为30天

测试2:未来日期禁用

  1. 尝试选择今天之后的日期
  2. 验证这些日期是否被禁用(显示为灰色)

测试3:最小跨度限制

  1. 选择第一个日期
  2. 尝试选择与第一个日期相差小于10天的日期
  3. 验证这些日期是否被禁用

测试4:最大跨度限制

  1. 选择第一个日期
  2. 尝试选择与第一个日期相差大于30天的日期
  3. 验证这些日期是否被禁用

测试5:有效日期范围

  1. 选择第一个日期
  2. 选择与第一个日期相差10-30天之间的日期
  3. 验证这些日期是否可以选择

代码实现

getDefaultDateRange 方法

getDefaultDateRange() {
    const today = new Date()
    const thirtyDaysAgo = new Date()
    thirtyDaysAgo.setDate(today.getDate() - 30)
    
    return [
        moment(thirtyDaysAgo).format('YYYY-MM-DD'),
        moment(today).format('YYYY-MM-DD')
    ]
}

disabledDate 方法

disabledDate(time) {
    const today = new Date().setHours(0, 0, 0, 0)
    const timeStamp = time.getTime()
    
    // 禁用今天之后的日期
    if (timeStamp > today) {
        return true
    }
    
    // 禁用最早日期之前的日期
    if (timeStamp < (this.minDate - (24*60*60*1000))) {
        return true
    }
    
    // 如果已选择首个日期,限制选择范围
    if (this.firstSelectedDate) {
        const startTime = this.firstSelectedDate.getTime();
        const diff = Math.abs(timeStamp - startTime);
        const minDiff = 10 * 24 * 3600 * 1000  // 最小10天
        const maxDiff = 30 * 24 * 3600 * 1000  // 最大30天
        
        // 小于10天或大于30天都禁用
        if (diff < minDiff || diff > maxDiff) {
            return true
        }
    }
    
    return false
}

注意事项

  1. 确保 moment 库已正确导入
  2. 日期计算基于本地时间
  3. 时间跨度限制在用户选择第一个日期后生效
  4. 默认日期范围在组件初始化时设置
 <el-date-picker
                size="small"
                :key="pickerKey"
                v-model="dateRange"
                type="daterange"
                range-separator="至"
                start-placeholder="开始日期"
                end-placeholder="结束日期"
                :picker-options="pickerOptions"
                value-format="yyyy-MM-dd"
                @change="handleDateChange"
            ></el-date-picker>
            export default {
            data(){
                 return {
                        dateRange: this.getDefaultDateRange(),
                        minDate: new Date('2025-05-08').getTime(),
                        minDateMonth: new Date(2025, 4, 1).setHours(0, 0, 0, 0),
                        pickerOptions:{
                              onPick: ({ maxDate, minDate }) => {
                                this.firstSelectedDate = minDate;
                            },
                            disabledDate: time => this.disabledDate(time)
                        },
                        firstSelectedDate:null,
                 }
            },
            methods:{
             // 获取默认日期范围(今天往前30天)
                getDefaultDateRange() {
                    const today = new Date()
                    const thirtyDaysAgo = new Date()
                    thirtyDaysAgo.setDate(today.getDate() - 30)

                    return [
                        moment(thirtyDaysAgo).format('YYYY-MM-DD'),
                        moment(today).format('YYYY-MM-DD')
                    ]
                },

                // 禁用日期逻辑
                disabledDate(time) {
                    const today = new Date().setHours(0, 0, 0, 0)
                    const timeStamp = time.getTime()

                    // 禁用今天之后的日期
                    if (timeStamp > today) {
                        return true
                    }

                    // 禁用最早日期之前的日期
                    if (timeStamp < (this.minDate - (24*60*60*1000))) {
                        return true
                    }

                    // 如果已选择首个日期,限制选择范围
                    if (this.firstSelectedDate) {
                        const startTime = this.firstSelectedDate.getTime();
                        const diff = Math.abs(timeStamp - startTime);
                        const minDiff = 10 * 24 * 3600 * 1000  // 最小10天
                        const maxDiff = 30 * 24 * 3600 * 1000  // 最大30天

                        // 小于10天或大于30天都禁用
                        if (diff < minDiff || diff > maxDiff) {
                            return true
                        }
                    }

                    return false
                },
                 handleDateChange(value){
                    if (value === null || (value && value.length === 0)) {
                        this.firstSelectedDate = null;
                        this.dateRange = []
                    }
                    // 调用接口
                },
            }
           }