328 lines
9.6 KiB
JavaScript
328 lines
9.6 KiB
JavaScript
// pages/community/index.js
|
|
import request from '../../utils/request';
|
|
|
|
Page({
|
|
data: {
|
|
posts: [],
|
|
displayedPosts: [],
|
|
activePostId: null, // For showing action popup
|
|
showCommentBar: false,
|
|
commentingPostId: null,
|
|
commentText: '',
|
|
isLoading: false,
|
|
current: 1,
|
|
pageSize: 10,
|
|
hasMore: true,
|
|
userInfo: null,
|
|
scrollTop: 0,
|
|
isRefreshing: false
|
|
},
|
|
|
|
onLoad() {
|
|
this.fetchPosts(true);
|
|
},
|
|
|
|
onShow() {
|
|
if (typeof this.getTabBar === 'function' && this.getTabBar()) {
|
|
this.getTabBar().setData({ selected: 2 });
|
|
}
|
|
|
|
// Update user info for header
|
|
const app = getApp();
|
|
const info = app.globalData.userInfo || wx.getStorageSync('userInfo');
|
|
if (info) {
|
|
this.setData({ userInfo: info });
|
|
}
|
|
},
|
|
|
|
// Called by create post page or Pull Down
|
|
onRefresh() {
|
|
this.setData({ isRefreshing: true });
|
|
this.fetchPosts(true).then(() => {
|
|
this.setData({ isRefreshing: false });
|
|
});
|
|
},
|
|
|
|
onTabItemTap() {
|
|
this.setData({ scrollTop: Math.random() * 0.01 });
|
|
},
|
|
|
|
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, hasReviewed: 1 });
|
|
|
|
// 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,
|
|
content: item.content,
|
|
images: (item.imgList || []).map(img => img.url),
|
|
location: item.location || '',
|
|
time: item.createdAtStr || '刚刚',
|
|
likes: item.hasLiked === 1 ? ['我'] : [],
|
|
comments: (item.commentList || []).map(c => ({
|
|
id: c.id,
|
|
user: c.commentator ? (c.commentator.nickName || c.commentator.name) : '花友',
|
|
content: c.content
|
|
})),
|
|
likedByMe: item.hasLiked === 1,
|
|
isFavorited: item.hasStar === 1,
|
|
likeCount: item.likeCount || 0,
|
|
stars: (item.starList || []).map(s => s.starer ? (s.starer.nickName || s.starer.name) : '花友'),
|
|
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() {
|
|
// Just sync posts to displayedPosts
|
|
this.setData({ displayedPosts: this.data.posts });
|
|
},
|
|
|
|
// Preview image in full screen
|
|
previewImage(e) {
|
|
const { url, urls } = e.currentTarget.dataset;
|
|
const resolvedUrls = urls.map(img => img);
|
|
|
|
wx.previewImage({
|
|
current: url,
|
|
urls: resolvedUrls
|
|
});
|
|
},
|
|
|
|
// Toggle action popup (WeChat style)
|
|
toggleActionPopup(e) {
|
|
const postId = e.currentTarget.dataset.id;
|
|
if (this.data.activePostId === postId) {
|
|
this.setData({ activePostId: null });
|
|
} else {
|
|
this.setData({ activePostId: postId });
|
|
}
|
|
},
|
|
|
|
hideActionPopup() {
|
|
if (this.data.activePostId) {
|
|
this.setData({ activePostId: null });
|
|
}
|
|
},
|
|
|
|
stopPropagation() {
|
|
// Just stop event propagation, do nothing
|
|
},
|
|
|
|
// Like post
|
|
async likePost(e) {
|
|
const postId = e.currentTarget.dataset.id;
|
|
const post = this.data.posts.find(p => p.id === postId);
|
|
if (!post) return;
|
|
|
|
const type = post.likedByMe ? 2 : 1;
|
|
|
|
try {
|
|
await request.get('/post/like', { id: postId, type });
|
|
|
|
// Optimistic Update
|
|
const updatedPosts = this.data.posts.map(p => {
|
|
if (p.id === postId) {
|
|
const liked = !p.likedByMe;
|
|
return {
|
|
...p,
|
|
likedByMe: liked,
|
|
likes: liked ? ['我'] : []
|
|
};
|
|
}
|
|
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' });
|
|
}
|
|
},
|
|
|
|
// Collect post
|
|
async collectPost(e) {
|
|
const postId = e.currentTarget.dataset.id;
|
|
const post = this.data.posts.find(p => p.id === postId);
|
|
if (!post) return;
|
|
|
|
const type = post.isFavorited ? 2 : 1; // 1: Collect, 2: Cancel
|
|
|
|
try {
|
|
await request.get('/post/star', { id: postId, type });
|
|
|
|
// Optimistic Update
|
|
const updatedPosts = this.data.posts.map(p => {
|
|
if (p.id === postId) {
|
|
return { ...p, isFavorited: !p.isFavorited };
|
|
}
|
|
return p;
|
|
});
|
|
|
|
this.setData({
|
|
posts: updatedPosts,
|
|
displayedPosts: updatedPosts,
|
|
activePostId: null
|
|
});
|
|
|
|
// Refresh list to sync detailed data (like IDs if needed)
|
|
this.fetchPosts(true);
|
|
|
|
wx.showToast({ title: type === 1 ? '已收藏' : '已取消', icon: 'success' });
|
|
|
|
} catch (err) {
|
|
console.error('Collect failed', err);
|
|
wx.showToast({ title: '操作失败', icon: 'none' });
|
|
}
|
|
},
|
|
|
|
// Show comment input bar
|
|
showCommentInput(e) {
|
|
const postId = e.currentTarget.dataset.id;
|
|
this.setData({
|
|
showCommentBar: true,
|
|
commentingPostId: postId,
|
|
commentText: '',
|
|
activePostId: null // Hide popup
|
|
});
|
|
},
|
|
|
|
hideCommentBar() {
|
|
this.setData({
|
|
showCommentBar: false,
|
|
commentingPostId: null,
|
|
commentText: ''
|
|
});
|
|
},
|
|
|
|
onCommentInput(e) {
|
|
this.setData({ commentText: e.detail.value });
|
|
},
|
|
|
|
async submitComment() {
|
|
const { commentText, commentingPostId } = this.data;
|
|
|
|
if (!commentText.trim()) {
|
|
return;
|
|
}
|
|
|
|
try {
|
|
await request.post('/post/comment', {
|
|
postId: commentingPostId,
|
|
content: commentText.trim()
|
|
});
|
|
|
|
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 });
|
|
}
|
|
})
|