Skip to content

DateRange 日期范围

日期范围选择组件,基于 Element Plus DatePicker 封装,提供开始和结束日期的选择功能。

🎮 在线演示

想要查看日期范围组件的使用效果?请访问 在线演示 查看功能演示

特性

📅 日期范围

支持开始和结束日期选择

✅ 智能验证

内置日期范围和逻辑验证

🔧 高度配置

支持自定义标签、格式和限制

📱 响应式

完美适配各种屏幕尺寸

基础用法

最简单的日期范围选择:

查看代码
vue
<template>
  <div class="demo-space">
    <h3>基础日期范围选择</h3>
    <ImDateRange 
      v-model="dateRange" 
      @change="handleDateChange"
    />
    
    <div class="mt-4 text-sm text-gray-600">
      选择的日期范围: {{ dateRange[0] }} 至 {{ dateRange[1] }}
    </div>
  </div>
</template>

<script setup>
import { ref } from 'vue'

const dateRange = ref([null, null])

const handleDateChange = (value) => {
  console.log('日期范围变化:', value)
}
</script>

自定义标签

可以自定义开始和结束日期的标签:

查看代码
vue
<template>
  <div class="demo-space">
    <h3>自定义标签</h3>
    <ImDateRange 
      v-model="dateRange"
      start-label="入职日期"
      end-label="离职日期"
      start-placeholder="请选择入职日期"
      end-placeholder="请选择离职日期"
    />
  </div>
</template>

<script setup>
import { ref } from 'vue'

const dateRange = ref([null, null])
</script>

必填验证

设置日期范围为必选项:

查看代码
vue
<template>
  <div class="demo-space">
    <h3>必填验证</h3>
    <ImDateRange 
      v-model="dateRange"
      :required="true"
      start-label="项目开始"
      end-label="项目结束"
    />
    
    <div class="mt-4">
      <el-button type="primary" @click="handleValidate">验证</el-button>
    </div>
  </div>
</template>

<script setup>
import { ref } from 'vue'
import { ElMessage } from 'element-plus'

const dateRange = ref([null, null])

const handleValidate = () => {
  if (!dateRange.value[0] || !dateRange.value[1]) {
    ElMessage.error('请选择完整的日期范围')
    return
  }
  ElMessage.success('验证通过')
}
</script>

日期范围限制

可以设置最小和最大的日期范围:

查看代码
vue
<template>
  <div class="demo-space">
    <h3>日期范围限制</h3>
    
    <div class="mb-4">
      <h4 class="text-sm font-medium mb-2">最大30天范围</h4>
      <ImDateRange 
        v-model="maxRangeDate"
        :max-range="30"
        start-label="开始时间"
        end-label="结束时间"
      />
    </div>
    
    <div class="mb-4">
      <h4 class="text-sm font-medium mb-2">最小7天范围</h4>
      <ImDateRange 
        v-model="minRangeDate"
        :min-range="7"
        start-label="开始时间"
        end-label="结束时间"
      />
    </div>
    
    <div class="mb-4">
      <h4 class="text-sm font-medium mb-2">7-30天范围</h4>
      <ImDateRange 
        v-model="limitRangeDate"
        :min-range="7"
        :max-range="30"
        start-label="开始时间"
        end-label="结束时间"
      />
    </div>
  </div>
</template>

<script setup>
import { ref } from 'vue'

const maxRangeDate = ref([null, null])
const minRangeDate = ref([null, null])
const limitRangeDate = ref([null, null])
</script>

可选日期范围

限制可选择的日期范围:

查看代码
vue
<template>
  <div class="demo-space">
    <h3>可选日期范围</h3>
    
    <div class="mb-4">
      <h4 class="text-sm font-medium mb-2">只能选择未来30天</h4>
      <ImDateRange 
        v-model="futureDate"
        :min-date="today"
        :max-date="maxDate"
        start-label="开始日期"
        end-label="结束日期"
      />
    </div>
    
    <div class="mb-4">
      <h4 class="text-sm font-medium mb-2">只能选择过去一年</h4>
      <ImDateRange 
        v-model="pastDate"
        :min-date="minDate"
        :max-date="today"
        start-label="开始日期"
        end-label="结束日期"
      />
    </div>
  </div>
</template>

<script setup>
import { ref, computed } from 'vue'

const futureDate = ref([null, null])
const pastDate = ref([null, null])

const today = computed(() => {
  return new Date().toISOString().split('T')[0]
})

const maxDate = computed(() => {
  const date = new Date()
  date.setDate(date.getDate() + 30)
  return date.toISOString().split('T')[0]
})

const minDate = computed(() => {
  const date = new Date()
  date.setFullYear(date.getFullYear() - 1)
  return date.toISOString().split('T')[0]
})
</script>

自定义样式

