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