Files
fitness-coach/miniprogram/pages/detail/detail.js

162 lines
5.1 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

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,
favRight: 8,
favTop: 20,
id: '',
planId: '',
exercise: null,
heroSrc: '',
heroGif: '',
heroError: false,
related: [],
loading: true,
favorited: false
},
onLoad(query) {
const id = query.id || '';
const planId = query.planId || '';
// 收藏按钮需避让微信右上角胶囊按钮(···◯):用胶囊实际位置算出安全右/上边距
let favRight = 8;
let favTop = (app.globalData.statusBarHeight || 20) + 6;
try {
const menu = wx.getMenuButtonBoundingClientRect();
const win = (wx.getWindowInfo && wx.getWindowInfo()) || wx.getSystemInfoSync();
if (menu && win) {
favRight = Math.max(8, win.windowWidth - menu.left + 8);
favTop = menu.top + Math.max(0, (menu.height - 36) / 2);
}
} catch (e) {}
this.setData({ statusBarHeight: app.globalData.statusBarHeight || 20, favRight, favTop, 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(() => {});
},
// 底部主按钮:加入计划(真实选择器)
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(() => planSvc.listMine()).then((res) => {
const plans = (res && res.items) || res || [];
if (!plans.length) {
wx.showModal({
title: '还没有训练计划',
content: '先创建一个计划,再把动作加进去吧~',
confirmText: '去创建',
cancelText: '稍后',
success: (r) => { if (r.confirm) wx.navigateTo({ url: '/pages/plan-edit/plan-edit' }); }
});
return;
}
const names = plans.slice(0, 6).map((p) => p.name);
wx.showActionSheet({
itemList: names,
success: (sheet) => {
const plan = plans[sheet.tapIndex];
if (!plan) return;
planSvc.addExercise(plan.id, this.data.id).then(() => {
wx.showToast({ title: '已加入「' + plan.name + '」', icon: 'success' });
}).catch(() => {});
}
});
}).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
};
}
});