目录前言实现思路具体实现组件模板定义定义props属性 type设置默认属性值定义核心计算属性pickerOptions处理手动输入的情况使用效果完整代码实现前言 最近遇到一个需求:
最近遇到一个需求:需要限制报表下载的日期范围,统一为半个月,防止用户选择范围过广,导致报表生成缓慢。
项目中使用的element-ui的el-date-picker日期选择组件。
声明了全局组件HalfMonthPicker
组件中使用v-bind="attrs"和v−on="attrs"和v-on="attrs"和v−on="listeners"进行了属性和事件透传,方便后期维护。
<el-date-picker
v-bind="$attrs"
v-on="$listeners"
:type="type"
:range-separator="rangeSeparator"
:start-placeholder="startPlaceholder"
:end-placeholder="endPlaceholder"
:value="value"
:picker-options="pickerOptions"></el-date-picker>
el-date-picker目前支持的范围属性为daterange和datetimerange,内部使用了校验函数,确保传入的参数值,默认为daterange。
props: {
type: {
type: String,
default: 'daterange',
validator(val) {
return ['daterange', 'datetimerange'].includes(val)
}
}
}
由于页面中组件使用时都传入了自定义的range-separator,start-placeholder,和end-placeholder,其属性值相同,所以在组件内部定义了props,并设置了默认值,避免页面中重复定义。
props: {
rangeSeparator: {
type: String,
default: '至'
},
startPlaceholder: {
type: String,
default: '起止日期'
},
endPlaceholder: {
type: String,
default: '截止日期'
}
}
基本变量定义
currentFirstDate
首个选中的日期
currentFirstTime
首个选中的日期毫秒数
currentMinTime
小于currentFirstTime半个月的毫秒数
currentMaxTime
大于currentFirstTime半个月的毫秒数
currentTime
disabledDate函数传入的日期值的毫秒数,用于判断是否在currentMinTime与currentMaxTime之间
shortcuts快捷选项
此处按照产品需求,内置了最近一周和最近半个月的快捷选项。
disabledDate实现
如果存在currentFirstDate,将小于半月或超出半月的日期置为不可选中。
如果不存在,则皆可选。
onPick注意事项
1.当maxDate和minDate都不存在
将currentFirstDate置为null,不限制日期选择
2.minDate存在,而maxDate不存在
currentFirstDate = minDate,并限制日期选择为前后半个月
3.maxDate和minDate同时存在
考虑如下情况,type为datetimerange时,即使选中了开始日期和结束日期,如果没有点确定,弹框并不会消失,此时应该可以重新选择新的开始日期,所以需要将currentFirstDate置为null,不在限制日期的选择。
未置为null
置为null
computed: {
pickerOptions() {
const { value } = this
// 选中的首个日期
let currentFirstDate = Array.isArray(value) && value.length === 1 && value[0] ? value[0] : null
// 选中的首个日期毫秒数
let currentFirstTime = null
// 当前日期毫秒数
let currentTime = null
// 当前可选最小日期毫秒数
let currentMinTime = null
// 当前可选最大日期毫秒数
let currentMaxTime = null
return {
// 快捷选项
shortcuts: [
{
text: '最近一周',
onClick(picker) {
const end = new Date()
const start = new Date()
start.setTime(start.getTime() - 3600 * 1000 * 24 * 6)
picker.$emit('pick', [start, end])
}
},
{
text: '最近半月',
onClick(picker) {
const end = new Date()
const start = new Date()
start.setTime(start.getTime() - 3600 * 1000 * 24 * 14)
picker.$emit('pick', [start, end])
}
}
],
// 禁选逻辑
disabledDate(date) {
if (currentFirstDate) {
currentFirstTime = new Date(currentFirstDate).getTime()
currentTime = new Date(date).getTime()
currentMinTime = currentFirstTime - 3600 * 1000 * 24 * 15
currentMaxTime = currentFirstTime + 3600 * 1000 * 24 * 15
// 确保当前可选日期在半月之间
return !(currentTime > currentMinTime && currentTime < currentMaxTime)
}
return false
},
// 选中项
onPick({ maxDate, minDate }) {
// console.log(maxDate)
currentFirstDate = !maxDate ? minDate : null
}
}
}
}
考虑如下场景,当用户选择在input框中手动输入日期时,pickerOptions中的disabledDate禁选属性便无法对用户产生拦截作用,此时便需要通过监听value属性的变化,当newVal间隔大于半个月时,重置回oldVal。
watch: {
// 处理手动输入的情况
value: {
handler(newVal, oldVal) {
if (Array.isArray(newVal) && newVal.length === 2) {
if (this.compareHalfMonthInterval(newVal[0], newVal[1])) {
this.$message.warning('日期间隔不能超过半个月')
// 重置为oldVal或null
this.$emit('input', oldVal || null)
}
}
},
immediate: true
}
},
methods: {
compareHalfMonthInterval(startDate, endDate) {
if (!startDate || !endDate) {
return false
}
const startTime = new Date(startDate).getTime()
const endTime = new Date(endDate).getTime()
return (endTime - startTime) > 3600 * 1000 * 24 * 15
}
}
页面中使用
使用前
使用后
选择开始日期
选择结束日期
<template>
<el-date-picker
v-bind="$attrs"
v-on="$listeners"
:type="type"
:range-separator="rangeSeparator"
:start-placeholder="startPlaceholder"
:end-placeholder="endPlaceholder"
:value="value"
:picker-options="pickerOptions"></el-date-picker>
</template>
<script>
export default {
name: 'HalfMonthPicker',
props: {
type: {
type: String,
default: 'daterange',
validator(val) {
return ['daterange', 'datetimerange'].includes(val)
}
},
value: {
type: Array,
default: () => []
},
rangeSeparator: {
type: String,
default: '至'
},
startPlaceholder: {
type: String,
default: '起止日期'
},
endPlaceholder: {
type: String,
default: '截止日期'
}
},
computed: {
pickerOptions() {
const { value } = this
// 选中的首个日期
let currentFirstDate = Array.isArray(value) && value.length === 1 && value[0] ? value[0] : null
// 选中的首个日期毫秒数
let currentFirstTime = null
// 当前日期毫秒数
let currentTime = null
// 当前可选最小日期毫秒数
let currentMinTime = null
// 当前可选最大日期毫秒数
let currentMaxTime = null
return {
// 快捷选项
shortcuts: [
{
text: '最近一周',
onClick(picker) {
const end = new Date()
const start = new Date()
start.setTime(start.getTime() - 3600 * 1000 * 24 * 6)
picker.$emit('pick', [start, end])
}
},
{
text: '最近半月',
onClick(picker) {
const end = new Date()
const start = new Date()
start.setTime(start.getTime() - 3600 * 1000 * 24 * 14)
picker.$emit('pick', [start, end])
}
}
],
// 禁选逻辑
disabledDate(date) {
if (currentFirstDate) {
currentFirstTime = new Date(currentFirstDate).getTime()
currentTime = new Date(date).getTime()
currentMinTime = currentFirstTime - 3600 * 1000 * 24 * 15
currentMaxTime = currentFirstTime + 3600 * 1000 * 24 * 15
// 确保当前可选日期在半月之间
return !(currentTime > currentMinTime && currentTime < currentMaxTime)
}
return false
},
// 选中项
onPick({ maxDate, minDate }) {
// console.log(maxDate)
currentFirstDate = !maxDate ? minDate : null
}
}
}
},
watch: {
// 处理手动输入的情况
value: {
handler(newVal, oldVal) {
if (Array.isArray(newVal) && newVal.length === 2) {
if (this.compareHalfMonthInterval(newVal[0], newVal[1])) {
this.$message.warning('日期间隔不能超过半个月')
// 重置为oldVal或null
this.$emit('input', oldVal || null)
}
}
},
immediate: true
}
},
methods: {
compareHalfMonthInterval(startDate, endDate) {
if (!startDate || !endDate) {
return false
}
const startTime = new Date(startDate).getTime()
const endTime = new Date(endDate).getTime()
return (endTime - startTime) > 3600 * 1000 * 24 * 15
}
}
}
</script>
到此这篇关于el-date-picker日期范围限制的实现的文章就介绍到这了,更多相关el-date-picker日期范围限制内容请搜索编程网以前的文章或继续浏览下面的相关文章希望大家以后多多支持编程网!
--结束END--
本文标题: el-date-picker日期范围限制的实现
本文链接: https://www.lsjlt.com/news/212682.html(转载时请注明来源链接)
有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341
下载Word文档到电脑,方便收藏和打印~
2024-01-12
2023-05-20
2023-05-20
2023-05-20
2023-05-20
2023-05-20
2023-05-20
2023-05-20
2023-05-20
2023-05-20
回答
回答
回答
回答
回答
回答
回答
回答
回答
回答
0