feat(预约日历): 添加分页功能和响应式布局
实现日历的分页浏览功能,支持28天预约范围 添加响应式布局适配不同屏幕尺寸 改进日期状态显示和交互逻辑
This commit is contained in:
@@ -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 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>
|
||||
<?php endfor; ?>
|
||||
|
||||
<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">
|
||||
|
||||
Reference in New Issue
Block a user