import { moduleMock } from './mockData.js' function clone(value) { return JSON.parse(JSON.stringify(value)) } export function getDefaultModuleState() { return { trainingReport: clone(moduleMock.trainingReport), coupons: clone(moduleMock.coupons), couponCenter: clone(moduleMock.couponCenter), pointsHistory: clone(moduleMock.pointsHistory), pointsRewards: clone(moduleMock.pointsRewards), redeemRecords: [], referralRecords: clone(moduleMock.referralRecords), myCourses: clone(moduleMock.myCourses), checkInHistory: clone(moduleMock.checkInHistory) } } export function mergeModuleState(saved) { const defaults = getDefaultModuleState() if (!saved) return defaults return { trainingReport: { ...defaults.trainingReport, ...(saved.trainingReport || {}) }, coupons: saved.coupons?.length ? saved.coupons : defaults.coupons, couponCenter: saved.couponCenter?.length ? saved.couponCenter : defaults.couponCenter, pointsHistory: saved.pointsHistory?.length ? saved.pointsHistory : defaults.pointsHistory, pointsRewards: saved.pointsRewards?.length ? saved.pointsRewards : defaults.pointsRewards, redeemRecords: saved.redeemRecords || defaults.redeemRecords, referralRecords: saved.referralRecords?.length ? saved.referralRecords : defaults.referralRecords, myCourses: saved.myCourses ? mergeMyCourses(defaults.myCourses, saved.myCourses) : defaults.myCourses, checkInHistory: saved.checkInHistory?.length ? saved.checkInHistory : defaults.checkInHistory } } function mergeMyCourses(defaults, saved) { return { group: saved.group || defaults.group, private: saved.private || defaults.private, online: saved.online?.length ? saved.online : defaults.online, package: saved.package?.length ? saved.package : defaults.package } } function syncCouponSummary(store) { const available = store.modules.coupons.filter((c) => c.status === 'available') const top = available[0] store.couponPoints = { ...store.couponPoints, amount: top ? `¥${top.amount}` : '暂无', couponDesc: top ? `满${top.minSpend}可用 · ${available.length}张` : '暂无可用优惠券', couponAction: available.length ? '去使用' : '去领取', points: store.stats.pointsBalance, pointsLabel: '我的积分', pointsAction: '去兑换' } return store } export function finalizeModules(store) { syncCouponSummary(store) store.checkIns = store.modules.checkInHistory.slice(0, 3).map((item) => ({ ...item })) return store } export function getTrainingReportData(store, period = 'week') { const report = store.modules.trainingReport const trend = period === 'month' ? report.monthlyHours : report.weeklyHours const calTrend = period === 'month' ? report.monthlyCalories : report.weeklyHours.map((w, i) => ({ label: w.label, value: Math.round((report.summary.calories / 7) * (w.value || 0.5)) })) return { ...report, period, summary: { ...report.summary, hours: store.stats.trainingHours ?? report.summary.hours, visits: report.summary.visits ?? store.stats.checkInCount ?? 5 }, trendHours: trend.map((t) => ({ ...t, id: t.label })), trendCalories: calTrend.map((t) => ({ ...t, id: t.label })), sessions: report.sessions.map((s) => ({ ...s })) } } export function getTrainingSessionById(store, id) { const session = store.modules.trainingReport.sessions.find((s) => s.id === Number(id)) if (!session) return null return { ...session, heartRate: '128 bpm', comment: '动作标准,核心发力良好,下次可增加负重。', checkInTime: `${session.date} ${session.time.split('-')[0]}` } } export function filterTrainingSessions(store, filters = {}) { let list = store.modules.trainingReport.sessions.map((s) => ({ ...s })) if (filters.type && filters.type !== 'all') { list = list.filter((s) => s.type === filters.type) } return list } export function getCouponsByStatus(store, status) { return store.modules.coupons.filter((c) => c.status === status).map((c) => ({ ...c })) } export function getCouponById(store, id) { const c = store.modules.coupons.find((item) => item.id === Number(id)) return c ? { ...c } : null } export function useCoupon(store, id) { const coupon = store.modules.coupons.find((c) => c.id === id) if (!coupon || coupon.status !== 'available') return null coupon.status = 'used' coupon.usedAt = new Date().toISOString().slice(0, 10) syncCouponSummary(store) return coupon } export function deleteExpiredCoupon(store, id) { const idx = store.modules.coupons.findIndex((c) => c.id === id && c.status === 'expired') if (idx >= 0) store.modules.coupons.splice(idx, 1) syncCouponSummary(store) return store } export function getCouponCenterList(store) { return store.modules.couponCenter.map((c) => ({ ...c })) } export function claimCouponFromCenter(store, centerId) { const item = store.modules.couponCenter.find((c) => c.id === centerId) if (!item || item.claimed) return { ok: false, message: '已领取或不存在' } const nextId = store.modules.coupons.reduce((m, c) => Math.max(m, c.id || 0), 0) + 1 const expire = new Date() expire.setDate(expire.getDate() + item.expireDays) store.modules.coupons.unshift({ id: nextId, status: 'available', amount: item.amount, title: item.title, desc: item.desc, expire: expire.toISOString().slice(0, 10), minSpend: item.minSpend, tag: item.tag, rules: `领取后${item.expireDays}天内有效,满${item.minSpend}可用`, scope: '全门店', flow: '预约课程时使用' }) item.claimed = true syncCouponSummary(store) return { ok: true, message: '领取成功' } } export function getPointsPageData(store) { return { balance: store.stats.pointsBalance, config: moduleMock.pointsConfig, history: store.modules.pointsHistory.map((h) => ({ ...h })), rewards: store.modules.pointsRewards.map((r) => ({ ...r })), redeemRecords: (store.modules.redeemRecords || []).map((r) => ({ ...r })) } } function nextHistoryId(history) { return (history || []).reduce((max, item) => Math.max(max, item.id || 0), 0) + 1 } function formatNow() { const d = new Date() const pad = (n) => String(n).padStart(2, '0') return `${d.getFullYear()}-${pad(d.getMonth() + 1)}-${pad(d.getDate())} ${pad(d.getHours())}:${pad(d.getMinutes())}` } export function redeemPointsReward(store, rewardId) { const reward = store.modules.pointsRewards.find((r) => r.id === rewardId) if (!reward || reward.stock <= 0) return { ok: false, message: '库存不足' } if (store.stats.pointsBalance < reward.cost) { return { ok: false, message: '积分不足' } } store.stats.pointsBalance -= reward.cost reward.stock -= 1 store.modules.pointsHistory.unshift({ id: nextHistoryId(store.modules.pointsHistory), type: 'spend', title: `兑换${reward.name}`, amount: -reward.cost, time: formatNow(), balance: store.stats.pointsBalance }) store.modules.redeemRecords = store.modules.redeemRecords || [] store.modules.redeemRecords.unshift({ id: nextHistoryId(store.modules.redeemRecords), name: reward.name, cost: reward.cost, time: formatNow() }) syncCouponSummary(store) return { ok: true, message: '兑换成功', reward } } export function filterPointsHistory(store, filter = 'all') { const list = store.modules.pointsHistory if (filter === 'earn') return list.filter((h) => h.amount > 0).map((h) => ({ ...h })) if (filter === 'spend') return list.filter((h) => h.amount < 0).map((h) => ({ ...h })) return list.map((h) => ({ ...h })) } export function getReferralPageData(store) { return { ...store.referral, records: store.modules.referralRecords.map((r) => ({ ...r })), rules: moduleMock.referralRules, rewardSummary: moduleMock.referralRewardSummary } } export function getMyCoursesData(store, tab) { const data = store.modules.myCourses if (tab === 'group') return { ...data.group } if (tab === 'private') return { ...data.private } if (tab === 'online') return { list: data.online.map((c) => ({ ...c })) } if (tab === 'package') return { list: data.package.map((c) => ({ ...c })) } return {} } export function getOnlineCourseById(store, id) { const course = store.modules.myCourses.online.find((c) => c.id === Number(id)) if (!course) return null return { ...course, chapters: [ { id: 1, title: '热身激活', duration: '8分钟', done: true }, { id: 2, title: '核心训练 A', duration: '12分钟', done: true }, { id: 3, title: '核心训练 B', duration: '10分钟', done: true }, { id: 4, title: '拉伸放松', duration: '8分钟', done: true }, { id: 5, title: '进阶组合', duration: '15分钟', done: false }, { id: 6, title: '总结复盘', duration: '5分钟', done: false } ], comments: [{ user: '学员A', text: '跟着练很方便' }] } } export function updateOnlineProgress(store, courseId, progress) { const course = store.modules.myCourses.online.find((c) => c.id === Number(courseId)) if (course) course.progress = progress return course } export function getCheckInHistory(store, filter = 'all') { const list = store.modules.checkInHistory if (filter === 'all') return list.map((i) => ({ ...i })) return list.filter((i) => i.tagTheme === filter).map((i) => ({ ...i })) } /** @deprecated use getMyCoursesData */ export function getMyCoursesByTab(store, tab) { if (tab === 'ongoing') return store.modules.myCourses.group?.ongoing || [] if (tab === 'completed') return store.modules.myCourses.group?.completed || [] return [] } export { moduleMock }