调整组件的样式和布局:

查看代码
vue
<template>
  <div class="demo-space">
    <h3>自定义样式</h3>
    
    <div class="mb-4">
      <h4 class="text-sm font-medium mb-2">垂直布局</h4>
      <ImDateRange 
        v-model="verticalDate"
        :inline="false"
        label-width="100px"
        size="large"
      />
    </div>
    
    <div class="mb-4">
      <h4 class="text-sm font-medium mb-2">小尺寸</h4>
      <ImDateRange 
        v-model="smallDate"
        size="small"
        label-width="60px"
      />
    </div>
    
    <div class="mb-4">
      <h4 class="text-sm font-medium mb-2">禁用状态</h4>
      <ImDateRange 
        v-model="disabledDate"
        :disabled="true"
      />
    </div>
    
    <div class="mb-4">
      <h4 class="text-sm font-medium mb-2">不可清空</h4>
      <ImDateRange 
        v-model="nonClearDate"
        :clearable="false"
      />
    </div>
  </div>
</template>

<script setup>
import { ref } from 'vue'

const verticalDate = ref([null, null])
const smallDate = ref([null, null])
const disabledDate = ref(['2024-01-01', '2024-01-31'])
const nonClearDate = ref([null, null])
</script>

自定义验证消息

可以自定义验证错误消息:

查看代码
vue
<template>
  <div class="demo-space">
    <h3>自定义验证消息</h3>
    <ImDateRange 
      v-model="dateRange"
      :required="true"
      :max-range="10"
      :validate-message="{
        required: '请选择查询时间段',
        endBeforeStart: '结束时间不能早于开始时间',
        rangeExceed: '查询时间段不能超过限制',
        rangeLess: '查询时间段不能少于限制'
      }"
      start-label="查询开始"
      end-label="查询结束"
    />
  </div>
</template>

<script setup>
import { ref } from 'vue'

const dateRange = ref([null, null])
</script>

API

Props

参数说明类型默认值
modelValue / v-model绑定值 [开始日期, 结束日期]Array[null, null]
startLabel开始日期标签String'开始日期'
endLabel结束日期标签String'结束日期'
startPlaceholder开始日期占位符String'请选择开始日期'
endPlaceholder结束日期占位符String'请选择结束日期'
format显示格式String'YYYY-MM-DD'
valueFormat值格式String'YYYY-MM-DD'
inline是否行内布局Booleantrue
labelWidth标签宽度String'80px'
size尺寸大小String'default'
required是否必填Booleanfalse
clearable是否可清空Booleantrue
disabled是否禁用Booleanfalse
editable是否可输入Booleanfalse
maxRange最大日期范围(天)Numbernull
minRange最小日期范围(天)Numbernull
minDate最小可选日期String/Datenull
maxDate最大可选日期String/Datenull
validateMessage自定义验证消息Object见下方说明

validateMessage 默认值

js
{
  required: "请选择日期",
  endBeforeStart: "结束日期不能早于开始日期", 
  rangeExceed: "日期范围超出限制",
  rangeLess: "日期范围不足最小要求"
}

Events

事件名说明参数
change日期范围改变时触发(value: Array)
start-change开始日期改变时触发(value: String)
end-change结束日期改变时触发(value: String)

Methods

方法名说明参数
validate验证日期范围() => Promise<boolean>
resetFields重置表单字段() => void
clearValidate清除验证状态() => void

使用场景

查询条件

在列表页面中作为时间范围查询条件:

vue
<template>
  <div class="search-form">
    <ImDateRange 
      v-model="searchForm.dateRange"
      start-label="开始时间"
      end-label="结束时间"
      :max-range="90"
      @change="handleSearch"
    />
  </div>
</template>

表单字段

在表单中作为日期范围输入字段:

vue
<template>
  <el-form :model="form" :rules="rules">
    <el-form-item label="项目周期" prop="projectPeriod">
      <ImDateRange 
        v-model="form.projectPeriod"
        :required="true"
        :min-range="7"
        start-label="开始日期"
        end-label="结束日期"
      />
    </el-form-item>
  </el-form>
</template>

数据筛选

用于数据报表的时间范围筛选:

vue
<template>
  <div class="report-filter">
    <ImDateRange 
      v-model="filterDate"
      start-label="统计开始"
      end-label="统计结束"
      :max-range="365"
      @change="loadReportData"
    />
  </div>
</template>

最佳实践

  1. 合理设置范围限制:根据业务需求设置合适的最大和最小日期范围
  2. 提供清晰的标签:使用具有业务含义的标签文本
  3. 验证用户输入:使用内置验证或自定义验证逻辑
  4. 响应式设计:在移动端考虑使用垂直布局
  5. 性能优化:避免在大表单中频繁触发验证

基于 MIT 许可发布