整合api请求、添加购买会员卡页面、登陆页面
This commit is contained in:
@@ -1,9 +1,3 @@
|
||||
import { bodyTestMock } from './mockData.js'
|
||||
|
||||
function clone(value) {
|
||||
return JSON.parse(JSON.stringify(value))
|
||||
}
|
||||
|
||||
function formatRecordTime(date) {
|
||||
const y = date.getFullYear()
|
||||
const m = String(date.getMonth() + 1).padStart(2, '0')
|
||||
@@ -28,9 +22,9 @@ function formatTime(date) {
|
||||
|
||||
export function getDefaultBodyTestState() {
|
||||
return {
|
||||
settings: { ...bodyTestMock.settings },
|
||||
device: { ...bodyTestMock.device },
|
||||
records: clone(bodyTestMock.records)
|
||||
settings: {},
|
||||
device: { connected: false, battery: 80 },
|
||||
records: []
|
||||
}
|
||||
}
|
||||
|
||||
@@ -167,14 +161,26 @@ export function getBodyTestTrendData(store, metricKey, limit = 6) {
|
||||
}))
|
||||
}
|
||||
|
||||
function getMetricDefs() {
|
||||
return [
|
||||
{ key: 'weight', label: '体重' },
|
||||
{ key: 'bmi', label: 'BMI' },
|
||||
{ key: 'bodyFat', label: '体脂率' },
|
||||
{ key: 'muscleMass', label: '肌肉量' },
|
||||
{ key: 'visceralFat', label: '内脏脂肪' },
|
||||
{ key: 'bmr', label: '基础代谢' }
|
||||
]
|
||||
}
|
||||
|
||||
export function getCompareData(store, idA, idB) {
|
||||
const a = getBodyTestRecordById(store, idA)
|
||||
const b = getBodyTestRecordById(store, idB)
|
||||
if (!a || !b) return null
|
||||
const metricDefs = getMetricDefs()
|
||||
const keys = ['weight', 'bmi', 'bodyFat', 'muscleMass', 'visceralFat', 'bmr']
|
||||
const metrics = keys.map((key) => ({
|
||||
key,
|
||||
label: bodyTestMock.metricDefs.find((m) => m.key === key)?.label || key,
|
||||
label: metricDefs.find((m) => m.key === key)?.label || key,
|
||||
valueA: a.metrics[key],
|
||||
valueB: b.metrics[key],
|
||||
diff: Math.round((a.metrics[key] - b.metrics[key]) * 10) / 10
|
||||
@@ -183,8 +189,7 @@ export function getCompareData(store, idA, idB) {
|
||||
}
|
||||
|
||||
export function getRecommendedCourses(record) {
|
||||
const ids = record?.recommendedCourseIds || []
|
||||
return bodyTestMock.recommendedCourses.filter((c) => ids.includes(c.id))
|
||||
return []
|
||||
}
|
||||
|
||||
export function updateBodyTestSettings(store, patch) {
|
||||
@@ -243,9 +248,9 @@ export function saveSimulatedBodyTestRecord(store, finalMetrics) {
|
||||
status,
|
||||
metrics,
|
||||
radar,
|
||||
bodySegments: clone(bodyTestMock.records[0].bodySegments),
|
||||
advice: clone(bodyTestMock.records[0].advice),
|
||||
recommendedCourseIds: [1, 2]
|
||||
bodySegments: [],
|
||||
advice: [],
|
||||
recommendedCourseIds: []
|
||||
}
|
||||
|
||||
if (previous) {
|
||||
@@ -279,5 +284,3 @@ export function interpolateMeasuringMetrics(progress, profile) {
|
||||
bodyWater: Math.round((51 + (target.bodyWater - 51) * ratio) * 10) / 10
|
||||
}
|
||||
}
|
||||
|
||||
export { bodyTestMock }
|
||||
|
||||
@@ -57,6 +57,14 @@ export function canCancelBooking(item) {
|
||||
return diff >= 2 * 3600000
|
||||
}
|
||||
|
||||
export function canSigninCourse(item) {
|
||||
if (!item?.courseDate || !item?.startTime) return false
|
||||
if (item.status !== 'booked' && item.status !== 0) return false
|
||||
const start = new Date(`${item.courseDate} ${item.startTime}`.replace(/-/g, '/'))
|
||||
const diff = start - Date.now()
|
||||
return diff <= 2 * 3600000 && diff >= -2 * 3600000
|
||||
}
|
||||
|
||||
export function bookCourse(store, courseId) {
|
||||
const course = store.courseCatalog.find((c) => c.id === Number(courseId))
|
||||
if (!course) return { ok: false, message: '课程不存在' }
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
export { memberCenterMock, userInfoMock, fitnessGoalOptions, bookingMock, memberCardMock, bodyTestMock, moduleMock, courseCatalogMock } from './mockData.js'
|
||||
export { statusBarTimeMixin, subPageMixin } from './mixins.js'
|
||||
export {
|
||||
loadMemberStore,
|
||||
@@ -31,8 +30,7 @@ export {
|
||||
connectBodyTestDevice,
|
||||
disconnectBodyTestDevice,
|
||||
saveSimulatedBodyTestRecord,
|
||||
interpolateMeasuringMetrics,
|
||||
bodyTestMock
|
||||
interpolateMeasuringMetrics
|
||||
} from './bodyTestStore.js'
|
||||
export {
|
||||
getTrainingReportData,
|
||||
@@ -52,8 +50,7 @@ export {
|
||||
getMyCoursesByTab,
|
||||
getOnlineCourseById,
|
||||
updateOnlineProgress,
|
||||
getCheckInHistory,
|
||||
moduleMock
|
||||
getCheckInHistory
|
||||
} from './moduleStore.js'
|
||||
export {
|
||||
filterCourses,
|
||||
@@ -61,8 +58,7 @@ export {
|
||||
bookCourse,
|
||||
canCancelBooking,
|
||||
enrichCourseForDisplay,
|
||||
getWeekDates,
|
||||
courseCatalogMock
|
||||
getWeekDates
|
||||
} from './bookingStore.js'
|
||||
export { previewImage, persistChosenImage, isLocalFilePath } from './media.js'
|
||||
export { maskPhone, formatMemberCenterPhone, normalizePhoneForStore } from './format.js'
|
||||
|
||||
@@ -1,6 +1,9 @@
|
||||
/** 个人中心模块 mock 数据(后续可替换为 API) */
|
||||
|
||||
export const memberCenterMock = {
|
||||
// Mock 数据开关 - 设为 false 可关闭所有 mock 数据
|
||||
export const MOCK_ENABLED = false
|
||||
|
||||
export const memberCenterMock = MOCK_ENABLED ? {
|
||||
userInfo: {
|
||||
name: '张小芳',
|
||||
phone: '13812345678 已绑定微信',
|
||||
@@ -65,7 +68,7 @@ export const memberCenterMock = {
|
||||
registered: 3,
|
||||
purchased: 2
|
||||
}
|
||||
}
|
||||
} : null
|
||||
|
||||
export const userInfoMock = {
|
||||
name: '张小芳',
|
||||
|
||||
@@ -1,9 +1,3 @@
|
||||
import {
|
||||
memberCenterMock,
|
||||
userInfoMock,
|
||||
memberCardMock,
|
||||
bookingMock
|
||||
} from './mockData.js'
|
||||
import { formatMemberCenterPhone, normalizePhoneForStore } from './format.js'
|
||||
import {
|
||||
getDefaultBodyTestState,
|
||||
@@ -24,10 +18,6 @@ import {
|
||||
|
||||
const STORAGE_KEY = 'gym_member_info_v1'
|
||||
|
||||
function clone(value) {
|
||||
return JSON.parse(JSON.stringify(value))
|
||||
}
|
||||
|
||||
export function buildCardTip(remainingDays) {
|
||||
return `距离下次到期还有${remainingDays}天,请及时续费`
|
||||
}
|
||||
@@ -70,24 +60,26 @@ function finalizeStore(store) {
|
||||
|
||||
function getDefaultStore() {
|
||||
return finalizeStore({
|
||||
profile: { ...userInfoMock, avatar: memberCenterMock.userInfo.avatar },
|
||||
memberProfile: { ...memberCenterMock.userInfo },
|
||||
stats: { ...memberCenterMock.stats },
|
||||
cardInfo: { ...memberCenterMock.cardInfo },
|
||||
card: { ...memberCardMock.card },
|
||||
records: clone(memberCardMock.records),
|
||||
ongoingBookings: clone(bookingMock.ongoing),
|
||||
historyBookings: clone(bookingMock.history),
|
||||
checkIns: clone(memberCenterMock.checkIns),
|
||||
bodyReport: { ...memberCenterMock.bodyReport },
|
||||
profile: {},
|
||||
memberProfile: {},
|
||||
stats: {},
|
||||
cardInfo: {},
|
||||
card: {},
|
||||
records: [],
|
||||
ongoingBookings: [],
|
||||
historyBookings: [],
|
||||
checkIns: [],
|
||||
bodyReport: {},
|
||||
bodyTest: getDefaultBodyTestState(),
|
||||
modules: getDefaultModuleState(),
|
||||
courseCatalog: getDefaultCourseCatalog(),
|
||||
couponPoints: { ...memberCenterMock.couponPoints },
|
||||
referral: { ...memberCenterMock.referral }
|
||||
couponPoints: {},
|
||||
referral: {}
|
||||
})
|
||||
}
|
||||
|
||||
export { getDefaultStore }
|
||||
|
||||
function mergeDefaults(saved) {
|
||||
const defaults = getDefaultStore()
|
||||
return finalizeStore({
|
||||
@@ -204,7 +196,11 @@ export function getBookingPreview(store, limit = 2) {
|
||||
export function getCenterPageData(store) {
|
||||
return {
|
||||
userInfo: { ...store.memberProfile },
|
||||
stats: { ...store.stats },
|
||||
stats: {
|
||||
checkInCount: store.stats?.checkInCount ?? 0,
|
||||
trainingHours: store.stats?.trainingHours ?? 0,
|
||||
pointsBalance: store.stats?.pointsBalance ?? 0
|
||||
},
|
||||
cardInfo: { ...store.cardInfo },
|
||||
bookingPreview: getBookingPreview(store),
|
||||
checkIns: store.checkIns.map((item) => ({ ...item })),
|
||||
@@ -234,6 +230,15 @@ export function cancelOngoingBooking(store, id) {
|
||||
const course = store.courseCatalog.find((c) => c.id === removed.courseId)
|
||||
if (course && course.enrolled > 0) course.enrolled -= 1
|
||||
}
|
||||
|
||||
// 同步从 myCourses.group.ongoing 中移除
|
||||
if (store.modules?.myCourses?.group?.ongoing) {
|
||||
const myCoursesIndex = store.modules.myCourses.group.ongoing.findIndex((c) => c.id === id)
|
||||
if (myCoursesIndex >= 0) {
|
||||
store.modules.myCourses.group.ongoing.splice(myCoursesIndex, 1)
|
||||
}
|
||||
}
|
||||
|
||||
store.historyBookings.unshift({
|
||||
...removed,
|
||||
status: 'cancelled',
|
||||
|
||||
Reference in New Issue
Block a user