refactor(views): 重构多个视图组件代码结构,优化类型定义和逻辑组织
feat(services): 新增文章分页查询方法,支持按状态筛选文章 style(styles): 调整主布局样式,优化分页组件显示效果 docs(README): 更新API文档,完善服务模块说明和类型定义 fix(components): 修复左侧模块点击属性时使用错误字段名的问题 chore(package): 移除未使用的依赖项,清理项目依赖 perf(layouts): 优化主布局组件性能,拆分功能模块,减少重复计算 test(views): 为分页组件添加基础测试用例 build: 更新构建配置,优化生产环境打包 ci: 调整CI配置,添加类型检查步骤
This commit is contained in:
@@ -9,7 +9,7 @@
|
||||
<!-- 错误状态 -->
|
||||
<div v-else-if="error" class="error-state-container">
|
||||
<el-alert :title="error" type="error" show-icon />
|
||||
<el-button type="primary" @click="fetchArticleDetail">重新加载</el-button>
|
||||
<el-button type="primary" @click="initializeArticleDetail">重新加载</el-button>
|
||||
</div>
|
||||
|
||||
<!-- 文章详情 -->
|
||||
@@ -40,14 +40,11 @@
|
||||
<!-- 文章底部信息 -->
|
||||
<div class="article-footer-section">
|
||||
<div class="article-tag-list">
|
||||
<!-- <span v-for="tag in article.tags || []" :key="tag" class="el-tag el-tag--primary">
|
||||
{{ tag }}
|
||||
</span> -->
|
||||
</div>
|
||||
|
||||
<!-- 文章操作按钮 -->
|
||||
<div class="article-actions-group">
|
||||
<el-button type="primary" @click="goBack" plain>
|
||||
<el-button type="primary" @click="navigateBack" plain>
|
||||
返回
|
||||
</el-button>
|
||||
</div>
|
||||
@@ -57,11 +54,11 @@
|
||||
<div class="related-articles-section" v-if="relatedArticles.length > 0">
|
||||
<h3>相关文章</h3>
|
||||
<div class="related-articles-list">
|
||||
<div v-for="item in relatedArticles" :key="item.articleid" class="related-article-card"
|
||||
<!-- <div v-for="item in relatedArticles" :key="item.articleid" class="related-article-card"
|
||||
@click="handleRelatedArticleClick(item.articleid)">
|
||||
<i class="el-icon-document"></i>
|
||||
<span>{{ item.title }}</span>
|
||||
</div>
|
||||
</div> -->
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -80,92 +77,185 @@
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
// 导入必要的依赖
|
||||
import { useRoute, useRouter } from 'vue-router'
|
||||
// =========================================================================
|
||||
// 组件导入和初始化
|
||||
// =========================================================================
|
||||
|
||||
/**
|
||||
* 导入Vue核心功能
|
||||
*/
|
||||
import { ref, onMounted } from 'vue'
|
||||
|
||||
/**
|
||||
* 导入路由相关功能
|
||||
*/
|
||||
import { useRouter } from 'vue-router'
|
||||
|
||||
/**
|
||||
* 导入状态管理和UI组件
|
||||
*/
|
||||
import { useGlobalStore } from '@/store/globalStore'
|
||||
import { ElMessage } from 'element-plus'
|
||||
|
||||
/**
|
||||
* 导入类型和工具函数
|
||||
*/
|
||||
import type { Article } from '@/types'
|
||||
import { formatRelativeTime } from '@/utils/dateUtils'
|
||||
|
||||
/**
|
||||
* 导入子组件
|
||||
*/
|
||||
import messageboard from './messageboard.vue'
|
||||
import markdownViewer from './markdown.vue'
|
||||
// 路由相关
|
||||
|
||||
// =========================================================================
|
||||
// 路由和状态初始化
|
||||
// =========================================================================
|
||||
|
||||
/**
|
||||
* 初始化路由
|
||||
*/
|
||||
const router = useRouter()
|
||||
|
||||
// 响应式状态管理
|
||||
/**
|
||||
* 初始化全局状态管理
|
||||
*/
|
||||
const globalStore = useGlobalStore()
|
||||
const article = ref<Article | null>(null) // 使用 null 作为初始值,避免类型不匹配问题
|
||||
const loading = ref(false)
|
||||
const error = ref('')
|
||||
const relatedArticles = ref<Article[]>([])
|
||||
|
||||
/**
|
||||
* 响应式状态定义
|
||||
*/
|
||||
const article = ref<Article | null>(null) // 文章详情数据,初始为null避免类型不匹配
|
||||
const loading = ref(false) // 加载状态
|
||||
const error = ref('') // 错误信息
|
||||
const relatedArticles = ref<Article[]>([]) // 相关文章列表
|
||||
|
||||
// =========================================================================
|
||||
// 文章数据处理模块
|
||||
// =========================================================================
|
||||
|
||||
/**
|
||||
* 获取文章ID
|
||||
* @returns {number | null} 文章ID或null
|
||||
*/
|
||||
const getArticleId = (): number | null => {
|
||||
return globalStore.getValue('articleInfo')?.articleid || null
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取文章详情数据
|
||||
* @returns {Promise<Article | null>} 文章数据或null
|
||||
*/
|
||||
const fetchArticleDetail = async () => {
|
||||
const fetchArticleData = async (): Promise<Article | null> => {
|
||||
try {
|
||||
// 从全局状态获取文章信息
|
||||
const response = await globalStore.getValue('articleInfo')
|
||||
return response || null
|
||||
} catch (err) {
|
||||
console.error('获取文章数据失败:', err)
|
||||
throw new Error('获取文章数据失败')
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 增加文章浏览量
|
||||
* @param {Article} articleData 文章数据
|
||||
*/
|
||||
const incrementViewCount = (articleData: Article): void => {
|
||||
if (articleData.viewCount) {
|
||||
articleData.viewCount++
|
||||
} else {
|
||||
articleData.viewCount = 1
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 处理文章不存在的情况
|
||||
*/
|
||||
const handleArticleNotFound = (): void => {
|
||||
error.value = '文章不存在或已被删除'
|
||||
ElMessage.error(error.value)
|
||||
}
|
||||
|
||||
/**
|
||||
* 处理获取文章数据过程中的错误
|
||||
* @param {unknown} err 错误对象
|
||||
*/
|
||||
const handleArticleFetchError = (err: unknown): void => {
|
||||
error.value = err instanceof Error ? err.message : '获取文章详情失败,请稍后重试'
|
||||
console.error('获取文章详情失败:', err)
|
||||
ElMessage.error(error.value)
|
||||
}
|
||||
|
||||
/**
|
||||
* 初始化文章详情数据
|
||||
*/
|
||||
const initializeArticleDetail = async (): Promise<void> => {
|
||||
try {
|
||||
loading.value = true
|
||||
error.value = ''
|
||||
|
||||
// 获取路由参数
|
||||
const articleId = globalStore.getValue('articleInfo')?.articleid || null
|
||||
// 获取文章ID
|
||||
const articleId = getArticleId()
|
||||
if (!articleId) {
|
||||
throw new Error('文章不存在')
|
||||
handleArticleNotFound()
|
||||
return
|
||||
}
|
||||
// 获取文章详情
|
||||
const response = await globalStore.getValue('articleInfo')
|
||||
// const markdowndata = await
|
||||
if (response) {
|
||||
article.value = response
|
||||
// 获取并设置分类名称
|
||||
// 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
|
||||
}
|
||||
|
||||
// 获取文章数据
|
||||
const articleData = await fetchArticleData()
|
||||
if (articleData) {
|
||||
article.value = articleData
|
||||
// 增加浏览量
|
||||
incrementViewCount(articleData)
|
||||
} else {
|
||||
throw new Error('文章不存在或已被删除')
|
||||
handleArticleNotFound()
|
||||
}
|
||||
} catch (err) {
|
||||
error.value = err instanceof Error ? err.message : '获取文章详情失败,请稍后重试'
|
||||
console.error('获取文章详情失败:', err)
|
||||
ElMessage.error(error.value)
|
||||
handleArticleFetchError(err)
|
||||
} finally {
|
||||
loading.value = false
|
||||
}
|
||||
}
|
||||
|
||||
// =========================================================================
|
||||
// 导航和用户交互模块
|
||||
// =========================================================================
|
||||
|
||||
/**
|
||||
* 返回上一页
|
||||
*/
|
||||
const goBack = () => {
|
||||
const navigateBack = (): void => {
|
||||
router.back()
|
||||
}
|
||||
|
||||
/**
|
||||
* 处理相关文章点击事件
|
||||
* 导航到相关文章
|
||||
* @param {number} id - 相关文章ID
|
||||
*/
|
||||
const handleRelatedArticleClick = (id: number) => {
|
||||
const navigateToRelatedArticle = (id: number): void => {
|
||||
router.push({
|
||||
path: '/article/:url',
|
||||
query: { url: id }
|
||||
})
|
||||
}
|
||||
|
||||
// =========================================================================
|
||||
// 组件生命周期和初始化
|
||||
// =========================================================================
|
||||
|
||||
/**
|
||||
* 组件挂载时获取文章详情
|
||||
* 组件挂载时的初始化操作
|
||||
*/
|
||||
const setupComponent = (): void => {
|
||||
initializeArticleDetail()
|
||||
}
|
||||
/**
|
||||
* 组件挂载生命周期钩子
|
||||
*/
|
||||
onMounted(() => {
|
||||
fetchArticleDetail()
|
||||
setupComponent()
|
||||
})
|
||||
</script>
|
||||
|
||||
|
||||
Reference in New Issue
Block a user