refactor(store): 移除未使用的Login导入并优化全局状态管理
refactor(router): 重构路由守卫逻辑,简化登录状态检查 refactor(components): 重构LeftModule组件,使用分类树数据并移除冗余代码 refactor(layouts): 优化MainLayout组件,使用分类树数据并简化模态框逻辑 refactor(views): 重构aericlelist视图,使用分类树数据并优化文章计数逻辑
This commit is contained in:
@@ -77,7 +77,7 @@
|
|||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import { reactive, ref, onMounted, onUnmounted } from 'vue'
|
import { reactive, ref, onMounted, onUnmounted } from 'vue'
|
||||||
import { useRouter } from 'vue-router'
|
import { useRouter } from 'vue-router'
|
||||||
import { articleService, categoryService, categoryAttributeService } from "@/services";
|
import { categoryService } from "@/services";
|
||||||
|
|
||||||
// 当前激活菜单
|
// 当前激活菜单
|
||||||
const activeIndex = ref('/:type')
|
const activeIndex = ref('/:type')
|
||||||
@@ -92,6 +92,9 @@ const state = reactive({
|
|||||||
// 分类相关状态
|
// 分类相关状态
|
||||||
// defineEmits
|
// defineEmits
|
||||||
const emit = defineEmits(['update-data', 'CategoryModal', 'AttributeModal'])
|
const emit = defineEmits(['update-data', 'CategoryModal', 'AttributeModal'])
|
||||||
|
const categoryCount = ref(0)
|
||||||
|
const AttributeCount = ref(0)
|
||||||
|
const articleCount = ref(0)
|
||||||
|
|
||||||
// 标签相关状态
|
// 标签相关状态
|
||||||
// 处理菜单选择跳转
|
// 处理菜单选择跳转
|
||||||
@@ -103,87 +106,36 @@ const handleSelect = (key: string) => {
|
|||||||
router.beforeEach((to) => {
|
router.beforeEach((to) => {
|
||||||
activeIndex.value = to.path
|
activeIndex.value = to.path
|
||||||
})
|
})
|
||||||
|
// 分类树遍历函数
|
||||||
// 文章数量状态
|
const traverseCategoryTree = (tree) => {
|
||||||
const articleCount = ref(0)
|
categoryCount.value = tree.length
|
||||||
// 分类数量状态
|
tree.forEach((category) => {
|
||||||
const categoryCount = ref(0)
|
category.children.forEach((child) => {
|
||||||
// 标签数量状态
|
articleCount.value += child.articlecount || 0
|
||||||
const AttributeCount = ref(0)
|
})
|
||||||
|
AttributeCount.value += category.children.length || 0
|
||||||
// 获取文章数量
|
})
|
||||||
const fetchArticleCount = async () => {
|
|
||||||
try {
|
|
||||||
const response = await articleService.getAllArticles();
|
|
||||||
articleCount.value = response.data?.length || 0
|
|
||||||
} catch (error) {
|
|
||||||
console.error('获取文章数量失败:', error)
|
|
||||||
articleCount.value = 0
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
// 获取分类数据
|
// 获取分类数据
|
||||||
const fetchCategories = async () => {
|
const fetchCategoriestree = async () => {
|
||||||
|
|
||||||
// 分类数据状态
|
// 分类数据状态
|
||||||
const categories = ref<any[]>([])
|
|
||||||
try {
|
try {
|
||||||
const response = await categoryService.getAllCategories();
|
const response = await categoryService.getCategoryTree()
|
||||||
// 如果API返回的数据结构不包含count属性,我们可以模拟一些数据
|
// 如果API返回的数据结构不包含count属性,我们可以模拟一些数据
|
||||||
categories.value = response.data?.map((category: any) => ({
|
traverseCategoryTree(response.data || [])
|
||||||
...category,
|
return response.data || []
|
||||||
count: 0
|
|
||||||
})) || [];
|
|
||||||
categories.value.forEach(async (category: any) => {
|
|
||||||
const attributeResponse = await categoryAttributeService.getAttributesByCategory(category.categoryid)
|
|
||||||
if (attributeResponse.data?.length) {
|
|
||||||
category.count = attributeResponse.data?.length || 0
|
|
||||||
}
|
|
||||||
})
|
|
||||||
categoryCount.value = categories.value.length
|
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
|
|
||||||
console.error('获取分类失败:', error)
|
console.error('获取分类失败:', error)
|
||||||
// 如果API调用失败,使用模拟数据
|
// 如果API调用失败,使用模拟数据
|
||||||
categories.value = [
|
return []
|
||||||
|
|
||||||
];
|
|
||||||
categoryCount.value = categories.value.length
|
|
||||||
}
|
}
|
||||||
return categories.value
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// 获取标签数据
|
|
||||||
const fetchAttributes = async () => {
|
|
||||||
// 标签数据状态
|
|
||||||
const attributes = ref<any[]>([])
|
|
||||||
try {
|
|
||||||
const response = await categoryAttributeService.getAllAttributes();
|
|
||||||
// 如果API返回的数据结构不包含count属性,我们可以模拟一些数据
|
|
||||||
attributes.value = response.data?.map((attribute: any) => ({
|
|
||||||
...attribute,
|
|
||||||
count: 0
|
|
||||||
})) || [];
|
|
||||||
attributes.value.forEach(async (attribute: any) => {
|
|
||||||
const articleResponse = await articleService.getArticlesByAttributeId(attribute.attributeid)
|
|
||||||
if (articleResponse.data?.length) {
|
|
||||||
attribute.count = articleResponse.data?.length || 0
|
|
||||||
}
|
|
||||||
})
|
|
||||||
AttributeCount.value = attributes.value.length
|
|
||||||
} catch (error) {
|
|
||||||
console.error('获取标签失败:', error)
|
|
||||||
// 如果API调用失败,使用模拟数据
|
|
||||||
attributes.value = [
|
|
||||||
];
|
|
||||||
AttributeCount.value = attributes.value.length
|
|
||||||
}
|
|
||||||
return attributes.value
|
|
||||||
}
|
|
||||||
|
|
||||||
// 向父组件传递标签数据
|
// 向父组件传递标签数据
|
||||||
const sendData = () => {
|
const sendData = () => {
|
||||||
const data = { fetchAttributes: fetchAttributes(), fetchCategories: fetchCategories() }
|
const data = { fetchCategoriestree: fetchCategoriestree() }
|
||||||
emit('update-data', data)
|
emit('update-data', data)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -206,7 +158,6 @@ const handleScroll = () => {
|
|||||||
// 生命周期管理事件监听,防止内存泄漏
|
// 生命周期管理事件监听,防止内存泄漏
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
window.addEventListener('scroll', handleScroll)
|
window.addEventListener('scroll', handleScroll)
|
||||||
fetchArticleCount() // 组件挂载时获取文章数量
|
|
||||||
sendData() // 组件挂载时获取标签数据和分类数据
|
sendData() // 组件挂载时获取标签数据和分类数据
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|||||||
@@ -83,9 +83,9 @@
|
|||||||
<button class="category-modal-close" @click="closeCategoryModal">×</button>
|
<button class="category-modal-close" @click="closeCategoryModal">×</button>
|
||||||
</div>
|
</div>
|
||||||
<div class="category-modal-body">
|
<div class="category-modal-body">
|
||||||
<button v-for="category in categories" :key="category.typeid" class="category-button"
|
<button v-for="category in Categoriestree" :key="category.typeid" class="category-button"
|
||||||
@click="handleCategoryClick(category)">
|
@click="handleCategoryClick(category)">
|
||||||
{{ category.typename }} <span class="category-button-count">({{ category.count || 0 }})</span>
|
{{ category.name }} <span class="category-button-count">({{ category.children?.length || 0 }})</span>
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -101,16 +101,17 @@
|
|||||||
<button class="category-modal-close" @click="closeAttributeModal">×</button>
|
<button class="category-modal-close" @click="closeAttributeModal">×</button>
|
||||||
</div>
|
</div>
|
||||||
<div class="category-modal-body">
|
<div class="category-modal-body">
|
||||||
<button v-for="attribute in attributes" :key="attribute.attributeid" class="category-button"
|
<!-- 扁平化处理 -->
|
||||||
|
<button v-for="attribute in getAllAttributes()" :key="attribute.attributeid" class="category-button"
|
||||||
@click="handleAttributeClick(attribute)">
|
@click="handleAttributeClick(attribute)">
|
||||||
{{ attribute.attributename }} <span class="category-button-count">({{ attribute.count || 0 }})</span>
|
{{ attribute.attributename }} <span class="category-button-count">({{ attribute.articlecount || 0 }})</span>
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</Transition>
|
</Transition>
|
||||||
<!-- 管理员 -->
|
<!-- 管理员 -->
|
||||||
<Establish class="establish-container" v-if="Login" />
|
<Establish class="establish-container" v-if="Login" />
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
@@ -122,7 +123,7 @@ import Footer from '@/views/Footer.vue';
|
|||||||
|
|
||||||
// ========== 组件初始化 ==========
|
// ========== 组件初始化 ==========
|
||||||
|
|
||||||
// 路由相关
|
// 路由相关状态
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
const route = useRoute();
|
const route = useRoute();
|
||||||
|
|
||||||
@@ -173,22 +174,13 @@ let heroIndex = 0;
|
|||||||
let heroTimer: number | undefined;
|
let heroTimer: number | undefined;
|
||||||
|
|
||||||
// 蒙版相关状态
|
// 蒙版相关状态
|
||||||
const categories = ref<any[]>([])
|
const Categoriestree = ref<any[]>([])
|
||||||
const showCategoryModal = ref(false)
|
const showCategoryModal = ref(false)
|
||||||
const attributes = ref<any[]>([])
|
|
||||||
const showAttributeModal = ref(false)
|
const showAttributeModal = ref(false)
|
||||||
// 显示分类蒙板
|
|
||||||
const openCategoryModal = () => {
|
|
||||||
showCategoryModal.value = true;
|
|
||||||
}
|
|
||||||
// 关闭分类蒙板
|
// 关闭分类蒙板
|
||||||
const closeCategoryModal = () => {
|
const closeCategoryModal = () => {
|
||||||
showCategoryModal.value = false;
|
showCategoryModal.value = false;
|
||||||
}
|
}
|
||||||
// 显示标签蒙板
|
|
||||||
const openAttributeModal = () => {
|
|
||||||
showAttributeModal.value = true;
|
|
||||||
}
|
|
||||||
// 关闭标签蒙板
|
// 关闭标签蒙板
|
||||||
const closeAttributeModal = () => {
|
const closeAttributeModal = () => {
|
||||||
showAttributeModal.value = false;
|
showAttributeModal.value = false;
|
||||||
@@ -196,40 +188,22 @@ const closeAttributeModal = () => {
|
|||||||
// 左侧状态栏传值
|
// 左侧状态栏传值
|
||||||
const updateData = (data: any) => {
|
const updateData = (data: any) => {
|
||||||
// 处理异步数据
|
// 处理异步数据
|
||||||
if (data.fetchCategories && typeof data.fetchCategories.then === 'function') {
|
// console.log(data.fetchCategoriestree)
|
||||||
data.fetchCategories.then(result => {
|
if (data.fetchCategoriestree && typeof data.fetchCategoriestree.then === 'function') {
|
||||||
categories.value = result || []
|
data.fetchCategoriestree.then(result => {
|
||||||
|
Categoriestree.value = result || []
|
||||||
})
|
})
|
||||||
} else {
|
} else {
|
||||||
categories.value = data.fetchCategories || []
|
Categoriestree.value = data.fetchCategoriestree || []
|
||||||
}
|
|
||||||
if (data.fetchAttributes && typeof data.fetchAttributes.then === 'function') {
|
|
||||||
data.fetchAttributes.then(result => {
|
|
||||||
attributes.value = result || []
|
|
||||||
})
|
|
||||||
} else {
|
|
||||||
attributes.value = data.fetchAttributes || []
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// 分类相关状态
|
// 分类相关状态
|
||||||
const CategoryModal = async (data: any) => {
|
const CategoryModal = async (data: any) => {
|
||||||
if (data.ifmodal) {
|
showCategoryModal.value = data.ifmodal
|
||||||
openCategoryModal()
|
|
||||||
// console.log('打开分类蒙板')
|
|
||||||
} else {
|
|
||||||
closeCategoryModal()
|
|
||||||
// console.log('关闭分类蒙板')
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
// 标签相关状态
|
// 标签相关状态
|
||||||
const AttributeModal = async (data: any) => {
|
const AttributeModal = async (data: any) => {
|
||||||
if (data.ifmodal) {
|
showAttributeModal.value = data.ifmodal
|
||||||
openAttributeModal()
|
|
||||||
// console.log('打开标签蒙板')
|
|
||||||
} else {
|
|
||||||
closeAttributeModal()
|
|
||||||
// console.log('关闭标签蒙板')
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
// ========== 蒙版事件 ==========
|
// ========== 蒙版事件 ==========
|
||||||
|
|
||||||
@@ -262,6 +236,11 @@ const handleAttributeClick = (attribute: any) => {
|
|||||||
closeAttributeModal()
|
closeAttributeModal()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 获取所有标签,扁平化处理
|
||||||
|
const getAllAttributes = () => {
|
||||||
|
return Categoriestree.value.flatMap(category => category.children || [])
|
||||||
|
}
|
||||||
|
|
||||||
// ========== 打字机效果模块 ==========
|
// ========== 打字机效果模块 ==========
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -580,7 +559,7 @@ const removeGlobalStoreValue = () => {
|
|||||||
globalStore.removeValue('articlestatus');
|
globalStore.removeValue('articlestatus');
|
||||||
globalStore.removeValue('attribute');
|
globalStore.removeValue('attribute');
|
||||||
}
|
}
|
||||||
// 不在article或者不在articlesave移除文章全局状态值
|
// 不在article或者不在articlesave移除文章全局状态值
|
||||||
if (rpsliturl[1] !== 'article' && rpsliturl[1] !== 'articlesave') {
|
if (rpsliturl[1] !== 'article' && rpsliturl[1] !== 'articlesave') {
|
||||||
globalStore.removeValue('articleInfo');
|
globalStore.removeValue('articleInfo');
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,10 +6,8 @@ import NonsensePage from '../views/nonsense.vue'
|
|||||||
import MessageBoardPage from '../views/messageboard.vue'
|
import MessageBoardPage from '../views/messageboard.vue'
|
||||||
import AboutMePage from '../views/aboutme.vue'
|
import AboutMePage from '../views/aboutme.vue'
|
||||||
import ArticleContentPage from '../views/articlecontents.vue'
|
import ArticleContentPage from '../views/articlecontents.vue'
|
||||||
import LoginPage from '../views/login.vue'
|
|
||||||
import ArticleSavePage from '../views/articlesave.vue'
|
import ArticleSavePage from '../views/articlesave.vue'
|
||||||
// 导入全局状态管理
|
import LoginPage from '../views/login.vue'
|
||||||
import { useGlobalStore } from '@/store/globalStore'
|
|
||||||
// 导入Element Plus消息组件
|
// 导入Element Plus消息组件
|
||||||
import { ElMessage } from 'element-plus'
|
import { ElMessage } from 'element-plus'
|
||||||
|
|
||||||
@@ -149,31 +147,30 @@ router.beforeEach((to, from, next) => {
|
|||||||
document.title = '个人博客'
|
document.title = '个人博客'
|
||||||
}
|
}
|
||||||
|
|
||||||
// 获取全局状态
|
// 从localStorage获取token和登录状态
|
||||||
const globalStore = useGlobalStore()
|
|
||||||
|
|
||||||
// 从localStorage获取token
|
|
||||||
const token = localStorage.getItem('token')
|
const token = localStorage.getItem('token')
|
||||||
|
const savedSpecificData = localStorage.getItem('globalStoreSpecificData')
|
||||||
|
const initialSpecificData = savedSpecificData ? JSON.parse(savedSpecificData) : {}
|
||||||
|
|
||||||
// 如果有token但登录状态为false,自动恢复登录状态
|
// 检查token是否有效
|
||||||
if (token && !globalStore.Login && !isTokenExpired(token)) {
|
const isTokenValid = token && !isTokenExpired(token)
|
||||||
globalStore.setLoginStatus(true)
|
|
||||||
}
|
|
||||||
|
|
||||||
// 如果有token但已过期,清除token和登录状态
|
// 如果有token但已过期,清除token和登录状态
|
||||||
if (token && isTokenExpired(token)) {
|
if (token && isTokenExpired(token)) {
|
||||||
localStorage.removeItem('token')
|
localStorage.removeItem('token')
|
||||||
globalStore.setLoginStatus(false)
|
// 直接更新localStorage中的登录状态
|
||||||
|
initialSpecificData.Login = false
|
||||||
|
localStorage.setItem('globalStoreSpecificData', JSON.stringify(initialSpecificData))
|
||||||
ElMessage.error('登录已过期,请重新登录')
|
ElMessage.error('登录已过期,请重新登录')
|
||||||
}
|
}
|
||||||
|
|
||||||
// 检查是否需要认证
|
// 检查是否需要认证
|
||||||
if (to.meta.requiresAuth) {
|
if (to.meta.requiresAuth) {
|
||||||
// 如果已登录,允许访问
|
// 如果token有效,允许访问
|
||||||
if (globalStore.Login) {
|
if (isTokenValid) {
|
||||||
next()
|
next()
|
||||||
} else {
|
} else {
|
||||||
// 未登录,重定向到登录页
|
// 未登录或token已过期,重定向到登录页
|
||||||
ElMessage.warning('请先登录')
|
ElMessage.warning('请先登录')
|
||||||
next('/login')
|
next('/login')
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ import { ElMessage } from 'element-plus'
|
|||||||
|
|
||||||
// 创建axios实例
|
// 创建axios实例
|
||||||
const api = axios.create({
|
const api = axios.create({
|
||||||
baseURL: '/api',
|
baseURL: 'http://localhost:7071/api',
|
||||||
timeout: 10000, // 请求超时时间
|
timeout: 10000, // 请求超时时间
|
||||||
withCredentials: true // 允许跨域请求携带凭证(如cookies)
|
withCredentials: true // 允许跨域请求携带凭证(如cookies)
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -1,6 +1,4 @@
|
|||||||
import Login from '@/views/login.vue'
|
|
||||||
import { defineStore } from 'pinia'
|
import { defineStore } from 'pinia'
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 全局状态管理store
|
* 全局状态管理store
|
||||||
* 提供全局的传值和获取值的功能
|
* 提供全局的传值和获取值的功能
|
||||||
|
|||||||
@@ -15,21 +15,21 @@
|
|||||||
<el-button type="primary" @click="fetchCategories">重新加载</el-button>
|
<el-button type="primary" @click="fetchCategories">重新加载</el-button>
|
||||||
</div>
|
</div>
|
||||||
<!-- 分类列表 -->
|
<!-- 分类列表 -->
|
||||||
<div v-else-if="categories.length > 0" class="article-content" id="category-list">
|
<div v-else-if="categoriestree.length > 0" class="article-content" id="category-list">
|
||||||
<p><strong></strong></p>
|
<p><strong></strong></p>
|
||||||
<div class="alert alert-primary"><strong><span class="alert-inner-text">文章分类如下,点击跳转</span> </strong></div>
|
<div class="alert alert-primary"><strong><span class="alert-inner-text">文章分类如下,点击跳转</span> </strong></div>
|
||||||
<div v-for="categoryGroup in categories" :key="categoryGroup.Categoryid" class="category-group-container">
|
<div v-for="categoryGroup in categoriestree" :key="categoryGroup.id" class="category-group-container">
|
||||||
<div v-if="categoryGroup.attributes.length > 0 && categoryGroup.attributes.some(cat => cat.articles && cat.articles.length > 0)">
|
<div v-if="calculateTotalArticles(categoryGroup.children) > 0">
|
||||||
<h2 id="header-id-1">{{ categoryGroup.typename }}</h2>
|
<h2 id="header-id-1">{{ categoryGroup.name }}</h2>
|
||||||
<!-- 计算该分类组中实际有文章的属性数量 -->
|
<span class="badge badge-primary">共 {{ calculateTotalArticles(categoryGroup.children) }} 篇</span>
|
||||||
<span class="badge badge-primary">共 {{ categoryGroup.attributes.reduce((total, cat) => total + (cat.articles && cat.articles.length ? cat.articles.length : 0), 0) }} 篇</span>
|
|
||||||
<ul class="category-item-list">
|
<ul class="category-item-list">
|
||||||
<div v-for="attribute in categoryGroup.attributes" :key="attribute.attributeid">
|
<div v-for="attribute in categoryGroup.children" :key="attribute.id">
|
||||||
<li v-if="attribute.articles && attribute.articles.length > 0">
|
<li v-if="attribute.articlecount && attribute.articlecount > 0">
|
||||||
<a class="category-link" @click="handleCategoryClick(attribute)"><kbd>{{ attribute.attributename}}</kbd></a>
|
<a class="category-link" @click="handleCategoryClick(attribute)"><kbd>{{
|
||||||
— —({{ attribute.articles.length }})
|
attribute.attributename}}</kbd></a>
|
||||||
|
— —({{ attribute.articlecount }})
|
||||||
</li>
|
</li>
|
||||||
</div>
|
</div>
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@@ -50,14 +50,14 @@ import { ref, onMounted } from 'vue'
|
|||||||
// 由于模块 '@/services' 没有导出的成员 'CategoryService',请确认正确的导出名称后修改此处
|
// 由于模块 '@/services' 没有导出的成员 'CategoryService',请确认正确的导出名称后修改此处
|
||||||
// 以下代码仅作示例,实际需根据 '@/services' 模块的真实导出调整
|
// 以下代码仅作示例,实际需根据 '@/services' 模块的真实导出调整
|
||||||
import { ElMessage } from 'element-plus'
|
import { ElMessage } from 'element-plus'
|
||||||
import { categoryService, categoryAttributeService, articleService } from '@/services'
|
import { categoryService } from '@/services'
|
||||||
import { useGlobalStore } from '@/store/globalStore'
|
import { useGlobalStore } from '@/store/globalStore'
|
||||||
|
|
||||||
const globalStore = useGlobalStore()
|
const globalStore = useGlobalStore()
|
||||||
const router = useRouter()
|
const router = useRouter()
|
||||||
|
|
||||||
// 响应式状态
|
// 响应式状态
|
||||||
const categories = ref<any[]>([])
|
const categoriestree = ref<any[]>([])
|
||||||
const loading = ref(false)
|
const loading = ref(false)
|
||||||
const error = ref('')
|
const error = ref('')
|
||||||
|
|
||||||
@@ -67,46 +67,44 @@ const error = ref('')
|
|||||||
const fetchCategories = async () => {
|
const fetchCategories = async () => {
|
||||||
try {
|
try {
|
||||||
loading.value = true;
|
loading.value = true;
|
||||||
const res = await categoryService.getAllCategories();
|
const res = await categoryService.getCategoryTree();
|
||||||
let processedCategories: any[] = [];
|
if (res.code !== 200) {
|
||||||
if (res.code === 200) {
|
return []
|
||||||
processedCategories = res.data.map(item => ({
|
|
||||||
...item,
|
|
||||||
attributes: [] // 使用更清晰的命名
|
|
||||||
}));
|
|
||||||
|
|
||||||
// 使用Promise.all等待所有异步操作完成
|
|
||||||
await Promise.all(
|
|
||||||
processedCategories.map(async category => {
|
|
||||||
const attributes = await categoryAttributeService.getAttributesByCategory(category.categoryid);
|
|
||||||
if (attributes.code === 200 && Array.isArray(attributes.data)) {
|
|
||||||
const processedAttributes = await Promise.all(
|
|
||||||
attributes.data.map(async item => {
|
|
||||||
const articleItem = {
|
|
||||||
...item,
|
|
||||||
articles: []
|
|
||||||
};
|
|
||||||
const articlesRes = await articleService.getArticlesByAttributeId(item.attributeid);
|
|
||||||
if(articlesRes.code === 200 && Array.isArray(articlesRes.data)){
|
|
||||||
articleItem.articles = articlesRes.data;
|
|
||||||
}
|
|
||||||
return articleItem;
|
|
||||||
})
|
|
||||||
);
|
|
||||||
category.attributes = processedAttributes;
|
|
||||||
}
|
|
||||||
})
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
categories.value = processedCategories;
|
|
||||||
// console.log('获取分类列表成功:', categories.value);
|
categoriestree.value = res.data;
|
||||||
|
// console.log('获取分类列表成功:', categoriestree.value);
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
console.error('获取分类列表失败:', err);
|
console.error('获取分类列表失败:', err);
|
||||||
ElMessage.error('获取分类列表失败,请稍后重试');
|
ElMessage.error('获取分类列表失败,请稍后重试');
|
||||||
}finally{
|
} finally {
|
||||||
loading.value = false;
|
loading.value = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
/**
|
||||||
|
* 过滤出有文章的分类组
|
||||||
|
* @param {any[]} categoryGroups - 分类组数组
|
||||||
|
* @returns {any[]} - 有文章的分类组数组
|
||||||
|
*/
|
||||||
|
const filterCategoriesWithArticles = (categoryGroups: any[]) => {
|
||||||
|
return categoryGroups.filter(group =>
|
||||||
|
group.children.some(child => child.articlecount && child.articlecount > 0)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* 计算文章总数
|
||||||
|
* @param {any[]} categoryGroups - 分类组数组
|
||||||
|
* @returns {number} - 文章总数
|
||||||
|
*/
|
||||||
|
const calculateTotalArticles = (categoryGroups: any[]) => {
|
||||||
|
let TotalArticles = 0
|
||||||
|
if (categoryGroups.length > 0) {
|
||||||
|
categoryGroups.forEach(group => {
|
||||||
|
TotalArticles += group.articlecount
|
||||||
|
})
|
||||||
|
}
|
||||||
|
return TotalArticles
|
||||||
|
}
|
||||||
/**
|
/**
|
||||||
* 处理分类点击事件
|
* 处理分类点击事件
|
||||||
* 注意:现在实际上使用的是属性ID而不是分类ID
|
* 注意:现在实际上使用的是属性ID而不是分类ID
|
||||||
@@ -115,7 +113,7 @@ const fetchCategories = async () => {
|
|||||||
const handleCategoryClick = (attribute: any) => {
|
const handleCategoryClick = (attribute: any) => {
|
||||||
globalStore.removeValue('attribute')
|
globalStore.removeValue('attribute')
|
||||||
globalStore.setValue('attribute', {
|
globalStore.setValue('attribute', {
|
||||||
id: attribute.attributeid,
|
id: attribute.attributeid,
|
||||||
name: attribute.attributename
|
name: attribute.attributename
|
||||||
})
|
})
|
||||||
router.push({
|
router.push({
|
||||||
@@ -124,20 +122,7 @@ const handleCategoryClick = (attribute: any) => {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* 计算分类组中的文章总数
|
|
||||||
* @param {Array} categoryItems - 分类项数组
|
|
||||||
* @returns {number} 文章总数
|
|
||||||
*/
|
|
||||||
const getCategorySum = (categoryItems: any[]): number => {
|
|
||||||
if (!categoryItems || !Array.isArray(categoryItems)) {
|
|
||||||
return 0
|
|
||||||
}
|
|
||||||
|
|
||||||
return categoryItems.reduce((total, item) => {
|
|
||||||
return total + (item.sum || 0)
|
|
||||||
}, 0)
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 组件挂载时获取分类列表
|
* 组件挂载时获取分类列表
|
||||||
|
|||||||
@@ -102,17 +102,12 @@ const loadNonsenseList = async () => {
|
|||||||
pageNum: pageNum.value - 1,
|
pageNum: pageNum.value - 1,
|
||||||
pageSize: pageSize.value
|
pageSize: pageSize.value
|
||||||
})
|
})
|
||||||
// console.log(response)
|
|
||||||
if (response.code === 200) {
|
if (response.code === 200) {
|
||||||
nonsenseList.value = response.data
|
nonsenseList.value = response.data
|
||||||
// 计算总页数
|
// 计算总页数
|
||||||
totalPages.value = response.totalPages
|
totalPages.value = response.totalPages
|
||||||
// 显示当前页的内容
|
// 显示当前页的内容
|
||||||
displayedNonsenseList.value = response.data
|
displayedNonsenseList.value = response.data
|
||||||
// 初始化字符样式
|
|
||||||
// initializeCharStyles()
|
|
||||||
// 开始颜色变化定时器
|
|
||||||
// console.log(displayedNonsenseList.value)
|
|
||||||
} else {
|
} else {
|
||||||
ElMessage.error('加载吐槽内容失败')
|
ElMessage.error('加载吐槽内容失败')
|
||||||
error.value = true
|
error.value = true
|
||||||
|
|||||||
Reference in New Issue
Block a user