185 lines
4.1 KiB
Vue
185 lines
4.1 KiB
Vue
<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>
|