feat(预约日历): 添加分页功能和响应式布局

实现日历的分页浏览功能,支持28天预约范围
添加响应式布局适配不同屏幕尺寸
改进日期状态显示和交互逻辑
This commit is contained in:
2025-11-19 16:08:30 +08:00
parent 3d33e595dd
commit 8085d582ec
+169 -22
View File
@@ -334,30 +334,177 @@ $packages_json = json_encode(array_map(function($package) {
<div class="booking-container">
<div class="calendar-section">
<h2>📅 选择预约日期</h2>
<div class="calendar">
<?php for ($i = 0; $i < 7; $i++):
$date = date('Y-m-d', strtotime("+{$i} days"));
$date_display = date('m/d', strtotime("+{$i} days"));
$weekday = ['日', '一', '二', '三', '四', '五', '六'][date('w', strtotime("+{$i} days"))];
$booking_count = $booking_schedule[$date] ?? 0;
$is_today = $i === 0;
$is_full = $booking_count >= 8; // 假设每天最多8个时段
$status_class = $is_full ? 'full' : ($booking_count > 0 ? 'busy' : 'available');
$status_text = $is_full ? '已满' : ($booking_count > 0 ? '繁忙' : '可预约');
?>
<div class="calendar-day <?= $status_class ?> <?= $is_today ? 'today' : '' ?>"
data-date="<?= $date ?>"
data-booking-count="<?= $booking_count ?>"
onclick="showDateDetails('<?= $date ?>')">
<div class="day-number"><?= $date_display ?></div>
<div class="day-week">周<?= $weekday ?></div>
<div class="day-status"><?= $status_text ?></div>
<div class="booking-count"><?= $booking_count ?>个预约</div>
</div>
<?php endfor; ?>
<!-- 分页控制 -->
<div class="pagination-controls">
<button type="button" id="prevPage" class="btn btn-sm btn-secondary" onclick="changePage(-1)">上一页</button>
<span id="pageInfo" class="page-info">第 1 页 / 共 4 页</span>
<button type="button" id="nextPage" class="btn btn-sm btn-secondary" onclick="changePage(1)">下一页</button>
</div>
<style>
/* 分页控制样式 */
.pagination-controls {
display: flex;
justify-content: center;
align-items: center;
margin-bottom: 20px;
gap: 15px;
}
.page-info {
font-size: 14px;
font-weight: bold;
color: #333;
}
.btn:disabled {
opacity: 0.5;
cursor: not-allowed;
}
/* 日历布局样式 */
.calendar {
display: grid;
grid-template-columns: repeat(7, 1fr);
gap: 10px;
margin-bottom: 20px;
}
/* 确保响应式布局 */
@media (max-width: 768px) {
.calendar {
grid-template-columns: repeat(4, 1fr);
}
}
@media (max-width: 480px) {
.calendar {
grid-template-columns: repeat(2, 1fr);
}
}
/* 超出范围日期样式 */
.calendar-day.disabled {
background-color: #f5f5f5;
color: #999;
cursor: not-allowed;
}
.calendar-day.disabled:hover {
transform: none;
box-shadow: none;
}
</style>
<div class="calendar" id="calendarContainer">
<!-- 日期将通过JavaScript动态生成 -->
</div>
<script>
// 初始化当前页码(从0开始)
let currentPage = 0;
const totalPages = 4; // 总共4页(28天)
const daysPerPage = 7; // 每页7天
// 获取本周一的日期
function getCurrentMonday() {
const today = new Date();
const dayOfWeek = today.getDay(); // 0是周日,1-6是周一到周六
const diff = today.getDate() - dayOfWeek + (dayOfWeek === 0 ? -6 : 1); // 调整为周一
const monday = new Date(today);
monday.setDate(diff);
return monday;
}
// 生成日历数据 - 按周一到周日顺序排列
const generateCalendarDays = () => {
const calendarContainer = document.getElementById('calendarContainer');
calendarContainer.innerHTML = '';
// 获取基准周一日期
const baseMonday = getCurrentMonday();
// 根据页码计算当前页的起始周
const weekOffset = currentPage;
// 计算当前页第一周的周一
const pageStartMonday = new Date(baseMonday);
pageStartMonday.setDate(baseMonday.getDate() + weekOffset * 7);
// 按周一到周日的顺序生成日期
for (let dayOffset = 0; dayOffset < 7; dayOffset++) {
const date = new Date(pageStartMonday);
date.setDate(pageStartMonday.getDate() + dayOffset);
const dateStr = date.toISOString().split('T')[0];
const dateDisplay = `${date.getMonth() + 1}/${date.getDate()}`;
const weekday = ['日', '一', '二', '三', '四', '五', '六'][date.getDay()];
// 获取今天的日期字符串用于比较
const today = new Date();
const todayStr = today.toISOString().split('T')[0];
const isToday = dateStr === todayStr;
// 获取预约数量
const bookingCount = bookingsByDate[dateStr] ? bookingsByDate[dateStr].length : 0;
const isFull = bookingCount >= 8; // 假设每天最多8个时段
// 检查日期是否在未来28天内
const currentDate = new Date();
const maxDate = new Date(currentDate);
maxDate.setDate(currentDate.getDate() + 27); // 28天包括今天
const isWithinRange = date >= currentDate && date <= maxDate;
const statusClass = isFull ? 'full' : (bookingCount > 0 ? 'busy' : (isWithinRange ? 'available' : 'disabled'));
const statusText = isFull ? '已满' : (bookingCount > 0 ? '繁忙' : (isWithinRange ? '可预约' : '超出范围'));
const dayDiv = document.createElement('div');
dayDiv.className = `calendar-day ${statusClass} ${isToday ? 'today' : ''}`;
dayDiv.dataset.date = dateStr;
dayDiv.dataset.bookingCount = bookingCount;
// 只有在范围内的日期才可点击
if (isWithinRange) {
dayDiv.onclick = () => showDateDetails(dateStr);
}
dayDiv.innerHTML = `
<div class="day-number">${dateDisplay}</div>
<div class="day-week">周${weekday}</div>
<div class="day-status">${statusText}</div>
<div class="booking-count">${bookingCount}个预约</div>
`;
calendarContainer.appendChild(dayDiv);
}
// 更新分页信息
updatePaginationInfo();
};
// 更新分页信息
const updatePaginationInfo = () => {
const pageInfo = document.getElementById('pageInfo');
pageInfo.textContent = `第 ${currentPage + 1} 页 / 共 ${totalPages} 页`;
// 启用/禁用翻页按钮
document.getElementById('prevPage').disabled = currentPage === 0;
document.getElementById('nextPage').disabled = currentPage === totalPages - 1;
};
// 切换页面
const changePage = (direction) => {
const newPage = currentPage + direction;
if (newPage >= 0 && newPage < totalPages) {
currentPage = newPage;
generateCalendarDays();
}
};
// 页面加载时生成第一页
document.addEventListener('DOMContentLoaded', function() {
generateCalendarDays();
});
</script>
<div class="time-slots" id="timeSlots" style="display: none;">
<h3>🕐 选择时间段</h3>
<div class="quick-duration">