会员个人中心页面初步完成
This commit is contained in:
@@ -0,0 +1,127 @@
|
||||
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 }
|
||||
Reference in New Issue
Block a user