practice_code/web/graduation/src/pages/culture/[slug].astro
2025-04-12 15:29:10 +08:00

336 lines
14 KiB
Plaintext

---
import { getCollection, type CollectionEntry } from "astro:content";
import MainLayout from "../../components/MainLayout.astro";
// 定义Props类型
export interface Props {
entry: CollectionEntry<"culture">;
}
// 生成静态路径
export async function getStaticPaths() {
const cultures = await getCollection("culture");
return cultures.map((entry) => ({
params: { slug: entry.slug },
props: { entry },
}));
}
// 获取当前文化数据
const { entry } = Astro.props;
const { Content } = await entry.render();
// 获取相关文化
const allCultures = await getCollection("culture");
const relatedCultures = allCultures
.filter(
(item) =>
item.slug !== entry.slug &&
item.data.tags.some((tag) => entry.data.tags.includes(tag))
)
.slice(0, 3);
---
<MainLayout title={`${entry.data.title} - 河北游礼`}>
<!-- 移动端浮动返回按钮 -->
<div class="md:hidden fixed bottom-6 left-1/2 transform -translate-x-1/2 z-50">
<a
href="/culture"
class="flex items-center space-x-2 px-5 py-3 bg-ancient-accent dark:bg-ancient-accent-dark text-ancient-white rounded-full shadow-lg hover:bg-ancient-accent/90 dark:hover:bg-ancient-accent-dark/90 transition-colors border border-ancient-accent/30 dark:border-ancient-accent-dark/30 backdrop-blur-sm"
aria-label="返回所有文化"
>
<svg xmlns="http://www.w3.org/2000/svg" class="h-5 w-5" fill="none" viewBox="0 0 24 24" stroke="currentColor">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M11 17l-5-5m0 0l5-5m-5 5h12" />
</svg>
<span>返回文化列表</span>
</a>
</div>
<!-- 页面标题区域 - 古籍风格 -->
<div class="relative py-16 bg-ancient-paper dark:bg-ancient-paper-dark overflow-hidden">
<div class="absolute inset-0 bg-opacity-20 bg-amber-100 dark:bg-opacity-20 dark:bg-amber-900"></div>
<div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 relative z-10">
<div class="flex flex-wrap items-center gap-2 mb-4">
<a href="/" class="text-ancient-black/80 dark:text-ancient-white/80 hover:text-ancient-accent dark:hover:text-ancient-accent-dark transition-colors font-ancient-small">首页</a>
<span class="text-ancient-black/60 dark:text-ancient-white/60 font-ancient-small">/</span>
<a href="/culture" class="text-ancient-black/80 dark:text-ancient-white/80 hover:text-ancient-accent dark:hover:text-ancient-accent-dark transition-colors font-ancient-small">文化</a>
<span class="text-ancient-black/60 dark:text-ancient-white/60 font-ancient-small">/</span>
<span class="text-ancient-black/60 dark:text-ancient-white/60 font-ancient-small">{entry.data.title}</span>
</div>
<!-- 典籍风格标题 -->
<div class="official-title">
<h1 class="text-4xl md:text-5xl font-ancient text-ancient-black dark:text-ancient-white mb-4 leading-snug">{entry.data.title}</h1>
<div class="w-40 h-0.5 my-6 bg-ancient-accent dark:bg-ancient-accent-dark"></div>
</div>
<div class="flex flex-wrap items-center gap-4 mb-4">
{entry.data.city && entry.data.city.length > 0 && (
<div class="flex items-center text-ancient-black/90 dark:text-ancient-white/90 font-ancient-body">
<span class="mr-1">📍</span>
{entry.data.city.map((cityName, index) => (
<>
<span>{cityName}</span>
{index < entry.data.city.length - 1 && <span>, </span>}
</>
))}
</div>
)}
{entry.data.pubDate && (
<div class="flex items-center text-ancient-black/90 dark:text-ancient-white/90 font-ancient-body">
<span class="mr-1">📅</span> {new Date(entry.data.pubDate).toLocaleDateString('zh-CN')}
</div>
)}
<div class="flex items-center text-ancient-black/90 dark:text-ancient-white/90 font-ancient-body">
<span class="mr-1">🏷️</span> {entry.data.category}
</div>
</div>
<div class="flex flex-wrap gap-2 mb-6">
{entry.data.tags.map((tag) => (
<span class="px-3 py-1 bg-ancient-paper/70 dark:bg-ancient-paper-dark/70 text-ancient-black dark:text-ancient-white text-sm font-ancient-small border border-ancient-accent/30 dark:border-ancient-accent-dark/30 hover:border-ancient-accent/50 dark:hover:border-ancient-accent-dark/50 rounded-full">
{tag}
</span>
))}
</div>
<p class="text-xl text-ancient-black/90 dark:text-ancient-white/90 max-w-3xl font-ancient-body">{entry.data.description}</p>
</div>
</div>
<!-- 主要内容区域 - 古籍风格 -->
<div class="py-12 bg-ancient-paper dark:bg-ancient-paper-dark">
<div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
<div class="grid grid-cols-1 lg:grid-cols-12 gap-6">
<!-- 左侧内容 - 古籍风格 -->
<div class="lg:col-span-8">
<div class="prose prose-lg dark:prose-invert max-w-none font-ancient-body bg-ancient-paper-light/30 dark:bg-ancient-paper-dark/30 p-0 relative">
<Content />
</div>
</div>
<!-- 右侧边栏 - 古籍风格 -->
<div class="lg:col-span-4 space-y-6">
<!-- 文化图片 - 古籍风格 -->
<div class="border border-ancient-accent/40 dark:border-ancient-accent-dark/40 overflow-hidden shadow-md">
<div class="h-64 bg-ancient-paper-light/70 dark:bg-ancient-paper-dark/70 flex items-center justify-center relative">
{entry.data.image ? (
<img
src={entry.data.image}
alt={entry.data.title}
class="w-full h-full object-cover"
/>
) : (
<span class="text-ancient-black/40 dark:text-ancient-white/40 font-ancient">{entry.data.title} 图片</span>
)}
</div>
</div>
<!-- 文化信息卡片 - 古籍风格 -->
<div class="bg-ancient-paper-light dark:bg-ancient-paper-dark-light p-5 border border-ancient-accent/30 dark:border-ancient-accent-dark/30 shadow-md">
<h3 class="text-xl font-ancient-heading text-ancient-black dark:text-ancient-white mb-4 flex items-center">
<svg class="w-5 h-5 mr-2 text-ancient-accent dark:text-ancient-accent-dark" fill="none" stroke="currentColor" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M13 16h-1v-4h-1m1-4h.01M21 12a9 9 0 11-18 0 9 9 0 0118 0z" />
</svg>
文化信息
</h3>
<div class="space-y-3 font-ancient-body">
{entry.data.city && entry.data.city.length > 0 && (
<div class="flex">
<span class="w-24 flex-shrink-0 text-ancient-black/60 dark:text-ancient-white/60">分布地区:</span>
<div class="text-ancient-black dark:text-ancient-white">
{entry.data.city.map((cityName, index) => (
<>
<span>{cityName}</span>
{index < entry.data.city.length - 1 && <span>, </span>}
</>
))}
</div>
</div>
)}
<div class="flex">
<span class="w-24 flex-shrink-0 text-ancient-black/60 dark:text-ancient-white/60">文化类型:</span>
<span class="text-ancient-black dark:text-ancient-white">{entry.data.category}</span>
</div>
<div class="flex">
<span class="w-24 flex-shrink-0 text-ancient-black/60 dark:text-ancient-white/60">特色标签:</span>
<div class="flex flex-wrap gap-1">
{entry.data.tags.map((tag) => (
<span class="px-2 py-0.5 bg-ancient-paper/70 dark:bg-ancient-paper-dark/70 text-sm font-ancient-small border border-ancient-accent/30 dark:border-ancient-accent-dark/30 text-ancient-black dark:text-ancient-white text-xs rounded-full">
{tag}
</span>
))}
</div>
</div>
{entry.data.pubDate && (
<div class="flex">
<span class="w-24 flex-shrink-0 text-ancient-black/60 dark:text-ancient-white/60">发布时间:</span>
<span class="text-ancient-black dark:text-ancient-white">{new Date(entry.data.pubDate).toLocaleDateString('zh-CN')}</span>
</div>
)}
</div>
</div>
<!-- 相关文化 - 古籍风格 -->
{relatedCultures.length > 0 && (
<div class="bg-ancient-paper-light dark:bg-ancient-paper-dark-light p-5 border border-ancient-accent/30 dark:border-ancient-accent-dark/30 shadow-md">
<h3 class="text-xl font-ancient-heading text-ancient-black dark:text-ancient-white mb-4 flex items-center">
<svg class="w-5 h-5 mr-2 text-ancient-accent dark:text-ancient-accent-dark" fill="none" stroke="currentColor" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2" />
</svg>
相关文化
</h3>
<div class="space-y-4">
{relatedCultures.map((culture) => (
<a
href={`/culture/${culture.slug}`}
class="block group"
>
<div class="flex items-start space-x-3">
<div class="w-16 h-16 flex-shrink-0 bg-ancient-paper/70 dark:bg-ancient-paper-dark/70 border border-ancient-accent/20 dark:border-ancient-accent-dark/20 rounded flex items-center justify-center overflow-hidden">
{culture.data.image ? (
<img
src={culture.data.image}
alt={culture.data.title}
class="w-full h-full object-cover"
/>
) : (
<span class="text-xs text-ancient-black/40 dark:text-ancient-white/40">图片</span>
)}
</div>
<div>
<h4 class="text-base font-ancient-heading text-ancient-black dark:text-ancient-white group-hover:text-ancient-accent dark:group-hover:text-ancient-accent-dark transition-colors">
{culture.data.title}
</h4>
<p class="text-sm text-ancient-black/70 dark:text-ancient-white/70 line-clamp-2 font-ancient-body">
{culture.data.description.substring(0, 60)}...
</p>
</div>
</div>
</a>
))}
</div>
</div>
)}
<!-- 返回按钮 - 仅在非移动端显示 - 古籍风格 -->
<div class="hidden md:block">
<a
href="/culture"
class="block w-full py-4 mt-8 mb-4 text-center bg-ancient-accent dark:bg-ancient-accent-dark text-ancient-white rounded-md hover:bg-ancient-accent/90 dark:hover:bg-ancient-accent-dark/90 transition-colors font-ancient shadow-lg border border-ancient-accent/50 dark:border-ancient-accent-dark/50 text-lg backdrop-blur-sm"
>
返回所有文化
</a>
</div>
</div>
</div>
</div>
</div>
</MainLayout>
<style>
/* 确保这些CSS类对此页面有效 */
.prose {
color: var(--ancient-black) !important;
}
.dark .prose {
color: var(--ancient-white) !important;
}
.prose h1, .prose h2, .prose h3, .prose h4 {
color: var(--ancient-black) !important;
font-family: var(--font-ancient-heading);
}
.dark .prose h1, .dark .prose h2, .dark .prose h3, .dark .prose h4 {
color: var(--ancient-white) !important;
}
.prose p, .prose ul, .prose ol {
font-family: var(--font-ancient-body);
}
.prose a {
color: var(--ancient-accent) !important;
text-decoration: none;
border-bottom: 1px dashed var(--ancient-accent);
transition: all 0.2s ease;
}
.dark .prose a {
color: var(--ancient-accent-dark) !important;
border-bottom-color: var(--ancient-accent-dark);
}
.prose a:hover {
border-bottom-style: solid;
color: var(--ancient-red) !important;
}
.dark .prose a:hover {
color: var(--ancient-red-dark) !important;
}
.prose blockquote {
border-left-color: var(--ancient-accent) !important;
background-color: rgba(var(--ancient-paper-light-rgb), 0.3) !important;
font-style: italic;
}
.dark .prose blockquote {
border-left-color: var(--ancient-accent-dark) !important;
background-color: rgba(var(--ancient-paper-dark-rgb), 0.3) !important;
}
.prose code {
background-color: rgba(var(--ancient-paper-light-rgb), 0.5) !important;
color: var(--ancient-black) !important;
padding: 0.2em 0.4em;
border-radius: 0.25em;
font-size: 0.875em;
}
.dark .prose code {
background-color: rgba(var(--ancient-paper-dark-rgb), 0.5) !important;
color: var(--ancient-white) !important;
}
.prose pre {
background-color: rgba(var(--ancient-paper-light-rgb), 0.8) !important;
border: 1px solid rgba(var(--ancient-accent-rgb), 0.2) !important;
}
.dark .prose pre {
background-color: rgba(var(--ancient-paper-dark-rgb), 0.8) !important;
border-color: rgba(var(--ancient-accent-dark-rgb), 0.2) !important;
}
.prose img {
border: 1px solid rgba(var(--ancient-accent-rgb), 0.2);
border-radius: 0.25rem;
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.05);
}
.dark .prose img {
border-color: rgba(var(--ancient-accent-dark-rgb), 0.2);
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.2);
}
.prose hr {
border-color: rgba(var(--ancient-accent-rgb), 0.2) !important;
}
.dark .prose hr {
border-color: rgba(var(--ancient-accent-dark-rgb), 0.2) !important;
}
</style>