fix: - 首页'我的计划'卡片误绑 onExercise(跳动作详情),改为 onPlanTap 正确跳训练计划详情页 - 修复后点击计划可正常打开 plan-detail feat(留言反馈): - 后端新增 feedback 模块:POST /api/feedback(AuthGuard,content 必填/contact 选填),JsonStore 持久化 - 前端新增 pages/feedback 页面(留言内容 textarea + 联系方式选填 + 提交),profile 菜单新增'意见反馈'入口 - icon-svg 新增 message-circle 图标(反馈页用)
133 lines
3.6 KiB
JavaScript
133 lines
3.6 KiB
JavaScript
const app = getApp();
|
||
const auth = require('../../utils/auth');
|
||
const favSvc = require('../../services/favorite');
|
||
const planSvc = require('../../services/plan');
|
||
|
||
// UGC 头像图标选择器:Lucide 运动子集(非 emoji)
|
||
const ICONS = ['dumbbell', 'accessibility', 'person-standing', 'bike', 'heart', 'flame',
|
||
'target', 'medal', 'trophy', 'award', 'star', 'activity', 'sparkles', 'zap', 'trending-up'];
|
||
|
||
Page({
|
||
data: {
|
||
statusBarHeight: 20,
|
||
loggedIn: false,
|
||
profile: { nickname: '', avatar: 'user' },
|
||
counts: { fav: 0, plans: 0, favPlans: 0 },
|
||
loading: false,
|
||
// 编辑态
|
||
showEmojiPicker: false,
|
||
emojis: ICONS,
|
||
draftNickname: '',
|
||
draftAvatar: 'user'
|
||
},
|
||
|
||
onLoad() {
|
||
this.setData({ statusBarHeight: app.globalData.statusBarHeight || 20 });
|
||
},
|
||
|
||
onShow() {
|
||
this.loadData();
|
||
},
|
||
|
||
loadData() {
|
||
if (!auth.isLogin()) {
|
||
this.setData({ loggedIn: false });
|
||
return;
|
||
}
|
||
const profile = auth.getProfile();
|
||
this.setData({ loggedIn: true, profile, loading: true });
|
||
Promise.all([
|
||
favSvc.listExercises().catch(() => []),
|
||
planSvc.listMine().catch(() => []),
|
||
favSvc.listPlans().catch(() => [])
|
||
]).then(([fav, plans, favPlans]) => {
|
||
this.setData({
|
||
counts: {
|
||
fav: (fav || []).length,
|
||
plans: (plans || []).length,
|
||
favPlans: (favPlans || []).length
|
||
},
|
||
loading: false
|
||
});
|
||
}).catch(() => {
|
||
this.setData({ loading: false });
|
||
});
|
||
},
|
||
|
||
onLogin() {
|
||
auth.login().then(() => {
|
||
this.loadData();
|
||
wx.showToast({ title: '登录成功', icon: 'success' });
|
||
}).catch(() => {});
|
||
},
|
||
|
||
onEdit() {
|
||
const cur = this.data.profile;
|
||
wx.showModal({
|
||
title: '修改昵称',
|
||
editable: true,
|
||
placeholderText: '输入昵称',
|
||
content: cur.nickname || '',
|
||
success: (res) => {
|
||
if (res.confirm) {
|
||
this.setData({
|
||
draftNickname: (res.content || '').trim() || cur.nickname,
|
||
draftAvatar: cur.avatar || 'user',
|
||
showEmojiPicker: true
|
||
});
|
||
}
|
||
}
|
||
});
|
||
},
|
||
|
||
onPickEmoji(e) {
|
||
this.setData({ draftAvatar: e.currentTarget.dataset.emoji });
|
||
},
|
||
|
||
onCancelEdit() {
|
||
this.setData({ showEmojiPicker: false });
|
||
},
|
||
|
||
onConfirmEdit() {
|
||
const nickname = (this.data.draftNickname || '').trim();
|
||
const avatar = this.data.draftAvatar;
|
||
if (!nickname) {
|
||
wx.showToast({ title: '昵称不能为空', icon: 'none' });
|
||
return;
|
||
}
|
||
wx.showLoading({ title: '保存中…', mask: true });
|
||
auth.updateProfile({ nickname, avatar }).then((p) => {
|
||
wx.hideLoading();
|
||
this.setData({ profile: p, showEmojiPicker: false });
|
||
wx.showToast({ title: '已保存', icon: 'success' });
|
||
}).catch(() => {
|
||
wx.hideLoading();
|
||
});
|
||
},
|
||
|
||
onLogout() {
|
||
wx.showModal({
|
||
title: '退出登录',
|
||
content: '确定要退出当前账号吗?',
|
||
success: (res) => {
|
||
if (res.confirm) {
|
||
auth.logout();
|
||
this.setData({
|
||
loggedIn: false,
|
||
profile: { nickname: '', avatar: 'user' },
|
||
counts: { fav: 0, plans: 0, favPlans: 0 }
|
||
});
|
||
}
|
||
}
|
||
});
|
||
},
|
||
|
||
goFav() { wx.navigateTo({ url: '/pages/favorites/favorites' }); },
|
||
goPlans() { wx.navigateTo({ url: '/pages/my-plans/my-plans' }); },
|
||
goFavPlans() { wx.navigateTo({ url: '/pages/plan-favorites/plan-favorites' }); },
|
||
goOfficial() { wx.navigateTo({ url: '/pages/collection/collection' }); },
|
||
goFeedback() { wx.navigateTo({ url: '/pages/feedback/feedback' }); },
|
||
|
||
noop() {}
|
||
});
|