feat: 任务和社区页面
This commit is contained in:
+168
-57
@@ -1,5 +1,5 @@
|
||||
// pages/community/index.js
|
||||
import { MOCK_POSTS } from '../../utils/mockData';
|
||||
import request from '../../utils/request';
|
||||
|
||||
Page({
|
||||
data: {
|
||||
@@ -8,31 +8,110 @@ Page({
|
||||
activePostId: null, // For showing action popup
|
||||
showCommentBar: false,
|
||||
commentingPostId: null,
|
||||
commentText: ''
|
||||
commentText: '',
|
||||
isLoading: false,
|
||||
current: 1,
|
||||
pageSize: 10,
|
||||
hasMore: true
|
||||
},
|
||||
|
||||
onLoad() {
|
||||
this.setData({ posts: MOCK_POSTS });
|
||||
this.updateDisplayedPosts();
|
||||
this.fetchPosts(true);
|
||||
},
|
||||
|
||||
onShow() {
|
||||
if (typeof this.getTabBar === 'function' && this.getTabBar()) {
|
||||
this.getTabBar().setData({ selected: 2 });
|
||||
}
|
||||
// Refresh posts in case new ones were added
|
||||
this.setData({ posts: MOCK_POSTS });
|
||||
this.updateDisplayedPosts();
|
||||
},
|
||||
|
||||
// Called by create post page
|
||||
onRefresh() {
|
||||
this.fetchPosts(true);
|
||||
},
|
||||
|
||||
onPullDownRefresh() {
|
||||
this.fetchPosts(true).then(() => {
|
||||
wx.stopPullDownRefresh();
|
||||
});
|
||||
},
|
||||
|
||||
onReachBottom() {
|
||||
if (this.data.hasMore && !this.data.isLoading) {
|
||||
this.fetchPosts(false);
|
||||
}
|
||||
},
|
||||
|
||||
async fetchPosts(reset = false) {
|
||||
if (this.data.isLoading) return;
|
||||
|
||||
this.setData({ isLoading: true });
|
||||
|
||||
const current = reset ? 1 : this.data.current;
|
||||
const pageSize = this.data.pageSize;
|
||||
|
||||
try {
|
||||
// Correct API Endpoint and Params
|
||||
const res = await request.post('/post/page', { current, pageSize });
|
||||
|
||||
// Handle response structure: { code: 200, data: { list: [], ... } }
|
||||
// OR if request.js unwraps it: { list: [], ... }
|
||||
const data = res.data || res || {};
|
||||
const rawList = data.list || [];
|
||||
|
||||
// Map backend data to UI model
|
||||
const newPosts = rawList.map(item => {
|
||||
const publisher = item.publisher || {};
|
||||
const avatarObj = publisher.avatar || {};
|
||||
|
||||
return {
|
||||
id: item.id,
|
||||
user: publisher.nickName || publisher.name || '花友',
|
||||
avatar: avatarObj.url || '/assets/default_avatar.png',
|
||||
content: item.content,
|
||||
images: (item.imgList || []).map(img => img.url),
|
||||
time: item.createdAtStr || '刚刚',
|
||||
likes: (item.likeList || []).map(l => l.liker ? (l.liker.nickName || l.liker.name) : '花友'),
|
||||
comments: (item.commentList || []).map(c => ({
|
||||
id: c.id,
|
||||
user: c.commentator ? (c.commentator.nickName || c.commentator.name) : '花友',
|
||||
content: c.content
|
||||
})),
|
||||
likedByMe: item.hasLiked === 1,
|
||||
likeCount: item.likeCount || 0,
|
||||
commentCount: item.commentCount || 0,
|
||||
isExpanded: false
|
||||
};
|
||||
});
|
||||
|
||||
if (reset) {
|
||||
this.setData({
|
||||
posts: newPosts,
|
||||
displayedPosts: newPosts,
|
||||
current: 2,
|
||||
hasMore: newPosts.length >= pageSize
|
||||
});
|
||||
} else {
|
||||
const combined = [...this.data.posts, ...newPosts];
|
||||
this.setData({
|
||||
posts: combined,
|
||||
displayedPosts: combined,
|
||||
current: current + 1,
|
||||
hasMore: newPosts.length >= pageSize
|
||||
});
|
||||
}
|
||||
|
||||
} catch (err) {
|
||||
console.error('Fetch posts failed', err);
|
||||
wx.showToast({ title: '加载失败', icon: 'none' });
|
||||
} finally {
|
||||
this.setData({ isLoading: false });
|
||||
}
|
||||
},
|
||||
|
||||
updateDisplayedPosts() {
|
||||
const { posts } = this.data;
|
||||
// Show all posts with likedByMe flag
|
||||
const displayed = posts.map(post => ({
|
||||
...post,
|
||||
likedByMe: post.likes.includes('我的花园')
|
||||
}));
|
||||
this.setData({ displayedPosts: displayed });
|
||||
// Just sync posts to displayedPosts
|
||||
this.setData({ displayedPosts: this.data.posts });
|
||||
},
|
||||
|
||||
// Preview image in full screen
|
||||
@@ -72,31 +151,37 @@ Page({
|
||||
},
|
||||
|
||||
// Like post
|
||||
likePost(e) {
|
||||
async likePost(e) {
|
||||
const postId = e.currentTarget.dataset.id;
|
||||
const posts = this.data.posts.map(post => {
|
||||
if (post.id === postId) {
|
||||
const likes = [...post.likes];
|
||||
const myName = '我的花园';
|
||||
if (likes.includes(myName)) {
|
||||
// Unlike
|
||||
const idx = likes.indexOf(myName);
|
||||
likes.splice(idx, 1);
|
||||
} else {
|
||||
// Like
|
||||
likes.push(myName);
|
||||
}
|
||||
return { ...post, likes };
|
||||
}
|
||||
return post;
|
||||
});
|
||||
const post = this.data.posts.find(p => p.id === postId);
|
||||
if (!post) return;
|
||||
|
||||
this.setData({
|
||||
posts,
|
||||
activePostId: null // Hide popup after action
|
||||
}, () => {
|
||||
this.updateDisplayedPosts();
|
||||
});
|
||||
const type = post.likedByMe ? 2 : 1;
|
||||
|
||||
try {
|
||||
await request.get('/post/like', { id: postId, type });
|
||||
|
||||
// Optimistic Update: Only toggle button state. Do NOT modify likes list text.
|
||||
const updatedPosts = this.data.posts.map(p => {
|
||||
if (p.id === postId) {
|
||||
return { ...p, likedByMe: !p.likedByMe };
|
||||
}
|
||||
return p;
|
||||
});
|
||||
|
||||
this.setData({
|
||||
posts: updatedPosts,
|
||||
displayedPosts: updatedPosts,
|
||||
activePostId: null
|
||||
});
|
||||
|
||||
// Call page API to refresh list data (including Like List text)
|
||||
this.fetchPosts(true);
|
||||
|
||||
} catch (err) {
|
||||
console.error('Like failed', err);
|
||||
wx.showToast({ title: '操作失败', icon: 'none' });
|
||||
}
|
||||
},
|
||||
|
||||
// Show comment input bar
|
||||
@@ -122,39 +207,65 @@ Page({
|
||||
this.setData({ commentText: e.detail.value });
|
||||
},
|
||||
|
||||
submitComment() {
|
||||
async submitComment() {
|
||||
const { commentText, commentingPostId } = this.data;
|
||||
|
||||
if (!commentText.trim()) {
|
||||
return;
|
||||
}
|
||||
|
||||
const posts = this.data.posts.map(post => {
|
||||
if (post.id === commentingPostId) {
|
||||
const comments = [...post.comments, {
|
||||
id: Date.now().toString(),
|
||||
user: '我的花园',
|
||||
content: commentText.trim()
|
||||
}];
|
||||
return { ...post, comments };
|
||||
}
|
||||
return post;
|
||||
});
|
||||
try {
|
||||
await request.post('/post/comment', {
|
||||
postId: commentingPostId,
|
||||
content: commentText.trim()
|
||||
});
|
||||
|
||||
this.setData({
|
||||
posts,
|
||||
showCommentBar: false,
|
||||
commentingPostId: null,
|
||||
commentText: ''
|
||||
}, () => {
|
||||
this.updateDisplayedPosts();
|
||||
wx.showToast({ title: '评论成功', icon: 'success' });
|
||||
});
|
||||
|
||||
// Optimistic update
|
||||
const posts = this.data.posts.map(post => {
|
||||
if (post.id === commentingPostId) {
|
||||
const comments = [...post.comments, {
|
||||
id: Date.now().toString(),
|
||||
user: '我',
|
||||
content: commentText.trim()
|
||||
}];
|
||||
return { ...post, comments };
|
||||
}
|
||||
return post;
|
||||
});
|
||||
|
||||
this.setData({
|
||||
posts,
|
||||
displayedPosts: posts,
|
||||
showCommentBar: false,
|
||||
commentingPostId: null,
|
||||
commentText: ''
|
||||
});
|
||||
|
||||
// Silent refresh from server
|
||||
this.fetchPosts(true);
|
||||
|
||||
} catch (err) {
|
||||
console.error('Comment failed', err);
|
||||
wx.showToast({ title: '评论失败', icon: 'none' });
|
||||
}
|
||||
},
|
||||
|
||||
goToCreatePost() {
|
||||
wx.navigateTo({
|
||||
url: '/pages/community/create/index'
|
||||
});
|
||||
},
|
||||
|
||||
toggleCommentExpand(e) {
|
||||
const postId = e.currentTarget.dataset.id;
|
||||
const posts = this.data.posts.map(p => {
|
||||
if (p.id === postId) {
|
||||
return { ...p, isExpanded: !p.isExpanded };
|
||||
}
|
||||
return p;
|
||||
});
|
||||
this.setData({ posts, displayedPosts: posts });
|
||||
}
|
||||
})
|
||||
|
||||
Reference in New Issue
Block a user