hulai-website/pages/pricing.vue
wx ac90205395 feat: 官网代码全量更新
覆盖最新版本代码,包含:
- 新增品牌百科、公司百科页面及CMS管理
- 新增微信引导组件(WechatCTA)
- 新增品牌/公司图片资源
- 全站组件/页面/数据/样式更新

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-16 13:21:11 +08:00

416 行
10 KiB
Vue

此文件含有模棱两可的 Unicode 字符

此文件含有可能会与其他字符混淆的 Unicode 字符。 如果您是想特意这样的,可以安全地忽略该警告。 使用 Escape 按钮显示他们。

<template>
<div class="page-pricing">
<LayoutPageHero
:title="seo.h1"
subtitle="不藏价格,不绕弯子"
:breadcrumbs="[{ text: '价格参考' }]"
background-image="/images/team/hero-grassland.jpg"
/>
<!-- TL;DR -->
<section class="page-tldr" aria-label="价格参考摘要">
<div class="container">
<div class="page-tldr-inner">
<p>呼伦贝尔亲子游价格参考根据出行天数和人数每人每天800-1500元区间全程无隐形消费含正规电子合同和1000万旅游责任险报价后2小时内回复</p>
</div>
</div>
</section>
<!-- 简介 -->
<section v-if="pricing" class="section section-intro reveal">
<div class="container">
<div class="intro-box">
<p class="intro-text">{{ pricing.intro }}</p>
<div class="trust-badges">
<span class="badge">✓ 全程无隐形消费</span>
<span class="badge">✓ 正规电子合同</span>
<span class="badge">✓ 1000万旅游责任险</span>
<span class="badge">✓ 报价后2小时回复</span>
</div>
</div>
</div>
</section>
<!-- 产品价格卡片 -->
<section class="section reveal">
<div class="container">
<CommonSectionTitle
title="产品线价格参考"
subtitle="6条定制游线路 + 1个亲子游学营 + 秋季产品"
/>
<div class="pricing-grid">
<div
v-for="product in pricing.products"
:key="product.id"
class="pricing-card"
>
<div class="card-header">
<span class="card-tag">{{ product.tag }}</span>
<h3 class="card-name">{{ product.name }}</h3>
<p class="card-audience">适合:{{ product.audience }}</p>
</div>
<div class="card-body">
<div class="card-duration" v-if="product.days > 0">
<span class="duration-text">{{ product.days }}天{{ product.nights }}晚</span>
</div>
<ul class="card-highlights">
<li v-for="h in product.highlights" :key="h">{{ h }}</li>
</ul>
</div>
<div class="card-footer">
<div class="price-label">{{ product.priceLabel }}</div>
<p class="price-note">{{ product.priceNote }}</p>
<NuxtLink :to="product.url" class="card-link">查看产品详情 →</NuxtLink>
</div>
</div>
</div>
</div>
</section>
<!-- 费用包含/不含 -->
<section v-if="pricing" class="section section-inclusions reveal">
<div class="container">
<CommonSectionTitle
title="费用说明"
subtitle="所有产品遵循同一套费用标准"
/>
<div class="inclusions-grid">
<div class="inclusion-col included">
<h3 class="inclusion-title">
<span class="inclusion-icon">✓</span> 费用包含
</h3>
<ul class="inclusion-list">
<li v-for="item in pricing.included" :key="item">{{ item }}</li>
</ul>
</div>
<div class="inclusion-col excluded">
<h3 class="inclusion-title">
<span class="inclusion-icon">✗</span> 费用不含
</h3>
<ul class="inclusion-list">
<li v-for="item in pricing.excluded" :key="item">{{ item }}</li>
</ul>
</div>
</div>
</div>
</section>
<!-- 价格透明原则 -->
<section v-if="pricing?.philosophy" class="section section-philosophy reveal">
<div class="container">
<div class="philosophy-box">
<h2 class="philosophy-title">{{ pricing.philosophy.title }}</h2>
<p class="philosophy-content">{{ pricing.philosophy.content }}</p>
<p class="philosophy-promise">{{ pricing.philosophy.promise }}</p>
</div>
</div>
</section>
<!-- CTA -->
<CommonSectionCTA
v-if="pricing?.cta"
:title="pricing.cta.title"
:description="pricing.cta.description"
:links="[{ to: pricing.cta.to, text: pricing.cta.button }]"
/>
<CommonWechatCTA
title="想了解具体报价?扫码问定制师"
description="每个家庭的行程不同,精确报价需要根据出行时间、人数和偏好来定。扫码添加定制师微信,2小时内给你方案和报价。"
/>
</div>
</template>
<script setup>
import { useOrganizationSchema, useBreadcrumbSchema, usePricingSchema } from '~/composables/useJsonLd'
const { data: pricing } = await usePublicApi('pricing')
const { data: brand } = await usePublicApi('brand')
const { data: contact } = await usePublicApi('contact')
const seo = useSEO('pricing')
useScrollReveal()
useOrganizationSchema(brand.value, contact.value)
usePricingSchema(pricing.value?.products)
useBreadcrumbSchema([
{ text: '首页', to: '/' },
{ text: '价格参考' },
])
</script>
<style lang="less" scoped>
.intro-box {
max-width: 800px;
margin: 0 auto;
text-align: center;
}
.intro-text {
font-size: @font-size-md;
color: @color-text-secondary;
line-height: @line-height-loose;
margin-bottom: @space-xl;
}
.trust-badges {
display: flex;
flex-wrap: wrap;
gap: @space-md;
justify-content: center;
}
.badge {
display: inline-block;
padding: @space-sm @space-lg;
background: @color-primary-bg;
color: @color-primary;
border-radius: @border-radius-full;
font-size: @font-size-sm;
font-weight: @font-weight-medium;
border: 1px solid @color-primary-lighter;
}
.pricing-grid {
display: grid;
grid-template-columns: repeat(3, 1fr);
gap: @space-xl;
margin-top: @space-2xl;
@media (max-width: @breakpoint-lg) {
grid-template-columns: repeat(2, 1fr);
}
@media (max-width: @breakpoint-md) {
grid-template-columns: 1fr;
}
}
.pricing-card {
display: flex;
flex-direction: column;
border: 1px solid @color-border;
border-radius: @border-radius-lg;
overflow: hidden;
background: @color-bg-white;
transition: box-shadow @transition-base, transform @transition-base;
&:hover {
box-shadow: @shadow-md;
transform: translateY(-2px);
}
}
.card-header {
padding: @space-xl @space-xl @space-lg;
background: @color-bg-gray;
border-bottom: 1px solid @color-border;
}
.card-tag {
display: inline-block;
padding: 2px @space-sm;
background: @color-primary;
color: @color-bg-white;
border-radius: @border-radius-sm;
font-size: @font-size-xs;
font-weight: @font-weight-medium;
margin-bottom: @space-sm;
}
.card-name {
font-size: @font-size-md;
font-weight: @font-weight-bold;
color: @color-text-primary;
margin-bottom: @space-sm;
line-height: @line-height-tight;
}
.card-audience {
font-size: @font-size-sm;
color: @color-text-muted;
margin: 0;
}
.card-body {
flex: 1;
padding: @space-lg @space-xl;
}
.card-duration {
margin-bottom: @space-md;
}
.duration-text {
font-size: @font-size-sm;
color: @color-accent;
font-weight: @font-weight-medium;
background: #FFF8F0;
padding: 2px @space-sm;
border-radius: @border-radius-sm;
}
.card-highlights {
list-style: none;
padding: 0;
margin: 0;
display: flex;
flex-direction: column;
gap: @space-sm;
li {
font-size: @font-size-sm;
color: @color-text-secondary;
padding-left: @space-md;
position: relative;
line-height: @line-height-base;
&::before {
content: '·';
position: absolute;
left: 0;
color: @color-primary;
font-weight: @font-weight-bold;
}
}
}
.card-footer {
padding: @space-lg @space-xl @space-xl;
border-top: 1px solid @color-border;
}
.price-label {
font-size: @font-size-xl;
font-weight: @font-weight-bold;
color: @color-primary;
margin-bottom: @space-sm;
}
.price-note {
font-size: @font-size-xs;
color: @color-text-muted;
line-height: @line-height-base;
margin-bottom: @space-md;
}
.card-link {
font-size: @font-size-sm;
color: @color-primary;
text-decoration: none;
font-weight: @font-weight-medium;
&:hover {
text-decoration: underline;
}
}
.section-inclusions {
background: @color-bg-gray;
}
.inclusions-grid {
display: grid;
grid-template-columns: 1fr 1fr;
gap: @space-2xl;
margin-top: @space-2xl;
@media (max-width: @breakpoint-md) {
grid-template-columns: 1fr;
gap: @space-xl;
}
}
.inclusion-col {
padding: @space-2xl;
border-radius: @border-radius-lg;
&.included {
background: @color-primary-bg;
border: 1px solid @color-primary-lighter;
}
&.excluded {
background: @color-bg-white;
border: 1px solid @color-border;
}
}
.inclusion-title {
font-size: @font-size-lg;
font-weight: @font-weight-bold;
color: @color-text-primary;
margin-bottom: @space-lg;
display: flex;
align-items: center;
gap: @space-sm;
}
.inclusion-icon {
.included & {
color: @color-primary;
}
.excluded & {
color: @color-text-muted;
}
}
.inclusion-list {
list-style: none;
padding: 0;
margin: 0;
display: flex;
flex-direction: column;
gap: @space-md;
li {
font-size: @font-size-base;
color: @color-text-secondary;
line-height: @line-height-base;
padding-left: @space-md;
position: relative;
&::before {
content: '—';
position: absolute;
left: 0;
color: @color-text-muted;
}
}
}
.section-philosophy {
background: @color-bg-warm;
}
.philosophy-box {
max-width: 760px;
margin: 0 auto;
}
.philosophy-title {
font-size: @font-size-2xl;
font-weight: @font-weight-bold;
color: @color-text-primary;
margin-bottom: @space-lg;
}
.philosophy-content {
font-size: @font-size-md;
color: @color-text-secondary;
line-height: @line-height-loose;
margin-bottom: @space-lg;
}
.philosophy-promise {
font-size: @font-size-base;
color: @color-primary;
font-weight: @font-weight-medium;
line-height: @line-height-base;
padding: @space-lg;
background: @color-primary-bg;
border-radius: @border-radius-md;
border-left: 3px solid @color-primary;
margin: 0;
}
</style>