You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何实现jQuery UI Datepicker禁用数据库已预订日期区间

jQuery UI日期选择器实现已预订日期禁用+双选联动方案

现存问题梳理

当前代码无法达到预期效果的核心原因有三点:

  • PHP查询到的预订日期直接以带<br>的文本形式输出在页面head中,没有转换成前端JS可识别的结构化日期区间数据,无法用于日期禁用判断
  • 两个日期选择器没有做联动逻辑,结束日期固定写死minDate:1,没有和用户选择的开始日期绑定,导致运行异常
  • 没有调用Datepicker官方提供的beforeShowDay钩子做日期可用性校验,这是实现自定义日期禁用的核心API

当前问题效果参考

  • 开始日期选择器初始效果:
    开始日期选择器效果
  • 异常的结束日期选择器效果:
    结束日期选择器异常效果

分步实现代码

1. 修改PHP数据输出逻辑

删除原来直接循环echo日期加<br>的代码,将查询到的预订区间整理为标准数组,直接输出为JS可读取的全局变量,注意日期统一转成Y-m-d格式避免JS解析错误,代码放在jQuery与jQuery UI引用之后即可:

<?php
$huis_ID = "1";
// 只查询需要的两个日期字段,减少不必要的数据传输
$sql = "SELECT start_datum, eind_datum FROM reserveringen WHERE huis_ID = ?";
$stmt = $conn->prepare($sql);
$stmt->bind_param("i", $huis_ID);
$stmt->execute();
$result = $stmt->get_result();
$bookedRanges = [];
while($row = $result->fetch_assoc()){
    $bookedRanges[] = [
        'start' => date('Y-m-d', strtotime($row['start_datum'])),
        'end' => date('Y-m-d', strtotime($row['eind_datum']))
    ];
}
// 输出为JS全局变量,供前端日期校验使用
echo '<script>var bookedDateRanges = '.json_encode($bookedRanges).';</script>';
?>

2. 重写日期选择器初始化逻辑

封装通用的日期可用性判断函数,通过beforeShowDay钩子对每个渲染的日期做已预订校验,同时添加双选联动逻辑:选完开始日期后自动更新结束日期的最小可选值,避免选到无效区间。

$(function() {
    // 通用日期可用性校验:判断日期是否落在已预订区间内
    function checkDateAvailable(date){
        const currentDate = $.datepicker.formatDate('yy-mm-dd', date);
        for(let i=0; i<bookedDateRanges.length; i++){
            const range = bookedDateRanges[i];
            if(currentDate >= range.start && currentDate <= range.end){
                // 返回格式:[是否可选, 自定义样式类名, 悬浮提示文本]
                return [false, 'booked-date', '该日期已被预订'];
            }
        }
        return [true, '', ''];
    }

    // 初始化开始日期选择器
    $("#datepicker").datepicker({
        numberOfMonths: 1,
        minDate: 0,
        showButtonPanel: true,
        dateFormat: 'dd-mm-yy', // 和原有日期格式保持一致
        beforeShowDay: checkDateAvailable,
        onSelect: function(){
            // 选中开始日期后,自动设置结束日期的最小可选值为开始日期+1天
            const selectedStart = $(this).datepicker('getDate');
            const minEnd = new Date(selectedStart.getTime());
            minEnd.setDate(minEnd.getDate() + 1);
            $("#datepicker1").datepicker('option', 'minDate', minEnd);
            
            // 如果之前选的结束日期早于新选的开始日期,清空结束日期输入框
            const selectedEnd = $("#datepicker1").datepicker('getDate');
            if(selectedEnd && selectedEnd <= selectedStart){
                $("#datepicker1").val('');
            }
        }
    });

    // 初始化结束日期选择器
    $("#datepicker1").datepicker({
        numberOfMonths: 1,
        minDate: 1,
        showButtonPanel: true,
        dateFormat: 'dd-mm-yy',
        beforeShowDay: checkDateAvailable
    });
});

3. 添加禁用日期样式

在页面head中加入如下CSS,让已预订的不可选日期有明确的视觉区分:

.booked-date a {
    background-color: #f0f0f0 !important;
    color: #999 !important;
    cursor: not-allowed !important;
    border: none !important;
}

最终实现效果

  • 所有落在数据库存储的预订起止区间内的日期,会自动置为不可点击状态,鼠标悬浮显示已预订提示
  • 开始日期只能选择今天及以后的未预订日期
  • 选择开始日期后,结束日期自动限定为开始日期次日及以后的未预订日期,不会出现结束日期早于开始日期的逻辑错误
  • 解决原有结束日期选择器的运行异常问题

内容的提问来源于stack exchange,提问作者user18149678

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.28 04:36:23