feat: 添加分类树接口和分页组件,优化留言板功能

refactor: 重构文章服务和留言服务API调用方式
fix: 修复token验证逻辑和全局状态管理问题
style: 更新页脚样式和关于页面内容
docs: 添加类型定义和接口注释
This commit is contained in:
qingfeng1121
2025-12-23 13:57:35 +08:00
parent 8193bab566
commit 0151afcde7
19 changed files with 330 additions and 533 deletions

View File

@@ -15,11 +15,11 @@
<div v-if="article.marked" class="article-special-tag">标记文章</div>
<p class="article-content-preview">{{ formatContentPreview(article.content, 150) }}</p>
<div class="article-meta-info">
<span class="article-publish-date">{{ formatRelativeTime(article.createdAt || article.createTime) }}</span>
<span v-if="article.categoryName" class="article-category-badge">{{ article.categoryName }} </span>
<span v-if="article.viewCount" class="article-views-count">{{ article.viewCount }} 阅读</span>
<span class="article-publish-date">{{ formatRelativeTime(article.createtime || article.createtime) }}</span>
<span v-if="article.attributename" class="article-category-badge">{{ article.attributename }} </span>
<span v-if="article.viewcount" class="article-views-count">{{ article.viewcount }} 阅读</span>
<span v-if="article.likes > 0" class="article-likes-count">{{ article.likes }} 点赞</span>
<span v-if="article.commentCount > 0" class="article-comments-count">{{ article.commentCount }} 评论</span>
<span v-if="article.commentcount > 0" class="article-comments-count">{{ article.commentcount }} 评论</span>
<div class="article-status-badge-container" v-if="globalStore.Login">
<span v-if="article.status === 0" class="article-status-badge badge badge-warning">草稿</span>
<span v-if="article.status === 1" class="article-status-badge badge badge-success">已发表</span>
@@ -28,7 +28,12 @@
</div>
</div>
<!-- 分页区域 -->
<el-pagination size="medium" background :layout="pageLayout" v-model:current-page="pageNum" hide-on-single-page="true" @current-change="changePage" :page-size="pageSize" :page-count="totalPages" class="mt-4" />
<CustomPagination
v-model:pageNum="pageNum"
:pageSize="pageSize"
:totalPages="totalPages"
@pageChange="changePage"
/>
</transition-group>
<!-- 空状态 -->
<div v-if="!loading && articleList.length === 0" class="empty-state-container">
@@ -44,8 +49,8 @@ import { formatRelativeTime } from '@/utils/dateUtils'
import { formatContentPreview } from '@/utils/stringUtils'
import { ElMessage } from 'element-plus'
import { articleService, messageService, categoryAttributeService } from '@/services'
import PaginationComponent from '@/views/page.vue'
import { useGlobalStore } from '@/store/globalStore'
import CustomPagination from '@/components/CustomPagination.vue'
// ========== 组件初始化 ==========
@@ -59,7 +64,6 @@ const route = useRoute()
const pageNum = ref(1) // 当前页码
const pageSize = ref(10) // 每页数量
const totalPages = ref(0) // 总页数
const pageLayout = ref('pager, next')// 分页布局
// 响应式状态
const articleList = ref([])
@@ -84,7 +88,6 @@ const getArticlesByRoute = async () => {
// 检查URL参数确定获取文章的方式
const pathSegment = route.path.split('/')[2]
// console.log('当前路由分段:', pathSegment)
switch (pathSegment) {
case 'aericleattribute':
// 按属性类型获取文章
@@ -97,12 +100,13 @@ const getArticlesByRoute = async () => {
case 'aericletitle':
// 按标题搜索文章
const titleData = globalStore.getValue('articleserarch')
console.log('按标题搜索文章:', titleData.name)
// console.log('按标题搜索文章:', titleData.name)
return await articleService.getPagedArticles({title: titleData?.name}, pageNum.value, pageSize.value)
case 'aericlestatus':
// 按状态获取文章
const statusData = globalStore.getValue('articlestatus')
return await articleService.getPagedArticles({status: statusData?.status}, pageNum.value, pageSize.value)
// console.log('按状态获取文章:', statusData.status)
return await articleService.getPagedArticles({status: statusData.status}, pageNum.value, pageSize.value)
default:
// 默认获取所有文章
// console.log('获取所有文章列表')
@@ -110,50 +114,6 @@ const getArticlesByRoute = async () => {
}
}
/**
* 为单篇文章补充额外信息(留言数量、分类名称等)
* @param {Object} article - 文章对象
* @returns {Promise<Object>} 补充信息后的文章对象
*/
const enrichArticleWithExtraInfo = async (article) => {
try {
// 获取留言数量
const messageResponse = await messageService.getMessagesByArticleId(article.articleid)
// 获取分类名称
const categoryResponse = await categoryAttributeService.getAttributeById(article.attributeid)
// 设置分类名称
article.categoryName = categoryResponse?.data?.attributename || '未分类'
// 设置评论数量
article.commentCount = messageResponse?.data?.length || 0
// 标准化标记字段名
article.marked = article.mg
return article
} catch (err) {
console.error(`获取文章${article.articleid}额外信息失败:`, err)
// 错误情况下设置默认值
article.commentCount = 0
article.categoryName = '未分类'
return article
}
}
/**
* 批量为文章列表补充额外信息
* @param {Array} articles - 原始文章列表
* @returns {Promise<Array>} 补充信息后的文章列表
*/
const enrichArticlesWithExtraInfo = async (articles) => {
const enrichedArticles = []
for (const article of articles) {
const enrichedArticle = await enrichArticleWithExtraInfo(article)
enrichedArticles.push(enrichedArticle)
}
return enrichedArticles
}
/**
@@ -161,7 +121,6 @@ const enrichArticlesWithExtraInfo = async (articles) => {
*/
const fetchArticles = async () => {
let response = {}
try {
loading.value = true
@@ -170,16 +129,17 @@ const fetchArticles = async () => {
// console.log('更新后的文章列表:', response)
// 2. 确保数据存在
if (!response.data.content || !Array.isArray(response.data.content)) {
if (!response.data || !Array.isArray(response.data)) {
articleList.value = []
totalPages.value = 0
return
}
// 3. 为文章列表补充额外信息
const enrichedArticles = await enrichArticlesWithExtraInfo(response.data.content)
console.log('补充额外信息后的文章列表:', response.data)
// 4. 更新文章列表
articleList.value = enrichedArticles
articleList.value = response.data
// 5. 更新总页数
totalPages.value = response.totalPages
} catch (error) {
console.error('获取文章列表失败:', error)
ElMessage.error('获取文章列表失败,请稍后重试')
@@ -197,13 +157,10 @@ const fetchArticles = async () => {
const handleArticleClick = (article) => {
try {
// 增加文章浏览量(异步操作,不阻塞后续流程)
articleService.incrementArticleViews(article.articleId).catch(err => {
articleService.incrementArticleViews(article.articleid).catch(err => {
console.error('增加文章浏览量失败:', err)
})
// 清除之前的文章信息
globalStore.removeValue('articleInfo')
// 存储文章信息到全局状态
globalStore.setValue('articleInfo', article)
@@ -221,18 +178,8 @@ const handleArticleClick = (article) => {
* @param {number} newPage - 新的页码
*/
const changePage = (newPage) => {
pageNum.value = newPage
fetchArticles()
// 根据当前页码优化分页布局
if (page === 1) {
// 第一页只显示页码和下一页按钮
pageLayout.value = 'pager, next'
} else if (page === totalPages.value) {
// 最后一页只显示上一页按钮和页码
pageLayout.value = 'prev, pager'
} else {
// 中间页显示完整的上一页、页码、下一页
pageLayout.value = 'prev, pager, next'
}
}
// ========== 生命周期和监听器 ==========