From f4263af34311a26d19c0a4a096b4f4869ed0971f Mon Sep 17 00:00:00 2001 From: qingfeng1121 Date: Thu, 18 Dec 2025 15:20:14 +0800 Subject: [PATCH] =?UTF-8?q?refactor(=E5=89=8D=E7=AB=AF):=20=E9=87=8D?= =?UTF-8?q?=E6=9E=84=E5=89=8D=E7=AB=AF=E4=BB=A3=E7=A0=81=E7=BB=93=E6=9E=84?= =?UTF-8?q?=E5=B9=B6=E4=BC=98=E5=8C=96=E5=8A=9F=E8=83=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 重构路由配置和API调用逻辑,统一分页处理方式 优化分类和标签模块的交互,提取蒙版组件到主布局 调整样式和布局,增强响应式设计 更新接口字段名以保持前后端一致性 添加网站运行时间显示功能 --- src/components/LeftModule.vue | 305 +++++----------------------- src/layouts/MainLayout.vue | 343 ++++++++++++++++++++++++++++---- src/router/Router.js | 10 +- src/services/articleService.js | 13 +- src/services/categoryService.js | 18 +- src/services/messageService.js | 32 ++- src/types/index.ts | 6 +- src/views/Footer.vue | 148 ++++++++++++-- src/views/aericlelist.vue | 18 +- src/views/articlecontents.vue | 9 +- src/views/home.vue | 75 +++---- src/views/messageboard.vue | 171 +++++++++++++--- vite.config.js | 4 +- 13 files changed, 722 insertions(+), 430 deletions(-) diff --git a/src/components/LeftModule.vue b/src/components/LeftModule.vue index de974ee..422ce94 100644 --- a/src/components/LeftModule.vue +++ b/src/components/LeftModule.vue @@ -51,13 +51,13 @@
- + {{ categoryCount }} 分类
- + {{ AttributeCount }} 标签 @@ -69,50 +69,8 @@
- - - -
-
-
-

所有分类

- -
-
- -
-
-
-
- - - -
-
-
-

所有标签

