const app = getApp(); const svc = require('../../services/exercise'); const favSvc = require('../../services/favorite'); const planSvc = require('../../services/plan'); const auth = require('../../utils/auth'); Page({ data: { statusBarHeight: 20, id: '', planId: '', exercise: null, heroSrc: '', heroGif: '', heroError: false, related: [], loading: true, favorited: false }, onLoad(query) { const id = query.id || ''; const planId = query.planId || ''; this.setData({ statusBarHeight: app.globalData.statusBarHeight || 20, id, planId }); // 防御:id 缺失直接显示空态,避免请求 /api/exercises/ 导致错乱或 404 if (!id) { this.setData({ loading: false }); return; } this.load(); if (auth.isLogin()) { favSvc.exerciseStatus(id).then((r) => { this.setData({ favorited: !!(r && r.favorited) }); }).catch(() => {}); } }, load() { this.setData({ loading: true }); svc.getExercise(this.data.id).then((ex) => { // 海报用超分 JPG(720px 清晰);动图用原始 GIF,由 gif-player 组件逐帧播放 const heroSrc = ex && (ex.image || ex.gifUrl) ? (ex.image || ex.gifUrl) : ''; const heroGif = ex && ex.gifUrl ? ex.gifUrl : ''; this.setData({ exercise: ex, heroSrc, heroGif, heroError: false, loading: false }); if (ex && ex.target) { svc.listExercises({ target: ex.target, pageSize: 6 }).then((res) => { const related = ((res && res.items) || []) .filter(i => i.id !== ex.id) .slice(0, 6); this.setData({ related }); }).catch(() => {}); } }).catch(() => { this.setData({ loading: false }); }); }, // 收藏 / 取消收藏(心形按钮) onToggleFav() { auth.ensureLogin().then(() => { const id = this.data.id; const wasFav = this.data.favorited; const op = wasFav ? favSvc.removeExercise(id) : favSvc.addExercise(id); op.then(() => { this.setData({ favorited: !wasFav }); wx.showToast({ title: wasFav ? '已取消收藏' : '已收藏', icon: 'none' }); }).catch(() => {}); }).catch(() => {}); }, // 底部主按钮:加入计划 // - 若从某计划内进入(带 planId),直接加入该计划 // - 否则进入「加入计划」选择器页,可浏览全部计划并筛选 onAdd() { if (this.data.planId) { planSvc.addExercise(this.data.planId, this.data.id).then(() => { wx.showToast({ title: '已加入计划', icon: 'success' }); setTimeout(() => wx.navigateBack(), 500); }).catch(() => {}); return; } auth.ensureLogin().then(() => { const name = this.data.exercise ? (this.data.exercise.displayName || this.data.exercise.name) : ''; wx.navigateTo({ url: '/pages/plan-select/plan-select?exerciseId=' + encodeURIComponent(this.data.id) + '&name=' + encodeURIComponent(name || '') }); }).catch(() => {}); }, onBack() { const pages = getCurrentPages(); if (pages.length > 1) { wx.navigateBack(); } else { wx.reLaunch({ url: '/pages/index/index' }); } }, // 详情大图加载失败:JPG↔GIF 互为降级,最后 emoji 占位,保证不空白 onHeroError() { const ex = this.data.exercise || {}; const cur = this.data.heroSrc; if (cur === ex.image && ex.gifUrl) { this.setData({ heroSrc: ex.gifUrl }); } else if (cur === ex.gifUrl && ex.image) { this.setData({ heroSrc: ex.image }); } else { this.setData({ heroError: true }); } }, onExercise(e) { if (!e || !e.detail || !e.detail.id) return; wx.navigateTo({ url: '/pages/detail/detail?id=' + encodeURIComponent(e.detail.id) }); }, onShareAppMessage() { const ex = this.data.exercise || {}; const name = ex.displayName || ex.name || ''; return { title: name ? ('FITCOACH · ' + name) : 'FITCOACH 智能健身教练', path: '/pages/detail/detail?id=' + this.data.id }; }, onShareTimeline() { return { title: 'FITCOACH · 精准训练推荐', query: 'id=' + this.data.id }; } });