Files
fitness-coach/miniprogram/pages/plan-detail/plan-detail.js
wm 54a5ae858d fix(plan-detail): 增加加载/错误/重试/未找到四态,杜绝静默空白
- 此前详情页请求失败时仅 setData(loading:false),plan 仍为 null,
  整页只显示一行小字,用户感知为「空白」且无法定位原因。
- 现明确区分 loading / error(带重试按钮) / not-found 三种空态;
  request 失败时按 statusCode 给具体提示(401 登录失效 / 404 未找到 / 其他网络错误)。
- onLoad 对 getApp().globalData 取值加防御;缺失 id 直接报错不发起请求。
2026-07-22 23:58:48 +08:00

98 lines
2.8 KiB
JavaScript

const app = getApp();
const planSvc = require('../../services/plan');
const { iconName } = require('../../utils/icon-name');
Page({
data: {
statusBarHeight: 20,
id: '',
plan: null,
exercises: [],
loading: true,
error: false,
errorMsg: ''
},
onLoad(query) {
const id = query.id || '';
const h = (app && app.globalData && app.globalData.statusBarHeight) || 20;
this.setData({ statusBarHeight: h, id });
this.load();
},
load() {
const id = this.data.id;
if (!id) {
this.setData({ loading: false, error: true, errorMsg: '缺少计划标识,无法打开' });
return;
}
this.setData({ loading: true, error: false });
planSvc.get(id).then((plan) => {
if (!plan || !plan.id) {
this.setData({ loading: false, error: true, errorMsg: '未找到该计划' });
return;
}
const raw = plan && plan.updatedAt;
const updatedAtText = typeof raw === 'string'
? raw.slice(0, 10)
: (raw ? String(raw).slice(0, 10) : '');
this.setData({
plan: { ...plan, updatedAtText, icon: iconName(plan.emoji) },
exercises: (plan && plan.exercises) || [],
loading: false,
error: false
});
}).catch((err) => {
const status = err && err.statusCode;
const msg = status === 404
? '未找到该计划'
: (status === 401 ? '登录已失效,请重新登录' : '加载失败,请检查网络后重试');
this.setData({ loading: false, error: true, errorMsg: msg });
});
},
onRetry() {
this.load();
},
onRemoveExercise(e) {
const exerciseId = e.currentTarget.dataset.id;
planSvc.removeExercise(this.data.id, exerciseId).then(() => {
this.setData({ exercises: this.data.exercises.filter(i => i.id !== exerciseId) });
wx.showToast({ title: '已移除', icon: 'none' });
}).catch(() => {});
},
onExercise(e) {
if (!e || !e.detail || !e.detail.id) return;
wx.navigateTo({
url: '/pages/detail/detail?planId=' + encodeURIComponent(this.data.id) +
'&id=' + encodeURIComponent(e.detail.id)
});
},
onAdd() {
wx.navigateTo({ url: '/pages/search/search?mode=select&planId=' + encodeURIComponent(this.data.id) });
},
onEdit() {
wx.navigateTo({ url: '/pages/plan-edit/plan-edit?mode=edit&id=' + encodeURIComponent(this.data.id) });
},
onDelete() {
wx.showModal({
title: '删除计划',
content: '确定要删除该训练计划吗?此操作不可恢复。',
confirmColor: '#FF5C5C',
success: (res) => {
if (res.confirm) {
planSvc.remove(this.data.id).then(() => {
wx.showToast({ title: '已删除', icon: 'success' });
setTimeout(() => wx.navigateBack(), 500);
}).catch(() => {});
}
}
});
}
});