import { courseCatalogMock } from './mockData.js' function clone(value) { return JSON.parse(JSON.stringify(value)) } export function getDefaultCourseCatalog() { return clone(courseCatalogMock.courses) } export function mergeCourseCatalog(saved) { const defaults = getDefaultCourseCatalog() if (!saved?.length) return defaults return saved.map((item, i) => ({ ...defaults[i], ...item })) } function parseCourseStart(course) { const str = `${course.date} ${course.startTime}`.replace(/-/g, '/') return new Date(str) } function getPeriod(hour) { if (hour < 12) return 'morning' if (hour < 18) return 'afternoon' return 'evening' } export function filterCourses(courses, filters = {}) { const { date = '', weekDates = [], type = 'all', coach = '全部', period = 'all' } = filters return courses.filter((c) => { if (type !== 'all' && c.type !== type) return false if (coach !== '全部' && c.coach !== coach) return false if (period !== 'all' && c.period !== period) return false if (date && c.date !== date) { if (!weekDates.length || !weekDates.includes(c.date)) return false } return true }) } export function getCourseById(store, id) { const course = (store.courseCatalog || []).find((c) => c.id === Number(id)) return course ? { ...course } : null } export function canCancelBooking(item) { if (!item?.courseDate || !item?.startTime) return !!item?.canCancel const start = new Date(`${item.courseDate} ${item.startTime}`.replace(/-/g, '/')) const diff = start - Date.now() return diff >= 2 * 3600000 } export function bookCourse(store, courseId) { const course = store.courseCatalog.find((c) => c.id === Number(courseId)) if (!course) return { ok: false, message: '课程不存在' } if (course.enrolled >= course.capacity) return { ok: false, message: '课程已约满' } const exists = store.ongoingBookings.some((b) => b.courseId === course.id) if (exists) return { ok: false, message: '您已预约该课程' } course.enrolled += 1 const nextId = store.ongoingBookings.reduce((m, b) => Math.max(m, b.id || 0), 0) + 1 const parts = course.date.split('-') const booking = { id: nextId, courseId: course.id, title: course.title, banner: course.banner, status: 'booked', statusLabel: '已预约', schedule: `${parts[1]}月${parts[2]}日 ${course.startTime}-${course.endTime}`, dateDay: parts[2], dateMonth: `月${parts[2]}日`, timeRange: `${course.startTime}-${course.endTime}`, courseDate: course.date, startTime: course.startTime, coach: course.coach, coachShort: course.coach.replace('教练', ''), location: course.location, footerText: `可取消(需提前2小时,截止 ${parts[1]}/${parts[2]} ${course.startTime} 前2小时)`, canCancel: true, type: course.type } store.ongoingBookings.unshift(booking) return { ok: true, message: '预约成功', booking } } export function getWeekDates(baseDateStr) { const base = baseDateStr ? new Date(baseDateStr.replace(/-/g, '/')) : new Date() const day = base.getDay() || 7 const monday = new Date(base) monday.setDate(base.getDate() - day + 1) const dates = [] for (let i = 0; i < 7; i += 1) { const d = new Date(monday) d.setDate(monday.getDate() + i) dates.push(formatIso(d)) } return dates } function formatIso(d) { const y = d.getFullYear() const m = String(d.getMonth() + 1).padStart(2, '0') const day = String(d.getDate()).padStart(2, '0') return `${y}-${m}-${day}` } export function enrichCourseForDisplay(course) { const remaining = course.capacity - course.enrolled const percent = Math.round((course.enrolled / course.capacity) * 100) return { ...course, remaining, percent, full: remaining <= 0, scarcityLabel: remaining > 0 && remaining <= 5 ? `仅剩${remaining}席` : '' } } export { courseCatalogMock }