Datepicker选择未被识别:无法触发可用预约时段下拉框填充
问题描述
我需要实现根据选中的医生与日期,在下拉框中填充该医生当日未被预约的时段,但当前存在以下问题:
- 选择日期后,系统无法识别选中的日期,无法触发对应的AJAX请求;
- 仅当先选择医生、再选日期,随后切换其他医生并切回原医生时,下拉框才会正确填充可用时段。
怀疑问题出在为限制医生可用日期而销毁重建datepicker的逻辑上。
相关代码
前端AJAX触发代码
<script> $(document).ready(function(){ $('#datepicker').datepicker({ onSelect: function() { setTimeout(triggerAjaxCall, 0); } }); $('#selMedico').change(function(){ triggerAjaxCall(); }); function triggerAjaxCall() { var doctor = $('#selMedico').val(); var date = $('#datepicker').val(); console.log('Doctor:', doctor); console.log('Date:', date); if (!doctor || !date) { console.log('Doctor or date not selected'); return; } // AJAX call $.ajax({ type: 'POST', url: 'fetchConsultas.php', data: { medico: doctor, dia: date }, dataType: 'json', success: function(response) { console.log('AJAX request successful'); console.log('Response:', response); $('#hora').empty(); $.each(response, function(index, value) { $('#hora').append('<option value="' + value + '">' + value + '</option>'); }); }, error: function(jqXHR, textStatus, errorThrown) { console.log('AJAX request failed:', textStatus, errorThrown); } }); } }); </script>
后端fetchConsultas.php代码
<?php if (isset($_POST['medico']) && isset($_POST['dia'])) { $medicoSelecionado = $_POST['medico']; $dataSelecionada = $_POST['dia']; include 'connection.php'; $stmt = $pdo->prepare('SELECT id_hora FROM tabconsultas WHERE id_medico = ? AND id_dia = ? ;'); $stmt->execute([$medicoSelecionado, $dataSelecionada]); $horarios = $stmt->fetchAll(PDO::FETCH_COLUMN, 0); // 生成8:00-18:00的所有时段(排除13:00) $allHours = []; for ($i = 8; $i <= 18; $i++) { if ($i != 13) { $hour = str_pad($i, 2, '0', STR_PAD_LEFT) . ':00:00'; $allHours[] = $hour; } } // 计算未被预约的时段 $availableHours = array_diff($allHours, $horarios); echo json_encode($availableHours); $pdo = null; $stmt = null; } else { echo "No doctor or date selected."; } die();
医生选择HTML代码
<?php $consulta = "SELECT DISTINCT tabutilizador.id_utilizador, tabutilizador.nome FROM tabutilizador LEFT JOIN tabconsultas ON tabutilizador.id_utilizador = tabconsultas.id_medico WHERE tabutilizador.tipo = 'medico'"; $resultado = $conexao->query($consulta); // 渲染医生下拉列表 echo '<form id="formulario" action="formhandler.inc.php" method="POST">'; echo '<label for="medico">Médico</label><br><br>'; echo '<select id="selMedico" name="medico" onchange="fetchServicosPorMedico(this.value)" required>'; echo '<option value="" disabled selected>Escolha um Médico</option>'; while ($linha = $resultado->fetch_assoc()) { echo '<option value="' . $linha['id_utilizador'] . '">' . $linha['nome'] . '</option>'; } echo '</select><br><br>'; ?>
日期输入HTML代码
<?php echo '<label for="dia">Data da Consulta</label><br><br>'; echo '<input type="text" id="datepicker" name="dia" placeholder="Selecione uma data" required><br><br>'; ?>
重建datepicker的JS代码
<script> $(document).ready(function() { $('#selMedico').change(function() { var medicoSelecionado = $(this).val(); $.ajax({ url: 'fetchDiasPorMedico.php', type: 'post', data: { medico: medicoSelecionado }, success: function(response) { $('#resultado').html(response); var diasDisp = response; $(function() { $("#datepicker").datepicker("destroy").datepicker({ dateFormat: 'yy-mm-dd', dayNames: ['Domingo', 'Segunda-feira', 'Terça-feira', 'Quarta-feira', 'Quinta-feira', 'Sexta-feira', 'Sábado'], dayNamesMin: ['Dom', 'Seg', 'Ter', 'Qua', 'Qui', 'Sex', 'Sáb'], dayNamesShort: ['Dom', 'Seg', 'Ter', 'Qua', 'Qui', 'Sex', 'Sáb'], monthNames: ['Janeiro', 'Fevereiro', 'Março', 'Abril', 'Maio', 'Junho', 'Julho', 'Agosto', 'Setembro', 'Outubro', 'Novembro', 'Dezembro'], monthNamesShort: ['Jan', 'Fev', 'Mar', 'Abr', 'Mai', 'Jun', 'Jul', 'Ago', 'Set', 'Out', 'Nov', 'Dez'], nextText: 'Próximo', prevText: 'Anterior', beforeShowDay: function(date) { var day = date.getDay(); // 根据返回逻辑判断日期是否可用 var disableDay = new Function('day', 'return ' + diasDisp); return [disableDay(day), '']; }, onSelect: function(dateText, inst) { var selectedDate = $(this).datepicker('getDate'); var dayOfWeek = selectedDate.getDay(); }, minDate: 0 }); }); } }); }); }); </script>
问题根源
问题出在两次初始化datepicker的事件冲突:
- 第一次初始化时,给
datepicker绑定了onSelect事件,用于触发triggerAjaxCall; - 选择医生时,代码会销毁原datepicker并重新创建,新datepicker的
onSelect被替换成了仅获取星期几的逻辑,完全丢失了触发AJAX的代码; - 切换医生再切回时,医生的
change事件会触发triggerAjaxCall,此时如果已有日期选择,才会填充时段。
解决方案
修改重建datepicker的代码,在新的onSelect事件中调用triggerAjaxCall,同时统一函数作用域,避免事件丢失:
修改后的完整JS代码
<script> $(document).ready(function() { // 全局作用域定义triggerAjaxCall,确保重建datepicker时能访问 function triggerAjaxCall() { var doctor = $('#selMedico').val(); var date = $('#datepicker').val(); console.log('Doctor:', doctor); console.log('Date:', date); if (!doctor || !date) { console.log('Doctor or date not selected'); return; } // AJAX请求获取可用时段 $.ajax({ type: 'POST', url: 'fetchConsultas.php', data: { medico: doctor, dia: date }, dataType: 'json', success: function(response) { console.log('AJAX request successful'); console.log('Response:', response); $('#hora').empty(); $.each(response, function(index, value) { $('#hora').append('<option value="' + value + '">' + value + '</option>'); }); }, error: function(jqXHR, textStatus, errorThrown) { console.log('AJAX request failed:', textStatus, errorThrown); } }); } // 医生选择事件处理 $('#selMedico').change(function(){ var medicoSelecionado = $(this).val(); // 先触发一次AJAX(如果已有日期选择) triggerAjaxCall(); // 请求医生可用日期并重建datepicker $.ajax({ url: 'fetchDiasPorMedico.php', type: 'post', data: { medico: medicoSelecionado }, success: function(response) { $('#resultado').html(response); var diasDisp = response; $("#datepicker").datepicker("destroy").datepicker({ dateFormat: 'yy-mm-dd', dayNames: ['Domingo', 'Segunda-feira', 'Terça-feira', 'Quarta-feira', 'Quinta-feira', 'Sexta-feira', 'Sábado'], dayNamesMin: ['Dom', 'Seg', 'Ter', 'Qua', 'Qui', 'Sex', 'Sáb'], dayNamesShort: ['Dom', 'Seg', 'Ter', 'Qua', 'Qui', 'Sex', 'Sáb'], monthNames: ['Janeiro', 'Fevereiro', 'Março', 'Abril', 'Maio', 'Junho', 'Julho', 'Agosto', 'Setembro', 'Outubro', 'Novembro', 'Dezembro'], monthNamesShort: ['Jan', 'Fev', 'Mar', 'Abr', 'Mai', 'Jun', 'Jul', 'Ago', 'Set', 'Out', 'Nov', 'Dez'], nextText: 'Próximo', prevText: 'Anterior', beforeShowDay: function(date) { var day = date.getDay(); var disableDay = new Function('day', 'return ' + diasDisp); return [disableDay(day), '']; }, // 关键:在新的onSelect中调用triggerAjaxCall onSelect: function(dateText, inst) { var selectedDate = $(this).datepicker('getDate'); var dayOfWeek = selectedDate.getDay(); triggerAjaxCall(); // 触发AJAX获取可用时段 }, minDate: 0 }); } }); }); // 页面加载时,如果已有选中的医生,自动初始化datepicker var initialDoctor = $('#selMedico').val(); if(initialDoctor){ $('#selMedico').trigger('change'); } }); </script>
优化说明
- 移除了原有的单独datepicker初始化代码,避免重复初始化;
- 将
triggerAjaxCall函数放到外层作用域,确保重建datepicker时能访问; - 在医生切换事件中,先触发一次
triggerAjaxCall,处理已有日期的情况; - 初始加载时自动触发医生选择事件,避免手动选择两次。
内容的提问来源于stack exchange,提问作者José Filipe Silva
相关产品推荐
相关产品推荐

