diff --git a/珞珈岛-项目相关文件/luojia-island/vue-frontend/src/stores/postdetail.js b/珞珈岛-项目相关文件/luojia-island/vue-frontend/src/stores/postdetail.js index 2420ec5..45f66cb 100644 --- a/珞珈岛-项目相关文件/luojia-island/vue-frontend/src/stores/postdetail.js +++ b/珞珈岛-项目相关文件/luojia-island/vue-frontend/src/stores/postdetail.js @@ -1,39 +1,117 @@ import { defineStore } from "pinia"; import request from "@/utils/request"; +import { ElMessage } from "element-plus"; export const usePostDetailStore = defineStore("postDetail", { state: () => ({ post: null, // 帖子主要信息 comments: [], // 评论列表 userInfo: null, // 用户信息 - totalComments: 0, // 评论总数 - likeCount: 0, // 点赞数 - commentCount: 0, // 评论数 - favoriteCount: 0, // 收藏数 - viewCount: 0, // 浏览数 isLike: false, // 是否点赞 - loading: false, // 加载状态 + lastVal: 0, // 用于滚动分页的时间戳 + offset: 0, // 偏移量 + size: 5, // 每页评论数 + detailLoading: false, // 加载状态 + commentsLoading: false, // 评论加载状态 + commentsFinished: false, // 是否加载完全部评论 }), actions: { - setPost(post) { - this.post = post; - }, - setComments(comments) { - this.comments = comments; - this.totalComments = comments.length; - }, - setUserInfo(userInfo) { - this.userInfo = userInfo; + async fetchComments() { + if (this.commentsLoading || this.commentsFinished) return; + this.commentsLoading = true; + const RequestCommentData = { + lastVal: this.lastVal, + offset: this.offset, + size: this.size, + postId: this.post.postId + }; + try { + const response = await request.post('/comment/list', RequestCommentData); + if (response.code === 200) { + // 初始化每条评论的子评论分页状态 + const comments = (response.data.records || []).map(item => ({ + ...item, + replies: [], + repliesLastVal: Date.now(), + repliesOffset: 0, + repliesSize: 5, + repliesLoading: false, + repliesFinished: false, + })); + this.comments.push(...comments); + this.lastVal = response.data.lastVal; + this.offset = response.data.offset; + if (comments.length < this.size) { + this.commentsFinished = true; // 如果评论数少于每页大小,标记为已加载完 + } + } + else { + ElMessage({ + message: '获取评论失败,请稍后重试', + type: 'error', + duration: 500 + }); + } + } catch (error) { + console.error("获取评论失败:", error); + alert(error.response?.message || '获取评论失败,请稍后重试'); + }finally { + this.commentsLoading = false; + } }, - addComment(comment) { - this.comments.push(comment); - this.totalComments += 1; + // 获取某条评论的子评论(多级结构,分页) + async fetchReplies(parentCommentId, commentObj) { + if (commentObj.repliesLoading || commentObj.repliesFinished) return; + commentObj.repliesLoading = true; + // 请求子评论数据 + const RequestReplyData = { + lastVal: commentObj.repliesLastVal, + offset: commentObj.repliesOffset, + size: commentObj.repliesSize, + postId: this.post?.postId, + parentCommentId: parentCommentId, + }; + try { + const res = await request.post('/comment/list/reply', RequestReplyData); + if (res.code === 200) { + const records = (res.data.records || []).map(item => ({ + ...item, + replies: [], + repliesLastVal: 0, + repliesOffset: 0, + repliesSize: 5, + repliesFinished: false, + repliesLoading: false, + })); + commentObj.replies.push(...records); + commentObj.repliesLastVal = res.data.lastVal; + commentObj.repliesOffset = res.data.offset; + if (records.length < commentObj.repliesSize) { + commentObj.repliesFinished = true; + } + } + else { + ElMessage({ + message: '获取子评论失败,请稍后重试', + type: 'error', + duration: 500 + }); + } + } catch (error) { + console.error("获取子评论失败:", error); + alert(error.response?.message || '获取子评论失败,请稍后重试'); + } finally { + commentObj.repliesLoading = false; + } }, - async fetchPostDetail(postId, { lastVal = Date.now(), offset = 0, size = 10 } = {}) { - this.loading = true; + async fetchPostDetail(postId) { + this.detailLoading = true; try { // 获取帖子详情 - const postRes = await request.get(`/post/detail/${postId}`); + const RequestPostDetailData = { + id: postId, + }; + const postRes = await request.get('/post/detail/', RequestPostDetailData); if (postRes.code === 200 && postRes.data) { const { id, @@ -58,6 +136,10 @@ export const usePostDetailStore = defineStore("postDetail", { title, content, createTime, + commentCount, + likeCount, + favoriteCount, + viewCount, }; // 用户信息 @@ -67,27 +149,24 @@ export const usePostDetailStore = defineStore("postDetail", { userAvatar: userAvatar, followers:1234,//先预设粉丝占位 }; - // 其余字段 - this.likeCount = likeCount; - this.commentCount = commentCount; - this.favoriteCount = favoriteCount; - this.viewCount = viewCount; this.isLike = isLike; + // 获取评论列表 + this.lastVal = Date.now(); + this.fetchComments(); } - - // 获取评论列表 - const commentRes = await request.post('/comment/list', { - lastVal, - offset, - size, - postId - }); - if (commentRes.code === 200) { - this.setComments(commentRes.data.records || []); - } - } finally { - this.loading = false; + else { + ElMessage({ + message: '获取帖子详情失败,请稍后重试', + type: 'error', + duration: 500 + }); + } + } catch (error) { + console.error("获取帖子详情失败:", error); + alert(error.response?.message || '获取帖子详情失败,请稍后重试'); + }finally { + this.detailLoading = false; } }, }, diff --git a/珞珈岛-项目相关文件/luojia-island/vue-frontend/src/stores/postlist.js b/珞珈岛-项目相关文件/luojia-island/vue-frontend/src/stores/postlist.js index e9abb6b..75c01b2 100644 --- a/珞珈岛-项目相关文件/luojia-island/vue-frontend/src/stores/postlist.js +++ b/珞珈岛-项目相关文件/luojia-island/vue-frontend/src/stores/postlist.js @@ -1,5 +1,6 @@ import {defineStore} from 'pinia'; import request from '@/utils/request'; +import { ElMessage } from 'element-plus'; export const usePostListStore = defineStore('postList', { state: () => ({ @@ -33,18 +34,24 @@ export const usePostListStore = defineStore('postList', { this.posts = this.posts.filter(post => post.id !== postId); this.total -= 1; // 更新总数 }, - async getList({ lastVal = this.lastVal, offset = this.offset, size = this.pageSize } = {}) { + async getList() { if (this.loading || this.finished) return; this.loading = true; + const requestData = { + lastVal:this.lastVal, + offset: this.offset, + size: this.pageSize, + }; try { - const res = await request.post('/post/list', { lastVal, offset, size }); + const res = await request.post('/post/list', requestData); if (res.code === 200) { const { records, lastVal: newLastVal, offset: newOffset, size: newSize } = res.data; if (records.length > 0) { // 字段映射 const mappedRecords = records.map(post => ({ id: post.id, - avatar: post.userAvatar || post.image || require('@/assets/default-avatar/boy_1.png'), + image: post.image, + avatar: post.userAvatar , title: post.title, summary: post.content ? post.content.slice(0, 40) + (post.content.length > 40 ? '...' : '') : '', likes: post.likeCount, @@ -59,11 +66,23 @@ export const usePostListStore = defineStore('postList', { this.offset = newOffset; this.pageSize = newSize; } - if (records.length < size) { + if (records.length < this.pageSize) { this.finished = true; // 没有更多数据 } } - } finally { + else { + // 登录失败 + ElMessage({ + message: '获取帖子列表失败,请稍后重试', + type: 'error', + duration: 500 + }); + } + }catch (error) { + console.error("获取帖子列表失败:", error); + console.error('获取失败', error); + alert(error.response?.message || '获取失败,请稍后重试'); + }finally { this.loading = false; } }, diff --git a/珞珈岛-项目相关文件/luojia-island/vue-frontend/src/views/PostDetail.vue b/珞珈岛-项目相关文件/luojia-island/vue-frontend/src/views/PostDetail.vue index d205ba9..0b079f4 100644 --- a/珞珈岛-项目相关文件/luojia-island/vue-frontend/src/views/PostDetail.vue +++ b/珞珈岛-项目相关文件/luojia-island/vue-frontend/src/views/PostDetail.vue @@ -35,11 +35,25 @@ 评论者头像

{{ comment.userName }}

-

{{ comment.content }}

-
- {{ comment.createTime ? formatTime(comment.createTime) : '' }} - 赞 {{ comment.likeCount ?? 0 }} -
+

{{ comment.content }}

+
+ {{ comment.createTime ? formatTime(comment.createTime) : '' }} + 赞 {{ comment.likeCount ?? 0 }} + + + +
+ +
@@ -58,7 +72,7 @@ @@ -334,4 +371,38 @@ onMounted(() => { text-align: left; /* 设置居左 */ color: #333; } + +.replies-list { + list-style: none; + padding-left: 40px; /* 缩进,区分主评论 */ + margin: 8px 0 0 0; +} + +.reply-item { + display: flex; + align-items: flex-start; + padding: 6px 0; + border-bottom: 1px solid #f3f3f3; + font-size: 13px; + color: #444; +} + +.reply-user { + font-weight: bold; + margin-right: 6px; + color: #5aa76f; +} + +.reply-content { + flex: 1; + color: #333; +} + +.reply-loading, +.reply-finished { + color: #999; + font-size: 12px; + padding: 6px 0; + text-align: left; +} \ No newline at end of file