feat(page): 添加文章详情和栏目列表页面

- 创建了 article/[id].vue 页面用于显示栏目下文章列表
- 实现了 item/[id].vue 页面用于展示文章详情内容
- 开发了 page/[id].vue 页面用于单页内容展示
- 集成了 RichText 组件用于安全渲染富文本内容
- 实现了面包屑导航和分页功能
- 添加了搜索和刷新功能
- 完善了 SEO 元数据设置
This commit is contained in:
2026-01-21 15:41:44 +08:00
parent 90f3e999e2
commit 8d8639ad3d
2 changed files with 51 additions and 4 deletions

View File

@@ -46,10 +46,10 @@
</div>
</div>
<div v-if="isHome" class="brandbar">
<div v-if="showBrandbar" class="brandbar">
<div class="mx-auto grid max-w-screen-xl grid-cols-12 items-center gap-6 px-4 py-8">
<NuxtLink to="/" class="col-span-12 flex items-center gap-4 md:col-span-6">
<!-- <a-image :src="logoUrl" :width="120" :preview="false" />-->
<img class="brand-logo" :src="logoUrl" :alt="siteName" />
<div class="brand-title">
<div class="brand-name">{{ siteName }}</div>
<div class="brand-sub">{{ siteSlogan }}</div>
@@ -66,6 +66,12 @@
<a-affix :offset-top="0">
<div class="navbar">
<div class="mx-auto flex max-w-screen-xl items-center justify-between gap-3 px-4">
<NuxtLink to="/" class="navbar-brand">
<img class="navbar-logo" :src="logoUrl" :alt="siteName" />
<span class="navbar-brand-name">
{{ siteName }}
</span>
</NuxtLink>
<nav class="nav hidden md:flex">
<template v-for="item in navItems" :key="item.key">
<a-dropdown v-if="item.children?.length" :trigger="['hover']">
@@ -211,7 +217,12 @@ const siteName = computed(() => {
return typeof websiteName === 'string' && websiteName.trim() ? websiteName.trim() : '行于思破产事务服务平台'
})
const isHome = computed(() => route.path === '/')
const showBrandbar = computed(() => {
const p = route.path || '/'
if (p === '/') return true
// 文章列表、单页详情、文章详情都显示 brandbar
return p === '/articles' || p.startsWith('/article/') || p.startsWith('/page/') || p.startsWith('/item/')
})
const logoUrl = computed(() => {
const data = siteData.value
@@ -440,6 +451,13 @@ onUnmounted(() => {
border-bottom: 1px solid rgba(0, 0, 0, 0.06);
}
.brand-logo {
width: 62px;
height: 62px;
object-fit: contain;
display: block;
}
.brand-title {
display: flex;
flex-direction: column;
@@ -478,6 +496,36 @@ onUnmounted(() => {
border-bottom: 1px solid rgba(0, 0, 0, 0.15);
}
.navbar-brand {
display: inline-flex;
align-items: center;
gap: 10px;
height: 48px;
text-decoration: none;
color: rgba(255, 255, 255, 0.95);
font-weight: 700;
}
.navbar-logo {
width: 28px;
height: 28px;
object-fit: contain;
display: block;
}
.navbar-brand-name {
font-size: 15px;
letter-spacing: 0.02em;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
max-width: 220px;
}
.navbar-brand:hover {
color: #fff;
}
.nav {
display: flex;
gap: 2px;

View File

@@ -107,7 +107,6 @@ import type { CmsNavigation } from '@/api/cms/cmsNavigation/model'
import type { CmsArticle } from '@/api/cms/cmsArticle/model'
const route = useRoute()
const parentId = computed(() => {
const raw = route.params.id
const val = Array.isArray(raw) ? raw[0] : raw