- 8 个页面 exercise-card 由 bind:tap 改为 catch:tap,拦截原生 tap 冒泡 避免一次点击被『自定义事件 + 原生冒泡』触发两次, 第二次 e.detail 无 id → navigateTo detail?id=undefined → 404 - 所有 onExercise 顶部加 id 守卫,无 id 直接 return - exercise-card 点击前校验 exercise.id,缺失不触发 - detail onLoad 的 id 为空时直接显示空态,不再发起错误请求
93 lines
2.6 KiB
JavaScript
93 lines
2.6 KiB
JavaScript
const app = getApp();
|
|
const svc = require('../../services/exercise');
|
|
|
|
Page({
|
|
data: {
|
|
statusBarHeight: 20,
|
|
step: 1, // 1: 选择目标肌群 / 2: 展示结果
|
|
bodyGroups: [],
|
|
selectedTarget: '',
|
|
selectedTargetLabel: '',
|
|
equipments: [],
|
|
selectedEquipment: '',
|
|
results: [],
|
|
loading: false
|
|
},
|
|
|
|
onLoad() {
|
|
this.setData({ statusBarHeight: app.globalData.statusBarHeight || 20 });
|
|
this.prepare();
|
|
},
|
|
|
|
prepare() {
|
|
this.setData({ loading: true });
|
|
Promise.all([
|
|
svc.getCategories('targets').catch(() => []),
|
|
svc.getCategories('equipment').catch(() => []),
|
|
svc.getCategories('body-parts').catch(() => [])
|
|
]).then(([targets, equipments, bodyParts]) => {
|
|
const tList = targets || [];
|
|
// 按 bodyPart 将目标肌群分组展示;后端未返回分组字段时退化为单组
|
|
const grouped = {};
|
|
(bodyParts || []).forEach(bp => { grouped[bp.value] = { label: bp.label, targets: [] }; });
|
|
tList.forEach(t => {
|
|
const key = t.bodyPart || 'other';
|
|
if (!grouped[key]) grouped[key] = { label: t.bodyPartLabel || '其他', targets: [] };
|
|
grouped[key].targets.push(t);
|
|
});
|
|
const bodyGroups = Object.keys(grouped)
|
|
.map(k => grouped[k])
|
|
.filter(g => g.targets.length);
|
|
this.setData({
|
|
bodyGroups: bodyGroups.length ? bodyGroups : [{ label: '全部目标肌群', targets: tList }],
|
|
equipments: equipments || [],
|
|
loading: false
|
|
});
|
|
}).catch(() => {
|
|
this.setData({ loading: false });
|
|
});
|
|
},
|
|
|
|
onSelectTarget(e) {
|
|
this.setData({
|
|
selectedTarget: e.currentTarget.dataset.value,
|
|
selectedTargetLabel: e.currentTarget.dataset.label
|
|
});
|
|
},
|
|
|
|
onSelectEquipment(e) {
|
|
const value = e.currentTarget.dataset.value;
|
|
this.setData({ selectedEquipment: this.data.selectedEquipment === value ? '' : value });
|
|
},
|
|
|
|
onConfirm() {
|
|
if (!this.data.selectedTarget) {
|
|
wx.showToast({ title: '请先选择目标肌群', icon: 'none' });
|
|
return;
|
|
}
|
|
this.setData({ loading: true, step: 2 });
|
|
svc.recommend({
|
|
target: this.data.selectedTarget,
|
|
equipment: this.data.selectedEquipment,
|
|
limit: 20
|
|
}).then((res) => {
|
|
this.setData({ results: (res && res.items) || [], loading: false });
|
|
}).catch(() => {
|
|
this.setData({ loading: false });
|
|
});
|
|
},
|
|
|
|
onBack() {
|
|
if (this.data.step === 2) {
|
|
this.setData({ step: 1 });
|
|
} else {
|
|
wx.navigateBack();
|
|
}
|
|
},
|
|
|
|
onExercise(e) {
|
|
if (!e || !e.detail || !e.detail.id) return;
|
|
wx.navigateTo({ url: '/pages/detail/detail?id=' + encodeURIComponent(e.detail.id) });
|
|
}
|
|
});
|