- -
-
- -
-
-
-
+ + @@ -120,8 +78,6 @@ import { reactive, ref, onMounted, onUnmounted } from 'vue' import { useRouter } from 'vue-router' import { articleService, categoryService, categoryAttributeService } from "@/services"; -import { useGlobalStore } from '@/store/globalStore' -const globalStore = useGlobalStore() // 当前激活菜单 const activeIndex = ref('/:type') @@ -134,13 +90,10 @@ const state = reactive({ }) // 分类相关状态 -const categories = ref([]) -const showCategoryModal = ref(false) +// defineEmits +const emit = defineEmits(['update-data', 'CategoryModal', 'AttributeModal']) // 标签相关状态 -const attributes = ref([]) -const showAttributeModal = ref(false) - // 处理菜单选择跳转 const handleSelect = (key: string) => { router.push({ path: key }) @@ -160,9 +113,9 @@ const AttributeCount = ref(0) // 获取文章数量 const fetchArticleCount = async () => { - try { - const response = await articleService.getAllArticles(); - articleCount.value = response.data?.length || 0 + try { + const response = await articleService.getAllArticles(); + articleCount.value = response.data?.length || 0 } catch (error) { console.error('获取文章数量失败:', error) articleCount.value = 0 @@ -171,15 +124,18 @@ const fetchArticleCount = async () => { // 获取分类数据 const fetchCategories = async () => { - try { + + // 分类数据状态 + const categories = ref([]) + try { const response = await categoryService.getAllCategories(); // 如果API返回的数据结构不包含count属性,我们可以模拟一些数据 categories.value = response.data?.map((category: any) => ({ ...category, - count: 0 + count: 0 })) || []; categories.value.forEach(async (category: any) => { - const attributeResponse = await categoryAttributeService.getAttributesByCategory(category.typeid) + const attributeResponse = await categoryAttributeService.getAttributesByCategory(category.categoryid) if (attributeResponse.data?.length) { category.count = attributeResponse.data?.length || 0 } @@ -190,20 +146,23 @@ const fetchCategories = async () => { console.error('获取分类失败:', error) // 如果API调用失败,使用模拟数据 categories.value = [ - + ]; categoryCount.value = categories.value.length } + return categories.value } // 获取标签数据 const fetchAttributes = async () => { - try { + // 标签数据状态 + const attributes = ref([]) + try { const response = await categoryAttributeService.getAllAttributes(); // 如果API返回的数据结构不包含count属性,我们可以模拟一些数据 attributes.value = response.data?.map((attribute: any) => ({ ...attribute, - count: 0 + count: 0 })) || []; attributes.value.forEach(async (attribute: any) => { const articleResponse = await articleService.getArticlesByAttributeId(attribute.attributeid) @@ -216,56 +175,27 @@ const fetchAttributes = async () => { console.error('获取标签失败:', error) // 如果API调用失败,使用模拟数据 attributes.value = [ - ]; AttributeCount.value = attributes.value.length } + return attributes.value } -// 显示分类蒙板 -const showCategories = () => { - showCategoryModal.value = true +// 向父组件传递标签数据 +const sendData = () => { + const data = { fetchAttributes: fetchAttributes(), fetchCategories: fetchCategories() } + emit('update-data', data) } -// 关闭分类蒙板 -const closeCategoryModal = () => { - showCategoryModal.value = false +// 显示标签蒙版 +const showAttributesModel = () => { + emit('AttributeModal', { ifmodal: true }) +} +// 显示分类蒙版 +const showCategoriesModel = () => { + emit('CategoryModal', { ifmodal: true }) } -// 处理分类点击 -const handleCategoryClick = (category: any) => { - // 这里可以根据实际需求跳转到对应分类的文章列表页 - console.log('点击了分类:', category.typename) - // 示例:router.push(`/article-list?category=${category.typeid}`) - closeCategoryModal() -} - -// 显示标签蒙板 -const showAttributes = () => { - showAttributeModal.value = true -} - -// 关闭标签蒙板 -const closeAttributeModal = () => { - showAttributeModal.value = false -} - -// 处理标签点击 -const handleAttributeClick = (attribute: any) => { - // 重置全局属性状态 - globalStore.removeValue('attribute') - - globalStore.setValue('attribute', { - id: attribute.attributeid, - name: attribute.attributename - }) - console.log(attribute) - router.push({ - path: '/home/aericletype', - - }) - closeAttributeModal() -} // 控制底部模块吸顶效果 const scrollY = ref(false) @@ -277,8 +207,7 @@ const handleScroll = () => { onMounted(() => { window.addEventListener('scroll', handleScroll) fetchArticleCount() // 组件挂载时获取文章数量 - fetchCategories() // 组件挂载时获取分类数据 - fetchAttributes() // 组件挂载时获取标签数据 + sendData() // 组件挂载时获取标签数据和分类数据 }) onUnmounted(() => { @@ -314,15 +243,17 @@ onUnmounted(() => { /* 内容区域样式 */ #cont { - padding:0 0 10px 0; + padding: 0 0 10px 0; border-radius: 10px; background-color: rgba(255, 255, 255, 0.9); /* 白色半透明背景 */ } -#cont .cont1{ + +#cont .cont1 { margin-bottom: 5px; } -#cont .cont2{ + +#cont .cont2 { margin-bottom: 0px; } @@ -349,16 +280,12 @@ onUnmounted(() => { background-color: rgba(0, 0, 0, 0); /* 白色半透明背景 */ } + .cont2 .el-menu-vertical-demo li { font-size: 14px; height: 35px; } -.cont2 .el-menu-vertical-demo .el-menu-item:nth-child(3) { - /* border-radius: 0 0 10px 10px; */ - /* margin-bottom: 10px; */ -} - .cont2 .el-menu-vertical-demo .el-menu-item:hover { background-color: rgba(64, 158, 255, 0.9); } @@ -429,11 +356,12 @@ onUnmounted(() => { /* 白色半透明背景 */ padding: 10px; } + .site-state-item-count { - display: block; - text-align: center; - color: #32325d; - font-weight: bold; + display: block; + text-align: center; + color: #32325d; + font-weight: bold; } .demo-tabs { @@ -444,14 +372,16 @@ onUnmounted(() => { margin-left: 100px; padding: 10px 20px; } + .mylogo_name { font-size: 13px; } + .mylogo_description { font-size: 13px; opacity: 0.8; color: #c21f30; - margin: 10px 0; + margin: 10px 0; } .stat-container { @@ -508,145 +438,6 @@ onUnmounted(() => { transform: translateY(0); } } -/* 分类蒙板样式 */ -.category-modal { - position: fixed; - top: 0; - left: 0; - right: 0; - bottom: 0; - background-color: rgba(0, 0, 0, 0.5); - display: flex; - justify-content: center; - align-items: center; - z-index: 1000; - /* 确保在任何情况下都能居中显示 */ - margin: 0; - padding: 0; -} -.category-modal-content { - background-color: white; - border-radius: 10px; - width: 90%; - max-width: 500px; - max-height: 80vh; - overflow: hidden; - box-shadow: 0 4px 20px rgba(0, 0, 0, 0.15); - /* 确保内容块在父容器中完美居中 */ -} -.category-modal-header { - display: flex; - justify-content: space-between; - align-items: center; - padding: 15px 20px; - border-bottom: 1px solid #eee; -} - -.category-modal-header h3 { - margin: 0; - font-size: 18px; - color: #333; -} - -.category-modal-close { - background: none; - border: none; - font-size: 24px; - cursor: pointer; - color: #999; - width: 30px; - height: 30px; - display: flex; - align-items: center; - justify-content: center; - border-radius: 50%; - transition: all 0.3s; -} - -.category-modal-close:hover { - background-color: #f5f5f5; - color: #333; -} - -.category-modal-body { - padding: 20px; - display: grid; - grid-template-columns: repeat(auto-fill, minmax(120px, 1fr)); - gap: 12px; - max-height: 60vh; - overflow-y: auto; -} - -.category-button { - background-color: rgba(102, 161, 216, 0.1); - border: 1px solid rgba(102, 161, 216, 0.3); - border-radius: 6px; - padding: 10px 15px; - cursor: pointer; - transition: all 0.3s; - font-size: 14px; - color: #333; - text-align: center; - display: flex; - flex-direction: column; - align-items: center; - gap: 4px; -} - -.category-button:hover { - background-color: rgba(102, 161, 216, 0.3); - transform: translateY(-2px); - box-shadow: 0 2px 8px rgba(102, 161, 216, 0.2); -} - -.category-button-count { - font-size: 12px; - color: #66a1d8; - font-weight: 500; -} - -/* 蒙板动画 */ -.modal-enter-active, -.modal-leave-active { - transition: opacity 0.3s ease; -} - -.modal-enter-from, -.modal-leave-to { - opacity: 0; -} - -.modal-enter-active .category-modal-content, -.modal-leave-active .category-modal-content { - transition: transform 0.3s ease; -} - -.modal-enter-from .category-modal-content { - transform: scale(0.9); -} - -.modal-leave-to .category-modal-content { - transform: scale(0.9); -} - -/* 滚动条样式 */ -.category-modal-body::-webkit-scrollbar { - width: 6px; -} - -.category-modal-body::-webkit-scrollbar-track { - background: #f1f1f1; - border-radius: 3px; -} - -.category-modal-body::-webkit-scrollbar-thumb { - background: #ccc; - border-radius: 3px; -} - -.category-modal-body::-webkit-scrollbar-thumb:hover { - background: #999; -} \ No newline at end of file diff --git a/src/layouts/MainLayout.vue b/src/layouts/MainLayout.vue index 7ab8d45..0107105 100644 --- a/src/layouts/MainLayout.vue +++ b/src/layouts/MainLayout.vue @@ -63,18 +63,54 @@
- +
- +
+ + +
+
+ + +
+
+
+

所有分类

+ +
+
+ +
+
+
+
- + + +
+
+
+

所有标签

+ +
+
+ +
+
+
+
+ - -