Ant-Design-Vue 中,在调用RangePicker时,要求限制最大值、最小值,以及间隔,时分秒也需要限制

2025-03-23 09:51:57

一. 需求描述

最近在进行项目开发过程中,由于业务要求,需要:

要求限制最大值、最小值,以及间隔,时分秒也需要限制

需要考虑到:

  1. 年月日限制、时分秒限制
  2. 最大间隔时间(天)
  3. 当选择开始时间时,结束时间的最大时间
  4. 当选择结束时间是,开始时间的最小值
  5. 如果已经赋值了,重新选择时,也要满足上述要求

二. 完整代码

由于项目中,一个页面日期选择动态生成,不确定含有多少了个,所以封装了一个日期组件。

info 属性格式:

{
  min: {
    value: "2025-01-12 06:30:30"
  },
  max: {
    value: "2025-01-31 08:20:00"
  },
  precision: "SECOND" // 精度
}

具体代码:

<template>
  <a-range-picker
    style="width: 100%"
    @calendarChange="onCalendarChange"
    @openChange="onOpenChange"
    :value="hackValue || props.value"
    @change="onChange"
    v-bind="renderRangePicker(props.info)"
  />
</template>

<script setup>
import dayjs from “dayjs”
import { rangePickerProps } from “ant-design-vue/lib/date-picker/generatePicker/props”

const props = defineProps(
  Object.assign(
    {
      info: Object
    },
    rangePickerProps()
  )
)
const dates = ref()
const hackValue = ref()

const onCalendarChange = (val) => {
  dates.value = val
}

const onOpenChange = (open) => {
  if (open) {
    dates.value = []
    hackValue.value = []
  } else {
    hackValue.value = undefined
  }
}

const onChange = (val) => {
  props[“onUpdate:value”] && props[“onUpdate:value”](val)
}

const getDataPickerFormatShowTimeProps = (precision) => {
    switch (precision) {
      case "SECOND": // 秒
        return {
          showTime: true,
          format: "YYYY-MM-DD HH:mm:ss"
        }
      case "MINUTE": // 分
        return {
          showTime: true,
          format: "YYYY-MM-DD HH:mm"
        }
      case "HOUR": // 时
        return {
          showTime: true,
          format: "YYYY-MM-DD HH"
        }
      case "DAY": // 天
        return {
          format: "YYYY-MM-DD"
        }
      case "MONTH": // 月
        return {
          picker: "month",
          format: "YYYY-MM"
        }
      case "YEAR": // 年
        return {
          picker: "year",
          format: "YYYY"
        }
      default:
        return {
          format: "YYYY-MM-DD"
        }
    }
  }

const renderRangePicker = (record) => {
  // 表示根据精度获取相应的format、showTime
  const pickerProps = tools.getDataPickerFormatShowTimeProps(record.precision)
  const minDayjs = record.minValue?.value ? dayjs(record.minValue.value) : null
  const maxDayjs = record.maxValue?.value ? dayjs(record.maxValue.value) : null
  const maxInterval = record.maxInterval // 间隔 天

  return {
    ...pickerProps,
    disabledDate: (current) => {
      if (!current) return false

      const min = record.minValue?.value ? minDayjs.startOf("day") : null
      const max = record.maxValue?.value ? maxDayjs.endOf("day") : null
      // 限制最早日期
      if (min && current < min) return true
      // 限制最晚日期
      if (max && current > max) return true

      if (!dates.value || dates.value.length === 0) return false

      // 限制最大间隔天数
      if (dates.value[0] && maxInterval) {
        const maxAllowed = dates.value[0].add(maxInterval, "day").endOf("day")
        return current.isAfter(maxAllowed)
      }
      if (dates.value[1] && maxInterval) {
        const minAllowed = dates.value[1].subtract(maxInterval, "day").startOf("day")
        return current.isBefore(minAllowed)
      }

      return false
    },
    disabledTime: (current) => {
      let disabledHours = () => []
      let disabledMinutes = () => []
      let disabledSeconds = () => []

      if (!current) return { disabledHours, disabledMinutes, disabledSeconds }

      if (minDayjs && current.isSame(minDayjs, "day")) {
        disabledHours = () => Array.from({ length: 24 }, (_, i) => i).filter((h) => h < minDayjs.hour())
        disabledMinutes = (h) =>
          h === minDayjs.hour() ? Array.from({ length: 60 }, (_, i) => i).filter((m) => m < minDayjs.minute()) : []
        disabledSeconds = (h, m) =>
          h === minDayjs.hour() && unref(m) === minDayjs.minute()
            ? Array.from({ length: 60 }, (_, i) => i).filter((s) => s < minDayjs.second())
            : []
      }

      if (maxDayjs && current.isSame(maxDayjs, "day")) {
        disabledHours = () => Array.from({ length: 24 }, (_, i) => i).filter((h) => h > maxDayjs.hour())
        disabledMinutes = (h) =>
          h === maxDayjs.hour() ? Array.from({ length: 60 }, (_, i) => i).filter((m) => m > maxDayjs.minute()) : []
        disabledSeconds = (h, m) =>
          h === maxDayjs.hour() && unref(m) === maxDayjs.minute()
            ? Array.from({ length: 60 }, (_, i) => i).filter((s) => s > maxDayjs.second())
            : []
      }

      // 处理最大间隔天数的时分秒限制
      if (dates.value?.[0] && maxInterval && current.isSame(dates.value[0].add(maxInterval, "day"), "day")) {
        const maxAllowedTime = dates.value[0].add(maxInterval, "day")

        disabledHours = () => Array.from({ length: 24 }, (_, i) => i).filter((h) => h > maxAllowedTime.hour())
        disabledMinutes = (h) =>
          h === maxAllowedTime.hour()
            ? Array.from({ length: 60 }, (_, i) => i).filter((m) => m > maxAllowedTime.minute())
            : []
        disabledSeconds = (h, m) =>
          h === maxAllowedTime.hour() && unref(m) === maxAllowedTime.minute()
            ? Array.from({ length: 60 }, (_, i) => i).filter((s) => s > maxAllowedTime.second())
            : []
      }

      if (dates.value?.[1] && maxInterval && current.isSame(dates.value[1].subtract(maxInterval, "day"), "day")) {
        const minAllowedTime = dates.value[1].subtract(maxInterval, "day")

        disabledHours = () => Array.from({ length: 24 }, (_, i) => i).filter((h) => h < minAllowedTime.hour())
        disabledMinutes = (h) =>
          h === minAllowedTime.hour()
            ? Array.from({ length: 60 }, (_, i) => i).filter((m) => m < minAllowedTime.minute())
            : []
        disabledSeconds = (h, m) =>
          h === minAllowedTime.hour() && unref(m) === minAllowedTime.minute()
            ? Array.from({ length: 60 }, (_, i) => i).filter((s) => s < minAllowedTime.second())
            : []
      }

      return { disabledHours, disabledMinutes, disabledSeconds }
    }
  }
}
</script>

目录