feat(plan): 新增「加入计划」选择器页 + 增强官方计划浏览,修复返回不刷新
1) 新增 pages/plan-select(加入我的计划选择器,替换详情页 actionSheet) - 默认展示我全部计划(浏览,不再强制搜索),支持 最近创建/动作最多 排序 + 名称搜索 - 点选即把动作加入该计划并返回;无计划时引导新建 - 入口接在 detail 页「加入计划」(无 planId 时 navigate 至此) 2) 增强 pages/collection(官方训练计划) - 默认展示全部分级,新增 等级筛选 chips + 名称搜索(均用现有字段,不改后端) - 筛选/搜索纯前端,viewGroups 驱动渲染 3) 修复 plan-detail 从「添加动作」返回后列表不刷新(上轮已单独提交 7ff55a6) 4) app.json 注册 plan-select 页面
This commit is contained in:
92
miniprogram/pages/plan-select/plan-select.js
Normal file
92
miniprogram/pages/plan-select/plan-select.js
Normal file
@@ -0,0 +1,92 @@
|
||||
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();
|
||||
}
|
||||
});
|
||||
Reference in New Issue
Block a user