feat: init fitness-coach (backend + miniprogram)
- backend: NestJS service with exercise/plan data - miniprogram: WeChat mini program client - exclude node_modules, dist, runtime data-store, local env
This commit is contained in:
91
miniprogram/pages/recommend/recommend.js
Normal file
91
miniprogram/pages/recommend/recommend.js
Normal file
@@ -0,0 +1,91 @@
|
||||
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) {
|
||||
wx.navigateTo({ url: '/pages/detail/detail?id=' + encodeURIComponent(e.detail.id) });
|
||||
}
|
||||
});
|
||||
Reference in New Issue
Block a user