first commit

This commit is contained in:
2026-06-03 10:09:03 +08:00
commit 81f5039458
6266 changed files with 188236 additions and 0 deletions
+184
View File
@@ -0,0 +1,184 @@
<template>
<div class="onepage-container">
<Header />
<div class="headtop"></div>
<div v-if="loading" class="loading">
<i class="fas fa-spinner fa-spin"></i>
<span>加载中...</span>
</div>
<div v-else-if="error" class="error">
<i class="fas fa-exclamation-triangle"></i>
<p>{{ error }}</p>
<button @click="loadOnePage" class="retry-btn">重试</button>
</div>
<div v-else-if="onePage" class="content">
<div class="page-wrapper" v-html="onePage.content"></div>
</div>
<div v-else class="not-found">
<i class="fas fa-file-alt"></i>
<p>单页内容不存在</p>
</div>
<Footer />
</div>
</template>
<script setup lang="ts">
import { ref, onMounted } from 'vue'
import { useRoute, useRouter } from 'vue-router'
import Header from '../components/header.vue'
import Footer from '../components/footer.vue'
import { getOnePageByPath } from '@/api/index'
interface OnePage {
id: number
title: string
content: string
path: string
sort: number
status: 0 | 1
}
const route = useRoute()
const router = useRouter()
const loading = ref(false)
const error = ref('')
const onePage = ref<OnePage | null>(null)
// 根据路由路径获取单页内容
const loadOnePage = async () => {
const path = route.path
if (!path || path === '/') {
router.push('/404')
return
}
// 检查当前路由是否已匹配到其他组件(type 2 的页面)
// 如果已匹配到具体组件,说明不是单页,不应该由单页组件处理
const matchedRoute = route.matched[route.matched.length - 1]
if (matchedRoute && matchedRoute.name && matchedRoute.name !== 'OnePage') {
// 如果匹配到的不是 OnePage,说明是其他路由(如 type 2 的页面),不应该处理
// 但通配符路由会匹配所有路径,所以需要检查 meta
if (matchedRoute.meta && matchedRoute.meta.menuType === 2) {
router.push('/404')
return
}
}
loading.value = true
error.value = ''
try {
const result = await getOnePageByPath(path)
if (result.code === 200 && result.data) {
onePage.value = result.data
} else {
// 如果单页不存在,重定向到404
router.push('/404')
}
} catch (err: any) {
// 如果请求失败,重定向到404
router.push('/404')
} finally {
loading.value = false
}
}
onMounted(() => {
loadOnePage()
})
</script>
<style lang="scss" scoped>
.onepage-container {
min-height: 100vh;
display: flex;
flex-direction: column;
width: 100%;
}
// 头部占位符,高度与固定头部一致(80px)
.headtop {
height: 80px;
width: 100%;
flex-shrink: 0;
background-color: #F8F8F8;
}
.loading,
.error,
.not-found {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
min-height: 60vh;
gap: 16px;
color: #666;
padding: 40px 20px;
flex: 1;
i {
font-size: 48px;
color: #999;
}
p {
margin: 0;
font-size: 16px;
}
}
.error {
i {
color: #f56c6c;
}
}
.retry-btn {
padding: 10px 20px;
background-color: #3973ff;
color: white;
border: none;
border-radius: 4px;
cursor: pointer;
font-size: 14px;
transition: background-color 0.3s;
&:hover {
background-color: #66b1ff;
}
}
.content {
flex: 1;
width: 100%;
min-height: 0; // 允许 flex 子元素缩小
.page-wrapper {
width: 100%;
min-height: 100%;
position: relative; // 确保定位上下文正确
// 确保单页内容样式正确显示
:deep(*) {
box-sizing: border-box;
}
// 确保单页内容中的下拉菜单不受前端导航栏样式影响
// 只针对单页内容中的下拉菜单,不影响前端导航栏
:deep(.dropdown-menu:not(.site-header-dropdown-menu)) {
position: relative !important;
top: auto !important;
left: auto !important;
right: auto !important;
width: auto !important;
z-index: auto !important;
}
// 确保单页内容中的元素不会影响前端导航栏的下拉菜单
:deep(*) {
z-index: auto !important;
}
}
}
</style>