Files
sundynix-pets/pets-fe/pages/community/community.js
T
Blizzard e446019546 fix(fe): 补齐无宠物状态 + 用户操作失败不再静默
自查发现的四处,都属于「不报错但用户懵」:

1. record/plan/report 三页在 currentPetId 为空时直接 return,留下一堆
   空卡片却不解释——用户以为坏了。加统一的 .no-pet 引导块,说清建档后
   会有什么,并给一个建档按钮。

2. 首页门面卡在没建档时点击会打开「编辑宠物」的空表单。改成没档案就走
   「添加」,文案也跟着变成「点这里建一份档案」。

3. 没建档时在快速记录弹层点「保存」,createAndClose 因为拿不到 petID
   直接 close 掉——用户以为存上了,其实什么都没发生。改成明确提示。

4. 用户主动触发的操作失败不再静默:勾任务、全部完成、勾计划节点、点赞
   四处的 .catch(() => {}) 换成 toast。后台加载类的静默保持不变——
   那些失败了重进页面会自愈,弹 toast 反而是噪音。

事件绑定做了一次全量扫描:18 个 wxml 里所有 bind/catch 绑的方法在对应
js 里都有实现,没有「点了没反应」的死按钮。

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-07-29 14:23:58 +08:00

153 lines
4.8 KiB
JavaScript

const store = require('../../utils/store.js');
const api = require('../../utils/api.js');
const { toastErr } = require('../../utils/ui.js');
const TAG_CLASS = { 求助: 'warn', 经验: 'blue', 精选: 'purple', 避坑: 'red', 晒宠: '' };
function mapPost(p) {
const tags = p.tags || [];
const tag = tags[0] || '';
return {
id: p.id,
author_name: p.author_name,
author_emoji: p.author_emoji || '🐾',
content: p.content,
images: p.images || [],
like_count: p.like_count,
comment_count: p.comment_count,
liked: false,
tag,
tagClass: TAG_CLASS[tag] || '',
is_ai: !!p.is_ai,
user_id: p.user_id,
followed: !!p.followed,
is_self: !!p.is_self,
};
}
Page({
data: {
pet: {},
feedTabs: ['推荐', '关注', '新手求助', '晒宠', '经验'],
feedIdx: 0,
posts: [],
sheetShow: false,
sheetType: '',
sheetPostId: '',
loaded: false,
loadErr: '',
},
onLoad() {
this._unsub = store.subscribe((pet) => this.setData({ pet }));
},
onUnload() {
if (this._unsub) this._unsub();
},
onShow() {
if (typeof this.getTabBar === 'function' && this.getTabBar()) {
this.getTabBar().setData({ selected: 4 });
}
store
.ready()
.then(() => {
this.setData({ pet: store.getPet() });
this.loadPosts();
})
.catch((e) => wx.showToast({ title: e.message || '加载失败', icon: 'none' }));
},
loadPosts() {
const tab = this.data.feedTabs[this.data.feedIdx];
this.setData({ loadErr: '' });
api
.listPosts(tab, 1)
.then((page) => this.setData({ posts: (page.list || []).map(mapPost), loaded: true }))
.catch((e) => {
// 不能让「加载失败」显示成「还没有帖子」,那是在骗用户
this.setData({ loadErr: e.message || '加载失败', loaded: true });
toastErr(e);
});
},
// 来自 seg-tabs 的 change 事件
switchFeedTab(e) {
this.setData({ feedIdx: Number(e.detail.index) });
this.loadPosts();
},
likePost(e) {
const i = e.currentTarget.dataset.index;
const post = this.data.posts[i];
api
.likePost(post.id)
.then((res) => {
this.setData({ [`posts[${i}].like_count`]: res.like_count, [`posts[${i}].liked`]: true });
})
.catch((e) => toastErr(e, '点赞失败'));
},
openComments(e) {
this.setData({ sheetPostId: e.currentTarget.dataset.id, sheetType: 'comments', sheetShow: true });
},
openSheet(e) {
this.setData({ sheetType: e.currentTarget.dataset.type, sheetPostId: '', sheetShow: true });
},
closeSheet() {
this.setData({ sheetShow: false });
},
onPosted() {
this.setData({ sheetShow: false });
this.loadPosts();
},
onCommented() {
this.loadPosts();
},
goLearn() {
wx.navigateTo({ url: '/pages/learn/learn' });
},
onFab() {
wx.navigateTo({ url: '/pages/ai/ai' });
},
// 长按自己的帖子可删除
onLongPressPost(e) {
const p = this.data.posts[e.currentTarget.dataset.index];
if (!p || !p.is_self) return;
wx.showModal({
title: '删除帖子',
content: '确定删除这条帖子?删除后其他人将看不到。',
confirmColor: '#D9534F',
success: (res) => {
if (!res.confirm) return;
api.deletePost(p.id)
.then(() => { wx.showToast({ title: '已删除', icon: 'success' }); this.loadPosts(); })
.catch((err) => wx.showToast({ title: err.message || '删除失败', icon: 'none' }));
},
});
},
// 关注 / 取关帖子作者
toggleFollow(e) {
const i = e.currentTarget.dataset.index;
const p = this.data.posts[i];
if (!p || !p.user_id || p.is_self) return;
const fn = p.followed ? api.unfollowUser : api.followUser;
fn(p.user_id)
.then(() => {
// 同一作者的所有帖子一起更新状态
const posts = this.data.posts.map((x) =>
x.user_id === p.user_id ? { ...x, followed: !p.followed } : x,
);
this.setData({ posts });
wx.showToast({ title: p.followed ? '已取消关注' : '已关注', icon: 'none' });
if (this.data.feedTabs[this.data.feedIdx] === '关注') this.loadPosts();
})
.catch((err) => wx.showToast({ title: err.message || '操作失败', icon: 'none' }));
},
onShareAppMessage(e) {
// 从帖子上的分享按钮转发:带上该帖内容做标题
if (e && e.from === 'button') {
const c = (e.target.dataset.content || '').slice(0, 40);
return { title: c ? '宠友圈:' + c : '来宠友圈看看大家的毛孩子', path: '/pages/community/community' };
}
return { title: '宠友圈 · 和铲屎官们交流养宠经验', path: '/pages/community/community' };
},
onShareTimeline() {
return { title: '宠友圈 · 和铲屎官们交流养宠经验' };
},
});