- 后台全面引入 Naive UI 组件库,统一 UI 规范 - 前台 usePublicApi 切换到 API 调用(GET /api/content/[key]) - 前后台数据源统一(site_content 表) - 产品线统一管理(tour/camp/course 三套编辑器) - 产品数据归一化(itinerary/faq/pricing 格式统一) - 表单提交 API 改写入 submissions 表 - 新增 submissions 标记已读 API - site-content PUT 支持 upsert - 修复前台 bug(stories 路由冲突、占位符警告、selector breadcrumb) - 消除 PageHero 类型警告(useSEO reactive 修复) - 25 个前台页面全部 HTTP 200,展示效果不变 Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
192 行
3.8 KiB
Vue
192 行
3.8 KiB
Vue
<template>
|
|
<section
|
|
class="page-hero"
|
|
:class="{
|
|
'page-hero--compact': compact,
|
|
'page-hero--has-bg': backgroundImage,
|
|
}"
|
|
>
|
|
<!-- 背景图模式 -->
|
|
<div v-if="backgroundImage" class="page-hero-bg">
|
|
<img :src="backgroundImage" :alt="title" class="page-hero-bg-img" />
|
|
<div class="page-hero-overlay" />
|
|
</div>
|
|
|
|
<!-- 无背景图时的装饰 -->
|
|
<div v-else class="page-hero-decor">
|
|
<div class="decor-circle decor-circle--1" />
|
|
<div class="decor-circle decor-circle--2" />
|
|
<div class="decor-line" />
|
|
</div>
|
|
|
|
<div class="container page-hero-content">
|
|
<CommonBreadcrumbNav :items="breadcrumbs" />
|
|
<h1 class="page-hero-title">{{ title }}</h1>
|
|
<p v-if="subtitle" class="page-hero-subtitle">{{ subtitle }}</p>
|
|
</div>
|
|
<div class="page-hero-curve">
|
|
<svg viewBox="0 0 1440 56" fill="none" preserveAspectRatio="none" aria-hidden="true">
|
|
<path d="M0 56h1440V28C1200 0 240 0 0 28v28z" fill="currentColor" />
|
|
</svg>
|
|
</div>
|
|
</section>
|
|
</template>
|
|
|
|
<script setup>
|
|
defineProps({
|
|
title: { type: String, required: true },
|
|
subtitle: { type: String, default: '' },
|
|
compact: { type: Boolean, default: false },
|
|
breadcrumbs: { type: Array, default: () => [] },
|
|
backgroundImage: { type: String, default: '' },
|
|
})
|
|
</script>
|
|
|
|
<style lang="less" scoped>
|
|
.page-hero {
|
|
background: @gradient-cool;
|
|
padding: @space-2xl 0 @space-3xl;
|
|
position: relative;
|
|
overflow: hidden;
|
|
|
|
.respond-md({
|
|
padding: @space-3xl 0 @space-4xl;
|
|
});
|
|
|
|
&--compact {
|
|
padding: @space-xl 0 @space-2xl;
|
|
}
|
|
|
|
&--has-bg {
|
|
padding: @space-2xl 0 @space-3xl;
|
|
min-height: 220px;
|
|
|
|
.respond-md({
|
|
padding: @space-4xl 0 100px;
|
|
min-height: 360px;
|
|
});
|
|
|
|
.page-hero-title {
|
|
color: #fff;
|
|
text-shadow: 0 2px 8px rgba(0, 0, 0, 0.3);
|
|
}
|
|
|
|
.page-hero-subtitle {
|
|
color: rgba(255, 255, 255, 0.9);
|
|
}
|
|
|
|
// 背景图模式下面包屑使用白色
|
|
:deep(.breadcrumb-link),
|
|
:deep(.breadcrumb-sep),
|
|
:deep(.breadcrumb-current) {
|
|
color: rgba(255, 255, 255, 0.85);
|
|
}
|
|
|
|
:deep(.breadcrumb-link:hover) {
|
|
color: #fff;
|
|
}
|
|
}
|
|
}
|
|
|
|
// 背景图
|
|
.page-hero-bg {
|
|
position: absolute;
|
|
inset: 0;
|
|
z-index: 0;
|
|
}
|
|
|
|
.page-hero-bg-img {
|
|
width: 100%;
|
|
height: 100%;
|
|
object-fit: cover;
|
|
}
|
|
|
|
.page-hero-overlay {
|
|
position: absolute;
|
|
inset: 0;
|
|
background: linear-gradient(
|
|
to bottom,
|
|
rgba(27, 67, 50, 0.55) 0%,
|
|
rgba(27, 67, 50, 0.7) 100%
|
|
);
|
|
}
|
|
|
|
// 装饰元素(无背景图时)
|
|
.page-hero-decor {
|
|
position: absolute;
|
|
inset: 0;
|
|
pointer-events: none;
|
|
overflow: hidden;
|
|
}
|
|
|
|
.decor-circle {
|
|
position: absolute;
|
|
border-radius: 50%;
|
|
border: 1px solid rgba(45, 106, 79, 0.08);
|
|
|
|
&--1 {
|
|
width: 400px;
|
|
height: 400px;
|
|
top: -200px;
|
|
right: -100px;
|
|
background: radial-gradient(circle, rgba(45, 106, 79, 0.04) 0%, transparent 70%);
|
|
}
|
|
|
|
&--2 {
|
|
width: 200px;
|
|
height: 200px;
|
|
bottom: -60px;
|
|
left: 10%;
|
|
background: radial-gradient(circle, rgba(212, 136, 58, 0.05) 0%, transparent 70%);
|
|
}
|
|
}
|
|
|
|
.decor-line {
|
|
position: absolute;
|
|
top: 50%;
|
|
right: 5%;
|
|
width: 120px;
|
|
height: 1px;
|
|
background: linear-gradient(90deg, transparent, rgba(45, 106, 79, 0.15), transparent);
|
|
transform: rotate(-30deg);
|
|
}
|
|
|
|
// 内容
|
|
.page-hero-content {
|
|
position: relative;
|
|
z-index: 1;
|
|
}
|
|
|
|
.page-hero-title {
|
|
margin-top: @space-md;
|
|
color: @color-text-primary;
|
|
}
|
|
|
|
.page-hero-subtitle {
|
|
margin-top: @space-sm;
|
|
font-size: @font-size-md;
|
|
color: @color-text-secondary;
|
|
max-width: 600px;
|
|
line-height: @line-height-relaxed;
|
|
}
|
|
|
|
.page-hero-curve {
|
|
position: absolute;
|
|
bottom: -1px;
|
|
left: 0;
|
|
right: 0;
|
|
line-height: 0;
|
|
color: #FAFAF8;
|
|
z-index: 1;
|
|
|
|
svg {
|
|
width: 100%;
|
|
height: 36px;
|
|
|
|
.respond-md({
|
|
height: 56px;
|
|
});
|
|
}
|
|
}
|
|
</style>
|