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

air-datepicker技术咨询:指定日期禁用、样式自定义及区间限制

我来帮你搞定这几个问题,咱们一步步调整代码,解决日期比较错误、标记特定日期和禁用预约区间的需求:

1. 修复日期比较的问题

你之前直接用字符串比较日期会出问题,比如'2018-10-1'和'2018-5-20'字符串对比时,'2018-10'会被认为比'2018-5'小(因为字符'1'比'5'的ASCII码小),但实际10月的日期更大。

解决办法是统一日期格式为带前导零的YYYY-MM-DD,这样字符串比较就和实际日期顺序一致了。修改你的日期格式化函数:

function getFormattedDate(date) {
  const year = date.getFullYear();
  // 月份和日期补前导零,确保是两位数字
  const month = String(date.getMonth() + 1).padStart(2, '0');
  const day = String(date.getDate()).padStart(2, '0');
  return `${year}-${month}-${day}`;
}

同时把disabledDates里的日期也改成统一格式,还可以扩展支持区间:

var disabledDates = [
  '2018-05-20', // 单个禁用日期
  { start: '2018-05-21', end: '2018-05-23' } // 预约区间
];

2. 给特定日期添加类名并设置禁用

air-datepicker的onRenderCell回调可以返回classes属性,用来给日期单元格加自定义类,方便你设置不同颜色。咱们先写一个辅助函数判断日期是否在禁用区间内:

function isDateInDisabledRange(currentDateStr) {
  // 把字符串转成Date对象,方便区间比较
  const [year, month, day] = currentDateStr.split('-').map(Number);
  const currentDate = new Date(year, month - 1, day);
  
  for (const item of disabledDates) {
    if (typeof item === 'object') {
      const [startYear, startMonth, startDay] = item.start.split('-').map(Number);
      const startDate = new Date(startYear, startMonth - 1, startDay);
      
      const [endYear, endMonth, endDay] = item.end.split('-').map(Number);
      const endDate = new Date(endYear, endMonth - 1, endDay);
      
      // 判断当前日期是否在区间内
      if (currentDate >= startDate && currentDate <= endDate) {
        return true;
      }
    }
  }
  return false;
}

然后修改onRenderCell回调,实现禁用和类名添加:

onRenderCell: function(date, cellType) {
  const formatted = getFormattedDate(date);
  if (cellType === 'day') {
    // 判断是否是单个禁用日期
    const isSingleDisabled = disabledDates.some(item => typeof item === 'string' && item === formatted);
    // 判断是否在禁用区间内
    const isInRange = isDateInDisabledRange(formatted);
    
    if (isSingleDisabled || isInRange) {
      return {
        disabled: true, // 设置日期禁用
        classes: 'reserved-date' // 添加自定义类名
      };
    }
    return {};
  }
}

接着在CSS里添加自定义类的样式,让禁用日期显示不同颜色:

.reservation-calendar {
  display: flex;
  padding: 20px;
}

/* 标记禁用日期的样式 */
.reserved-date {
  background-color: #ffdddd !important; /* 浅红色背景 */
  color: #c70000 !important; /* 深红色文字 */
  border-radius: 50%; /* 可选:圆形标记 */
}

3. 禁止选择已有预约的区间

上面的代码已经处理了禁用区间内的日期,用户无法点击这些日期。另外,你原来的onSelect逻辑可以优化一下,让选择体验更流畅:

onSelect: function (fd, date) {
  if (date) {
    const arrDate = fd.split(",");
    $startDate.val(arrDate[0]);
    $endDate.val(arrDate[1] || '');
    
    // 选择完结束日期后自动隐藏日期选择器
    if (arrDate[1]) {
      $('.datepicker').hide();
      $startDate.blur();
    }
    
    // 点击结束日期输入框时,打开日期选择器并保留已选的开始日期
    $endDate.off('click').on('click', function () {
      if ($startDate.val()) {
        $startDate.datepicker('show');
      }
    });
  }
}

完整修改后的代码

JavaScript

$(document).ready(function () { 
  // 支持单个日期和区间的禁用列表
  var disabledDates = [
    '2018-05-20',
    { start: '2018-05-21', end: '2018-05-23' },
    { start: '2018-06-01', end: '2018-06-05' }
  ]; 
  var $startDate = $('#start'); 
  var $endDate = $('#end'); 

  $startDate.datepicker({ 
    inline: false, 
    range: true, 
    toggleSelected: true, 
    minDate: new Date(), 
    multipleDatesSeparator: ",", 
    dateFormat: 'dd-mm-yyyy', 
    onSelect: function (fd, date) { 
      if(date){ 
        var arrDate = fd.split(","); 
        $startDate.val(arrDate[0]); 
        $endDate.val(arrDate[1] || ''); 
        
        if(arrDate[1]){ 
          $('.datepicker').hide(); 
          $startDate.blur(); 
        } 

        $endDate.off('click').on('click', function () { 
          if ($startDate.val()) {
            $startDate.datepicker('show');
          }
        }); 
      } 
    }, 
    onRenderCell: function(date, cellType) { 
      var formatted = getFormattedDate(date); 
      if (cellType == 'day') { 
        const isSingleDisabled = disabledDates.some(item => typeof item === 'string' && item === formatted);
        const isInRange = isDateInDisabledRange(formatted);

        if (isSingleDisabled || isInRange) {
          return {
            disabled: true,
            classes: 'reserved-date'
          };
        }
        return {};
      } 
    } 
  }); 

  function getFormattedDate(date) { 
    const year = date.getFullYear();
    const month = String(date.getMonth() + 1).padStart(2, '0');
    const day = String(date.getDate()).padStart(2, '0');
    return `${year}-${month}-${day}`;
  } 

  function isDateInDisabledRange(currentDateStr) {
    const [year, month, day] = currentDateStr.split('-').map(Number);
    const currentDate = new Date(year, month - 1, day);
    
    for (const item of disabledDates) {
      if (typeof item === 'object') {
        const [startYear, startMonth, startDay] = item.start.split('-').map(Number);
        const startDate = new Date(startYear, startMonth - 1, startDay);
        
        const [endYear, endMonth, endDay] = item.end.split('-').map(Number);
        const endDate = new Date(endYear, endMonth - 1, endDay);
        
        if (currentDate >= startDate && currentDate <= endDate) {
          return true;
        }
      }
    }
    return false;
  }
});

CSS

.reservation-calendar { 
  display: flex; 
  padding: 20px; 
}

.reserved-date {
  background-color: #ffdddd !important;
  color: #c70000 !important;
  border-radius: 50%;
}

HTML

<link href="https://cdnjs.cloudflare.com/ajax/libs/air-datepicker/2.2.3/css/datepicker.css" rel="stylesheet"/> 
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script> 
<script src="https://cdnjs.cloudflare.com/ajax/libs/air-datepicker/2.2.3/js/datepicker.js"></script> 
<div class="reservation-calendar"> 
  <div class="reservation-calendar__item line"> 
    <input class="start" type="text" id="start" placeholder="开始日期"> 
  </div> 
  - 
  <div class="reservation-calendar__item"> 
    <input class="end" type="text" id="end" placeholder="结束日期"> 
  </div> 
</div>

这样修改后,你就能正确比较日期、标记禁用日期的样式,并且禁止选择已有预约的区间了~

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.28 04:23:07