feat: 实现文章状态管理及分类标签展示功能

新增文章状态管理功能,支持草稿、已发表和已删除状态的显示与切换
重构分类和标签展示模块,添加点击跳转功能
优化文章列表页面,增加状态筛选和分页功能
完善疯言疯语模块,支持编辑和删除操作
修复路由跳转和页面刷新问题
This commit is contained in:
qingfeng1121
2025-11-08 11:16:15 +08:00
parent ad893b3e5c
commit 309aeaedc1
15 changed files with 840 additions and 325 deletions

View File

@@ -19,18 +19,16 @@
<h1 class="article-main-title">{{ article.title }}</h1>
<div class="article-meta-info">
<span class="meta-item">
<i class="el-icon-date"></i>
{{ formatDate(article.createdAt) }}
</span>
<span class="meta-item">
<i class="el-icon-folder"></i>
{{ article.categoryName || '未分类' }}
</span>
<span class="meta-item">
<i class="el-icon-view"></i>
{{ article.viewCount || 0 }} 阅读
</span>
<span class="article-publish-date">{{ formatRelativeTime(article.createdAt) }}</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 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>
<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>
<span v-if="article.status === 2" class="article-status-badge badge badge-danger">已删除</span>
</div>
</div>
</div>
@@ -85,12 +83,10 @@
// 导入必要的依赖
import { useRoute, useRouter } from 'vue-router'
import { ref, onMounted } from 'vue'
import { articleService } from '@/services'
import { categoryAttributeService } from '@/services'
import { useGlobalStore } from '@/store/globalStore'
import { ElMessage } from 'element-plus'
import type { Article } from '@/types'
import { formatDate } from '@/utils/dateUtils'
import { formatRelativeTime } from '@/utils/dateUtils'
import messageboard from './messageboard.vue'
import markdownViewer from './markdown.vue'
// 路由相关
@@ -122,22 +118,19 @@ const fetchArticleDetail = async () => {
if (response) {
article.value = response
// 获取并设置分类名称
const categoryResponse = await categoryAttributeService.getAttributeById(Number(article.value.attributeid))
article.value.categoryName = categoryResponse.data.attributename || '未分类'
// 增加文章浏览量
try {
await articleService.incrementArticleViews(Number(articleId))
// 更新前端显示的浏览量
if (article.value.viewCount) {
article.value.viewCount++
} else {
article.value.viewCount = 1
}
} catch (err) {
console.error('增加文章浏览量失败:', err)
// 不阻止主流程
// const categoryResponse = await categoryAttributeService.getAttributeById(Number(article.value.attributeid))
// article.value.categoryName = categoryResponse.data.attributename || '未分类'
// 获取并设置评论量
// const commentResponse = await messageService.getMessagesByArticleId(articleId)
// article.value.commentCount = commentResponse.data.length || 0
// 更新浏览量
// 更新前端显示的浏览量
if (article.value.viewCount) {
article.value.viewCount++
} else {
article.value.viewCount = 1
}
} else {
throw new Error('文章不存在或已被删除')
}
@@ -181,7 +174,7 @@ onMounted(() => {
.article-detail-wrapper {
max-width: 900px;
margin: 0 auto;
background-color: rgba(255, 255, 255, 0.85);
background-color: rgba(255, 255, 255, 0.85);
border-radius: 12px;
padding: 40px;
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1);
@@ -193,7 +186,7 @@ onMounted(() => {
max-width: 900px;
margin: 0 auto;
padding: 40px;
background-color: rgba(255, 255, 255, 0.85);
background-color: rgba(255, 255, 255, 0.85);
border-radius: 12px;
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1);
}
@@ -203,7 +196,7 @@ onMounted(() => {
max-width: 900px;
margin: 0 auto;
padding: 60px 40px;
background-color: rgba(255, 255, 255, 0.85);
background-color: rgba(255, 255, 255, 0.85);
border-radius: 12px;
text-align: center;
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1);
@@ -218,7 +211,7 @@ onMounted(() => {
max-width: 900px;
margin: 0 auto;
padding: 80px 40px;
background-color: rgba(255, 255, 255, 0.85);
background-color: rgba(255, 255, 255, 0.85);
border-radius: 12px;
text-align: center;
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1);