根因:CMS后台编辑保存到site_content key='qualifications', 但前端页面从key='about'读取,导致改了后台前端不生效。 现在前端改为从qualifications读取,CMS编辑即时生效。 Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
363 行
9.4 KiB
Vue
363 行
9.4 KiB
Vue
<template>
|
||
<div class="page-qualifications">
|
||
<LayoutPageHero
|
||
:title="seo.h1 || '资质荣誉'"
|
||
subtitle="三重旅行社资质 · 1000万责任险 · 行业认证"
|
||
:breadcrumbs="[{ text: '资质荣誉' }]"
|
||
background-image="/images/seasons/summer-hero.jpg"
|
||
/>
|
||
|
||
<!-- TL;DR -->
|
||
<section class="page-tldr" aria-label="资质荣誉摘要">
|
||
<div class="container">
|
||
<div class="page-tldr-inner">
|
||
<p>呼籁旅行资质荣誉:持有三重旅行社经营许可证,购买1000万旅游责任险,荣获小红书年度成长型品牌等行业认证。所有资质均可在线验证。</p>
|
||
</div>
|
||
</div>
|
||
</section>
|
||
|
||
<!-- 服务保障 -->
|
||
<section v-if="about" class="section" aria-label="服务保障">
|
||
<div class="container">
|
||
<CommonSectionTitle title="服务保障" subtitle="三重旅行社资质 · 1000万责任险 · 正规电子合同 · 全程无购物" />
|
||
|
||
<!-- 保障要点 -->
|
||
<div class="guarantee-grid">
|
||
<div v-for="g in about.guarantees" :key="g.title" class="guarantee-card">
|
||
<h3 class="guarantee-card__title">{{ g.title }}</h3>
|
||
<p class="guarantee-card__detail">{{ g.detail }}</p>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- 许可证详情 -->
|
||
<h3 class="sub-heading">旅行社经营许可证</h3>
|
||
<div class="licenses-grid">
|
||
<div v-for="license in about.licenses" :key="license.licenseNo" class="license-card">
|
||
<div class="license-card__badge">旅游经营许可证</div>
|
||
<h4 class="license-card__holder">{{ license.holder }}</h4>
|
||
<div class="license-card__info">
|
||
<div class="license-row">
|
||
<span class="license-label">颁发机构</span>
|
||
<span class="license-value">{{ license.issuer }}</span>
|
||
</div>
|
||
<div class="license-row">
|
||
<span class="license-label">许可证号</span>
|
||
<span class="license-value license-value--mono">{{ license.licenseNo }}</span>
|
||
</div>
|
||
<div class="license-row">
|
||
<span class="license-label">状态</span>
|
||
<span class="license-value license-value--valid">{{ license.validPeriod }}</span>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- 旅游责任险 -->
|
||
<div class="insurance-block">
|
||
<div class="insurance-icon">🛡️</div>
|
||
<div class="insurance-body">
|
||
<h3 class="insurance-title">{{ about.insurance.title }}</h3>
|
||
<p class="insurance-desc">{{ about.insurance.description }}</p>
|
||
<div class="insurance-details">
|
||
<div class="insurance-detail">
|
||
<span class="insurance-detail__label">承保方</span>
|
||
<span class="insurance-detail__value">{{ about.insurance.insurer }}</span>
|
||
</div>
|
||
<div class="insurance-detail">
|
||
<span class="insurance-detail__label">覆盖范围</span>
|
||
<span class="insurance-detail__value">{{ about.insurance.policyScope }}</span>
|
||
</div>
|
||
<div class="insurance-detail">
|
||
<span class="insurance-detail__label">理赔支持</span>
|
||
<span class="insurance-detail__value">{{ about.insurance.claimContact }}</span>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</section>
|
||
|
||
<!-- 荣誉认证 -->
|
||
<section v-if="about" class="section section--green" aria-label="荣誉与认证">
|
||
<div class="container">
|
||
<CommonSectionTitle title="荣誉与认证" subtitle="行业机构和平台对呼籁服务质量的认可" />
|
||
<div class="awards-grid">
|
||
<div v-for="award in about.awards" :key="award.title" class="award-card">
|
||
<div class="award-card__year">{{ award.year }}</div>
|
||
<h3 class="award-card__title">{{ award.title }}</h3>
|
||
<p class="award-card__detail">{{ award.detail }}</p>
|
||
<span class="award-card__issuer">{{ award.issuer }}</span>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</section>
|
||
|
||
<!-- CTA -->
|
||
<CommonSectionCTA
|
||
title="想了解我们的产品?"
|
||
description="查看额吉的故乡V9系列和小蒙马夏令营"
|
||
:links="[
|
||
{ to: '/products', text: '查看旅行产品' },
|
||
{ to: '/contact', text: '联系定制师' },
|
||
]"
|
||
/>
|
||
</div>
|
||
</template>
|
||
|
||
<script setup>
|
||
import { useOrganizationSchema, useBreadcrumbSchema } from '~/composables/useJsonLd'
|
||
|
||
const { data: qualData } = await usePublicApi('qualifications')
|
||
const { data: brand } = await usePublicApi('brand')
|
||
const { data: contact } = await usePublicApi('contact')
|
||
|
||
// qualifications key 用 safetyGuarantees,前端模板用 guarantees,做一层适配
|
||
const about = computed(() => {
|
||
if (!qualData.value) return null
|
||
return {
|
||
...qualData.value,
|
||
guarantees: qualData.value.guarantees || qualData.value.safetyGuarantees,
|
||
}
|
||
})
|
||
|
||
const seo = useSEO('qualifications')
|
||
|
||
useBreadcrumbSchema([
|
||
{ text: '首页', to: '/' },
|
||
{ text: '资质荣誉' },
|
||
])
|
||
useOrganizationSchema(brand.value, contact.value)
|
||
</script>
|
||
|
||
<style lang="less" scoped>
|
||
// ===== 服务保障 =====
|
||
.sub-heading {
|
||
font-size: @font-size-lg;
|
||
font-weight: @font-weight-bold;
|
||
color: @color-text-primary;
|
||
margin: @space-2xl 0 @space-lg;
|
||
}
|
||
|
||
.guarantee-grid {
|
||
display: grid;
|
||
grid-template-columns: repeat(2, 1fr);
|
||
gap: @space-md;
|
||
|
||
.respond-lg({
|
||
grid-template-columns: repeat(4, 1fr);
|
||
});
|
||
}
|
||
|
||
.guarantee-card {
|
||
text-align: center;
|
||
padding: @space-lg;
|
||
background: @color-primary-bg;
|
||
border-radius: @border-radius-lg;
|
||
|
||
&__title {
|
||
font-size: @font-size-sm;
|
||
font-weight: @font-weight-bold;
|
||
color: @color-primary;
|
||
margin: 0 0 @space-xs;
|
||
}
|
||
|
||
&__detail {
|
||
font-size: @font-size-xs;
|
||
color: @color-text-secondary;
|
||
margin: 0;
|
||
line-height: @line-height-base;
|
||
}
|
||
}
|
||
|
||
.licenses-grid {
|
||
display: grid;
|
||
grid-template-columns: 1fr;
|
||
gap: @space-lg;
|
||
|
||
.respond-lg({
|
||
grid-template-columns: repeat(3, 1fr);
|
||
});
|
||
}
|
||
|
||
.license-card {
|
||
background: @color-bg-white;
|
||
border: 1px solid @color-border;
|
||
border-radius: @border-radius-lg;
|
||
padding: @space-xl;
|
||
box-shadow: @shadow-card;
|
||
|
||
&__badge {
|
||
display: inline-block;
|
||
padding: @space-xs @space-md;
|
||
background: @color-primary;
|
||
color: #fff;
|
||
font-size: @font-size-xs;
|
||
font-weight: @font-weight-medium;
|
||
border-radius: @border-radius-full;
|
||
margin-bottom: @space-md;
|
||
}
|
||
|
||
&__holder {
|
||
font-size: @font-size-base;
|
||
font-weight: @font-weight-bold;
|
||
color: @color-text-primary;
|
||
margin: 0 0 @space-lg;
|
||
line-height: @line-height-tight;
|
||
}
|
||
|
||
&__info {
|
||
display: flex;
|
||
flex-direction: column;
|
||
gap: @space-sm;
|
||
}
|
||
}
|
||
|
||
.license-row {
|
||
display: flex;
|
||
gap: @space-sm;
|
||
font-size: @font-size-sm;
|
||
}
|
||
|
||
.license-label {
|
||
color: @color-text-muted;
|
||
min-width: 56px;
|
||
flex-shrink: 0;
|
||
}
|
||
|
||
.license-value {
|
||
color: @color-text-secondary;
|
||
|
||
&--mono {
|
||
font-family: monospace;
|
||
font-size: @font-size-xs;
|
||
color: @color-text-muted;
|
||
}
|
||
|
||
&--valid {
|
||
color: @color-primary;
|
||
font-weight: @font-weight-medium;
|
||
}
|
||
}
|
||
|
||
// ===== 责任险 =====
|
||
.insurance-block {
|
||
display: flex;
|
||
gap: @space-xl;
|
||
align-items: flex-start;
|
||
background: @color-bg-white;
|
||
border: 2px solid @color-primary-lighter;
|
||
border-radius: @border-radius-lg;
|
||
padding: @space-2xl;
|
||
box-shadow: @shadow-card;
|
||
margin-top: @space-2xl;
|
||
|
||
@media (max-width: 768px) {
|
||
flex-direction: column;
|
||
gap: @space-lg;
|
||
}
|
||
}
|
||
|
||
.insurance-icon {
|
||
font-size: 48px;
|
||
flex-shrink: 0;
|
||
line-height: 1;
|
||
}
|
||
|
||
.insurance-body {
|
||
flex: 1;
|
||
}
|
||
|
||
.insurance-title {
|
||
font-size: @font-size-xl;
|
||
font-weight: @font-weight-bold;
|
||
color: @color-text-primary;
|
||
margin: 0 0 @space-sm;
|
||
}
|
||
|
||
.insurance-desc {
|
||
font-size: @font-size-base;
|
||
color: @color-text-secondary;
|
||
margin: 0 0 @space-lg;
|
||
line-height: @line-height-base;
|
||
}
|
||
|
||
.insurance-details {
|
||
display: flex;
|
||
flex-direction: column;
|
||
gap: @space-sm;
|
||
}
|
||
|
||
.insurance-detail {
|
||
display: flex;
|
||
gap: @space-md;
|
||
font-size: @font-size-sm;
|
||
|
||
&__label {
|
||
color: @color-text-muted;
|
||
min-width: 60px;
|
||
flex-shrink: 0;
|
||
}
|
||
|
||
&__value {
|
||
color: @color-text-secondary;
|
||
}
|
||
}
|
||
|
||
// ===== 荣誉认证 =====
|
||
.awards-grid {
|
||
display: grid;
|
||
grid-template-columns: 1fr;
|
||
gap: @space-lg;
|
||
|
||
.respond-lg({
|
||
grid-template-columns: repeat(3, 1fr);
|
||
});
|
||
}
|
||
|
||
.award-card {
|
||
background: @color-bg-white;
|
||
border: 1px solid @color-border;
|
||
border-radius: @border-radius-lg;
|
||
padding: @space-xl;
|
||
text-align: center;
|
||
box-shadow: @shadow-card;
|
||
transition: box-shadow @transition-base, transform @transition-base;
|
||
|
||
&:hover {
|
||
box-shadow: @shadow-card-hover;
|
||
transform: translateY(-3px);
|
||
}
|
||
|
||
&__year {
|
||
display: inline-block;
|
||
font-size: @font-size-2xl;
|
||
font-weight: @font-weight-bold;
|
||
color: @color-primary;
|
||
line-height: 1;
|
||
margin-bottom: @space-md;
|
||
}
|
||
|
||
&__title {
|
||
font-size: @font-size-base;
|
||
font-weight: @font-weight-bold;
|
||
color: @color-text-primary;
|
||
margin: 0 0 @space-sm;
|
||
line-height: @line-height-tight;
|
||
}
|
||
|
||
&__detail {
|
||
font-size: @font-size-sm;
|
||
color: @color-text-secondary;
|
||
margin: 0 0 @space-md;
|
||
}
|
||
|
||
&__issuer {
|
||
font-size: @font-size-xs;
|
||
color: @color-text-muted;
|
||
padding: @space-xs @space-md;
|
||
background: @color-bg-gray;
|
||
border-radius: @border-radius-full;
|
||
}
|
||
}
|
||
</style>
|