Files
fitness-coach/miniprogram/pages/plan-select/plan-select.js
wm ff3a120b55 feat(plan): 新增「加入计划」选择器页 + 增强官方计划浏览,修复返回不刷新
1) 新增 pages/plan-select(加入我的计划选择器,替换详情页 actionSheet)
   - 默认展示我全部计划(浏览,不再强制搜索),支持 最近创建/动作最多 排序 + 名称搜索
   - 点选即把动作加入该计划并返回;无计划时引导新建
   - 入口接在 detail 页「加入计划」(无 planId 时 navigate 至此)
2) 增强 pages/collection(官方训练计划)
   - 默认展示全部分级,新增 等级筛选 chips + 名称搜索(均用现有字段,不改后端)
   - 筛选/搜索纯前端,viewGroups 驱动渲染
3) 修复 plan-detail 从「添加动作」返回后列表不刷新(上轮已单独提交 7ff55a6)
4) app.json 注册 plan-select 页面
2026-07-23 14:15:41 +08:00

93 lines
3.0 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 planSvc = require('../../services/plan');
const auth = require('../../utils/auth');
const { iconName } = require('../../utils/icon-name');
// 加入计划选择器:从动作详情「加入计划」进入,默认展示我全部计划,
// 支持 最近创建 / 动作最多 排序与名称搜索,点选即把动作加入该计划并返回。
Page({
data: {
statusBarHeight: 20,
exerciseId: '',
exerciseName: '',
allPlans: [],
plans: [],
filter: 'all', // 'all' | 'recent' | 'count'
keyword: '',
status: 'loading', // 'loading' | 'list' | 'empty' | 'error'
errorMsg: ''
},
onLoad(query) {
this.setData({
statusBarHeight: app.globalData.statusBarHeight || 20,
exerciseId: query.exerciseId || '',
exerciseName: query.name || ''
});
},
onShow() {
if (auth.isLogin()) this.load();
else {
wx.showToast({ title: '请先登录', icon: 'none' });
setTimeout(() => wx.navigateBack(), 600);
}
},
load() {
this.setData({ status: 'loading', errorMsg: '' });
planSvc.listMine().then((res) => {
const raw = (res && res.items) || res || [];
const plans = raw.map((p) => ({ ...p, icon: iconName(p.emoji, 'folder-open') }));
this.setData({ allPlans: plans, status: plans.length ? 'list' : 'empty' });
this.applyFilter();
}).catch((err) => {
const status = err && err.statusCode;
const msg = status === 401 ? '登录已失效,请重新登录' : '加载失败,请检查网络后重试';
this.setData({ status: 'error', errorMsg: msg });
});
},
// 排序 + 名称搜索(纯前端,基于已有字段 createdAt / exerciseCount / name
applyFilter() {
const f = this.data.filter;
let list = (this.data.allPlans || []).slice();
const k = (this.data.keyword || '').trim().toLowerCase();
if (k) list = list.filter((p) => (p.name || '').toLowerCase().includes(k));
if (f === 'recent') list.sort((a, b) => (a.createdAt < b.createdAt ? 1 : -1));
else if (f === 'count') list.sort((a, b) => b.exerciseCount - a.exerciseCount);
this.setData({ plans: list });
},
onFilter(e) {
this.setData({ filter: e.detail.value }, () => this.applyFilter());
},
onSearch(e) {
this.setData({ keyword: e.detail.value }, () => this.applyFilter());
},
onSelect(e) {
const id = e.currentTarget.dataset.id;
const name = e.currentTarget.dataset.name || '';
if (!id || !this.data.exerciseId) return;
wx.showLoading({ title: '加入中…', mask: true });
planSvc.addExercise(id, this.data.exerciseId).then(() => {
wx.hideLoading();
wx.showToast({ title: name ? ('已加入「' + name + '」') : '已加入计划', icon: 'success' });
setTimeout(() => wx.navigateBack(), 400);
}).catch(() => {
wx.hideLoading();
wx.showToast({ title: '加入失败,请重试', icon: 'none' });
});
},
onCreate() {
wx.navigateTo({ url: '/pages/plan-edit/plan-edit' });
},
onRetry() {
this.load();
}
});