Vue3+JeecgBoot实战:如何用DatePicker组件禁用历史日期(附dayjs代码示例)
Vue3JeecgBoot实战DatePicker组件禁用历史日期的3种高阶方案在JeecgBoot这类低代码平台中日期选择器的精细化控制一直是表单设计的痛点。最近接手了一个保险业务系统改造项目其中起保日期不得早于当前日期的业务规则让我对Vue3的DatePicker组件做了深度探索。本文将分享三种不同场景下的实现方案包括你可能从未注意过的动态校验技巧。1. 基础方案表单配置的disabledDate对于大多数基础场景直接在formSchema中配置componentProps是最快捷的方式。这种方式适合规则固定的场景比如永久禁用历史日期。{ label: 生效日期, field: effectiveDate, component: DatePicker, componentProps: ({ formModel }) ({ format: YYYY-MM-DD, disabledDate: (current: Dayjs) { // 禁用今天之前的所有日期含当天 return current current dayjs().startOf(day) } }) }关键细节说明dayjs().startOf(day)比dayjs()更精确避免时区问题返回true表示禁用与Element UI等库的规则相反函数参数current是dayjs对象无需再次转换注意在JeecgBoot中直接修改formSchema可能会影响其他表单项建议先复制原始schema再修改2. 进阶方案插槽方式的动态控制当需要根据其他字段值动态调整禁用规则时比如结束日期不能早于开始日期插槽方案更灵活template BasicForm registerregisterForm template #dateSlot{ model, field } a-date-picker v-model:valuemodel[field] :disabled-dategetDisabledDate(model.startDate) / /template /BasicForm /template script setup const getDisabledDate (startDate) (current) { if (!startDate) return current dayjs().startOf(day) return current dayjs(startDate) || current dayjs(startDate).add(30, day) } /script这种方案的优势在于可以访问组件实例和表单模型支持复杂的交叉校验逻辑便于添加自定义事件处理3. 企业级方案自定义Hooks封装在大型项目中我推荐将日期校验逻辑抽象为可复用的hooks// hooks/useDateRestrict.ts import type { Dayjs } from dayjs export enum DateRestrictMode { PAST past, FUTURE future, RANGE range } export default function useDateRestrict() { const disabledDateFactory ( mode: DateRestrictMode, boundary?: Dayjs | string ) { return (current: Dayjs) { const now dayjs().startOf(day) switch (mode) { case DateRestrictMode.PAST: return current now case DateRestrictMode.FUTURE: return current now case DateRestrictMode.RANGE: return boundary ? current dayjs(boundary).startOf(day) : false default: return false } } } return { disabledDateFactory } }使用示例script setup const { disabledDateFactory } useDateRestrict() const disabledDate disabledDateFactory(DateRestrictMode.PAST) /script企业级方案的价值统一校验逻辑避免各页面实现不一致支持TypeScript类型提示便于扩展新的校验规则单元测试友好4. 避坑指南与性能优化在实际项目中我们遇到过几个典型问题时区问题// 错误示例受本地时区影响 disabledDate: (current) current dayjs() // 正确做法统一使用UTC模式 disabledDate: (current) current dayjs().utc().startOf(day)性能陷阱 当需要禁用大量日期时如禁用过去十年日期每次渲染都会执行校验函数。这时可以用记忆化优化import memoize from lodash/memoize const disabledDate memoize((current: Dayjs) { return current current dayjs().startOf(day) }, (current) current.format(YYYY-MM-DD))移动端适配 在移动设备上Ant Design的DatePicker可能需要额外配置componentProps: { popupStyle: { position: fixed }, inputReadOnly: true // 防止移动端键盘弹出 }5. 扩展场景非JeecgBoot环境的实现对于纯Vue3项目这里提供一个完整的组合式API示例template a-date-picker v-model:valuedateValue :disabled-datedisabledDate :show-time{ defaultValue: dayjs().startOf(day) } / /template script setup langts import { ref } from vue import dayjs, { Dayjs } from dayjs const dateValue refDayjs() const disabledDate (current: Dayjs) { // 禁用今天之前的日期但允许选择当天的未来时间 return current current dayjs().subtract(1, day).endOf(day) } /script这个实现的特点是支持日期时间联合选择精确到秒级的控制完整的TypeScript类型支持在项目实践中根据业务复杂度选择合适的技术方案。简单的表单配置适合快速迭代而自定义Hooks更适合长期维护的大型项目。