// 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 }); } })