// 课程数据结构示例 const courseData = { // 按日期组织课程 "2023-06-12": [ { id: 1, name: "晨间瑜伽", type: "yoga", level: "beginner", startTime: "07:00", endTime: "08:00", trainer: { id: 2, name: "李教练", avatar: "http://picsum.photos/id/64/100/100" }, locations: "瑜伽室", capacity: 20, booked: 8, status: "available" // available, limited, full }, // 更多课程... ], // 更多日期... };
// 课程筛选函数 function filterCourses(courses, filters) { return courses.filter(course => { // 课程类型筛选 if (filters.type && course.type !== filters.type) return false; // 教练筛选 if (filters.trainer && course.trainer.id !== filters.trainer) return false; // 难度级别筛选 if (filters.level && course.level !== filters.level) return false; return true; }); } // 渲染课程表 function renderCourseTable(date) { const courses = courseData[date] || []; const filters = getCurrentFilters(); // 获取当前筛选条件 const filteredCourses = filterCourses(courses, filters); const tableBody = document.querySelector('#course-table tbody'); tableBody.innerHTML = ''; if (filteredCourses.length === 0) { tableBody.innerHTML = ` <tr> <td colspan="4" class="py-8 text-center text-gray-500"> 没有找到符合条件的课程 </td> </tr> `; return; } filteredCourses.forEach(course => { const statusClass = course.status === 'available' ? 'bg-green-100 text-green-800' : course.status === 'limited' ? 'bg-yellow-100 text-yellow-800' : 'bg-red-100 text-red-800'; const statusText = course.status === 'available' ? '可预约' : course.status === 'limited' ? `剩余${course.capacity - course.booked}席` : '已满'; const buttonHtml = course.status === 'full' ? '<button class="bg-gray-200 text-gray-500 px-4 py-1 rounded-md text-sm cursor-not-allowed">候补</button>' : `<button class="btn-outline py-1 px-4 text-sm" onclick="bookCourse(${course.id})">预约</button>`; const courseRow = document.createElement('tr'); courseRow.className = 'border-b hover:bg-light/50 transition-colors'; courseRow.innerHTML = ` <td class="py-4 px-6 font-medium">${course.startTime} - ${course.endTime}</td> <td class="py-4 px-4"> <div class="flex items-center"> <div class="w-10 h-10 rounded-full ${getCourseTypeColor(course.type)} flex items-center justify-center ${getCourseTypeTextColor(course.type)} mr-3"> <i class="${getCourseTypeIcon(course.type)}"></i> </div> <div> <div class="font-medium">${course.name}</div> <div class="text-sm text-gray-500">${getLevelText(course.level)} · ${course.locations}</div> </div> </div> </td> <td class="py-4 px-6 text-center"> <div class="flex items-center justify-center"> <img src="${course.trainer.avatar}" alt="${course.trainer.name}" class="w-8 h-8 rounded-full mr-2"> <span>${course.trainer.name}</span> </div> </td> <td class="py-4 px-6 text-center"> <span class="inline-block px-2 py-1 text-xs ${statusClass} rounded-full mr-2">${statusText}</span> ${buttonHtml} </td> `; tableBody.appendChild(courseRow); }); }
// 生成日历 function generateCalendar(year, month, availableDates) { const firstDay = new Date(year, month, 1).getDay(); const daysInMonth = new Date(year, month + 1, 0).getDate(); let calendarHtml = ''; // 生成星期标题 const weekdays = ['日', '一', '二', '三', '四', '五', '六']; weekdays.forEach(day => { calendarHtml += `<div class="text-center text-gray-500 text-sm">${day}</div>`; }); // 填充月初空白 for (let i = 0; i < firstDay; i++) { calendarHtml += '<div class="h-12"></div>'; } // 填充日期 for (let day = 1; day <= daysInMonth; day++) { const dateStr = `${year}-${String(month + 1).padStart(2, '0')}-${String(day).padStart(2, '0')}`; const isAvailable = availableDates.includes(dateStr); const isToday = new Date().toDateString() === new Date(year, month, day).toDateString(); let classes = 'h-12 flex items-center justify-center cursor-pointer transition-colors'; if (isToday) { classes += ' bg-primary text-white rounded-full'; } else if (!isAvailable) { classes += ' text-gray-400 cursor-not-allowed'; } else { classes += ' hover:bg-gray-100 rounded-full'; } calendarHtml += `<div class="${classes}" data-date="${dateStr}">${day}</div>`; } return calendarHtml; } // 加载教练可预约时间 function loadTrainerAvailability(trainerId, date) { // 模拟API请求 fetch(`/api/trainers/${trainerId}/availability?date=${date}`) .then(response => response.json()) .then(data => { renderTimeSlots(data.availableSlots, data.bookedSlots); }) .catch(error => { console.error('Failed to load availability:', error); }); } // 渲染时间段选择 function renderTimeSlots(availableSlots, bookedSlots) { const timeContainer = document.querySelector('#time-slots-container'); timeContainer.innerHTML = ''; // 生成一天中的可能时间段(例如8:00到22:00,每小时一个时段) for (let hour = 8; hour <= 22; hour++) { const timeStr = `${String(hour).padStart(2, '0')}:00`; const isBooked = bookedSlots.includes(timeStr); const isAvailable = availableSlots.includes(timeStr); let classes = 'py-2 border rounded-md transition-colors'; let clickHandler = ''; if (isBooked) { classes += ' border-gray-300 bg-gray-100 text-gray-400 cursor-not-allowed'; } else if (isAvailable) { classes += ' border-gray-300 hover:border-primary hover:text-primary cursor-pointer'; clickHandler = `onclick="selectTimeSlot('${timeStr}')"`; } else { classes += ' border-gray-300 bg-gray-50 text-gray-400 cursor-not-allowed'; } timeContainer.innerHTML += ` <button type="button" class="${classes}" ${clickHandler}>${timeStr}</button> `; } }
// 设置预约提醒 function setBookingReminder(bookingId, date, time, method = 'sms') { // 计算提醒时间(提前2小时) const reminderTime = new Date(date); const [hours, minutes] = time.split(':').map(Number); reminderTime.setHours(hours, minutes); reminderTime.setHours(reminderTime.getHours() - 2); // 计算当前时间与提醒时间的差值(毫秒) const now = new Date(); const timeDiff = reminderTime - now; if (timeDiff > 0) { // 设置本地提醒(实际应用中可能需要后端支持) setTimeout(() => { sendReminder(bookingId, method); }, timeDiff); // 存储提醒设置网页制作,以便页面刷新后恢复 saveReminderSetting(bookingId, reminderTime, method); } } // 发送提醒 function sendReminder(bookingId, method) { // 获取预约详情 const booking = getBookingDetails(bookingId); if (method === 'sms') { // 实际应用中调用短信API console.log(`发送短信提醒: 您预约的${booking.trainer}教练课程将于${booking.time}开始`); } else if (method === 'app') { // 应用内通知 showNotification(`您的私教课程将于${booking.time}开始`, '提醒'); } }