sync: 同步最新呼籁官网代码到仓库
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
这个提交包含在:
当前提交
a25f3a77ce
1
.claude/launch.json
普通文件
1
.claude/launch.json
普通文件
@ -0,0 +1 @@
|
|||||||
|
{"version":"0.0.1","configurations":[{"name":"hulai-website","runtimeExecutable":"npm","runtimeArgs":["run","dev"],"port":3000}]}
|
||||||
117
.claude/settings.local.json
普通文件
117
.claude/settings.local.json
普通文件
@ -0,0 +1,117 @@
|
|||||||
|
{
|
||||||
|
"permissions": {
|
||||||
|
"defaultMode": "bypassPermissions",
|
||||||
|
"allow": [
|
||||||
|
"Bash(npx nuxi:*)",
|
||||||
|
"Bash(NITRO_PRESET=static npx nuxi generate)",
|
||||||
|
"Bash(npm install:*)",
|
||||||
|
"Bash(pnpm approve-builds:*)",
|
||||||
|
"Bash(pnpm config:*)",
|
||||||
|
"Bash(python3 -c \":*)",
|
||||||
|
"Bash(npx esbuild:*)",
|
||||||
|
"Bash(kill %1)",
|
||||||
|
"Bash(pnpm list:*)",
|
||||||
|
"Bash(2)",
|
||||||
|
"mcp__Claude_Preview__preview_start",
|
||||||
|
"Skill(update-config)",
|
||||||
|
"Skill(update-config:*)",
|
||||||
|
"WebSearch",
|
||||||
|
"Bash(python3 -m venv venv)",
|
||||||
|
"Bash(source venv/bin/activate)",
|
||||||
|
"Bash(pip install:*)",
|
||||||
|
"Bash(mysql -u root -p123456 -e \"SELECT 1\")",
|
||||||
|
"Bash(brew list:*)",
|
||||||
|
"Bash(/usr/local/mysql/bin/mysql --version)",
|
||||||
|
"Bash(/opt/homebrew/bin/mysql --version)",
|
||||||
|
"Bash(brew install:*)",
|
||||||
|
"Bash(brew services:*)",
|
||||||
|
"Bash(/opt/homebrew/bin/mysql -u root -e \"SELECT 1 AS test\")",
|
||||||
|
"Bash(/opt/homebrew/bin/mysql -u root -e \"CREATE DATABASE IF NOT EXISTS hulai_admin CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci\")",
|
||||||
|
"Bash(python -m scripts.create_admin_user)",
|
||||||
|
"Bash(python -m scripts.migrate_json_to_db)",
|
||||||
|
"Bash(pkill -f \"uvicorn app.main\")",
|
||||||
|
"Bash(curl -s -X POST http://localhost:8000/api/auth/login -H \"Content-Type: application/json\" -d '{\"\"username\"\":\"\"admin\"\",\"\"password\"\":\"\"admin123\"\"}')",
|
||||||
|
"Bash(ls -la /Users/liutao/Desktop/hulai-website/public/images/*.png)",
|
||||||
|
"Bash(ls -la /Users/liutao/Desktop/hulai-website/public/images/*.jpg)",
|
||||||
|
"Bash(xargs ls:*)",
|
||||||
|
"Bash(find /Users/liutao/Desktop/hulai-admin-web/src/views -type f -name *.vue)",
|
||||||
|
"Bash(find /Users/liutao/Desktop/hulai-website/app/pages -type f -name *.vue)",
|
||||||
|
"Bash(grep -n \"useSEO\" /Users/liutao/Desktop/hulai-website/pages/*.vue)",
|
||||||
|
"Bash(grep -n \"useJsonLd\" /Users/liutao/Desktop/hulai-website/pages/*.vue)",
|
||||||
|
"Bash(grep -r \"mascot\\\\|吉祥物\" /Users/liutao/Desktop/hulai-admin-web/src --include=*.vue --include=*.js)",
|
||||||
|
"Read(//Users/liutao/Library/Application Support/Claude/local-agent-mode-sessions/skills-plugin/835ce9e1-3c5b-48dd-a4ce-3aa6de03ff1a/b5086808-e3f6-4da5-89f5-c6389c0bdcd7/skills/docx/**)",
|
||||||
|
"Bash(pandoc \"/Users/liutao/Desktop/五天四晚 森林版.docx\" -o /tmp/forest_5d4n.md)",
|
||||||
|
"Bash(python scripts/office/unpack.py \"/Users/liutao/Desktop/五天四晚 森林版.docx\" /tmp/forest_docx_unpacked/)",
|
||||||
|
"Bash(python3 scripts/office/unpack.py \"/Users/liutao/Desktop/五天四晚 森林版.docx\" /tmp/forest_docx_unpacked/)",
|
||||||
|
"Bash(python3 -c \"from PIL import Image; print\\(''Pillow available''\\)\")",
|
||||||
|
"Bash(python3:*)",
|
||||||
|
"Bash(dest=\"/Users/liutao/Desktop/呼籁智库/02_产品资料/旅行产品/额吉的故乡V9/额吉的故乡V9·5天4晚 森林版/images/forest-days\")",
|
||||||
|
"Bash(cp \"/Users/liutao/Desktop/5 天 4 晚森林版/第三天_副本/2.jpg\" \"$dest/d3-new-1.jpg\")",
|
||||||
|
"Bash(cp \"/Users/liutao/Desktop/5 天 4 晚森林版/第三天_副本/4.jpg\" \"$dest/d3-new-2.jpg\")",
|
||||||
|
"Bash(cp \"/Users/liutao/Desktop/5 天 4 晚森林版/第三天_副本/6.jpg\" \"$dest/d3-new-3.jpg\")",
|
||||||
|
"Bash(cp \"/Users/liutao/Desktop/5 天 4 晚森林版/第三天_副本/9be57a64c8a9f614a2961916f2e828d1_origin\\(1\\).jpg\" \"$dest/d3-new-4.jpg\")",
|
||||||
|
"Bash(chmod +x \"/Users/liutao/Desktop/呼籁智库/09_部署工具包/智库工具箱.sh\")",
|
||||||
|
"Bash(chmod +x \"/Users/liutao/Desktop/呼籁智库/09_部署工具包/启动工作台.command\")",
|
||||||
|
"Bash(bash 智库工具箱.sh)",
|
||||||
|
"Bash(chmod +x \"/Users/liutao/Desktop/呼籁智库/09_部署工具包/每日晨报.sh\")",
|
||||||
|
"Bash(chmod +x \"/Users/liutao/Desktop/呼籁智库/09_部署工具包/每日晨报.command\")",
|
||||||
|
"Bash(bash \"/Users/liutao/Desktop/呼籁智库/09_部署工具包/每日晨报.sh\")",
|
||||||
|
"Bash(done)",
|
||||||
|
"Bash(find /Users/liutao/Desktop/呼籁智库 -name *小红书* -o -name *笔记* -o -name *种草* -o -name *草原笔记*)",
|
||||||
|
"Bash(find /Users/liutao/Desktop/呼籁智库/04_实战产出 -name *.md -newer /Users/liutao/Desktop/呼籁智库/04_实战产出/2026-03-10_首战夜班)",
|
||||||
|
"Bash(sort -t/ -k8)",
|
||||||
|
"Bash(pkill -f \"工作台服务\")",
|
||||||
|
"Bash(find /Users/liutao/Desktop/hulai-website/.nuxt -name *route* -o -name *page*)",
|
||||||
|
"Bash(wc -l /Users/liutao/Desktop/hulai-website/data/*.json)",
|
||||||
|
"Bash(node -e \"JSON.parse\\(require\\(''fs''\\).readFileSync\\(''data/autumn-products.json'',''utf8''\\)\\); console.log\\(''JSON is valid''\\)\")",
|
||||||
|
"Bash(sips -g pixelWidth -g pixelHeight /Users/liutao/Desktop/hulai-website/public/images/seasons/summer-hero.jpg)",
|
||||||
|
"Bash(sips -g pixelWidth -g pixelHeight \"/Users/liutao/Desktop/呼籁智库/02_产品资料/旅行产品/额吉的故乡V9/额吉的故乡-6天5晚标准版/images/generated-1772790409231.png\")",
|
||||||
|
"Bash(mysql -u root -e \"SELECT 1\")",
|
||||||
|
"Read(//Library/Developer/CommandLineTools/Library/Frameworks/Python3.framework/Versions/3.9/bin/**)",
|
||||||
|
"Bash(find /Users/liutao/Desktop/hulai-admin-api -name python* -path */bin/*)",
|
||||||
|
"Bash(./venv/bin/python -m scripts.migrate_json_to_db)",
|
||||||
|
"Bash(mysql -u root hulai_admin -e \"SELECT COUNT\\(*\\) as cnt FROM seasonal_product_versions; SELECT COUNT\\(*\\) as cnt FROM seasonal_product_highlights; SELECT COUNT\\(*\\) as cnt FROM winter_camp_itinerary; SELECT COUNT\\(*\\) as cnt FROM destination_dimensions;\")",
|
||||||
|
"Bash(mysql -u root hulai_admin -e \"SELECT season, COUNT\\(*\\) FROM seasonal_product_versions GROUP BY season;\")",
|
||||||
|
"Bash(curl -s http://localhost:8000/openapi.json)",
|
||||||
|
"Bash(./venv/bin/python -c \":*)",
|
||||||
|
"Bash(__NEW_LINE_0e947b95cc8360a8__ echo:*)",
|
||||||
|
"Bash(pandoc \"/Users/liutao/Desktop/额吉的故乡V9 修改内容/统一修改/额吉的故乡V9修改 统一内容.docx\" -o /tmp/tongyi_content.md)",
|
||||||
|
"Read(//tmp/**)",
|
||||||
|
"Bash(find /Users/liutao/Desktop/hulai-website/components -name \"*orm\\\\|Form\\\\|Input\\\\|Form\" -type f)",
|
||||||
|
"Bash(node -e \"const d = require\\(''./data/blog.json''\\); console.log\\(''Articles:'', d.articles.length\\); d.articles.forEach\\(a => console.log\\('' -'', a.id, ''|'', a.category\\)\\)\")",
|
||||||
|
"Bash(find /Users/liutao/Desktop/hulai-website -name sitemap* -o -name *schema*)",
|
||||||
|
"Bash(node -e \":*)",
|
||||||
|
"Bash(grep -l useScrollReveal /Users/liutao/Desktop/hulai-website/pages/*.vue /Users/liutao/Desktop/hulai-website/pages/**/*.vue)",
|
||||||
|
"mcp__Claude_in_Chrome__tabs_context_mcp",
|
||||||
|
"Bash(npm run:*)",
|
||||||
|
"Bash(npx nuxt:*)",
|
||||||
|
"Bash(echo \"BUILD_EXIT_CODE: $?\")",
|
||||||
|
"Bash(cp \"/Users/liutao/Desktop/额吉的故乡V9 修改内容/8.2小蒙马白桦林休息地.jpg\" \"/Users/liutao/Desktop/呼籁智库/02_产品资料/旅行产品/额吉的故乡V9/额吉的故乡-7天6晚标准版/images/亲子版/第三天/白桦林营地.jpg\")",
|
||||||
|
"Bash(cp \"/Users/liutao/Desktop/额吉的故乡V9 修改内容/风车公路-1.jpg\" \"/Users/liutao/Desktop/呼籁智库/02_产品资料/旅行产品/额吉的故乡V9/额吉的故乡-7天6晚标准版/images/亲子版/第七天/风车公路.jpg\")",
|
||||||
|
"Bash(find /Users/liutao/Desktop/hulai-website -maxdepth 2 -not -path */node_modules/* -not -path */.nuxt/* -not -path */.output/* -type d)",
|
||||||
|
"Bash(grep -n \"useJsonLd\\\\|TouristAttraction\\\\|schema\" /Users/liutao/Desktop/hulai-website/pages/destinations/[id].vue)",
|
||||||
|
"Bash(pandoc \"/Users/liutao/Desktop/额吉的故乡V9 修改内容/5天4晚 /5 天 4 晚草原版与森林版修改.docx\" -o /tmp/5d4n_changes.md)",
|
||||||
|
"Bash(python3 -c \"import zipfile; z=zipfile.ZipFile\\(''/Users/liutao/Desktop/额吉的故乡V9 修改内容/5天4晚 /5 天 4 晚草原版与森林版修改.docx''\\); import xml.etree.ElementTree as ET; tree=ET.parse\\(z.open\\(''word/document.xml''\\)\\); root=tree.getroot\\(\\); ns={''w'':''http://schemas.openxmlformats.org/wordprocessingml/2006/main''}; [print\\(''''.join\\(t.text or '''' for t in p.findall\\(''.//w:t'',ns\\)\\)\\) for p in root.findall\\(''.//w:p'',ns\\)]\")",
|
||||||
|
"Bash(find \"/Users/liutao/Desktop/额吉的故乡V9 修改内容\" -type f \\\\\\( -name \"*.jpg\" -o -name \"*.jpeg\" -o -name \"*.png\" \\\\\\) -exec ls -lt {} +)",
|
||||||
|
"Bash(find /Users/liutao/Downloads /Users/liutao/Desktop -maxdepth 4 -type f \\\\\\(-name *.jpg -o -name *.jpeg -o -name *.png \\\\\\) -newer '/Users/liutao/Desktop/额吉的故乡V9 修改内容/cf01c4cd7b1d74c86715b5a8f88e210c_compress.jpeg')",
|
||||||
|
"Bash(ls \"/Users/liutao/Desktop/呼籁智库/02_产品资料/旅行产品/额吉的故乡V9/额吉的故乡-6天5晚标准版/\"*.pen)",
|
||||||
|
"Bash(pandoc \"/Users/liutao/Desktop/额吉的故乡V9 修改内容/统一修改/额吉的故乡V9修改 统一内容.docx\" -o /tmp/unified_changes.md)",
|
||||||
|
"Bash(find /Users/liutao/Desktop -name *室韦* -o -name *蒙兀*)",
|
||||||
|
"Bash(ls \"/Users/liutao/Desktop/额吉的故乡V9 修改内容/\"*.jpg \"/Users/liutao/Desktop/额吉的故乡V9 修改内容/\"*.jpeg \"/Users/liutao/Desktop/额吉的故乡V9 修改内容/\"*.png \"/Users/liutao/Desktop/额吉的故乡V9 修改内容/\"*.JPG)",
|
||||||
|
"Bash(curl -s -o /dev/null -w \"%{http_code}\" \"http://localhost:3000/\")",
|
||||||
|
"Bash(grep -r \"tldr\\\\|TldrBlock\\\\|PageTldr\\\\|page-tldr\" /Users/liutao/Desktop/hulai-website/components/ --include=*.vue -l)",
|
||||||
|
"Bash(head -5 grep -r \"tldr\\\\|TldrBlock\\\\|PageTldr\\\\|page-tldr\" /Users/liutao/Desktop/hulai-website/pages/ --include=*.vue -l)",
|
||||||
|
"Bash(head -20 grep -n \"page-tldr\\\\|page-hero\\\\|<section\\\\|</section>\" /Users/liutao/Desktop/hulai-website/pages/stories/index.vue)",
|
||||||
|
"Bash(find /Users/liutao/Desktop/hulai-website -not -path */node_modules/* -not -path */.output/* -not -path */.nuxt/* -type f)",
|
||||||
|
"Bash(head -20 grep -n \"page-tldr\\\\|page-hero\\\\|<section\\\\|</section>\" /Users/liutao/Desktop/hulai-website/pages/winter-camp.vue)",
|
||||||
|
"Bash(grep -n \"page-tldr\\\\|page-hero\\\\|<section\\\\|</section>\" /Users/liutao/Desktop/hulai-website/pages/products/[id].vue)",
|
||||||
|
"Bash(head -20 grep -n \"page-tldr\\\\|page-hero\\\\|<section\\\\|</section>\" /Users/liutao/Desktop/hulai-website/pages/products/autumn.vue)",
|
||||||
|
"Bash(head -15 grep -n \"page-tldr\\\\|page-hero\\\\|<section\\\\|</section>\" /Users/liutao/Desktop/hulai-website/pages/products/winter.vue)",
|
||||||
|
"Bash(grep -n \"page-tldr\\\\|page-hero\\\\|<section\\\\|</section>\" /Users/liutao/Desktop/hulai-website/pages/blog/[id].vue)",
|
||||||
|
"Bash(head -20 grep -n \"page-tldr\\\\|page-hero\\\\|<section\\\\|</section>\" /Users/liutao/Desktop/hulai-website/pages/destinations/[id].vue)",
|
||||||
|
"Bash(head -10 grep -n \"useJsonLd\\\\|useOrganizationSchema\\\\|useBreadcrumb\\\\|useWebPage\\\\|useFAQPage\" /Users/liutao/Desktop/hulai-website/pages/contact.vue)",
|
||||||
|
"Bash(curl -s -o /dev/null -w \"%{http_code}\" http://localhost:3000/selector)",
|
||||||
|
"Bash(curl -s -o /dev/null -w \"%{http_code}\" http://localhost:3000/)"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
8
.env.example
普通文件
8
.env.example
普通文件
@ -0,0 +1,8 @@
|
|||||||
|
# 企业微信群机器人 Webhook Key(可选)
|
||||||
|
# 配置后,每次表单提交会实时推送到企业微信群
|
||||||
|
# 在企业微信群 → 群设置 → 群机器人 → 添加机器人 → 复制 Webhook 地址中的 key 参数
|
||||||
|
WECOM_WEBHOOK_KEY=
|
||||||
|
|
||||||
|
# 示例(key 是 URL 中 ?key= 后面的部分):
|
||||||
|
# Webhook 完整地址:https://qyapi.weixin.qq.com/cgi-bin/webhook/send?key=xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
|
||||||
|
# WECOM_WEBHOOK_KEY=xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
|
||||||
28
.gitignore
vendored
普通文件
28
.gitignore
vendored
普通文件
@ -0,0 +1,28 @@
|
|||||||
|
# Dependencies
|
||||||
|
node_modules/
|
||||||
|
|
||||||
|
# Nuxt build
|
||||||
|
.nuxt/
|
||||||
|
.output/
|
||||||
|
dist/
|
||||||
|
|
||||||
|
# Environment
|
||||||
|
.env
|
||||||
|
.env.*
|
||||||
|
!.env.example
|
||||||
|
|
||||||
|
# IDE
|
||||||
|
.vscode/
|
||||||
|
.idea/
|
||||||
|
*.swp
|
||||||
|
*.swo
|
||||||
|
*~
|
||||||
|
.DS_Store
|
||||||
|
|
||||||
|
# Logs
|
||||||
|
*.log
|
||||||
|
npm-debug.log*
|
||||||
|
|
||||||
|
# Lock files (keep one)
|
||||||
|
# package-lock.json
|
||||||
|
# pnpm-lock.yaml
|
||||||
597
CMS-INTEGRATION.md
普通文件
597
CMS-INTEGRATION.md
普通文件
@ -0,0 +1,597 @@
|
|||||||
|
# 呼籁旅行官网 — 后台对接方案(CMS Integration)
|
||||||
|
|
||||||
|
> 本文档分析官网所有内容模块,标注哪些需要「写活」(后台可增删改查),哪些是固定结构不需要动态化,以及推荐的数据库设计和对接方式。
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 一、内容动态化分级
|
||||||
|
|
||||||
|
### 第一优先级:高频更新(运营同学日常操作)
|
||||||
|
|
||||||
|
| 模块 | 当前文件 | 操作类型 | 更新频率 | 说明 |
|
||||||
|
|------|---------|---------|---------|------|
|
||||||
|
| **客户评价** | `reviews.json` | 增、改、删 | 每周 | 每次收到好评都要加,是最高频的更新 |
|
||||||
|
| **FAQ问答** | `faq.json` | 增、改、删 | 每月 | 客户常问的问题会变化,需要随时补充和调整 |
|
||||||
|
| **联系方式** | `contact.json` | 改 | 偶尔 | 微信号、电话、邮箱可能变更 |
|
||||||
|
| **SEO信息** | `seo.json` | 改 | 偶尔 | 优化标题和描述以提升搜索排名 |
|
||||||
|
|
||||||
|
### 第二优先级:季节性更新(产品经理/罗盘操作)
|
||||||
|
|
||||||
|
| 模块 | 当前文件 | 操作类型 | 更新频率 | 说明 |
|
||||||
|
|------|---------|---------|---------|------|
|
||||||
|
| **产品版本** | `products.json → versions` | 增、改、删 | 每季 | 产品迭代到V10、新增冬季版等 |
|
||||||
|
| **小蒙马夏令营** | `products.json → summerCamp` | 改 | 每年 | 年龄、活动、定位调整 |
|
||||||
|
| **选择指南** | `products.json → selectionGuide` | 改 | 每季 | 新产品上线后需要更新推荐逻辑 |
|
||||||
|
| **定价说明** | `products.json → pricingPhilosophy` | 改 | 偶尔 | 价格策略调整时 |
|
||||||
|
| **产品叙事** | `products.json → narrative` | 改 | 偶尔 | 品牌定位调整时 |
|
||||||
|
|
||||||
|
### 第三优先级:低频变更(品牌层面)
|
||||||
|
|
||||||
|
| 模块 | 当前文件 | 操作类型 | 更新频率 | 说明 |
|
||||||
|
|------|---------|---------|---------|------|
|
||||||
|
| **品牌信息** | `brand.json` | 改 | 极少 | slogan、信任数据、差异化卖点 |
|
||||||
|
| **关于我们** | `about.json` | 改 | 极少 | 品牌故事、子公司、资质、团队、文化 |
|
||||||
|
| **导航** | `navigation.json` | 改 | 极少 | 新增/调整导航页面 |
|
||||||
|
|
||||||
|
### 不需要动态化(代码层面)
|
||||||
|
|
||||||
|
| 项目 | 说明 |
|
||||||
|
|------|------|
|
||||||
|
| 页面结构/布局 | Vue组件,需开发介入 |
|
||||||
|
| 样式/配色 | Less变量,需开发介入 |
|
||||||
|
| JSON-LD结构化数据 | 自动从内容数据生成,无需单独管理 |
|
||||||
|
| sitemap.xml | 只有页面增减时才需要改 |
|
||||||
|
| robots.txt | 基本不变 |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 二、每个JSON文件的字段级分析
|
||||||
|
|
||||||
|
### 1. reviews.json(评价管理 — 最高频)
|
||||||
|
|
||||||
|
```
|
||||||
|
后台需要的功能:
|
||||||
|
✅ 新增评价(上传截图 + 填写文字)
|
||||||
|
✅ 编辑评价
|
||||||
|
✅ 删除评价
|
||||||
|
✅ 调整排序
|
||||||
|
✅ 修改汇总数据(总数、好评率、关键词)
|
||||||
|
✅ 管理筛选标签(场景、关心点)
|
||||||
|
|
||||||
|
字段说明:
|
||||||
|
summary:
|
||||||
|
- totalCount: number → 后台可改(或自动计算)
|
||||||
|
- approvalRate: string → 后台可改
|
||||||
|
- keywords: string[] → 后台可增删
|
||||||
|
|
||||||
|
items[]:
|
||||||
|
- id: number → 自动生成
|
||||||
|
- nickname: string → 后台填写
|
||||||
|
- travelDate: string → 后台填写(如"2025年7月")
|
||||||
|
- productVersion: string → 后台选择(关联产品列表)
|
||||||
|
- screenshot: string → 后台上传图片,存储路径
|
||||||
|
- content: string → 后台填写(与截图内容一致,供AI抓取)
|
||||||
|
- scenes: string[] → 后台多选标签(带小孩/家庭游/情侣/朋友/带老人...)
|
||||||
|
- concerns: string[] → 后台多选标签(领队服务/行程安排/拍照超美/司机服务...)
|
||||||
|
```
|
||||||
|
|
||||||
|
### 2. faq.json(问答管理 — 高频)
|
||||||
|
|
||||||
|
```
|
||||||
|
后台需要的功能:
|
||||||
|
✅ 新增分类
|
||||||
|
✅ 在分类下新增/编辑/删除问答
|
||||||
|
✅ 调整分类排序和问答排序
|
||||||
|
✅ 管理相关链接
|
||||||
|
|
||||||
|
字段说明:
|
||||||
|
categories[]:
|
||||||
|
- id: string → 自动生成
|
||||||
|
- name: string → 后台填写(如"产品类")
|
||||||
|
- questions[]:
|
||||||
|
- id: string → 自动生成
|
||||||
|
- question: string → 后台填写
|
||||||
|
- answer: string → 后台填写(支持长文本)
|
||||||
|
- relatedLinks[]: → 后台配置
|
||||||
|
- text: string → 链接文字
|
||||||
|
- url: string → 链接地址(下拉选择站内页面)
|
||||||
|
```
|
||||||
|
|
||||||
|
### 3. products.json(产品管理 — 季节性)
|
||||||
|
|
||||||
|
```
|
||||||
|
后台需要的功能:
|
||||||
|
✅ 编辑产品叙事文案
|
||||||
|
✅ 新增/编辑/删除/排序产品版本
|
||||||
|
✅ 编辑夏令营信息
|
||||||
|
✅ 编辑选择指南
|
||||||
|
✅ 编辑定价说明
|
||||||
|
|
||||||
|
字段说明:
|
||||||
|
narrative: string → 后台富文本编辑
|
||||||
|
|
||||||
|
versions[]:
|
||||||
|
- id: string → 自动生成(如"v9-6d5n-family")
|
||||||
|
- name: string → 产品名称
|
||||||
|
- days: number → 天数
|
||||||
|
- nights: number → 晚数
|
||||||
|
- audience: string → 适合人群
|
||||||
|
- description: string → 产品描述
|
||||||
|
- highlights: string[] → 亮点列表(可增删)
|
||||||
|
- tag: string → 标签(如"经典版"/"人气王")
|
||||||
|
|
||||||
|
summerCamp:
|
||||||
|
- name: string → 名称
|
||||||
|
- ageRange: string → 年龄范围
|
||||||
|
- positioning: string → 定位描述
|
||||||
|
- coreActivities: array → 核心活动列表
|
||||||
|
- differenceFromV9: string → 与V9区别说明
|
||||||
|
|
||||||
|
selectionGuide:
|
||||||
|
- byVacationLength[]: → 按假期长度推荐
|
||||||
|
- byChildAge[]: → 按孩子年龄推荐
|
||||||
|
- byPreference[]: → 按偏好推荐
|
||||||
|
(每条:condition + recommendation,recommendation关联产品id)
|
||||||
|
|
||||||
|
pricingPhilosophy: string → 后台富文本编辑
|
||||||
|
```
|
||||||
|
|
||||||
|
### 4. contact.json(联系方式 — 偶尔更新)
|
||||||
|
|
||||||
|
```
|
||||||
|
后台需要的功能:
|
||||||
|
✅ 编辑联系渠道信息
|
||||||
|
✅ 新增/删除联系渠道
|
||||||
|
✅ 上传/更换二维码图片
|
||||||
|
✅ 编辑安全提示文案
|
||||||
|
|
||||||
|
字段说明:
|
||||||
|
channels[]:
|
||||||
|
- type: string → 渠道类型(wechat/phone/email/address等)
|
||||||
|
- label: string → 显示名称
|
||||||
|
- value: string → 联系值(微信号/电话/邮箱/地址)
|
||||||
|
- qrImage: string|null → 二维码图片路径(可选)
|
||||||
|
- primary: boolean → 是否主要渠道
|
||||||
|
- description: string → 补充说明
|
||||||
|
|
||||||
|
securityNotice: string → 安全提醒文案
|
||||||
|
```
|
||||||
|
|
||||||
|
### 5. brand.json(品牌信息 — 极少更新)
|
||||||
|
|
||||||
|
```
|
||||||
|
后台需要的功能:
|
||||||
|
✅ 编辑品牌基础信息
|
||||||
|
✅ 编辑信任数据
|
||||||
|
✅ 编辑差异化卖点
|
||||||
|
|
||||||
|
字段说明:
|
||||||
|
name: string → 品牌名
|
||||||
|
fullName: string → 公司全称
|
||||||
|
domain: string → 域名
|
||||||
|
url: string → 网址
|
||||||
|
slogan:
|
||||||
|
- emotional: string → 情感化口号
|
||||||
|
- functional: string → 功能化口号
|
||||||
|
trustStats[]:
|
||||||
|
- value: string → 数值(如"8000+")
|
||||||
|
- unit: string → 单位(如"组")
|
||||||
|
- label: string → 标签(如"已服务家庭")
|
||||||
|
- attribution: string → 补充说明(可选)
|
||||||
|
differentiators[]:
|
||||||
|
- title: string → 卖点标题
|
||||||
|
- description: string → 卖点描述
|
||||||
|
icp: string → ICP备案号
|
||||||
|
eContract: string → 电子合同资质
|
||||||
|
```
|
||||||
|
|
||||||
|
### 6. about.json(关于我们 — 极少更新)
|
||||||
|
|
||||||
|
```
|
||||||
|
后台需要的功能:
|
||||||
|
✅ 编辑品牌故事
|
||||||
|
✅ 管理子公司列表
|
||||||
|
✅ 管理资质列表
|
||||||
|
✅ 编辑团队和文化
|
||||||
|
|
||||||
|
字段说明:
|
||||||
|
story:
|
||||||
|
- sections[]: → 品牌故事段落
|
||||||
|
- title/content → 标题+内容
|
||||||
|
- foundingMoment: → 创始故事
|
||||||
|
- scene/reflection → 场景+感悟
|
||||||
|
subsidiaries[]:
|
||||||
|
- name: string → 公司名
|
||||||
|
- role: string → 业务角色
|
||||||
|
qualifications[]:
|
||||||
|
- name: string → 资质名称
|
||||||
|
- detail: string → 具体说明
|
||||||
|
team:
|
||||||
|
- summary: string → 团队概述
|
||||||
|
culture:
|
||||||
|
- values[]: → 企业文化
|
||||||
|
- word/expression → 关键词+表达
|
||||||
|
- transparency: string → 透明度说明
|
||||||
|
```
|
||||||
|
|
||||||
|
### 7. seo.json(SEO信息 — 偶尔优化)
|
||||||
|
|
||||||
|
```
|
||||||
|
后台需要的功能:
|
||||||
|
✅ 编辑每个页面的SEO信息
|
||||||
|
|
||||||
|
字段说明:
|
||||||
|
pages:
|
||||||
|
[pageKey]: → 页面标识(home/about/products/faq/reviews/contact)
|
||||||
|
- title: string → 页面标题(60字符内)
|
||||||
|
- description: string → 页面描述(155字符内)
|
||||||
|
- h1: string → 页面H1标题
|
||||||
|
- ogImage: string → 社交分享图片
|
||||||
|
```
|
||||||
|
|
||||||
|
### 8. navigation.json(导航 — 极少变更)
|
||||||
|
|
||||||
|
```
|
||||||
|
后台需要的功能:
|
||||||
|
✅ 编辑导航项(文字、链接)
|
||||||
|
✅ 调整排序
|
||||||
|
|
||||||
|
header[]:
|
||||||
|
- text: string → 导航文字
|
||||||
|
- to: string → 链接地址
|
||||||
|
footer[]:
|
||||||
|
- title: string → 分组标题
|
||||||
|
- links[]:
|
||||||
|
- text/to → 链接文字+地址
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 三、推荐的技术方案
|
||||||
|
|
||||||
|
### 方案 A:JSON文件 + 简易后台(推荐起步)
|
||||||
|
|
||||||
|
**适合阶段**:现在 → 日均UV 1000以内
|
||||||
|
|
||||||
|
```
|
||||||
|
架构:
|
||||||
|
┌──────────┐ ┌──────────────┐ ┌──────────────┐
|
||||||
|
│ 后台页面 │ ──→ │ API (读写JSON) │ ──→ │ data/*.json │
|
||||||
|
│ (Vue/React)│ │ (Node.js) │ │ (文件存储) │
|
||||||
|
└──────────┘ └──────────────┘ └──────────────┘
|
||||||
|
│
|
||||||
|
↓ 写完后触发
|
||||||
|
┌──────────────┐
|
||||||
|
│ nuxi generate │ → 重新生成静态页面
|
||||||
|
└──────────────┘
|
||||||
|
|
||||||
|
优点:
|
||||||
|
- 零数据库成本
|
||||||
|
- 当前代码零改动,后台只操作JSON文件
|
||||||
|
- 生成的还是静态页面,速度最快
|
||||||
|
- 适合当前团队规模
|
||||||
|
|
||||||
|
缺点:
|
||||||
|
- 每次改内容需要重新 generate(约30秒)
|
||||||
|
- 多人同时编辑可能冲突
|
||||||
|
```
|
||||||
|
|
||||||
|
### 方案 B:数据库 + API + SSR(推荐中期)
|
||||||
|
|
||||||
|
**适合阶段**:有后台系统后
|
||||||
|
|
||||||
|
```
|
||||||
|
架构:
|
||||||
|
┌──────────┐ ┌──────────────┐ ┌──────────────┐
|
||||||
|
│ 后台页面 │ ──→ │ API Server │ ──→ │ 数据库 │
|
||||||
|
│ │ │ (Node.js) │ │ (MySQL/PG) │
|
||||||
|
└──────────┘ └──────────────┘ └──────────────┘
|
||||||
|
│
|
||||||
|
↓ 同时提供
|
||||||
|
┌──────────────┐
|
||||||
|
│ Nuxt SSR渲染 │ → 实时读数据库渲染
|
||||||
|
└──────────────┘
|
||||||
|
|
||||||
|
改动点:
|
||||||
|
- nuxt.config.js: ssr改为true(当前已是),去掉prerender
|
||||||
|
- 页面中 import JSON → 改为 useFetch('/api/xxx')
|
||||||
|
- 新增 server/api/ 目录下的接口
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 四、数据库设计(方案B用)
|
||||||
|
|
||||||
|
### 表结构
|
||||||
|
|
||||||
|
```sql
|
||||||
|
-- 1. 评价表(最高频)
|
||||||
|
CREATE TABLE reviews (
|
||||||
|
id INT PRIMARY KEY AUTO_INCREMENT,
|
||||||
|
nickname VARCHAR(50) NOT NULL,
|
||||||
|
travel_date VARCHAR(20), -- "2025年7月"
|
||||||
|
product_version VARCHAR(100), -- 关联产品名称
|
||||||
|
screenshot_url VARCHAR(255), -- 截图CDN地址
|
||||||
|
content TEXT NOT NULL, -- 评价文字(AI抓取用)
|
||||||
|
scenes JSON, -- ["带小孩", "家庭游"]
|
||||||
|
concerns JSON, -- ["领队服务", "行程安排"]
|
||||||
|
sort_order INT DEFAULT 0, -- 排序权重
|
||||||
|
is_visible BOOLEAN DEFAULT TRUE, -- 是否显示
|
||||||
|
created_at DATETIME DEFAULT NOW(),
|
||||||
|
updated_at DATETIME DEFAULT NOW() ON UPDATE NOW()
|
||||||
|
);
|
||||||
|
|
||||||
|
-- 2. 评价汇总表
|
||||||
|
CREATE TABLE review_summary (
|
||||||
|
id INT PRIMARY KEY DEFAULT 1,
|
||||||
|
total_count INT DEFAULT 0,
|
||||||
|
approval_rate VARCHAR(10), -- "98%"
|
||||||
|
keywords JSON, -- ["贴心", "孩子玩疯了"]
|
||||||
|
updated_at DATETIME DEFAULT NOW() ON UPDATE NOW()
|
||||||
|
);
|
||||||
|
|
||||||
|
-- 3. FAQ分类表
|
||||||
|
CREATE TABLE faq_categories (
|
||||||
|
id VARCHAR(50) PRIMARY KEY, -- "product"
|
||||||
|
name VARCHAR(50) NOT NULL, -- "产品类"
|
||||||
|
sort_order INT DEFAULT 0,
|
||||||
|
created_at DATETIME DEFAULT NOW()
|
||||||
|
);
|
||||||
|
|
||||||
|
-- 4. FAQ问答表
|
||||||
|
CREATE TABLE faq_questions (
|
||||||
|
id VARCHAR(50) PRIMARY KEY,
|
||||||
|
category_id VARCHAR(50) NOT NULL,
|
||||||
|
question VARCHAR(200) NOT NULL,
|
||||||
|
answer TEXT NOT NULL,
|
||||||
|
related_links JSON, -- [{"text":"查看产品","url":"/products"}]
|
||||||
|
sort_order INT DEFAULT 0,
|
||||||
|
is_visible BOOLEAN DEFAULT TRUE,
|
||||||
|
created_at DATETIME DEFAULT NOW(),
|
||||||
|
updated_at DATETIME DEFAULT NOW() ON UPDATE NOW(),
|
||||||
|
FOREIGN KEY (category_id) REFERENCES faq_categories(id)
|
||||||
|
);
|
||||||
|
|
||||||
|
-- 5. 产品版本表
|
||||||
|
CREATE TABLE products (
|
||||||
|
id VARCHAR(50) PRIMARY KEY, -- "v9-6d5n-family"
|
||||||
|
name VARCHAR(100) NOT NULL,
|
||||||
|
days INT,
|
||||||
|
nights INT,
|
||||||
|
audience VARCHAR(100),
|
||||||
|
description TEXT,
|
||||||
|
highlights JSON, -- ["亮点1", "亮点2"]
|
||||||
|
tag VARCHAR(20), -- "人气王"
|
||||||
|
sort_order INT DEFAULT 0,
|
||||||
|
is_visible BOOLEAN DEFAULT TRUE,
|
||||||
|
created_at DATETIME DEFAULT NOW(),
|
||||||
|
updated_at DATETIME DEFAULT NOW() ON UPDATE NOW()
|
||||||
|
);
|
||||||
|
|
||||||
|
-- 6. 夏令营信息表
|
||||||
|
CREATE TABLE summer_camp (
|
||||||
|
id INT PRIMARY KEY DEFAULT 1,
|
||||||
|
name VARCHAR(100),
|
||||||
|
age_range VARCHAR(20),
|
||||||
|
positioning TEXT,
|
||||||
|
core_activities JSON,
|
||||||
|
difference_from_v9 TEXT,
|
||||||
|
updated_at DATETIME DEFAULT NOW() ON UPDATE NOW()
|
||||||
|
);
|
||||||
|
|
||||||
|
-- 7. 联系渠道表
|
||||||
|
CREATE TABLE contact_channels (
|
||||||
|
id INT PRIMARY KEY AUTO_INCREMENT,
|
||||||
|
type VARCHAR(20) NOT NULL, -- "wechat"/"phone"/"email"...
|
||||||
|
label VARCHAR(50) NOT NULL,
|
||||||
|
value VARCHAR(200) NOT NULL,
|
||||||
|
qr_image_url VARCHAR(255),
|
||||||
|
is_primary BOOLEAN DEFAULT FALSE,
|
||||||
|
description VARCHAR(200),
|
||||||
|
sort_order INT DEFAULT 0,
|
||||||
|
created_at DATETIME DEFAULT NOW()
|
||||||
|
);
|
||||||
|
|
||||||
|
-- 8. 品牌信息表(单行表)
|
||||||
|
CREATE TABLE brand_info (
|
||||||
|
id INT PRIMARY KEY DEFAULT 1,
|
||||||
|
name VARCHAR(50),
|
||||||
|
full_name VARCHAR(100),
|
||||||
|
domain VARCHAR(50),
|
||||||
|
slogan_emotional VARCHAR(200),
|
||||||
|
slogan_functional VARCHAR(200),
|
||||||
|
trust_stats JSON, -- 4个信任数据
|
||||||
|
differentiators JSON, -- 5个差异化卖点
|
||||||
|
icp VARCHAR(50),
|
||||||
|
e_contract VARCHAR(100),
|
||||||
|
updated_at DATETIME DEFAULT NOW() ON UPDATE NOW()
|
||||||
|
);
|
||||||
|
|
||||||
|
-- 9. 关于我们(单行表)
|
||||||
|
CREATE TABLE about_info (
|
||||||
|
id INT PRIMARY KEY DEFAULT 1,
|
||||||
|
story JSON, -- 品牌故事结构
|
||||||
|
subsidiaries JSON, -- 12家子公司
|
||||||
|
qualifications JSON, -- 资质列表
|
||||||
|
team JSON, -- 团队介绍
|
||||||
|
culture JSON, -- 文化价值观
|
||||||
|
updated_at DATETIME DEFAULT NOW() ON UPDATE NOW()
|
||||||
|
);
|
||||||
|
|
||||||
|
-- 10. SEO信息表
|
||||||
|
CREATE TABLE seo_pages (
|
||||||
|
page_key VARCHAR(20) PRIMARY KEY, -- "home"/"about"/...
|
||||||
|
title VARCHAR(100),
|
||||||
|
description VARCHAR(200),
|
||||||
|
h1 VARCHAR(100),
|
||||||
|
og_image VARCHAR(255),
|
||||||
|
updated_at DATETIME DEFAULT NOW() ON UPDATE NOW()
|
||||||
|
);
|
||||||
|
|
||||||
|
-- 11. 导航表
|
||||||
|
CREATE TABLE navigation (
|
||||||
|
id INT PRIMARY KEY AUTO_INCREMENT,
|
||||||
|
position ENUM('header', 'footer') NOT NULL,
|
||||||
|
parent_title VARCHAR(50), -- footer分组标题,header为NULL
|
||||||
|
text VARCHAR(50) NOT NULL,
|
||||||
|
url VARCHAR(100) NOT NULL,
|
||||||
|
sort_order INT DEFAULT 0
|
||||||
|
);
|
||||||
|
|
||||||
|
-- 12. 内容文案表(产品叙事、定价说明等长文本)
|
||||||
|
CREATE TABLE content_blocks (
|
||||||
|
block_key VARCHAR(50) PRIMARY KEY, -- "product_narrative" / "pricing_philosophy" / "security_notice"
|
||||||
|
content TEXT NOT NULL,
|
||||||
|
updated_at DATETIME DEFAULT NOW() ON UPDATE NOW()
|
||||||
|
);
|
||||||
|
|
||||||
|
-- 13. 选择指南表
|
||||||
|
CREATE TABLE selection_guide (
|
||||||
|
id INT PRIMARY KEY AUTO_INCREMENT,
|
||||||
|
guide_type ENUM('vacation_length', 'child_age', 'preference'),
|
||||||
|
condition_text VARCHAR(100), -- "3-4天假期"
|
||||||
|
recommendation VARCHAR(50), -- 关联产品id
|
||||||
|
sort_order INT DEFAULT 0
|
||||||
|
);
|
||||||
|
```
|
||||||
|
|
||||||
|
### 图片存储
|
||||||
|
|
||||||
|
```
|
||||||
|
推荐方案:
|
||||||
|
- 评价截图、二维码、Logo等 → 对象存储(阿里云OSS / 腾讯云COS)
|
||||||
|
- 后台上传图片 → API接收 → 上传到OSS → 返回CDN地址
|
||||||
|
- 数据库只存URL,不存文件
|
||||||
|
|
||||||
|
目录规划:
|
||||||
|
/hulai-oss/
|
||||||
|
├── reviews/ 评价截图
|
||||||
|
├── qrcodes/ 二维码图片
|
||||||
|
├── logo/ 品牌Logo
|
||||||
|
└── og/ 社交分享图
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 五、后台管理界面建议
|
||||||
|
|
||||||
|
### 后台菜单结构
|
||||||
|
|
||||||
|
```
|
||||||
|
📊 数据看板
|
||||||
|
- 内容统计(评价数、FAQ数、产品数)
|
||||||
|
|
||||||
|
📝 内容管理
|
||||||
|
├── 客户评价 → 列表 + 新增 + 编辑 + 删除 + 拖拽排序
|
||||||
|
├── 常见问答 → 分类管理 + 问答列表 + 拖拽排序
|
||||||
|
├── 旅行产品 → 产品列表 + 编辑 + 夏令营 + 选择指南
|
||||||
|
└── 联系方式 → 渠道列表 + 编辑 + 上传二维码
|
||||||
|
|
||||||
|
🏢 品牌设置
|
||||||
|
├── 品牌信息 → 基础信息 + 信任数据 + 差异化卖点
|
||||||
|
├── 关于我们 → 品牌故事 + 子公司 + 资质 + 团队 + 文化
|
||||||
|
└── SEO设置 → 6个页面的标题/描述/H1
|
||||||
|
|
||||||
|
⚙️ 系统设置
|
||||||
|
├── 导航管理 → 页头/页脚导航编辑
|
||||||
|
└── 发布管理 → 一键重新生成静态页面
|
||||||
|
```
|
||||||
|
|
||||||
|
### 后台技术栈建议
|
||||||
|
|
||||||
|
```
|
||||||
|
推荐:
|
||||||
|
- 前端:Vue 3 + Element Plus(与官网技术栈统一)
|
||||||
|
- 后端:Node.js + Express/Koa(或 Nuxt server routes)
|
||||||
|
- 数据库:MySQL 8.0(阿里云RDS)
|
||||||
|
- 图片:阿里云OSS + CDN
|
||||||
|
- 部署:同一台服务器,后台走 /admin 路径
|
||||||
|
|
||||||
|
对接方式:
|
||||||
|
1. 后台修改数据 → 写入数据库
|
||||||
|
2. 点击「发布」 → 触发 nuxi generate
|
||||||
|
3. 生成的静态文件部署到CDN/Nginx
|
||||||
|
|
||||||
|
或者(更简单的过渡方案):
|
||||||
|
1. 后台修改数据 → 直接修改 data/*.json 文件
|
||||||
|
2. 点击「发布」 → 触发 nuxi generate
|
||||||
|
3. 无需数据库,JSON就是数据库
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 六、当前代码对接友好度评估
|
||||||
|
|
||||||
|
### 已经写活的(直接能对接)
|
||||||
|
|
||||||
|
| 内容 | 数据源 | 对接方式 |
|
||||||
|
|------|-------|---------|
|
||||||
|
| 所有评价 | `reviews.json` | 替换为API即可 |
|
||||||
|
| 所有FAQ | `faq.json` | 替换为API即可 |
|
||||||
|
| 所有产品 | `products.json` | 替换为API即可 |
|
||||||
|
| 所有联系方式 | `contact.json` | 替换为API即可 |
|
||||||
|
| 品牌信息 | `brand.json` | 替换为API即可 |
|
||||||
|
| 关于信息 | `about.json` | 替换为API即可 |
|
||||||
|
| SEO信息 | `seo.json` | 替换为API即可 |
|
||||||
|
| 导航 | `navigation.json` | 替换为API即可 |
|
||||||
|
|
||||||
|
### 对接时的改动量
|
||||||
|
|
||||||
|
```
|
||||||
|
每个页面改动量很小,只需要把:
|
||||||
|
import data from '~/data/xxx.json'
|
||||||
|
改为:
|
||||||
|
const { data } = await useFetch('/api/xxx')
|
||||||
|
|
||||||
|
大约 6个页面 + 3个组件(Header/Footer/MobileNav)= 9个文件
|
||||||
|
每个文件改动 1-3 行代码
|
||||||
|
总改动量:约30行代码
|
||||||
|
```
|
||||||
|
|
||||||
|
### 评价图片已经对接友好
|
||||||
|
|
||||||
|
```
|
||||||
|
当前:screenshot: "/images/reviews/review-001.jpg" (本地路径)
|
||||||
|
对接后:screenshot: "https://cdn.1814.love/reviews/review-001.jpg" (CDN地址)
|
||||||
|
|
||||||
|
组件中用的是 :src="item.screenshot",路径换成CDN地址直接生效,零改动。
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 七、给运营同学的速查表
|
||||||
|
|
||||||
|
### 现在(没有后台之前)怎么改内容
|
||||||
|
|
||||||
|
| 要改什么 | 找哪个文件 | 怎么改 |
|
||||||
|
|---------|----------|-------|
|
||||||
|
| 新增客户评价 | `data/reviews.json` | 在 `items` 数组里加一条,图片放到 `public/images/reviews/` |
|
||||||
|
| 修改FAQ问答 | `data/faq.json` | 找到对应问题直接改文字 |
|
||||||
|
| 修改产品信息 | `data/products.json` | 找到对应版本直接改 |
|
||||||
|
| 换微信号/电话 | `data/contact.json` | 找到对应渠道改 `value` |
|
||||||
|
| 改页面标题/描述 | `data/seo.json` | 找到对应页面改 |
|
||||||
|
| 改品牌口号 | `data/brand.json` | 改 `slogan` 下的文字 |
|
||||||
|
| 改关于我们 | `data/about.json` | 找到对应位置改 |
|
||||||
|
|
||||||
|
**改完后**:需要运行 `npx nuxi generate` 重新生成页面,然后重新部署。
|
||||||
|
|
||||||
|
### 有后台之后怎么改
|
||||||
|
|
||||||
|
登录后台 → 找到对应模块 → 编辑 → 点击「发布」→ 完成
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 八、总结
|
||||||
|
|
||||||
|
```
|
||||||
|
当前架构优势:
|
||||||
|
✅ 所有内容都在 8 个 JSON 文件里,结构清晰
|
||||||
|
✅ 数据和展示完全分离,后台对接只需改数据源
|
||||||
|
✅ 对接工作量极小(约30行代码改动)
|
||||||
|
✅ 可以分步走:先用JSON文件+手动generate,再上后台
|
||||||
|
|
||||||
|
建议路线图:
|
||||||
|
Phase 1(现在):JSON文件 + 手动维护 + nuxi generate
|
||||||
|
Phase 2(1-2月后):简易后台 + 读写JSON + 一键generate
|
||||||
|
Phase 3(业务增长后):数据库 + API + CDN图片 + SSR渲染
|
||||||
|
```
|
||||||
582
README-HANDOFF.md
普通文件
582
README-HANDOFF.md
普通文件
@ -0,0 +1,582 @@
|
|||||||
|
# 呼籁旅行官网 - 后端对接 & 运营维护文档
|
||||||
|
|
||||||
|
> 域名:1814.love | 框架:Nuxt 3 SSG(静态站)| 语言:JavaScript + Vue 3 + Less
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 一、项目概览
|
||||||
|
|
||||||
|
这是一个**纯静态网站**,没有后端API、没有数据库。所有内容都存放在 `/data/*.json` 文件中,修改JSON即可更新网站内容。
|
||||||
|
|
||||||
|
### 技术栈
|
||||||
|
| 项目 | 说明 |
|
||||||
|
|------|------|
|
||||||
|
| 框架 | Nuxt 3(Vue 3) |
|
||||||
|
| 渲染方式 | SSG 静态生成(`npx nuxi generate`) |
|
||||||
|
| 样式 | Less |
|
||||||
|
| 部署产物 | `.output/public/` 目录,纯HTML/CSS/JS,丢到任何静态服务器即可 |
|
||||||
|
|
||||||
|
### 部署流程
|
||||||
|
```bash
|
||||||
|
# 1. 安装依赖(仅首次)
|
||||||
|
npm install
|
||||||
|
|
||||||
|
# 2. 生成静态文件
|
||||||
|
npx nuxi generate
|
||||||
|
|
||||||
|
# 3. 部署目录
|
||||||
|
.output/public/ # ← 这个目录就是最终产物,丢到nginx/CDN即可
|
||||||
|
|
||||||
|
# 4. 本地预览(可选)
|
||||||
|
npx serve .output/public
|
||||||
|
```
|
||||||
|
|
||||||
|
### 页面清单(共8页)
|
||||||
|
| 路径 | 页面 | 源文件 |
|
||||||
|
|------|------|--------|
|
||||||
|
| `/` | 首页 | `pages/index.vue` |
|
||||||
|
| `/about` | 关于我们 | `pages/about.vue` |
|
||||||
|
| `/products` | 产品线(额吉的故乡V9) | `pages/products.vue` |
|
||||||
|
| `/summer-camp` | 小蒙马夏令营 | `pages/summer-camp.vue` |
|
||||||
|
| `/guides` | 出行指南 | `pages/guides.vue` |
|
||||||
|
| `/faq` | 常见问答 | `pages/faq.vue` |
|
||||||
|
| `/reviews` | 客户评价 | `pages/reviews.vue` |
|
||||||
|
| `/contact` | 联系我们 | `pages/contact.vue` |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 二、内容维护指南(运营同学看这里)
|
||||||
|
|
||||||
|
### 核心原则
|
||||||
|
> **所有内容都在 `/data/` 目录的JSON文件里。** 打开文件,改引号里的文字,重新 generate 就行。不需要懂代码。
|
||||||
|
|
||||||
|
### 修改流程
|
||||||
|
```
|
||||||
|
1. 用任意文本编辑器打开 data/ 下的JSON文件
|
||||||
|
2. 修改引号内的文字内容
|
||||||
|
3. 保存文件
|
||||||
|
4. 终端执行 npx nuxi generate
|
||||||
|
5. 将 .output/public/ 部署到服务器
|
||||||
|
```
|
||||||
|
|
||||||
|
### ⚠️ JSON编辑注意事项
|
||||||
|
- 所有内容必须在英文双引号 `"..."` 内
|
||||||
|
- 内容中如果有双引号,要用 `\"` 转义
|
||||||
|
- 最后一项后面**不要**加逗号
|
||||||
|
- 换行用 `\n`,不要直接回车
|
||||||
|
- 建议用 VS Code 编辑,会自动提示格式错误
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 三、数据文件详细说明
|
||||||
|
|
||||||
|
### 3.1 `data/brand.json` — 品牌基础信息
|
||||||
|
|
||||||
|
> 影响页面:首页、关于页、联系页
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"name": "呼籁旅行", // 品牌名
|
||||||
|
"fullName": "内蒙古呼籁文旅投资开发集团有限公司", // 公司全称
|
||||||
|
"domain": "1814.love", // 域名
|
||||||
|
"url": "https://1814.love", // 完整URL
|
||||||
|
"slogan": {
|
||||||
|
"emotional": "情感化品牌主张", // 首页大标题(情感层)
|
||||||
|
"functional": "呼伦贝尔家庭定制游·一家一单一车" // 功能层
|
||||||
|
},
|
||||||
|
"trustStats": [ // 首页信任数据条(4项)
|
||||||
|
{
|
||||||
|
"value": "10000+", // 数字
|
||||||
|
"unit": "组", // 单位
|
||||||
|
"label": "已服务家庭", // 标签
|
||||||
|
"attribution": "来源说明(可选)"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"differentiators": [ // 核心卖点(首页展示)
|
||||||
|
{
|
||||||
|
"title": "自有营地", // 卖点标题
|
||||||
|
"description": "描述文字" // 详细说明
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"legal": { // 备案信息(页脚展示)
|
||||||
|
"icp": "蒙ICP备2025XXXXX号-1"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
**运营常改字段:**
|
||||||
|
- `trustStats[].value` — 更新服务家庭数等数字
|
||||||
|
- `slogan.emotional` — 修改品牌主张
|
||||||
|
- `differentiators[].description` — 更新卖点描述
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### 3.2 `data/products.json` — 产品线
|
||||||
|
|
||||||
|
> 影响页面:产品页、首页产品预览、小蒙马页
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"narrative": "产品线设计理念叙事文字...",
|
||||||
|
|
||||||
|
"versions": [ // 额吉的故乡V9系列(6个版本)
|
||||||
|
{
|
||||||
|
"id": "v9-4d3n", // 唯一标识,不要改
|
||||||
|
"name": "额吉的故乡V9·4天3晚", // 产品名称
|
||||||
|
"days": 4, // 天数
|
||||||
|
"nights": 3, // 晚数
|
||||||
|
"audience": "假期有限的家庭", // 目标人群
|
||||||
|
"description": "产品描述...", // 详细介绍
|
||||||
|
"highlights": [ // 3个亮点
|
||||||
|
"亮点1",
|
||||||
|
"亮点2",
|
||||||
|
"亮点3"
|
||||||
|
],
|
||||||
|
"tag": "精华版" // 标签(显示在卡片上)
|
||||||
|
}
|
||||||
|
],
|
||||||
|
|
||||||
|
"summerCamp": { // 小蒙马夏令营
|
||||||
|
"name": "小蒙马夏令营",
|
||||||
|
"positioning": "产品定位描述...",
|
||||||
|
"days": 6,
|
||||||
|
"nights": 5,
|
||||||
|
"sessions": { "2025": 11, "2026plan": 30 }, // 期数数据
|
||||||
|
"principles": ["原则1", "原则2", "原则3", "原则4"],
|
||||||
|
"coreActivities": ["活动1", "活动2"], // 核心体验项目
|
||||||
|
"itinerary": ["Day1 ...", "Day2 ..."], // 每日行程概览
|
||||||
|
"differenceFromV9": "与V9的区别说明..."
|
||||||
|
},
|
||||||
|
|
||||||
|
"selectionGuide": { // 选择指南
|
||||||
|
"byVacationLength": [...], // 按假期长度推荐
|
||||||
|
"byChildAge": [...], // 按孩子年龄推荐
|
||||||
|
"byPreference": [...] // 按偏好推荐
|
||||||
|
},
|
||||||
|
|
||||||
|
"pricingPhilosophy": "价格透明说明..."
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
**运营常改字段:**
|
||||||
|
- `versions[].description` / `highlights` — 更新产品描述和亮点
|
||||||
|
- `summerCamp` 整块 — 每年行程更新时修改
|
||||||
|
- `summerCamp.sessions` — 更新期数数据
|
||||||
|
- `summerCamp.itinerary` — 更新每日行程
|
||||||
|
- `pricingPhilosophy` — 价格说明
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### 3.3 `data/faq.json` — 常见问答(SEO最重要的页面)
|
||||||
|
|
||||||
|
> 影响页面:FAQ页、Google/百度搜索结果(FAQ Schema)
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"categories": [
|
||||||
|
{
|
||||||
|
"id": "product", // 分类ID,不要改
|
||||||
|
"name": "产品类", // 分类名称
|
||||||
|
"questions": [
|
||||||
|
{
|
||||||
|
"id": "what-is-eqi", // 问题ID,不要改
|
||||||
|
"question": "额吉的故乡是什么?", // 问题
|
||||||
|
"answer": "回答内容...", // 答案(150-300字最佳)
|
||||||
|
"relatedLinks": [ // 相关链接
|
||||||
|
{ "text": "查看产品详情", "url": "/products" }
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
**现有分类(5个,共20+个问答):**
|
||||||
|
| 分类ID | 名称 | 问答数 |
|
||||||
|
|--------|------|--------|
|
||||||
|
| product | 产品类 | 6 |
|
||||||
|
| preparation | 出行准备类 | 5 |
|
||||||
|
| trust | 信任类 | 5 |
|
||||||
|
| experience | 体验类 | 4 |
|
||||||
|
| popular | 高频咨询类 | 5 |
|
||||||
|
|
||||||
|
**运营常改字段:**
|
||||||
|
- `questions[].answer` — 更新答案内容
|
||||||
|
- 新增问答:在对应分类的 `questions` 数组末尾添加新对象
|
||||||
|
|
||||||
|
**新增一个FAQ示例:**
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"id": "new-question-id",
|
||||||
|
"question": "新问题?",
|
||||||
|
"answer": "新答案...",
|
||||||
|
"relatedLinks": [
|
||||||
|
{ "text": "链接文字", "url": "/products" }
|
||||||
|
]
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### 3.4 `data/reviews.json` — 客户评价
|
||||||
|
|
||||||
|
> 影响页面:评价页、首页精选评价
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"summary": {
|
||||||
|
"totalCount": 10000, // 总评价数
|
||||||
|
"approvalRate": "98%", // 好评率
|
||||||
|
"keywords": ["贴心", "孩子玩疯了"] // 高频关键词
|
||||||
|
},
|
||||||
|
"items": [
|
||||||
|
{
|
||||||
|
"id": 1, // 序号(递增,不要重复)
|
||||||
|
"nickname": "圆满妈妈", // 昵称
|
||||||
|
"travelDate": "2024年6月", // 出行时间
|
||||||
|
"productVersion": "额吉的故乡V9·6天5晚", // 产品版本
|
||||||
|
"screenshot": "/images/reviews/review-001.jpg", // 评价截图路径
|
||||||
|
"content": "评价文字内容...", // 评价文字(与截图一致,供AI抓取)
|
||||||
|
"scenes": ["带小孩", "家庭游"], // 出行场景标签
|
||||||
|
"concerns": ["领队服务", "行程安排"] // 关注点标签
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
**运营常改字段:**
|
||||||
|
- `summary.totalCount` — 更新总评价数
|
||||||
|
- `items` — 添加新评价
|
||||||
|
|
||||||
|
**添加新评价步骤:**
|
||||||
|
1. 将评价截图命名为 `review-XXX.jpg`(XXX为序号如083)
|
||||||
|
2. 放入 `public/images/reviews/` 目录
|
||||||
|
3. 在 `items` 数组末尾添加新评价对象
|
||||||
|
4. 截图建议宽度不超过1600px
|
||||||
|
|
||||||
|
**可用的 scenes 标签:** `带小孩`、`家庭游`、`闺蜜游`、`带老人`、`蜜月`
|
||||||
|
**可用的 concerns 标签:** `领队服务`、`行程安排`、`住宿品质`、`餐饮体验`、`亲子活动`、`拍照摄影`、`性价比`
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### 3.5 `data/about.json` — 关于我们
|
||||||
|
|
||||||
|
> 影响页面:关于页
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"story": {
|
||||||
|
"title": "品牌故事标题",
|
||||||
|
"content": "品牌故事正文..." // 支持较长文本
|
||||||
|
},
|
||||||
|
"subsidiaries": [ // 旗下企业
|
||||||
|
{
|
||||||
|
"name": "企业名称",
|
||||||
|
"role": "业务角色",
|
||||||
|
"established": "成立年份"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"certifications": [ // 资质荣誉
|
||||||
|
{
|
||||||
|
"name": "荣誉名称",
|
||||||
|
"detail": "详细说明",
|
||||||
|
"year": "2025"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"trademarks": { ... }, // 商标信息
|
||||||
|
"copyrights": [ ... ], // 版权信息
|
||||||
|
"guarantees": [ // 服务保障
|
||||||
|
{
|
||||||
|
"title": "保障标题",
|
||||||
|
"description": "保障说明"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"xiaohongshu": { // 小红书数据
|
||||||
|
"account": "Mr.小雷-呼籁旅行",
|
||||||
|
"followers": "9.6万+",
|
||||||
|
"likes": "26万+",
|
||||||
|
"awards": ["获奖列表"],
|
||||||
|
"description": "说明文字"
|
||||||
|
},
|
||||||
|
"team": {
|
||||||
|
"serviceModel": "3管+1师+1队",
|
||||||
|
"description": "团队说明...",
|
||||||
|
"milestones": ["里程碑1", "里程碑2"]
|
||||||
|
},
|
||||||
|
"culture": {
|
||||||
|
"values": [
|
||||||
|
{ "title": "真诚", "description": "说明" }
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
**运营常改字段:**
|
||||||
|
- `subsidiaries` — 新增/调整子公司
|
||||||
|
- `certifications` — 新增荣誉资质
|
||||||
|
- `xiaohongshu` — 更新小红书数据(粉丝数、获赞数、荣誉)
|
||||||
|
- `team.milestones` — 添加团队新事件
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### 3.6 `data/contact.json` — 联系方式
|
||||||
|
|
||||||
|
> 影响页面:联系页、页脚
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"channels": [
|
||||||
|
{
|
||||||
|
"type": "wechat", // 类型:wechat/mini-program/phone/address/email
|
||||||
|
"label": "微信客服", // 显示名
|
||||||
|
"value": "hulai1814", // 值(微信号/电话/地址等)
|
||||||
|
"description": "说明文字",
|
||||||
|
"qrCode": "/images/qr-wechat.jpg", // 二维码图片(可选)
|
||||||
|
"primary": true // 是否主要渠道
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"securityNotice": "安全提示文字..."
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### 3.7 `data/seo.json` — 各页面SEO配置
|
||||||
|
|
||||||
|
> 影响:每个页面的标题、描述、搜索引擎展示
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"pages": {
|
||||||
|
"home": {
|
||||||
|
"title": "呼籁旅行 - 呼伦贝尔家庭定制游·一家一单一车", // 浏览器标签页标题
|
||||||
|
"description": "搜索引擎展示的描述文字...", // 搜索结果摘要
|
||||||
|
"h1": "呼籁旅行 — 呼伦贝尔家庭定制游", // 页面大标题
|
||||||
|
"ogImage": "/images/og-home.jpg" // 社交分享图
|
||||||
|
},
|
||||||
|
"about": { ... },
|
||||||
|
"products": { ... },
|
||||||
|
"summer-camp": { ... },
|
||||||
|
"faq": { ... },
|
||||||
|
"reviews": { ... },
|
||||||
|
"guides": { ... },
|
||||||
|
"contact": { ... }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
**运营常改字段:**
|
||||||
|
- `title` — 控制搜索结果标题(建议60字以内)
|
||||||
|
- `description` — 控制搜索结果描述(建议150字以内)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### 3.8 `data/navigation.json` — 导航菜单
|
||||||
|
|
||||||
|
> 影响:顶部导航栏、底部链接
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"header": [ // 顶部导航(按顺序展示)
|
||||||
|
{ "text": "首页", "to": "/" },
|
||||||
|
{ "text": "关于我们", "to": "/about" },
|
||||||
|
{ "text": "产品线", "to": "/products" },
|
||||||
|
{ "text": "小蒙马夏令营", "to": "/summer-camp" },
|
||||||
|
{ "text": "出行指南", "to": "/guides" },
|
||||||
|
{ "text": "常见问答", "to": "/faq" },
|
||||||
|
{ "text": "客户评价", "to": "/reviews" },
|
||||||
|
{ "text": "联系我们", "to": "/contact" }
|
||||||
|
],
|
||||||
|
"footer": [ // 底部分组链接
|
||||||
|
{
|
||||||
|
"title": "了解呼籁",
|
||||||
|
"links": [
|
||||||
|
{ "text": "关于我们", "to": "/about" }
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### 3.9 `data/versions.json` — 产品版本迭代历史
|
||||||
|
|
||||||
|
> 影响页面:产品页(版本进化时间线、V8→V9对比等)
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"stats": { // 统计数据
|
||||||
|
"totalIterations": 9,
|
||||||
|
"totalUpgrades": "50+",
|
||||||
|
"firstVersion": "2023年3月",
|
||||||
|
"latestVersion": "2026年"
|
||||||
|
},
|
||||||
|
"upgrades2026": [ // 当年核心升级项
|
||||||
|
{
|
||||||
|
"title": "升级标题",
|
||||||
|
"description": "升级描述"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"highlights": [ // V9亮点
|
||||||
|
{ "title": "亮点", "description": "说明" }
|
||||||
|
],
|
||||||
|
"compareV8V9": [ // V8→V9对比
|
||||||
|
{ "category": "分类", "v8": "旧版", "v9": "新版" }
|
||||||
|
],
|
||||||
|
"timeline": [ // 历史版本时间线
|
||||||
|
{
|
||||||
|
"version": "V1",
|
||||||
|
"date": "2023.03",
|
||||||
|
"title": "标题",
|
||||||
|
"changes": [
|
||||||
|
{ "type": "add", "content": "新增内容" }
|
||||||
|
]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"philosophy": "产品哲学...",
|
||||||
|
"quote": { "text": "引用", "author": "作者" }
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### 3.10 `data/guides.json` — 出行指南
|
||||||
|
|
||||||
|
> 影响页面:出行指南页
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"sections": [
|
||||||
|
{
|
||||||
|
"id": "clothing",
|
||||||
|
"title": "穿搭指南",
|
||||||
|
"subtitle": "副标题",
|
||||||
|
"months": [ // 按月份的穿搭建议
|
||||||
|
{
|
||||||
|
"month": "5月",
|
||||||
|
"tempRange": "白天5~26°C / 夜间-6~8°C",
|
||||||
|
"style": "穿搭风格",
|
||||||
|
"items": ["具体衣物1", "具体衣物2"],
|
||||||
|
"tip": "小贴士"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "activities",
|
||||||
|
"title": "活动安全须知",
|
||||||
|
"items": [
|
||||||
|
{
|
||||||
|
"name": "骑马穿越",
|
||||||
|
"rules": ["规则1", "规则2"],
|
||||||
|
"notes": "注意事项"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 四、图片资源管理
|
||||||
|
|
||||||
|
### 目录结构
|
||||||
|
```
|
||||||
|
public/images/
|
||||||
|
├── logo.png # 网站Logo
|
||||||
|
├── logo-square.png # 方形Logo
|
||||||
|
├── mascot-sticker-qr.png # 吉祥物贴纸
|
||||||
|
├── mascot/ # 吉祥物图片
|
||||||
|
│ ├── mascot-front.png # 正面
|
||||||
|
│ ├── mascot-banner.png # 横幅
|
||||||
|
│ └── xiaomengma.png # 小蒙马
|
||||||
|
├── summer-camp/ # 小蒙马夏令营照片(4张)
|
||||||
|
│ ├── river-banner.jpg
|
||||||
|
│ ├── grassland-group.jpg
|
||||||
|
│ ├── birch-group.jpg
|
||||||
|
│ └── camp-graduation.jpg
|
||||||
|
├── team/ # 团队照片(8张)
|
||||||
|
│ ├── hero-family.jpg
|
||||||
|
│ ├── hero-grassland.jpg
|
||||||
|
│ ├── guide-group.jpg
|
||||||
|
│ ├── guide-training.jpg
|
||||||
|
│ ├── campsite-team.jpg
|
||||||
|
│ ├── ranch-store.jpg
|
||||||
|
│ ├── route-survey.jpg
|
||||||
|
│ └── route-survey-2025.jpg
|
||||||
|
├── xiaohongshu/ # 小红书相关(2张)
|
||||||
|
│ ├── storefront.jpg
|
||||||
|
│ └── profile.jpg
|
||||||
|
└── reviews/ # 评价截图(82张)
|
||||||
|
├── review-001.jpg
|
||||||
|
├── review-002.jpg
|
||||||
|
└── ... review-082.jpg
|
||||||
|
```
|
||||||
|
|
||||||
|
### 添加图片规范
|
||||||
|
- **格式**:JPG(照片)、PNG(Logo/图标)
|
||||||
|
- **尺寸**:宽度不超过1600px
|
||||||
|
- **命名**:英文小写+连字符,如 `new-photo.jpg`
|
||||||
|
- **路径**:代码中引用时用 `/images/xxx.jpg`(以 `/` 开头的绝对路径)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 五、sitemap 自动生成
|
||||||
|
|
||||||
|
文件位置:`server/routes/sitemap.xml.js`
|
||||||
|
|
||||||
|
如果**新增页面**,需要在这个文件的 `pages` 数组中添加:
|
||||||
|
```javascript
|
||||||
|
{ url: '/new-page', priority: '0.8', changefreq: 'monthly' }
|
||||||
|
```
|
||||||
|
|
||||||
|
当前已配置的页面:
|
||||||
|
| URL | 优先级 | 更新频率 |
|
||||||
|
|-----|--------|---------|
|
||||||
|
| `/` | 1.0 | weekly |
|
||||||
|
| `/faq` | 0.95 | weekly |
|
||||||
|
| `/products` | 0.9 | weekly |
|
||||||
|
| `/about` | 0.85 | monthly |
|
||||||
|
| `/summer-camp` | 0.85 | monthly |
|
||||||
|
| `/reviews` | 0.8 | weekly |
|
||||||
|
| `/contact` | 0.8 | monthly |
|
||||||
|
| `/guides` | 0.8 | monthly |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 六、常见运营操作速查
|
||||||
|
|
||||||
|
### 更新信任数据(服务家庭数等)
|
||||||
|
→ 改 `data/brand.json` 的 `trustStats`
|
||||||
|
|
||||||
|
### 添加新客户评价
|
||||||
|
→ 1. 截图放 `public/images/reviews/`
|
||||||
|
→ 2. 在 `data/reviews.json` 的 `items` 末尾加新对象
|
||||||
|
|
||||||
|
### 更新小蒙马夏令营行程
|
||||||
|
→ 改 `data/products.json` 的 `summerCamp` 部分
|
||||||
|
|
||||||
|
### 添加新FAQ
|
||||||
|
→ 在 `data/faq.json` 对应分类的 `questions` 数组末尾加新对象
|
||||||
|
|
||||||
|
### 更新小红书数据
|
||||||
|
→ 改 `data/about.json` 的 `xiaohongshu` 部分
|
||||||
|
|
||||||
|
### 修改页面SEO标题/描述
|
||||||
|
→ 改 `data/seo.json` 对应页面的 `title` 和 `description`
|
||||||
|
|
||||||
|
### 调整导航菜单
|
||||||
|
→ 改 `data/navigation.json`
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 七、注意事项
|
||||||
|
|
||||||
|
1. **每次改完JSON必须重新 generate** — 这是静态站,改JSON不会自动生效
|
||||||
|
2. **不要删除 `node_modules/`** — 删了要重新 `npm install`
|
||||||
|
3. **JSON格式很严格** — 少一个逗号、多一个逗号都会报错,建议用 VS Code 编辑
|
||||||
|
4. **图片要放在 `public/images/` 下** — 不要放在其他位置
|
||||||
|
5. **缺少 favicon.ico** — 需要补一个放在 `public/` 目录下
|
||||||
|
6. **部署只需要 `.output/public/`** — 这个目录是纯静态HTML,不需要Node.js运行环境
|
||||||
222
assets/less/global.less
普通文件
222
assets/less/global.less
普通文件
@ -0,0 +1,222 @@
|
|||||||
|
// ============================================
|
||||||
|
// 呼籁旅行官网 - 全局样式
|
||||||
|
// ============================================
|
||||||
|
|
||||||
|
// ---------- 重置 ----------
|
||||||
|
|
||||||
|
*,
|
||||||
|
*::before,
|
||||||
|
*::after {
|
||||||
|
box-sizing: border-box;
|
||||||
|
margin: 0;
|
||||||
|
padding: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
html {
|
||||||
|
font-size: @font-size-base;
|
||||||
|
-webkit-font-smoothing: antialiased;
|
||||||
|
-moz-osx-font-smoothing: grayscale;
|
||||||
|
scroll-behavior: smooth;
|
||||||
|
}
|
||||||
|
|
||||||
|
body {
|
||||||
|
font-family: @font-family-base;
|
||||||
|
font-size: @font-size-base;
|
||||||
|
line-height: @line-height-base;
|
||||||
|
color: @color-text-primary;
|
||||||
|
background-color: @color-bg-white;
|
||||||
|
}
|
||||||
|
|
||||||
|
// ---------- 排版 ----------
|
||||||
|
|
||||||
|
h1, h2, h3, h4, h5, h6 {
|
||||||
|
font-weight: @font-weight-bold;
|
||||||
|
line-height: @line-height-tight;
|
||||||
|
color: @color-text-primary;
|
||||||
|
}
|
||||||
|
|
||||||
|
h1 {
|
||||||
|
font-size: 28px;
|
||||||
|
|
||||||
|
.respond-md({
|
||||||
|
font-size: @font-size-hero;
|
||||||
|
});
|
||||||
|
|
||||||
|
.respond-lg({
|
||||||
|
font-size: @font-size-display;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
h2 {
|
||||||
|
font-size: @font-size-xl;
|
||||||
|
|
||||||
|
.respond-md({
|
||||||
|
font-size: @font-size-2xl;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
h3 {
|
||||||
|
font-size: @font-size-lg;
|
||||||
|
|
||||||
|
.respond-md({
|
||||||
|
font-size: @font-size-xl;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
p {
|
||||||
|
margin-bottom: @space-md;
|
||||||
|
color: @color-text-secondary;
|
||||||
|
}
|
||||||
|
|
||||||
|
a {
|
||||||
|
color: @color-primary;
|
||||||
|
text-decoration: none;
|
||||||
|
transition: color @transition-fast;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
color: @color-primary-light;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ul, ol {
|
||||||
|
list-style: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
img {
|
||||||
|
max-width: 100%;
|
||||||
|
height: auto;
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
|
||||||
|
// ---------- 容器 ----------
|
||||||
|
|
||||||
|
.container {
|
||||||
|
.container();
|
||||||
|
}
|
||||||
|
|
||||||
|
// ---------- 段落区块 ----------
|
||||||
|
|
||||||
|
.section {
|
||||||
|
.section-padding();
|
||||||
|
}
|
||||||
|
|
||||||
|
.section--gray {
|
||||||
|
background-color: @color-bg-gray;
|
||||||
|
}
|
||||||
|
|
||||||
|
.section--warm {
|
||||||
|
background-color: @color-bg-warm;
|
||||||
|
}
|
||||||
|
|
||||||
|
.section--green {
|
||||||
|
background-color: @color-primary-bg;
|
||||||
|
}
|
||||||
|
|
||||||
|
.section--accent {
|
||||||
|
background-color: @color-accent-bg;
|
||||||
|
}
|
||||||
|
|
||||||
|
.section--dark {
|
||||||
|
background-color: @color-primary-dark;
|
||||||
|
color: rgba(255, 255, 255, 0.9);
|
||||||
|
}
|
||||||
|
|
||||||
|
// ---------- 辅助类 ----------
|
||||||
|
|
||||||
|
.text-center {
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.text-left {
|
||||||
|
text-align: left;
|
||||||
|
}
|
||||||
|
|
||||||
|
.sr-only {
|
||||||
|
position: absolute;
|
||||||
|
width: 1px;
|
||||||
|
height: 1px;
|
||||||
|
padding: 0;
|
||||||
|
margin: -1px;
|
||||||
|
overflow: hidden;
|
||||||
|
clip: rect(0, 0, 0, 0);
|
||||||
|
white-space: nowrap;
|
||||||
|
border-width: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// ---------- 页面过渡 ----------
|
||||||
|
|
||||||
|
.page-enter-active,
|
||||||
|
.page-leave-active {
|
||||||
|
transition: opacity @transition-base;
|
||||||
|
}
|
||||||
|
|
||||||
|
.page-enter-from,
|
||||||
|
.page-leave-to {
|
||||||
|
opacity: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// ---------- 滚动入场动画 ----------
|
||||||
|
|
||||||
|
.reveal {
|
||||||
|
opacity: 0;
|
||||||
|
transform: translateY(16px);
|
||||||
|
transition: opacity 0.7s cubic-bezier(0.23, 1, 0.32, 1), transform 0.7s cubic-bezier(0.23, 1, 0.32, 1);
|
||||||
|
|
||||||
|
&.is-visible {
|
||||||
|
opacity: 1;
|
||||||
|
transform: translateY(0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 子元素交错入场(用于网格)
|
||||||
|
.reveal-stagger {
|
||||||
|
.reveal();
|
||||||
|
|
||||||
|
&:nth-child(2) { transition-delay: 0.08s; }
|
||||||
|
&:nth-child(3) { transition-delay: 0.16s; }
|
||||||
|
&:nth-child(4) { transition-delay: 0.24s; }
|
||||||
|
&:nth-child(5) { transition-delay: 0.32s; }
|
||||||
|
&:nth-child(6) { transition-delay: 0.40s; }
|
||||||
|
}
|
||||||
|
|
||||||
|
// ---------- 页面摘要 TL;DR(GEO/SEO 语义摘要块)----------
|
||||||
|
// 每个页面开头的精准摘要,帮助 AI 和搜索引擎理解"这个页面回答了什么问题"
|
||||||
|
.page-tldr {
|
||||||
|
background: @color-bg-gray;
|
||||||
|
border-bottom: 1px solid @color-border;
|
||||||
|
|
||||||
|
.page-tldr-inner {
|
||||||
|
max-width: 800px;
|
||||||
|
margin: 0 auto;
|
||||||
|
padding: @space-lg @space-xl;
|
||||||
|
border-left: 3px solid @color-primary;
|
||||||
|
background: @color-bg-white;
|
||||||
|
border-radius: 0 @border-radius-md @border-radius-md 0;
|
||||||
|
|
||||||
|
p {
|
||||||
|
font-size: @font-size-sm;
|
||||||
|
color: @color-text-secondary;
|
||||||
|
line-height: @line-height-loose;
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 容器内居中 + 内边距
|
||||||
|
.container {
|
||||||
|
padding-top: @space-md;
|
||||||
|
padding-bottom: @space-md;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ---------- 无障碍:减少动效偏好 ----------
|
||||||
|
|
||||||
|
@media (prefers-reduced-motion: reduce) {
|
||||||
|
*,
|
||||||
|
*::before,
|
||||||
|
*::after {
|
||||||
|
animation-duration: 0.01ms !important;
|
||||||
|
animation-iteration-count: 1 !important;
|
||||||
|
transition-duration: 0.01ms !important;
|
||||||
|
scroll-behavior: auto !important;
|
||||||
|
}
|
||||||
|
}
|
||||||
76
assets/less/mixins.less
普通文件
76
assets/less/mixins.less
普通文件
@ -0,0 +1,76 @@
|
|||||||
|
// ============================================
|
||||||
|
// 呼籁旅行官网 - Less混入
|
||||||
|
// ============================================
|
||||||
|
|
||||||
|
// 响应式断点
|
||||||
|
.respond-md(@rules) {
|
||||||
|
@media (min-width: @breakpoint-md) {
|
||||||
|
@rules();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.respond-lg(@rules) {
|
||||||
|
@media (min-width: @breakpoint-lg) {
|
||||||
|
@rules();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.respond-xl(@rules) {
|
||||||
|
@media (min-width: @breakpoint-xl) {
|
||||||
|
@rules();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 容器
|
||||||
|
.container() {
|
||||||
|
width: 100%;
|
||||||
|
max-width: @container-max-width;
|
||||||
|
margin-left: auto;
|
||||||
|
margin-right: auto;
|
||||||
|
padding-left: @container-padding;
|
||||||
|
padding-right: @container-padding;
|
||||||
|
|
||||||
|
.respond-lg({
|
||||||
|
padding-left: @container-padding-desktop;
|
||||||
|
padding-right: @container-padding-desktop;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// 段落间距 — 更大的呼吸感
|
||||||
|
.section-padding() {
|
||||||
|
padding-top: @space-2xl;
|
||||||
|
padding-bottom: @space-2xl;
|
||||||
|
|
||||||
|
.respond-md({
|
||||||
|
padding-top: @space-3xl;
|
||||||
|
padding-bottom: @space-3xl;
|
||||||
|
});
|
||||||
|
|
||||||
|
.respond-lg({
|
||||||
|
padding-top: 100px;
|
||||||
|
padding-bottom: 100px;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// 响应式网格:移动1列 → 平板2列 → 桌面3列
|
||||||
|
.grid-responsive(@gap: @space-lg; @md-cols: 2; @lg-cols: 3) {
|
||||||
|
display: grid;
|
||||||
|
grid-template-columns: 1fr;
|
||||||
|
gap: @gap;
|
||||||
|
|
||||||
|
.respond-md({
|
||||||
|
grid-template-columns: repeat(@md-cols, 1fr);
|
||||||
|
});
|
||||||
|
|
||||||
|
.respond-lg({
|
||||||
|
grid-template-columns: repeat(@lg-cols, 1fr);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// 多行截断
|
||||||
|
.text-clamp(@lines: 3) {
|
||||||
|
display: -webkit-box;
|
||||||
|
-webkit-line-clamp: @lines;
|
||||||
|
-webkit-box-orient: vertical;
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
105
assets/less/variables.less
普通文件
105
assets/less/variables.less
普通文件
@ -0,0 +1,105 @@
|
|||||||
|
// ============================================
|
||||||
|
// 呼籁旅行官网 - 设计变量
|
||||||
|
// 视觉定位:精致温暖,草原+大地色调
|
||||||
|
// ============================================
|
||||||
|
|
||||||
|
// ---------- 色彩系统 ----------
|
||||||
|
|
||||||
|
// 主色 - 深林绿:自然、稳重、值得信赖
|
||||||
|
@color-primary: #2D6A4F;
|
||||||
|
@color-primary-dark: #1B4332;
|
||||||
|
@color-primary-light: #40916C;
|
||||||
|
@color-primary-lighter: #B7E4C7;
|
||||||
|
@color-primary-bg: #F0F7F4;
|
||||||
|
|
||||||
|
// 点缀 - 暖琥珀:温暖、家庭、亲和
|
||||||
|
@color-accent: #D4883A;
|
||||||
|
@color-accent-light: #E8A85C;
|
||||||
|
@color-accent-bg: #FFF8F0;
|
||||||
|
|
||||||
|
// 中性色
|
||||||
|
@color-text-primary: #1A1A2E;
|
||||||
|
@color-text-secondary: #4A4A5A;
|
||||||
|
@color-text-muted: #8A8A9A;
|
||||||
|
@color-border: #E8E8ED;
|
||||||
|
@color-divider: #F0F0F4;
|
||||||
|
@color-bg-white: #FFFFFF;
|
||||||
|
@color-bg-gray: #F7F8FA;
|
||||||
|
@color-bg-warm: #FFFBF5;
|
||||||
|
|
||||||
|
// 语义色
|
||||||
|
@color-success: #2D6A4F;
|
||||||
|
@color-warning: #D4883A;
|
||||||
|
@color-error: #C1292E;
|
||||||
|
|
||||||
|
// ---------- 字体 ----------
|
||||||
|
|
||||||
|
@font-family-base: -apple-system, BlinkMacSystemFont, "PingFang SC",
|
||||||
|
"Hiragino Sans GB", "Microsoft YaHei", "Noto Sans CJK SC", sans-serif;
|
||||||
|
|
||||||
|
@font-size-xs: 12px;
|
||||||
|
@font-size-sm: 14px;
|
||||||
|
@font-size-base: 16px;
|
||||||
|
@font-size-md: 18px;
|
||||||
|
@font-size-lg: 20px;
|
||||||
|
@font-size-xl: 24px;
|
||||||
|
@font-size-2xl: 30px;
|
||||||
|
@font-size-3xl: 36px;
|
||||||
|
@font-size-hero: 42px;
|
||||||
|
@font-size-display: 48px;
|
||||||
|
|
||||||
|
@line-height-tight: 1.3;
|
||||||
|
@line-height-normal: 1.5;
|
||||||
|
@line-height-base: 1.7;
|
||||||
|
@line-height-relaxed: 1.8;
|
||||||
|
@line-height-loose: 2.0;
|
||||||
|
|
||||||
|
@font-weight-normal: 400;
|
||||||
|
@font-weight-medium: 500;
|
||||||
|
@font-weight-bold: 700;
|
||||||
|
|
||||||
|
// ---------- 间距(8px网格) ----------
|
||||||
|
|
||||||
|
@space-xs: 4px;
|
||||||
|
@space-sm: 8px;
|
||||||
|
@space-md: 16px;
|
||||||
|
@space-lg: 24px;
|
||||||
|
@space-xl: 32px;
|
||||||
|
@space-2xl: 48px;
|
||||||
|
@space-3xl: 64px;
|
||||||
|
@space-4xl: 96px;
|
||||||
|
|
||||||
|
// ---------- 容器 ----------
|
||||||
|
|
||||||
|
@container-max-width: 1200px;
|
||||||
|
@container-padding: 20px;
|
||||||
|
@container-padding-desktop: 40px;
|
||||||
|
|
||||||
|
// ---------- 断点 ----------
|
||||||
|
|
||||||
|
@breakpoint-sm: 375px;
|
||||||
|
@breakpoint-md: 768px;
|
||||||
|
@breakpoint-lg: 1024px;
|
||||||
|
@breakpoint-xl: 1200px;
|
||||||
|
|
||||||
|
// ---------- 圆角与阴影 ----------
|
||||||
|
|
||||||
|
@border-radius-sm: 4px;
|
||||||
|
@border-radius-md: 8px;
|
||||||
|
@border-radius-lg: 16px;
|
||||||
|
@border-radius-xl: 24px;
|
||||||
|
@border-radius-full: 9999px;
|
||||||
|
|
||||||
|
// 精致的阴影层次
|
||||||
|
@shadow-xs: 0 1px 2px rgba(0, 0, 0, 0.04);
|
||||||
|
@shadow-sm: 0 1px 3px rgba(0, 0, 0, 0.06);
|
||||||
|
@shadow-card: 0 2px 8px rgba(0, 0, 0, 0.06);
|
||||||
|
@shadow-md: 0 4px 16px rgba(0, 0, 0, 0.08);
|
||||||
|
@shadow-lg: 0 8px 32px rgba(0, 0, 0, 0.10);
|
||||||
|
@shadow-xl: 0 16px 48px rgba(0, 0, 0, 0.12);
|
||||||
|
|
||||||
|
// ---------- 过渡 ----------
|
||||||
|
|
||||||
|
@transition-fast: 0.15s ease;
|
||||||
|
@transition-base: 0.25s ease;
|
||||||
|
@transition-slow: 0.4s ease;
|
||||||
86
components/about/BrandStory.vue
普通文件
86
components/about/BrandStory.vue
普通文件
@ -0,0 +1,86 @@
|
|||||||
|
<template>
|
||||||
|
<section class="section">
|
||||||
|
<div class="container">
|
||||||
|
<CommonSectionTitle :title="story.title" align="left" />
|
||||||
|
<div class="story-layout">
|
||||||
|
<div class="story-content">
|
||||||
|
<template v-if="story.paragraphs">
|
||||||
|
<p v-for="(para, i) in story.paragraphs" :key="i" class="story-para">{{ para }}</p>
|
||||||
|
</template>
|
||||||
|
<p v-else>{{ story.content }}</p>
|
||||||
|
</div>
|
||||||
|
<div class="story-photo">
|
||||||
|
<div class="story-photo-card">
|
||||||
|
<img
|
||||||
|
:src="images.brandStory.photo"
|
||||||
|
alt="一家三口穿蒙古族传统服饰在草原上欢笑"
|
||||||
|
width="600"
|
||||||
|
height="400"
|
||||||
|
loading="lazy"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<p class="story-photo-caption">带孩子回到母亲的故乡</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup>
|
||||||
|
import images from '~/data/images.json'
|
||||||
|
defineProps({ story: { type: Object, required: true } })
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="less" scoped>
|
||||||
|
.story-layout {
|
||||||
|
display: grid;
|
||||||
|
grid-template-columns: 1fr;
|
||||||
|
gap: @space-xl;
|
||||||
|
align-items: center;
|
||||||
|
|
||||||
|
.respond-md({
|
||||||
|
grid-template-columns: 1fr 1fr;
|
||||||
|
gap: @space-3xl;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
.story-content {
|
||||||
|
p {
|
||||||
|
font-size: @font-size-md;
|
||||||
|
line-height: @line-height-loose;
|
||||||
|
color: @color-text-primary;
|
||||||
|
}
|
||||||
|
.story-para {
|
||||||
|
text-indent: 2em;
|
||||||
|
margin-bottom: @space-md;
|
||||||
|
&:last-child { margin-bottom: 0; }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.story-moment {
|
||||||
|
margin-top: @space-lg;
|
||||||
|
font-weight: @font-weight-medium;
|
||||||
|
}
|
||||||
|
|
||||||
|
.story-photo-card {
|
||||||
|
border-radius: @border-radius-lg;
|
||||||
|
overflow: hidden;
|
||||||
|
box-shadow: @shadow-lg;
|
||||||
|
|
||||||
|
img {
|
||||||
|
width: 100%;
|
||||||
|
display: block;
|
||||||
|
aspect-ratio: 4 / 3;
|
||||||
|
object-fit: cover;
|
||||||
|
object-position: center 35%;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.story-photo-caption {
|
||||||
|
text-align: center;
|
||||||
|
margin-top: @space-md;
|
||||||
|
font-size: @font-size-sm;
|
||||||
|
color: @color-text-muted;
|
||||||
|
letter-spacing: 0.5px;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
194
components/about/CopyrightList.vue
普通文件
194
components/about/CopyrightList.vue
普通文件
@ -0,0 +1,194 @@
|
|||||||
|
<template>
|
||||||
|
<section class="section">
|
||||||
|
<div class="container">
|
||||||
|
<CommonSectionTitle title="知识产权" subtitle="商标全品类注册 + 4项国家版权登记" />
|
||||||
|
<p class="copyright-intro">呼籁集团重视品牌知识产权保护。「呼籁」商标已完成全品类注册,核心产品名称、品牌标识和IP形象均已在中国版权保护中心完成作品登记。</p>
|
||||||
|
|
||||||
|
<!-- 商标 -->
|
||||||
|
<div v-if="trademark" class="trademark-card">
|
||||||
|
<div class="trademark-header">
|
||||||
|
<span class="trademark-badge">® 商标</span>
|
||||||
|
<h3 class="trademark-name">「{{ trademark.name }}」{{ trademark.scope }}</h3>
|
||||||
|
</div>
|
||||||
|
<p class="trademark-desc">{{ trademark.description }}</p>
|
||||||
|
<p class="trademark-holder">持有人:{{ trademark.holder }}</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- 版权 -->
|
||||||
|
<div class="copyright-grid">
|
||||||
|
<div v-for="c in copyrights" :key="c.regNo" class="copyright-card">
|
||||||
|
<div class="copyright-header">
|
||||||
|
<h3 class="copyright-name">{{ c.name }}</h3>
|
||||||
|
<span class="copyright-category">{{ c.category }}</span>
|
||||||
|
</div>
|
||||||
|
<p class="copyright-desc">{{ c.description }}</p>
|
||||||
|
<div class="copyright-meta">
|
||||||
|
<div class="copyright-meta-item">
|
||||||
|
<span class="meta-label">登记号</span>
|
||||||
|
<span class="meta-value">{{ c.regNo }}</span>
|
||||||
|
</div>
|
||||||
|
<div class="copyright-meta-item">
|
||||||
|
<span class="meta-label">登记日期</span>
|
||||||
|
<span class="meta-value">{{ c.date }}</span>
|
||||||
|
</div>
|
||||||
|
<div class="copyright-meta-item">
|
||||||
|
<span class="meta-label">著作权人</span>
|
||||||
|
<span class="meta-value">{{ c.holder }}</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<p class="copyright-note">以上作品均经中国版权保护中心审核,依据《作品自愿登记试行办法》予以登记。</p>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup>
|
||||||
|
defineProps({
|
||||||
|
copyrights: { type: Array, required: true },
|
||||||
|
trademark: { type: Object, default: null }
|
||||||
|
})
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="less" scoped>
|
||||||
|
.copyright-intro {
|
||||||
|
text-align: center;
|
||||||
|
max-width: 600px;
|
||||||
|
margin: 0 auto @space-xl;
|
||||||
|
font-size: @font-size-sm;
|
||||||
|
color: @color-text-secondary;
|
||||||
|
line-height: @line-height-base;
|
||||||
|
}
|
||||||
|
|
||||||
|
.trademark-card {
|
||||||
|
max-width: 900px;
|
||||||
|
margin: 0 auto @space-xl;
|
||||||
|
padding: @space-xl;
|
||||||
|
background: @color-primary-bg;
|
||||||
|
border: 1px solid fade(@color-primary, 20%);
|
||||||
|
border-radius: @border-radius-md;
|
||||||
|
box-shadow: 0 2px 12px rgba(0, 0, 0, 0.06);
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.trademark-header {
|
||||||
|
margin-bottom: @space-sm;
|
||||||
|
}
|
||||||
|
|
||||||
|
.trademark-badge {
|
||||||
|
display: inline-block;
|
||||||
|
font-size: @font-size-xs;
|
||||||
|
color: @color-bg-white;
|
||||||
|
background: @color-primary;
|
||||||
|
padding: 2px 10px;
|
||||||
|
border-radius: 20px;
|
||||||
|
margin-bottom: @space-sm;
|
||||||
|
}
|
||||||
|
|
||||||
|
.trademark-name {
|
||||||
|
font-size: @font-size-md;
|
||||||
|
font-weight: @font-weight-bold;
|
||||||
|
color: @color-text-primary;
|
||||||
|
margin: @space-sm 0 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.trademark-desc {
|
||||||
|
font-size: @font-size-sm;
|
||||||
|
color: @color-text-secondary;
|
||||||
|
line-height: @line-height-loose;
|
||||||
|
max-width: 700px;
|
||||||
|
margin: @space-sm auto @space-sm;
|
||||||
|
}
|
||||||
|
|
||||||
|
.trademark-holder {
|
||||||
|
font-size: @font-size-xs;
|
||||||
|
color: @color-text-muted;
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.copyright-grid {
|
||||||
|
display: grid;
|
||||||
|
grid-template-columns: 1fr;
|
||||||
|
gap: @space-md;
|
||||||
|
max-width: 900px;
|
||||||
|
margin: 0 auto;
|
||||||
|
|
||||||
|
.respond-md({
|
||||||
|
grid-template-columns: 1fr 1fr;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
.copyright-card {
|
||||||
|
background: @color-bg-white;
|
||||||
|
border: 1px solid @color-border;
|
||||||
|
border-radius: @border-radius-md;
|
||||||
|
padding: @space-lg;
|
||||||
|
transition: transform 0.2s ease;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
transform: translateY(-2px);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.copyright-header {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: space-between;
|
||||||
|
margin-bottom: @space-sm;
|
||||||
|
}
|
||||||
|
|
||||||
|
.copyright-name {
|
||||||
|
font-size: @font-size-md;
|
||||||
|
font-weight: @font-weight-bold;
|
||||||
|
color: @color-text-primary;
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.copyright-category {
|
||||||
|
font-size: @font-size-xs;
|
||||||
|
color: @color-primary;
|
||||||
|
background: @color-primary-bg;
|
||||||
|
padding: 2px 8px;
|
||||||
|
border-radius: @border-radius-sm;
|
||||||
|
flex-shrink: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.copyright-desc {
|
||||||
|
font-size: @font-size-sm;
|
||||||
|
color: @color-text-secondary;
|
||||||
|
line-height: @line-height-base;
|
||||||
|
margin-bottom: @space-md;
|
||||||
|
}
|
||||||
|
|
||||||
|
.copyright-meta {
|
||||||
|
border-top: 1px solid @color-bg-gray;
|
||||||
|
padding-top: @space-sm;
|
||||||
|
}
|
||||||
|
|
||||||
|
.copyright-meta-item {
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
align-items: baseline;
|
||||||
|
padding: 3px 0;
|
||||||
|
font-size: @font-size-xs;
|
||||||
|
}
|
||||||
|
|
||||||
|
.meta-label {
|
||||||
|
color: @color-text-muted;
|
||||||
|
flex-shrink: 0;
|
||||||
|
margin-right: @space-sm;
|
||||||
|
}
|
||||||
|
|
||||||
|
.meta-value {
|
||||||
|
color: @color-text-secondary;
|
||||||
|
text-align: right;
|
||||||
|
word-break: break-all;
|
||||||
|
}
|
||||||
|
|
||||||
|
.copyright-note {
|
||||||
|
text-align: center;
|
||||||
|
margin-top: @space-xl;
|
||||||
|
font-size: @font-size-xs;
|
||||||
|
color: @color-text-muted;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
@ -0,0 +1,33 @@
|
|||||||
|
<template>
|
||||||
|
<section class="section">
|
||||||
|
<div class="container">
|
||||||
|
<CommonSectionTitle title="企业文化" />
|
||||||
|
<p v-if="culture.core" class="culture-core">{{ culture.core }}</p>
|
||||||
|
<div class="values-grid">
|
||||||
|
<div v-for="v in culture.values" :key="v.name" class="value-item">
|
||||||
|
<h3 class="value-name">{{ v.name }}</h3>
|
||||||
|
<p class="value-expr">{{ v.expression }}</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup>
|
||||||
|
defineProps({ culture: { type: Object, required: true } })
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="less" scoped>
|
||||||
|
.culture-core {
|
||||||
|
text-align: center; font-size: @font-size-xl; font-weight: 600; color: @color-primary;
|
||||||
|
letter-spacing: 0.1em; margin-bottom: @space-2xl;
|
||||||
|
}
|
||||||
|
.values-grid {
|
||||||
|
display: grid; grid-template-columns: 1fr; gap: @space-lg;
|
||||||
|
.respond-md({ grid-template-columns: repeat(3, 1fr); });
|
||||||
|
}
|
||||||
|
.value-item { text-align: center; padding: @space-xl @space-lg; }
|
||||||
|
.value-name { font-size: @font-size-xl; color: @color-primary; margin-bottom: @space-sm; }
|
||||||
|
.value-expr { font-size: @font-size-base; color: @color-text-secondary; }
|
||||||
|
|
||||||
|
</style>
|
||||||
195
components/about/MascotShowcase.vue
普通文件
195
components/about/MascotShowcase.vue
普通文件
@ -0,0 +1,195 @@
|
|||||||
|
<template>
|
||||||
|
<section class="section section--warm">
|
||||||
|
<div class="container">
|
||||||
|
<CommonSectionTitle title="品牌IP · 籁小咩" subtitle="LAI XIAO MIE" />
|
||||||
|
|
||||||
|
<div class="mascot-hero">
|
||||||
|
<div class="mascot-image">
|
||||||
|
<img
|
||||||
|
:src="images.mascot.front"
|
||||||
|
alt="籁小咩 - 呼籁旅行品牌IP吉祥物,一只可爱的小羊形象"
|
||||||
|
width="280"
|
||||||
|
height="380"
|
||||||
|
loading="lazy"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div class="mascot-info">
|
||||||
|
<h3 class="mascot-name">籁小咩</h3>
|
||||||
|
<p class="mascot-intro">呼籁旅行的品牌IP吉祥物,灵感来自呼伦贝尔草原上自由奔跑的小羊。圆润的羊毛卷发、温暖的大眼睛、招手的小手势——籁小咩代表着呼籁对每一个家庭的热情欢迎。</p>
|
||||||
|
<div class="mascot-tags">
|
||||||
|
<span class="mascot-tag">原创IP形象</span>
|
||||||
|
<span class="mascot-tag">国家版权登记</span>
|
||||||
|
<span class="mascot-tag">表情包</span>
|
||||||
|
</div>
|
||||||
|
<p class="mascot-copyright">国家版权局作品登记:国作登字-2026-F-00020268</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- 草原场景 -->
|
||||||
|
<div class="mascot-banner">
|
||||||
|
<img
|
||||||
|
:src="images.mascot.banner"
|
||||||
|
alt="籁小咩在呼伦贝尔草原上向你招手"
|
||||||
|
width="800"
|
||||||
|
height="300"
|
||||||
|
loading="lazy"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- 表情包二维码 -->
|
||||||
|
<div class="mascot-sticker">
|
||||||
|
<div class="mascot-sticker-qr">
|
||||||
|
<img
|
||||||
|
:src="images.mascot.stickerQr"
|
||||||
|
alt="籁小咩微信表情包二维码"
|
||||||
|
width="160"
|
||||||
|
height="160"
|
||||||
|
loading="lazy"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div class="mascot-sticker-text">
|
||||||
|
<p class="mascot-sticker-title">把籁小咩带进你的聊天</p>
|
||||||
|
<p class="mascot-sticker-desc">微信扫一扫,免费领取「籁小咩」表情包。旅行前发给家人朋友,快乐先行一步。</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup>
|
||||||
|
import images from '~/data/images.json'
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="less" scoped>
|
||||||
|
.mascot-hero {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: center;
|
||||||
|
text-align: center;
|
||||||
|
gap: @space-xl;
|
||||||
|
max-width: 800px;
|
||||||
|
margin: 0 auto @space-2xl;
|
||||||
|
|
||||||
|
.respond-md({
|
||||||
|
flex-direction: row;
|
||||||
|
text-align: left;
|
||||||
|
gap: @space-2xl;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
.mascot-image {
|
||||||
|
flex-shrink: 0;
|
||||||
|
|
||||||
|
img {
|
||||||
|
width: 200px;
|
||||||
|
height: auto;
|
||||||
|
filter: drop-shadow(0 8px 24px rgba(0, 0, 0, 0.1));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.mascot-info {
|
||||||
|
flex: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
.mascot-name {
|
||||||
|
font-size: 28px;
|
||||||
|
font-weight: @font-weight-bold;
|
||||||
|
color: @color-text-primary;
|
||||||
|
margin: 0 0 @space-md;
|
||||||
|
}
|
||||||
|
|
||||||
|
.mascot-intro {
|
||||||
|
font-size: @font-size-base;
|
||||||
|
color: @color-text-secondary;
|
||||||
|
line-height: @line-height-loose;
|
||||||
|
margin-bottom: @space-lg;
|
||||||
|
}
|
||||||
|
|
||||||
|
.mascot-tags {
|
||||||
|
display: flex;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
gap: @space-sm;
|
||||||
|
margin-bottom: @space-md;
|
||||||
|
justify-content: center;
|
||||||
|
|
||||||
|
.respond-md({
|
||||||
|
justify-content: flex-start;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
.mascot-tag {
|
||||||
|
font-size: @font-size-xs;
|
||||||
|
color: @color-primary;
|
||||||
|
background: @color-primary-bg;
|
||||||
|
padding: 4px 12px;
|
||||||
|
border-radius: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.mascot-copyright {
|
||||||
|
font-size: @font-size-xs;
|
||||||
|
color: @color-text-muted;
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.mascot-banner {
|
||||||
|
max-width: 800px;
|
||||||
|
margin: 0 auto @space-2xl;
|
||||||
|
border-radius: @border-radius-lg;
|
||||||
|
overflow: hidden;
|
||||||
|
|
||||||
|
img {
|
||||||
|
width: 100%;
|
||||||
|
height: auto;
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.mascot-sticker {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: center;
|
||||||
|
text-align: center;
|
||||||
|
gap: @space-lg;
|
||||||
|
max-width: 500px;
|
||||||
|
margin: 0 auto;
|
||||||
|
padding: @space-xl;
|
||||||
|
background: @color-bg-white;
|
||||||
|
border-radius: @border-radius-lg;
|
||||||
|
border: 1px solid @color-border;
|
||||||
|
|
||||||
|
.respond-md({
|
||||||
|
flex-direction: row;
|
||||||
|
text-align: left;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
.mascot-sticker-qr {
|
||||||
|
flex-shrink: 0;
|
||||||
|
|
||||||
|
img {
|
||||||
|
width: 120px;
|
||||||
|
height: 120px;
|
||||||
|
border-radius: @border-radius-md;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.mascot-sticker-text {
|
||||||
|
flex: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
.mascot-sticker-title {
|
||||||
|
font-size: @font-size-md;
|
||||||
|
font-weight: @font-weight-medium;
|
||||||
|
color: @color-text-primary;
|
||||||
|
margin-bottom: @space-sm;
|
||||||
|
}
|
||||||
|
|
||||||
|
.mascot-sticker-desc {
|
||||||
|
font-size: @font-size-sm;
|
||||||
|
color: @color-text-secondary;
|
||||||
|
line-height: 1.6;
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
</style>
|
||||||
@ -0,0 +1,131 @@
|
|||||||
|
<template>
|
||||||
|
<section class="section">
|
||||||
|
<div class="container">
|
||||||
|
<!-- 资质认证 -->
|
||||||
|
<CommonSectionTitle title="资质认证" />
|
||||||
|
<div class="qual-list">
|
||||||
|
<div v-for="c in certifications" :key="c.title" class="qual-item qual-item--cert">
|
||||||
|
<div class="qual-icon">🏆</div>
|
||||||
|
<div class="qual-body">
|
||||||
|
<h3 class="qual-title">{{ c.title }}</h3>
|
||||||
|
<p class="qual-detail">{{ c.detail }}</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- 小红书WILL大会获奖照片 -->
|
||||||
|
<div class="award-gallery">
|
||||||
|
<div class="award-gallery-grid">
|
||||||
|
<img src="/images/awards/will-award-person.jpg" alt="呼籁旅行创始人在2026小红书WILL商业大会领取年度成长型品牌奖" class="award-img award-img--main" loading="lazy" />
|
||||||
|
<img src="/images/awards/will-award-trophy.jpg" alt="2026小红书WILL商业大会年度成长型品牌奖杯" class="award-img" loading="lazy" />
|
||||||
|
<img src="/images/awards/will-award-stage.jpg" alt="2026小红书WILL商业大会年度成长型品牌颁奖典礼" class="award-img" loading="lazy" />
|
||||||
|
</div>
|
||||||
|
<p class="award-caption">2026小红书WILL商业大会 · 年度成长型品牌 · 文旅行业仅6家获此殊荣</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- 服务保障 -->
|
||||||
|
<CommonSectionTitle title="服务保障" style="margin-top: 48px;" />
|
||||||
|
<div class="qual-list qual-list--grid">
|
||||||
|
<div v-for="g in guarantees" :key="g.title" class="qual-item qual-item--guarantee">
|
||||||
|
<div class="qual-icon">✅</div>
|
||||||
|
<div class="qual-body">
|
||||||
|
<h3 class="qual-title">{{ g.title }}</h3>
|
||||||
|
<p class="qual-detail">{{ g.detail }}</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup>
|
||||||
|
defineProps({
|
||||||
|
certifications: { type: Array, required: true },
|
||||||
|
guarantees: { type: Array, required: true }
|
||||||
|
})
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="less" scoped>
|
||||||
|
.qual-list {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
gap: @space-md;
|
||||||
|
max-width: 800px;
|
||||||
|
margin: 0 auto;
|
||||||
|
}
|
||||||
|
.qual-list--grid {
|
||||||
|
display: grid;
|
||||||
|
grid-template-columns: 1fr 1fr;
|
||||||
|
gap: @space-md;
|
||||||
|
.respond-md({
|
||||||
|
grid-template-columns: 1fr;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
.qual-item {
|
||||||
|
display: flex;
|
||||||
|
align-items: flex-start;
|
||||||
|
gap: @space-sm;
|
||||||
|
padding: @space-lg;
|
||||||
|
border-radius: @border-radius-md;
|
||||||
|
transition: transform 0.2s ease;
|
||||||
|
&:hover { transform: translateY(-2px); }
|
||||||
|
}
|
||||||
|
.qual-item--cert {
|
||||||
|
background: @color-primary-bg;
|
||||||
|
border-left: 3px solid @color-primary;
|
||||||
|
}
|
||||||
|
.qual-item--guarantee {
|
||||||
|
background: #f8faf5;
|
||||||
|
border-left: 3px solid @color-primary;
|
||||||
|
}
|
||||||
|
.qual-icon {
|
||||||
|
font-size: 24px;
|
||||||
|
flex-shrink: 0;
|
||||||
|
line-height: 1;
|
||||||
|
}
|
||||||
|
.qual-body { flex: 1; }
|
||||||
|
.qual-title {
|
||||||
|
font-size: @font-size-md;
|
||||||
|
color: @color-text-primary;
|
||||||
|
margin-bottom: @space-xs;
|
||||||
|
font-weight: @font-weight-bold;
|
||||||
|
}
|
||||||
|
.qual-detail {
|
||||||
|
font-size: @font-size-sm;
|
||||||
|
color: @color-text-secondary;
|
||||||
|
line-height: @line-height-base;
|
||||||
|
}
|
||||||
|
|
||||||
|
.award-gallery {
|
||||||
|
max-width: 800px;
|
||||||
|
margin: @space-xl auto 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.award-gallery-grid {
|
||||||
|
display: grid;
|
||||||
|
grid-template-columns: 1fr 1fr 1fr;
|
||||||
|
gap: @space-sm;
|
||||||
|
|
||||||
|
@media (max-width: 768px) {
|
||||||
|
grid-template-columns: 1fr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.award-img {
|
||||||
|
width: 100%;
|
||||||
|
border-radius: @border-radius-md;
|
||||||
|
object-fit: cover;
|
||||||
|
aspect-ratio: 3 / 4;
|
||||||
|
|
||||||
|
@media (max-width: 768px) {
|
||||||
|
aspect-ratio: 4 / 3;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.award-caption {
|
||||||
|
text-align: center;
|
||||||
|
margin-top: @space-md;
|
||||||
|
font-size: @font-size-xs;
|
||||||
|
color: @color-text-muted;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
104
components/about/SubsidiaryGrid.vue
普通文件
104
components/about/SubsidiaryGrid.vue
普通文件
@ -0,0 +1,104 @@
|
|||||||
|
<template>
|
||||||
|
<section class="section section--gray">
|
||||||
|
<div class="container">
|
||||||
|
<CommonSectionTitle :title="`${subsidiaries.length}家集团企业`" subtitle="各司其职,共同为您的旅行保驾护航" />
|
||||||
|
|
||||||
|
<!-- 集团母公司 -->
|
||||||
|
<div v-if="parent" class="sub-parent">
|
||||||
|
<span class="sub-parent-tag">集团母公司</span>
|
||||||
|
<h3 class="sub-parent-name">{{ parent.name }}</h3>
|
||||||
|
<p class="sub-parent-role">{{ parent.role }}</p>
|
||||||
|
<p v-if="parent.established" class="sub-parent-date">成立于{{ formatDate(parent.established) }}</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- 子公司网格 -->
|
||||||
|
<div class="sub-grid">
|
||||||
|
<div v-for="sub in children" :key="sub.name" class="sub-item">
|
||||||
|
<h3 class="sub-name">{{ sub.name }}</h3>
|
||||||
|
<p class="sub-role">{{ sub.role }}</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup>
|
||||||
|
const props = defineProps({ subsidiaries: { type: Array, required: true } })
|
||||||
|
|
||||||
|
const parent = props.subsidiaries.find(s => s.role.includes('集团母公司') || s.role.includes('母公司'))
|
||||||
|
const children = props.subsidiaries.filter(s => s !== parent)
|
||||||
|
|
||||||
|
function formatDate(dateStr) {
|
||||||
|
const [year, month] = dateStr.split('-')
|
||||||
|
return `${year}年${parseInt(month)}月`
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="less" scoped>
|
||||||
|
.sub-parent {
|
||||||
|
max-width: 900px;
|
||||||
|
margin: 0 auto @space-xl;
|
||||||
|
padding: @space-xl @space-2xl;
|
||||||
|
background: @color-bg-white;
|
||||||
|
border: 1px solid @color-border;
|
||||||
|
border-radius: @border-radius-lg;
|
||||||
|
box-shadow: 0 2px 12px rgba(0, 0, 0, 0.06);
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.sub-parent-tag {
|
||||||
|
display: inline-block;
|
||||||
|
font-size: @font-size-xs;
|
||||||
|
color: @color-bg-white;
|
||||||
|
background: @color-primary;
|
||||||
|
padding: 2px 12px;
|
||||||
|
border-radius: 20px;
|
||||||
|
margin-bottom: @space-sm;
|
||||||
|
}
|
||||||
|
|
||||||
|
.sub-parent-name {
|
||||||
|
font-size: @font-size-lg;
|
||||||
|
font-weight: @font-weight-bold;
|
||||||
|
color: @color-text-primary;
|
||||||
|
margin-bottom: @space-xs;
|
||||||
|
}
|
||||||
|
|
||||||
|
.sub-parent-role {
|
||||||
|
font-size: @font-size-base;
|
||||||
|
color: @color-text-secondary;
|
||||||
|
margin-bottom: @space-xs;
|
||||||
|
}
|
||||||
|
|
||||||
|
.sub-parent-date {
|
||||||
|
font-size: @font-size-xs;
|
||||||
|
color: @color-text-muted;
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.sub-grid {
|
||||||
|
display: grid;
|
||||||
|
grid-template-columns: 1fr;
|
||||||
|
gap: @space-md;
|
||||||
|
|
||||||
|
.respond-md({ grid-template-columns: repeat(2, 1fr); });
|
||||||
|
.respond-lg({ grid-template-columns: repeat(2, 1fr); max-width: 900px; margin-left: auto; margin-right: auto; });
|
||||||
|
}
|
||||||
|
|
||||||
|
.sub-item {
|
||||||
|
padding: @space-lg;
|
||||||
|
background: @color-bg-white;
|
||||||
|
border-radius: @border-radius-md;
|
||||||
|
border: 1px solid @color-border;
|
||||||
|
}
|
||||||
|
|
||||||
|
.sub-name {
|
||||||
|
font-size: @font-size-base;
|
||||||
|
color: @color-primary;
|
||||||
|
margin-bottom: @space-xs;
|
||||||
|
}
|
||||||
|
|
||||||
|
.sub-role {
|
||||||
|
font-size: @font-size-sm;
|
||||||
|
color: @color-text-secondary;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
179
components/about/TeamIntro.vue
普通文件
179
components/about/TeamIntro.vue
普通文件
@ -0,0 +1,179 @@
|
|||||||
|
<template>
|
||||||
|
<section class="section section--warm">
|
||||||
|
<div class="container">
|
||||||
|
<CommonSectionTitle title="我们的团队" />
|
||||||
|
<p class="team-summary">{{ team.summary }}</p>
|
||||||
|
|
||||||
|
<!-- 团队照片墙 -->
|
||||||
|
<div class="team-gallery">
|
||||||
|
<!-- 上排:两年踩线对比,体现年年坚持 -->
|
||||||
|
<div class="team-gallery-row team-gallery-row--survey">
|
||||||
|
<div class="team-photo-card">
|
||||||
|
<div class="team-photo-wrap team-photo-wrap--survey">
|
||||||
|
<img
|
||||||
|
:src="images.team.guideGroup"
|
||||||
|
alt="2024呼籁文旅车队踩线全体领队合影"
|
||||||
|
loading="lazy"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div class="team-photo-caption">
|
||||||
|
<span class="caption-tag">2024踩线</span>
|
||||||
|
<span class="caption-text">「额吉的故乡」全体车队师傅集体踩线</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="team-photo-card">
|
||||||
|
<div class="team-photo-wrap team-photo-wrap--survey">
|
||||||
|
<img
|
||||||
|
:src="images.team.routeSurvey"
|
||||||
|
alt="2025秋呼籁文旅游牧的森林车队踩线全体领队合影"
|
||||||
|
loading="lazy"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div class="team-photo-caption">
|
||||||
|
<span class="caption-tag">2025踩线</span>
|
||||||
|
<span class="caption-text">「游牧的森林」新品路线全员实地考察</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- 下排:培训 + 牧场 -->
|
||||||
|
<div class="team-gallery-row team-gallery-row--misc">
|
||||||
|
<div class="team-photo-card">
|
||||||
|
<div class="team-photo-wrap team-photo-wrap--misc">
|
||||||
|
<img
|
||||||
|
:src="images.team.guideTraining"
|
||||||
|
alt="呼籁文旅2026年司导线下培训"
|
||||||
|
loading="lazy"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div class="team-photo-caption">
|
||||||
|
<span class="caption-tag">专业培训</span>
|
||||||
|
<span class="caption-text">每年冬季集中培训,统一服务标准</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="team-photo-card">
|
||||||
|
<div class="team-photo-wrap team-photo-wrap--misc">
|
||||||
|
<img
|
||||||
|
:src="images.team.ranchStore"
|
||||||
|
alt="呼籁牧场线下店开业团队合影"
|
||||||
|
loading="lazy"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div class="team-photo-caption">
|
||||||
|
<span class="caption-tag">实体布局</span>
|
||||||
|
<span class="caption-text">呼籁牧场线下体验店正式落成</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup>
|
||||||
|
import images from '~/data/images.json'
|
||||||
|
defineProps({ team: { type: Object, required: true } })
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="less" scoped>
|
||||||
|
.team-summary {
|
||||||
|
max-width: 800px;
|
||||||
|
margin: 0 auto @space-2xl;
|
||||||
|
text-align: center;
|
||||||
|
font-size: @font-size-md;
|
||||||
|
line-height: @line-height-base;
|
||||||
|
color: @color-text-secondary;
|
||||||
|
}
|
||||||
|
|
||||||
|
.team-gallery {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
gap: @space-lg;
|
||||||
|
|
||||||
|
.respond-md({
|
||||||
|
gap: @space-xl;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
.team-gallery-row {
|
||||||
|
display: grid;
|
||||||
|
grid-template-columns: 1fr;
|
||||||
|
gap: @space-lg;
|
||||||
|
|
||||||
|
.respond-md({
|
||||||
|
gap: @space-xl;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
.team-gallery-row--survey {
|
||||||
|
.respond-md({
|
||||||
|
grid-template-columns: 1fr 1fr;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
.team-gallery-row--misc {
|
||||||
|
.respond-md({
|
||||||
|
grid-template-columns: 1fr 1fr;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
.team-photo-card {
|
||||||
|
border-radius: @border-radius-lg;
|
||||||
|
overflow: hidden;
|
||||||
|
background: @color-bg-white;
|
||||||
|
box-shadow: @shadow-md;
|
||||||
|
transition: transform @transition-base, box-shadow @transition-base;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
transform: translateY(-2px);
|
||||||
|
box-shadow: @shadow-lg;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.team-photo-wrap {
|
||||||
|
position: relative;
|
||||||
|
overflow: hidden;
|
||||||
|
|
||||||
|
img {
|
||||||
|
width: 100%;
|
||||||
|
display: block;
|
||||||
|
object-fit: cover;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.team-photo-wrap--survey {
|
||||||
|
img {
|
||||||
|
aspect-ratio: 16 / 9;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.team-photo-wrap--misc {
|
||||||
|
img {
|
||||||
|
aspect-ratio: 16 / 10;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.team-photo-caption {
|
||||||
|
padding: @space-md @space-lg;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: @space-md;
|
||||||
|
}
|
||||||
|
|
||||||
|
.caption-tag {
|
||||||
|
flex-shrink: 0;
|
||||||
|
display: inline-block;
|
||||||
|
padding: 3px 10px;
|
||||||
|
background: @color-primary-bg;
|
||||||
|
color: @color-primary;
|
||||||
|
font-size: @font-size-sm;
|
||||||
|
font-weight: @font-weight-medium;
|
||||||
|
border-radius: @border-radius-sm;
|
||||||
|
}
|
||||||
|
|
||||||
|
.caption-text {
|
||||||
|
font-size: @font-size-sm;
|
||||||
|
color: @color-text-secondary;
|
||||||
|
line-height: 1.5;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
@ -0,0 +1,211 @@
|
|||||||
|
<template>
|
||||||
|
<section class="section">
|
||||||
|
<div class="container">
|
||||||
|
<CommonSectionTitle title="小红书上的呼籁" subtitle="XIAOHONGSHU" />
|
||||||
|
|
||||||
|
<div class="xhs-card">
|
||||||
|
<!-- 顶部:品牌主页截图作为横幅 -->
|
||||||
|
<div class="xhs-banner">
|
||||||
|
<img
|
||||||
|
:src="images.xiaohongshu.storefront"
|
||||||
|
alt="呼籁旅行小红书品牌主页 - Mr.小雷-呼籁旅行 50万家庭青睐的草原旅行品牌"
|
||||||
|
width="800"
|
||||||
|
height="300"
|
||||||
|
loading="lazy"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- 底部:数据 + 信息 -->
|
||||||
|
<div class="xhs-body">
|
||||||
|
<!-- 账号信息 -->
|
||||||
|
<div class="xhs-header">
|
||||||
|
<div class="xhs-account">
|
||||||
|
<span class="xhs-account-name">{{ xhs.account }}</span>
|
||||||
|
<span class="xhs-badge">{{ xhs.verifiedType }}</span>
|
||||||
|
</div>
|
||||||
|
<p class="xhs-tagline">{{ xhs.tagline }}</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- 数据指标 -->
|
||||||
|
<div class="xhs-stats">
|
||||||
|
<div class="xhs-stat">
|
||||||
|
<span class="xhs-stat-value">{{ xhs.followers }}</span>
|
||||||
|
<span class="xhs-stat-label">粉丝</span>
|
||||||
|
</div>
|
||||||
|
<div class="xhs-stat-divider" />
|
||||||
|
<div class="xhs-stat">
|
||||||
|
<span class="xhs-stat-value">{{ xhs.likes }}</span>
|
||||||
|
<span class="xhs-stat-label">获赞与收藏</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- 荣誉 + 描述 -->
|
||||||
|
<div class="xhs-awards">
|
||||||
|
<span v-for="award in xhs.awards" :key="award" class="xhs-award">{{ award }}</span>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<p class="xhs-desc">{{ xhs.description }}</p>
|
||||||
|
|
||||||
|
<div class="xhs-tags">
|
||||||
|
<span v-for="tag in xhs.tags" :key="tag" class="xhs-tag">{{ tag }}</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup>
|
||||||
|
import images from '~/data/images.json'
|
||||||
|
defineProps({ xhs: { type: Object, required: true } })
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="less" scoped>
|
||||||
|
.xhs-card {
|
||||||
|
max-width: 800px;
|
||||||
|
margin: 0 auto;
|
||||||
|
border-radius: @border-radius-lg;
|
||||||
|
overflow: hidden;
|
||||||
|
background: @color-bg-white;
|
||||||
|
box-shadow: @shadow-md;
|
||||||
|
}
|
||||||
|
|
||||||
|
.xhs-banner {
|
||||||
|
position: relative;
|
||||||
|
overflow: hidden;
|
||||||
|
|
||||||
|
img {
|
||||||
|
width: 100%;
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.xhs-body {
|
||||||
|
padding: @space-xl;
|
||||||
|
|
||||||
|
.respond-md({
|
||||||
|
padding: @space-xl @space-2xl;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
.xhs-header {
|
||||||
|
margin-bottom: @space-lg;
|
||||||
|
}
|
||||||
|
|
||||||
|
.xhs-account {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: @space-sm;
|
||||||
|
margin-bottom: @space-xs;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
}
|
||||||
|
|
||||||
|
.xhs-account-name {
|
||||||
|
font-size: @font-size-lg;
|
||||||
|
font-weight: @font-weight-bold;
|
||||||
|
color: @color-text-primary;
|
||||||
|
}
|
||||||
|
|
||||||
|
.xhs-badge {
|
||||||
|
display: inline-block;
|
||||||
|
padding: 2px 10px;
|
||||||
|
background: #ff2442;
|
||||||
|
color: #fff;
|
||||||
|
font-size: @font-size-xs;
|
||||||
|
border-radius: 20px;
|
||||||
|
font-weight: @font-weight-medium;
|
||||||
|
}
|
||||||
|
|
||||||
|
.xhs-tagline {
|
||||||
|
font-size: @font-size-base;
|
||||||
|
color: @color-primary;
|
||||||
|
font-weight: @font-weight-medium;
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.xhs-stats {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: @space-lg;
|
||||||
|
padding: @space-lg 0;
|
||||||
|
margin-bottom: @space-lg;
|
||||||
|
border-top: 1px solid @color-border;
|
||||||
|
border-bottom: 1px solid @color-border;
|
||||||
|
}
|
||||||
|
|
||||||
|
.xhs-stat {
|
||||||
|
text-align: center;
|
||||||
|
flex: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
.xhs-stat-divider {
|
||||||
|
width: 1px;
|
||||||
|
height: 32px;
|
||||||
|
background: @color-border;
|
||||||
|
flex-shrink: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.xhs-stat-value {
|
||||||
|
display: block;
|
||||||
|
font-size: 24px;
|
||||||
|
font-weight: @font-weight-bold;
|
||||||
|
color: @color-text-primary;
|
||||||
|
line-height: 1.2;
|
||||||
|
|
||||||
|
.respond-md({
|
||||||
|
font-size: 28px;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
.xhs-stat-label {
|
||||||
|
font-size: @font-size-xs;
|
||||||
|
color: @color-text-muted;
|
||||||
|
margin-top: 4px;
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
|
||||||
|
.xhs-awards {
|
||||||
|
display: flex;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
gap: @space-sm;
|
||||||
|
margin-bottom: @space-md;
|
||||||
|
}
|
||||||
|
|
||||||
|
.xhs-award {
|
||||||
|
display: inline-flex;
|
||||||
|
align-items: center;
|
||||||
|
padding: 5px 12px;
|
||||||
|
background: linear-gradient(135deg, #FFF8E1, #FFF3CD);
|
||||||
|
color: #B8860B;
|
||||||
|
font-size: @font-size-sm;
|
||||||
|
font-weight: @font-weight-medium;
|
||||||
|
border-radius: @border-radius-sm;
|
||||||
|
border: 1px solid #F0D58C;
|
||||||
|
|
||||||
|
&::before {
|
||||||
|
content: "🏆";
|
||||||
|
margin-right: 6px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.xhs-desc {
|
||||||
|
font-size: @font-size-sm;
|
||||||
|
color: @color-text-secondary;
|
||||||
|
line-height: @line-height-loose;
|
||||||
|
margin-bottom: @space-md;
|
||||||
|
}
|
||||||
|
|
||||||
|
.xhs-tags {
|
||||||
|
display: flex;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
gap: @space-sm;
|
||||||
|
}
|
||||||
|
|
||||||
|
.xhs-tag {
|
||||||
|
font-size: @font-size-xs;
|
||||||
|
color: @color-text-secondary;
|
||||||
|
background: @color-bg-gray;
|
||||||
|
padding: 4px 12px;
|
||||||
|
border-radius: 20px;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
250
components/autumn/ProductCard.vue
普通文件
250
components/autumn/ProductCard.vue
普通文件
@ -0,0 +1,250 @@
|
|||||||
|
<template>
|
||||||
|
<article class="autumn-card" :class="{ 'autumn-card--popular': isPopular }">
|
||||||
|
<!-- 头部 -->
|
||||||
|
<div class="card-header">
|
||||||
|
<div v-if="isPopular" class="popular-badge">推荐</div>
|
||||||
|
<div class="card-duration">
|
||||||
|
<span class="duration-num">{{ product.days }}</span>
|
||||||
|
<span class="duration-unit">天</span>
|
||||||
|
<span class="duration-num">{{ product.nights }}</span>
|
||||||
|
<span class="duration-unit">晚</span>
|
||||||
|
</div>
|
||||||
|
<span class="card-tag">{{ product.tag }}</span>
|
||||||
|
<span class="card-line">{{ product.line }} · {{ product.route }}</span>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- 主体 -->
|
||||||
|
<div class="card-body">
|
||||||
|
<h3 class="card-name">{{ shortName }}</h3>
|
||||||
|
<p class="card-audience">适合:{{ product.audience }}</p>
|
||||||
|
<p class="card-desc">{{ product.description }}</p>
|
||||||
|
<ul class="card-highlights">
|
||||||
|
<li v-for="(h, i) in product.highlights" :key="i">
|
||||||
|
<span class="check" aria-hidden="true">✓</span>
|
||||||
|
{{ h }}
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- 行程概览 -->
|
||||||
|
<details v-if="product.itinerary && product.itinerary.length" class="card-itinerary">
|
||||||
|
<summary class="itinerary-toggle">查看每日行程 ▾</summary>
|
||||||
|
<ol class="itinerary-list">
|
||||||
|
<li v-for="(day, i) in product.itinerary" :key="i">{{ day }}</li>
|
||||||
|
</ol>
|
||||||
|
</details>
|
||||||
|
|
||||||
|
<!-- 底部 CTA -->
|
||||||
|
<NuxtLink to="/contact" class="card-cta">
|
||||||
|
咨询该行程 <span aria-hidden="true">→</span>
|
||||||
|
</NuxtLink>
|
||||||
|
</article>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup>
|
||||||
|
const props = defineProps({ product: { type: Object, required: true } })
|
||||||
|
|
||||||
|
const isPopular = computed(() => props.product.id === 'autumn-south-7d6n')
|
||||||
|
|
||||||
|
const shortName = computed(() => {
|
||||||
|
return props.product.name.replace(/^游牧的森林V3·/, '')
|
||||||
|
})
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="less" scoped>
|
||||||
|
.autumn-card {
|
||||||
|
background: @color-bg-white;
|
||||||
|
border: 1px solid @color-border;
|
||||||
|
border-radius: @border-radius-lg;
|
||||||
|
overflow: hidden;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
transition: box-shadow @transition-base, transform @transition-base;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
box-shadow: @shadow-lg;
|
||||||
|
transform: translateY(-4px);
|
||||||
|
}
|
||||||
|
|
||||||
|
&--popular {
|
||||||
|
border: 2px solid #D97706;
|
||||||
|
box-shadow: @shadow-md;
|
||||||
|
|
||||||
|
.card-header {
|
||||||
|
background: #D97706;
|
||||||
|
}
|
||||||
|
|
||||||
|
.duration-num,
|
||||||
|
.duration-unit,
|
||||||
|
.card-tag,
|
||||||
|
.card-line {
|
||||||
|
color: #fff;
|
||||||
|
}
|
||||||
|
|
||||||
|
.card-tag {
|
||||||
|
background: rgba(255, 255, 255, 0.2);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.card-header {
|
||||||
|
padding: @space-lg @space-lg @space-md;
|
||||||
|
background: #FEF3C7;
|
||||||
|
text-align: center;
|
||||||
|
position: relative;
|
||||||
|
}
|
||||||
|
|
||||||
|
.popular-badge {
|
||||||
|
position: absolute;
|
||||||
|
top: @space-sm;
|
||||||
|
right: @space-sm;
|
||||||
|
padding: @space-xs @space-sm;
|
||||||
|
font-size: @font-size-xs;
|
||||||
|
font-weight: @font-weight-bold;
|
||||||
|
color: #fff;
|
||||||
|
background: @color-accent;
|
||||||
|
border-radius: @border-radius-sm;
|
||||||
|
}
|
||||||
|
|
||||||
|
.card-duration {
|
||||||
|
display: flex;
|
||||||
|
align-items: baseline;
|
||||||
|
justify-content: center;
|
||||||
|
gap: 2px;
|
||||||
|
margin-bottom: @space-sm;
|
||||||
|
}
|
||||||
|
|
||||||
|
.duration-num {
|
||||||
|
font-size: @font-size-3xl;
|
||||||
|
font-weight: @font-weight-bold;
|
||||||
|
color: #D97706;
|
||||||
|
line-height: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
.duration-unit {
|
||||||
|
font-size: @font-size-sm;
|
||||||
|
color: #D97706;
|
||||||
|
font-weight: @font-weight-medium;
|
||||||
|
}
|
||||||
|
|
||||||
|
.card-tag {
|
||||||
|
display: inline-block;
|
||||||
|
padding: @space-xs @space-md;
|
||||||
|
font-size: @font-size-xs;
|
||||||
|
font-weight: @font-weight-medium;
|
||||||
|
color: #D97706;
|
||||||
|
background: @color-bg-white;
|
||||||
|
border-radius: @border-radius-full;
|
||||||
|
}
|
||||||
|
|
||||||
|
.card-line {
|
||||||
|
display: block;
|
||||||
|
font-size: @font-size-xs;
|
||||||
|
color: #64748B;
|
||||||
|
margin-top: @space-xs;
|
||||||
|
}
|
||||||
|
|
||||||
|
.card-body {
|
||||||
|
padding: @space-lg;
|
||||||
|
flex: 1;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
}
|
||||||
|
|
||||||
|
.card-name {
|
||||||
|
font-size: @font-size-lg;
|
||||||
|
font-weight: @font-weight-bold;
|
||||||
|
color: @color-text-primary;
|
||||||
|
margin-bottom: @space-xs;
|
||||||
|
}
|
||||||
|
|
||||||
|
.card-audience {
|
||||||
|
font-size: @font-size-sm;
|
||||||
|
color: @color-text-muted;
|
||||||
|
margin-bottom: @space-md;
|
||||||
|
}
|
||||||
|
|
||||||
|
.card-desc {
|
||||||
|
font-size: @font-size-sm;
|
||||||
|
color: @color-text-secondary;
|
||||||
|
line-height: @line-height-base;
|
||||||
|
margin-bottom: @space-md;
|
||||||
|
.text-clamp(3);
|
||||||
|
}
|
||||||
|
|
||||||
|
.card-highlights {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
gap: @space-sm;
|
||||||
|
margin-top: auto;
|
||||||
|
|
||||||
|
li {
|
||||||
|
display: flex;
|
||||||
|
align-items: flex-start;
|
||||||
|
gap: @space-sm;
|
||||||
|
font-size: @font-size-sm;
|
||||||
|
color: @color-text-secondary;
|
||||||
|
line-height: @line-height-base;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.check {
|
||||||
|
flex-shrink: 0;
|
||||||
|
color: #D97706;
|
||||||
|
font-size: @font-size-sm;
|
||||||
|
font-weight: @font-weight-bold;
|
||||||
|
margin-top: 2px;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 行程概览
|
||||||
|
.card-itinerary {
|
||||||
|
border-top: 1px solid @color-border;
|
||||||
|
}
|
||||||
|
|
||||||
|
.itinerary-toggle {
|
||||||
|
display: block;
|
||||||
|
padding: @space-md @space-lg;
|
||||||
|
font-size: @font-size-sm;
|
||||||
|
color: @color-text-muted;
|
||||||
|
cursor: pointer;
|
||||||
|
text-align: center;
|
||||||
|
transition: background @transition-fast;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
background: @color-bg-gray;
|
||||||
|
color: @color-text-primary;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.itinerary-list {
|
||||||
|
padding: 0 @space-lg @space-md;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
gap: @space-xs;
|
||||||
|
|
||||||
|
li {
|
||||||
|
font-size: @font-size-xs;
|
||||||
|
color: @color-text-secondary;
|
||||||
|
line-height: @line-height-base;
|
||||||
|
padding-left: @space-sm;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 底部 CTA
|
||||||
|
.card-cta {
|
||||||
|
display: block;
|
||||||
|
text-align: center;
|
||||||
|
padding: @space-md @space-lg;
|
||||||
|
font-size: @font-size-sm;
|
||||||
|
font-weight: @font-weight-medium;
|
||||||
|
color: #D97706;
|
||||||
|
background: @color-bg-gray;
|
||||||
|
text-decoration: none;
|
||||||
|
transition: all @transition-fast;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
background: #D97706;
|
||||||
|
color: #fff;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
@ -0,0 +1,55 @@
|
|||||||
|
<template>
|
||||||
|
<nav v-if="items.length" class="breadcrumb" aria-label="面包屑导航">
|
||||||
|
<ol class="breadcrumb-list">
|
||||||
|
<li class="breadcrumb-item">
|
||||||
|
<NuxtLink to="/" class="breadcrumb-link">首页</NuxtLink>
|
||||||
|
</li>
|
||||||
|
<li v-for="(item, index) in items" :key="index" class="breadcrumb-item">
|
||||||
|
<span class="breadcrumb-sep" aria-hidden="true">/</span>
|
||||||
|
<NuxtLink v-if="item.to" :to="item.to" class="breadcrumb-link">{{ item.text }}</NuxtLink>
|
||||||
|
<span v-else class="breadcrumb-current" aria-current="page">{{ item.text }}</span>
|
||||||
|
</li>
|
||||||
|
</ol>
|
||||||
|
</nav>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup>
|
||||||
|
defineProps({
|
||||||
|
items: { type: Array, default: () => [] },
|
||||||
|
})
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="less" scoped>
|
||||||
|
.breadcrumb-list {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
gap: @space-xs;
|
||||||
|
}
|
||||||
|
|
||||||
|
.breadcrumb-item {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: @space-xs;
|
||||||
|
}
|
||||||
|
|
||||||
|
.breadcrumb-sep {
|
||||||
|
color: @color-text-muted;
|
||||||
|
font-size: @font-size-sm;
|
||||||
|
}
|
||||||
|
|
||||||
|
.breadcrumb-link {
|
||||||
|
font-size: @font-size-sm;
|
||||||
|
color: @color-text-muted;
|
||||||
|
text-decoration: none;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
color: @color-primary;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.breadcrumb-current {
|
||||||
|
font-size: @font-size-sm;
|
||||||
|
color: @color-text-secondary;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
@ -0,0 +1,26 @@
|
|||||||
|
<template>
|
||||||
|
<div class="content-card" :class="{ 'content-card--hoverable': hoverable }">
|
||||||
|
<slot />
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup>
|
||||||
|
defineProps({
|
||||||
|
hoverable: { type: Boolean, default: true },
|
||||||
|
})
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="less" scoped>
|
||||||
|
.content-card {
|
||||||
|
background: @color-bg-white;
|
||||||
|
border: 1px solid @color-border;
|
||||||
|
border-radius: @border-radius-lg;
|
||||||
|
padding: @space-xl;
|
||||||
|
transition: box-shadow 0.3s cubic-bezier(0.23, 1, 0.32, 1), transform 0.3s cubic-bezier(0.23, 1, 0.32, 1);
|
||||||
|
|
||||||
|
&--hoverable:hover {
|
||||||
|
box-shadow: @shadow-md;
|
||||||
|
transform: translateY(-3px);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
@ -0,0 +1,37 @@
|
|||||||
|
<template>
|
||||||
|
<NuxtLink :to="to" class="internal-link">
|
||||||
|
<span>{{ text }}</span>
|
||||||
|
<span v-if="arrow" class="internal-link-arrow" aria-hidden="true">→</span>
|
||||||
|
</NuxtLink>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup>
|
||||||
|
defineProps({
|
||||||
|
to: { type: String, required: true },
|
||||||
|
text: { type: String, required: true },
|
||||||
|
arrow: { type: Boolean, default: true },
|
||||||
|
})
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="less" scoped>
|
||||||
|
.internal-link {
|
||||||
|
display: inline-flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: @space-sm;
|
||||||
|
font-size: @font-size-base;
|
||||||
|
color: @color-primary;
|
||||||
|
text-decoration: none;
|
||||||
|
font-weight: @font-weight-medium;
|
||||||
|
transition: gap @transition-fast;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
gap: @space-md;
|
||||||
|
color: @color-primary-light;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.internal-link-arrow {
|
||||||
|
font-size: @font-size-lg;
|
||||||
|
transition: transform @transition-fast;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
@ -0,0 +1,54 @@
|
|||||||
|
<template>
|
||||||
|
<div class="qr-block" :class="[`qr-block--${size}`]">
|
||||||
|
<img :src="image" :alt="`${label}二维码`" class="qr-image" loading="lazy" />
|
||||||
|
<span class="qr-label">{{ label }}</span>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup>
|
||||||
|
defineProps({
|
||||||
|
image: { type: String, required: true },
|
||||||
|
label: { type: String, required: true },
|
||||||
|
size: { type: String, default: 'normal' },
|
||||||
|
})
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="less" scoped>
|
||||||
|
.qr-block {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: center;
|
||||||
|
gap: @space-xs;
|
||||||
|
}
|
||||||
|
|
||||||
|
.qr-image {
|
||||||
|
border-radius: @border-radius-sm;
|
||||||
|
background: @color-bg-gray;
|
||||||
|
object-fit: contain;
|
||||||
|
|
||||||
|
.qr-block--small & {
|
||||||
|
width: 80px;
|
||||||
|
height: 80px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.qr-block--normal & {
|
||||||
|
width: 140px;
|
||||||
|
height: 140px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.qr-block--large & {
|
||||||
|
width: 180px;
|
||||||
|
height: 180px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.qr-label {
|
||||||
|
font-size: @font-size-xs;
|
||||||
|
color: @color-text-muted;
|
||||||
|
|
||||||
|
.qr-block--normal &,
|
||||||
|
.qr-block--large & {
|
||||||
|
font-size: @font-size-sm;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
160
components/common/SectionCTA.vue
普通文件
160
components/common/SectionCTA.vue
普通文件
@ -0,0 +1,160 @@
|
|||||||
|
<template>
|
||||||
|
<section class="section-cta" :class="`section-cta--${bg}`">
|
||||||
|
<div class="section-cta-bg" />
|
||||||
|
<div class="container text-center section-cta-inner">
|
||||||
|
<h2 class="section-cta-title">{{ title }}</h2>
|
||||||
|
<p class="section-cta-desc">{{ description }}</p>
|
||||||
|
<div class="section-cta-links">
|
||||||
|
<NuxtLink
|
||||||
|
v-for="(link, index) in links"
|
||||||
|
:key="link.to"
|
||||||
|
:to="link.to"
|
||||||
|
class="cta-btn"
|
||||||
|
:class="index === 0 ? 'cta-btn--primary' : 'cta-btn--outline'"
|
||||||
|
>
|
||||||
|
{{ link.text }}
|
||||||
|
</NuxtLink>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup>
|
||||||
|
defineProps({
|
||||||
|
title: { type: String, required: true },
|
||||||
|
description: { type: String, required: true },
|
||||||
|
links: { type: Array, required: true },
|
||||||
|
bg: { type: String, default: 'green' },
|
||||||
|
})
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="less" scoped>
|
||||||
|
.section-cta {
|
||||||
|
position: relative;
|
||||||
|
overflow: hidden;
|
||||||
|
.section-padding();
|
||||||
|
}
|
||||||
|
|
||||||
|
.section-cta--green {
|
||||||
|
background: linear-gradient(135deg, @color-primary-dark 0%, @color-primary 50%, @color-primary-light 100%);
|
||||||
|
}
|
||||||
|
|
||||||
|
.section-cta--warm {
|
||||||
|
background: linear-gradient(135deg, @color-bg-warm 0%, @color-accent-bg 100%);
|
||||||
|
}
|
||||||
|
|
||||||
|
.section-cta-bg {
|
||||||
|
position: absolute;
|
||||||
|
inset: 0;
|
||||||
|
background: radial-gradient(ellipse at 20% 50%, rgba(255, 255, 255, 0.08) 0%, transparent 60%),
|
||||||
|
radial-gradient(ellipse at 80% 50%, rgba(255, 255, 255, 0.05) 0%, transparent 60%);
|
||||||
|
pointer-events: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.section-cta-inner {
|
||||||
|
position: relative;
|
||||||
|
z-index: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
.section-cta-title {
|
||||||
|
.section-cta--green & {
|
||||||
|
color: #fff;
|
||||||
|
}
|
||||||
|
|
||||||
|
&::after {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.section-cta-desc {
|
||||||
|
margin-top: @space-md;
|
||||||
|
margin-bottom: @space-xl;
|
||||||
|
font-size: @font-size-md;
|
||||||
|
line-height: @line-height-relaxed;
|
||||||
|
max-width: 560px;
|
||||||
|
margin-left: auto;
|
||||||
|
margin-right: auto;
|
||||||
|
|
||||||
|
.section-cta--green & {
|
||||||
|
color: rgba(255, 255, 255, 0.8);
|
||||||
|
}
|
||||||
|
|
||||||
|
.section-cta--warm & {
|
||||||
|
color: @color-text-secondary;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.section-cta-links {
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
gap: @space-md;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
}
|
||||||
|
|
||||||
|
.cta-btn {
|
||||||
|
display: inline-flex;
|
||||||
|
align-items: center;
|
||||||
|
padding: 14px @space-xl;
|
||||||
|
border-radius: @border-radius-md;
|
||||||
|
font-size: @font-size-base;
|
||||||
|
font-weight: @font-weight-medium;
|
||||||
|
text-decoration: none;
|
||||||
|
transition: all @transition-base;
|
||||||
|
|
||||||
|
.respond-md({
|
||||||
|
padding: 16px 36px;
|
||||||
|
font-size: @font-size-md;
|
||||||
|
});
|
||||||
|
|
||||||
|
&--primary {
|
||||||
|
.section-cta--green & {
|
||||||
|
background: #fff;
|
||||||
|
color: @color-primary;
|
||||||
|
border: 1px solid #fff;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
background: rgba(255, 255, 255, 0.9);
|
||||||
|
color: @color-primary-dark;
|
||||||
|
transform: translateY(-2px);
|
||||||
|
box-shadow: 0 4px 16px rgba(0, 0, 0, 0.15);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.section-cta--warm & {
|
||||||
|
background: @color-primary;
|
||||||
|
color: #fff;
|
||||||
|
border: 1px solid @color-primary;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
background: @color-primary-light;
|
||||||
|
border-color: @color-primary-light;
|
||||||
|
color: #fff;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&--outline {
|
||||||
|
.section-cta--green & {
|
||||||
|
border: 1px solid rgba(255, 255, 255, 0.5);
|
||||||
|
color: #fff;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
background: rgba(255, 255, 255, 0.15);
|
||||||
|
border-color: rgba(255, 255, 255, 0.8);
|
||||||
|
color: #fff;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.section-cta--warm & {
|
||||||
|
background: transparent;
|
||||||
|
color: @color-primary;
|
||||||
|
border: 1px solid @color-primary;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
background: @color-primary;
|
||||||
|
color: #fff;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
@ -0,0 +1,74 @@
|
|||||||
|
<template>
|
||||||
|
<div class="section-title" :class="[`section-title--${align}`]">
|
||||||
|
<span v-if="label" class="section-title-label">{{ label }}</span>
|
||||||
|
<component :is="tag" class="section-title-text">{{ title }}</component>
|
||||||
|
<p v-if="subtitle" class="section-title-sub">{{ subtitle }}</p>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup>
|
||||||
|
defineProps({
|
||||||
|
title: { type: String, required: true },
|
||||||
|
subtitle: { type: String, default: '' },
|
||||||
|
label: { type: String, default: '' },
|
||||||
|
tag: { type: String, default: 'h2' },
|
||||||
|
align: { type: String, default: 'center' },
|
||||||
|
})
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="less" scoped>
|
||||||
|
.section-title {
|
||||||
|
margin-bottom: @space-xl;
|
||||||
|
|
||||||
|
.respond-md({
|
||||||
|
margin-bottom: @space-2xl;
|
||||||
|
});
|
||||||
|
|
||||||
|
&--center {
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
&--left {
|
||||||
|
text-align: left;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.section-title-label {
|
||||||
|
display: inline-block;
|
||||||
|
font-size: @font-size-xs;
|
||||||
|
font-weight: @font-weight-bold;
|
||||||
|
color: @color-primary;
|
||||||
|
text-transform: uppercase;
|
||||||
|
letter-spacing: 2px;
|
||||||
|
margin-bottom: @space-sm;
|
||||||
|
}
|
||||||
|
|
||||||
|
.section-title-text {
|
||||||
|
color: @color-text-primary;
|
||||||
|
|
||||||
|
// 标题下方品牌色渐变短线装饰
|
||||||
|
&::after {
|
||||||
|
content: '';
|
||||||
|
display: block;
|
||||||
|
width: 48px;
|
||||||
|
height: 3px;
|
||||||
|
background: linear-gradient(90deg, @color-primary, @color-primary-light);
|
||||||
|
border-radius: 2px;
|
||||||
|
margin-top: @space-md;
|
||||||
|
}
|
||||||
|
|
||||||
|
.section-title--center & {
|
||||||
|
&::after {
|
||||||
|
margin-left: auto;
|
||||||
|
margin-right: auto;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.section-title-sub {
|
||||||
|
margin-top: @space-md;
|
||||||
|
font-size: @font-size-md;
|
||||||
|
color: @color-text-muted;
|
||||||
|
line-height: @line-height-relaxed;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
83
components/common/TrustBadge.vue
普通文件
83
components/common/TrustBadge.vue
普通文件
@ -0,0 +1,83 @@
|
|||||||
|
<template>
|
||||||
|
<div class="trust-badge" :class="{ 'trust-badge--dark': dark }">
|
||||||
|
<div class="trust-badge-value">
|
||||||
|
<span class="trust-number">{{ value }}</span>
|
||||||
|
<span v-if="unit" class="trust-unit">{{ unit }}</span>
|
||||||
|
</div>
|
||||||
|
<div class="trust-badge-label">{{ label }}</div>
|
||||||
|
<div v-if="attribution" class="trust-badge-note">{{ attribution }}</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup>
|
||||||
|
defineProps({
|
||||||
|
value: { type: String, required: true },
|
||||||
|
unit: { type: String, default: '' },
|
||||||
|
label: { type: String, required: true },
|
||||||
|
attribution: { type: String, default: '' },
|
||||||
|
dark: { type: Boolean, default: false },
|
||||||
|
})
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="less" scoped>
|
||||||
|
.trust-badge {
|
||||||
|
text-align: center;
|
||||||
|
padding: @space-lg @space-md;
|
||||||
|
}
|
||||||
|
|
||||||
|
.trust-badge-value {
|
||||||
|
display: flex;
|
||||||
|
align-items: baseline;
|
||||||
|
justify-content: center;
|
||||||
|
gap: @space-xs;
|
||||||
|
}
|
||||||
|
|
||||||
|
.trust-number {
|
||||||
|
font-size: @font-size-3xl;
|
||||||
|
font-weight: @font-weight-bold;
|
||||||
|
color: @color-primary;
|
||||||
|
letter-spacing: -1px;
|
||||||
|
|
||||||
|
.respond-md({
|
||||||
|
font-size: @font-size-display;
|
||||||
|
});
|
||||||
|
|
||||||
|
.trust-badge--dark & {
|
||||||
|
color: #fff;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.trust-unit {
|
||||||
|
font-size: @font-size-base;
|
||||||
|
color: @color-primary-light;
|
||||||
|
|
||||||
|
.respond-md({
|
||||||
|
font-size: @font-size-md;
|
||||||
|
});
|
||||||
|
|
||||||
|
.trust-badge--dark & {
|
||||||
|
color: @color-primary-lighter;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.trust-badge-label {
|
||||||
|
margin-top: @space-sm;
|
||||||
|
font-size: @font-size-sm;
|
||||||
|
color: @color-text-secondary;
|
||||||
|
font-weight: @font-weight-medium;
|
||||||
|
|
||||||
|
.trust-badge--dark & {
|
||||||
|
color: rgba(255, 255, 255, 0.6);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.trust-badge-note {
|
||||||
|
margin-top: @space-xs;
|
||||||
|
font-size: @font-size-xs;
|
||||||
|
color: @color-text-muted;
|
||||||
|
|
||||||
|
.trust-badge--dark & {
|
||||||
|
color: rgba(255, 255, 255, 0.35);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
@ -0,0 +1,43 @@
|
|||||||
|
<template>
|
||||||
|
<CommonContentCard :class="{ 'channel-primary': channel.primary }">
|
||||||
|
<div class="channel">
|
||||||
|
<span v-if="channel.primary" class="channel-badge">推荐</span>
|
||||||
|
<h3 class="channel-label">{{ channel.label }}</h3>
|
||||||
|
<p class="channel-value">{{ channel.value }}</p>
|
||||||
|
<p v-if="channel.description" class="channel-desc">{{ channel.description }}</p>
|
||||||
|
<CommonQRCodeBlock
|
||||||
|
v-if="channel.qrImage"
|
||||||
|
:image="channel.qrImage"
|
||||||
|
:label="channel.label"
|
||||||
|
size="normal"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</CommonContentCard>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup>
|
||||||
|
defineProps({ channel: { type: Object, required: true } })
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="less" scoped>
|
||||||
|
.channel { text-align: center; }
|
||||||
|
.channel-label { font-size: @font-size-md; color: @color-primary; margin-bottom: @space-sm; }
|
||||||
|
.channel-value { font-size: @font-size-base; color: @color-text-primary; font-weight: @font-weight-medium; margin-bottom: @space-xs; }
|
||||||
|
.channel-desc { font-size: @font-size-sm; color: @color-text-muted; margin-bottom: @space-md; }
|
||||||
|
|
||||||
|
.channel-primary {
|
||||||
|
border: 2px solid @color-primary;
|
||||||
|
position: relative;
|
||||||
|
}
|
||||||
|
|
||||||
|
.channel-badge {
|
||||||
|
display: inline-block;
|
||||||
|
padding: @space-xs @space-md;
|
||||||
|
font-size: @font-size-xs;
|
||||||
|
font-weight: @font-weight-medium;
|
||||||
|
color: #fff;
|
||||||
|
background: @color-primary;
|
||||||
|
border-radius: @border-radius-full;
|
||||||
|
margin-bottom: @space-md;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
@ -0,0 +1,14 @@
|
|||||||
|
<template>
|
||||||
|
<div class="contact-map">
|
||||||
|
<p class="map-address">{{ address }}</p>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup>
|
||||||
|
defineProps({ address: { type: String, required: true } })
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="less" scoped>
|
||||||
|
.contact-map { padding: @space-lg; background: @color-bg-gray; border-radius: @border-radius-md; text-align: center; }
|
||||||
|
.map-address { color: @color-text-secondary; }
|
||||||
|
</style>
|
||||||
43
components/faq/FaqCategory.vue
普通文件
43
components/faq/FaqCategory.vue
普通文件
@ -0,0 +1,43 @@
|
|||||||
|
<template>
|
||||||
|
<section :id="category.id" class="faq-category">
|
||||||
|
<h2 class="faq-category-title">{{ category.name }}</h2>
|
||||||
|
<div class="faq-category-list">
|
||||||
|
<FaqItem
|
||||||
|
v-for="q in category.questions"
|
||||||
|
:key="q.id"
|
||||||
|
:question="q.question"
|
||||||
|
:answer="q.answer"
|
||||||
|
:related-links="q.relatedLinks"
|
||||||
|
:initial-open="initialOpen"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup>
|
||||||
|
defineProps({
|
||||||
|
category: { type: Object, required: true },
|
||||||
|
initialOpen: { type: Boolean, default: false },
|
||||||
|
})
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="less" scoped>
|
||||||
|
.faq-category {
|
||||||
|
margin-bottom: @space-2xl;
|
||||||
|
scroll-margin-top: 80px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.faq-category-title {
|
||||||
|
font-size: @font-size-xl;
|
||||||
|
color: @color-primary;
|
||||||
|
margin-bottom: @space-lg;
|
||||||
|
padding-bottom: @space-sm;
|
||||||
|
border-bottom: 2px solid @color-primary-lighter;
|
||||||
|
}
|
||||||
|
|
||||||
|
.faq-category-list {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
gap: @space-md;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
@ -0,0 +1,85 @@
|
|||||||
|
<template>
|
||||||
|
<nav class="faq-nav" aria-label="问题分类">
|
||||||
|
<ul class="faq-nav-list">
|
||||||
|
<li v-for="cat in categories" :key="cat.id">
|
||||||
|
<a
|
||||||
|
:href="`#${cat.id}`"
|
||||||
|
class="faq-nav-item"
|
||||||
|
:class="{ active: activeCat === cat.id }"
|
||||||
|
@click.prevent="$emit('select', cat.id)"
|
||||||
|
>
|
||||||
|
{{ cat.name }}
|
||||||
|
<span class="faq-nav-count">{{ cat.questions.length }}</span>
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</nav>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup>
|
||||||
|
defineProps({
|
||||||
|
categories: { type: Array, required: true },
|
||||||
|
activeCat: { type: String, default: '' },
|
||||||
|
})
|
||||||
|
|
||||||
|
defineEmits(['select'])
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="less" scoped>
|
||||||
|
.faq-nav {
|
||||||
|
overflow-x: auto;
|
||||||
|
-webkit-overflow-scrolling: touch;
|
||||||
|
|
||||||
|
// 移动端右侧渐变提示可横滑
|
||||||
|
mask-image: linear-gradient(to right, #000 85%, transparent 100%);
|
||||||
|
-webkit-mask-image: linear-gradient(to right, #000 85%, transparent 100%);
|
||||||
|
|
||||||
|
.respond-md({
|
||||||
|
mask-image: none;
|
||||||
|
-webkit-mask-image: none;
|
||||||
|
overflow-x: visible;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
.faq-nav-list {
|
||||||
|
display: flex;
|
||||||
|
gap: @space-sm;
|
||||||
|
min-width: max-content;
|
||||||
|
|
||||||
|
.respond-md({
|
||||||
|
justify-content: center;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
.faq-nav-item {
|
||||||
|
display: inline-flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: @space-xs;
|
||||||
|
padding: @space-sm @space-lg;
|
||||||
|
font-size: @font-size-sm;
|
||||||
|
color: @color-text-secondary;
|
||||||
|
background: @color-bg-gray;
|
||||||
|
border-radius: @border-radius-full;
|
||||||
|
text-decoration: none;
|
||||||
|
white-space: nowrap;
|
||||||
|
transition: all @transition-fast;
|
||||||
|
min-height: 44px;
|
||||||
|
touch-action: manipulation;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
background: @color-primary-bg;
|
||||||
|
color: @color-primary;
|
||||||
|
}
|
||||||
|
|
||||||
|
&.active {
|
||||||
|
background: @color-primary;
|
||||||
|
color: #fff;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.faq-nav-count {
|
||||||
|
font-size: @font-size-xs;
|
||||||
|
opacity: 0.7;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
170
components/faq/FaqItem.vue
普通文件
170
components/faq/FaqItem.vue
普通文件
@ -0,0 +1,170 @@
|
|||||||
|
<template>
|
||||||
|
<!--
|
||||||
|
SEO关键设计:
|
||||||
|
1. 用<details>/<summary>确保内容在HTML中始终存在(百度蜘蛛可抓取)
|
||||||
|
2. 问题用<h3>标签,语义化
|
||||||
|
3. 答案用<p>纯文本,AI直接引用
|
||||||
|
-->
|
||||||
|
<details class="faq-item" :open="initialOpen || undefined">
|
||||||
|
<summary class="faq-item-question">
|
||||||
|
<h3 class="faq-item-q-text">{{ question }}</h3>
|
||||||
|
<span class="faq-item-icon" aria-hidden="true"></span>
|
||||||
|
</summary>
|
||||||
|
<div class="faq-item-answer">
|
||||||
|
<p class="faq-item-a-text">{{ answer }}</p>
|
||||||
|
<div v-if="relatedLinks && relatedLinks.length" class="faq-item-links">
|
||||||
|
<NuxtLink
|
||||||
|
v-for="link in relatedLinks"
|
||||||
|
:key="link.url"
|
||||||
|
:to="link.url"
|
||||||
|
class="faq-item-link"
|
||||||
|
>
|
||||||
|
{{ link.text }} →
|
||||||
|
</NuxtLink>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</details>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup>
|
||||||
|
defineProps({
|
||||||
|
question: { type: String, required: true },
|
||||||
|
answer: { type: String, required: true },
|
||||||
|
relatedLinks: { type: Array, default: () => [] },
|
||||||
|
initialOpen: { type: Boolean, default: false },
|
||||||
|
})
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="less" scoped>
|
||||||
|
.faq-item {
|
||||||
|
background: @color-bg-white;
|
||||||
|
border: 1px solid @color-border;
|
||||||
|
border-radius: @border-radius-md;
|
||||||
|
overflow: hidden;
|
||||||
|
transition: border-color @transition-fast;
|
||||||
|
|
||||||
|
&[open] {
|
||||||
|
border-color: @color-primary-lighter;
|
||||||
|
|
||||||
|
.faq-item-icon {
|
||||||
|
transform: rotate(180deg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
border-color: @color-primary-lighter;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.faq-item-question {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: space-between;
|
||||||
|
padding: @space-lg;
|
||||||
|
cursor: pointer;
|
||||||
|
list-style: none;
|
||||||
|
touch-action: manipulation;
|
||||||
|
|
||||||
|
&::-webkit-details-marker {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
&::marker {
|
||||||
|
display: none;
|
||||||
|
content: '';
|
||||||
|
}
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
background: @color-bg-gray;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.faq-item-q-text {
|
||||||
|
font-size: @font-size-md;
|
||||||
|
font-weight: @font-weight-medium;
|
||||||
|
color: @color-text-primary;
|
||||||
|
flex: 1;
|
||||||
|
padding-right: @space-md;
|
||||||
|
}
|
||||||
|
|
||||||
|
.faq-item-icon {
|
||||||
|
width: 20px;
|
||||||
|
height: 20px;
|
||||||
|
flex-shrink: 0;
|
||||||
|
position: relative;
|
||||||
|
transition: transform @transition-base;
|
||||||
|
|
||||||
|
&::before,
|
||||||
|
&::after {
|
||||||
|
content: '';
|
||||||
|
position: absolute;
|
||||||
|
background: @color-text-muted;
|
||||||
|
transition: opacity @transition-fast;
|
||||||
|
}
|
||||||
|
|
||||||
|
&::before {
|
||||||
|
top: 50%;
|
||||||
|
left: 2px;
|
||||||
|
right: 2px;
|
||||||
|
height: 2px;
|
||||||
|
transform: translateY(-50%);
|
||||||
|
}
|
||||||
|
|
||||||
|
&::after {
|
||||||
|
left: 50%;
|
||||||
|
top: 2px;
|
||||||
|
bottom: 2px;
|
||||||
|
width: 2px;
|
||||||
|
transform: translateX(-50%);
|
||||||
|
}
|
||||||
|
|
||||||
|
details[open] & {
|
||||||
|
&::after {
|
||||||
|
opacity: 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 答案展开动画
|
||||||
|
.faq-item-answer {
|
||||||
|
padding: 0 @space-lg @space-lg;
|
||||||
|
animation: fadeSlideIn @transition-base;
|
||||||
|
}
|
||||||
|
|
||||||
|
@keyframes fadeSlideIn {
|
||||||
|
from {
|
||||||
|
opacity: 0;
|
||||||
|
transform: translateY(-8px);
|
||||||
|
}
|
||||||
|
to {
|
||||||
|
opacity: 1;
|
||||||
|
transform: translateY(0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.faq-item-a-text {
|
||||||
|
font-size: @font-size-base;
|
||||||
|
color: @color-text-secondary;
|
||||||
|
line-height: @line-height-base;
|
||||||
|
}
|
||||||
|
|
||||||
|
.faq-item-links {
|
||||||
|
display: flex;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
gap: @space-md;
|
||||||
|
margin-top: @space-md;
|
||||||
|
padding-top: @space-md;
|
||||||
|
border-top: 1px solid @color-border;
|
||||||
|
}
|
||||||
|
|
||||||
|
.faq-item-link {
|
||||||
|
font-size: @font-size-sm;
|
||||||
|
color: @color-primary;
|
||||||
|
text-decoration: none;
|
||||||
|
font-weight: @font-weight-medium;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
color: @color-primary-light;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
@ -0,0 +1,67 @@
|
|||||||
|
<template>
|
||||||
|
<div class="activity-card">
|
||||||
|
<h4 class="activity-name">
|
||||||
|
<span class="activity-icon">{{ activity.icon }}</span>
|
||||||
|
{{ activity.name }}
|
||||||
|
</h4>
|
||||||
|
<ul class="activity-points">
|
||||||
|
<li v-for="(point, i) in activity.points" :key="i" class="activity-point">
|
||||||
|
{{ point }}
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup>
|
||||||
|
defineProps({
|
||||||
|
activity: { type: Object, required: true },
|
||||||
|
})
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="less" scoped>
|
||||||
|
.activity-card {
|
||||||
|
background: @color-bg-white;
|
||||||
|
border: 1px solid @color-border;
|
||||||
|
border-radius: @border-radius-md;
|
||||||
|
padding: @space-lg;
|
||||||
|
}
|
||||||
|
|
||||||
|
.activity-name {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: @space-sm;
|
||||||
|
font-size: @font-size-md;
|
||||||
|
font-weight: @font-weight-bold;
|
||||||
|
color: @color-primary;
|
||||||
|
margin: 0 0 @space-md;
|
||||||
|
}
|
||||||
|
|
||||||
|
.activity-icon {
|
||||||
|
font-size: @font-size-lg;
|
||||||
|
}
|
||||||
|
|
||||||
|
.activity-points {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
gap: @space-sm;
|
||||||
|
padding: 0;
|
||||||
|
margin: 0;
|
||||||
|
list-style: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.activity-point {
|
||||||
|
font-size: @font-size-sm;
|
||||||
|
color: @color-text-secondary;
|
||||||
|
line-height: @line-height-base;
|
||||||
|
padding-left: @space-md;
|
||||||
|
position: relative;
|
||||||
|
|
||||||
|
&::before {
|
||||||
|
content: '·';
|
||||||
|
position: absolute;
|
||||||
|
left: 0;
|
||||||
|
color: @color-primary;
|
||||||
|
font-weight: @font-weight-bold;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
@ -0,0 +1,53 @@
|
|||||||
|
<template>
|
||||||
|
<div class="guide-checklist">
|
||||||
|
<div
|
||||||
|
v-for="(item, i) in items"
|
||||||
|
:key="i"
|
||||||
|
class="checklist-item"
|
||||||
|
:class="{ 'checklist-item--important': item.important }"
|
||||||
|
>
|
||||||
|
<span class="checklist-mark">{{ item.important ? '☑' : '☐' }}</span>
|
||||||
|
<span class="checklist-text">{{ item.text }}</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup>
|
||||||
|
defineProps({
|
||||||
|
items: { type: Array, required: true },
|
||||||
|
})
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="less" scoped>
|
||||||
|
.guide-checklist {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
gap: @space-sm;
|
||||||
|
}
|
||||||
|
|
||||||
|
.checklist-item {
|
||||||
|
display: flex;
|
||||||
|
gap: @space-sm;
|
||||||
|
padding: @space-sm @space-md;
|
||||||
|
border-left: 2px solid @color-border;
|
||||||
|
line-height: @line-height-base;
|
||||||
|
|
||||||
|
&--important {
|
||||||
|
border-left-color: @color-primary;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.checklist-mark {
|
||||||
|
flex-shrink: 0;
|
||||||
|
color: @color-primary;
|
||||||
|
}
|
||||||
|
|
||||||
|
.checklist-text {
|
||||||
|
font-size: @font-size-sm;
|
||||||
|
color: @color-text-secondary;
|
||||||
|
|
||||||
|
.checklist-item--important & {
|
||||||
|
color: @color-text-primary;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
@ -0,0 +1,107 @@
|
|||||||
|
<template>
|
||||||
|
<div class="clothing-card" :class="{ 'clothing-card--highlight': month.highlight }">
|
||||||
|
<div class="clothing-header">
|
||||||
|
<h4 class="clothing-month">{{ month.name }}</h4>
|
||||||
|
<span v-if="month.highlight" class="clothing-tag">大多数家庭选这个月</span>
|
||||||
|
</div>
|
||||||
|
<p class="clothing-desc">{{ month.desc }}</p>
|
||||||
|
<div class="clothing-temps">
|
||||||
|
<span class="temp-badge"><strong>白天</strong> {{ month.tempDay }}</span>
|
||||||
|
<span class="temp-badge"><strong>夜间</strong> {{ month.tempNight }}</span>
|
||||||
|
</div>
|
||||||
|
<div class="clothing-wear">
|
||||||
|
<p class="wear-line"><span class="wear-label">大人</span>{{ month.adultWear }}</p>
|
||||||
|
<p class="wear-line"><span class="wear-label">小朋友</span>{{ month.kidsWear }}</p>
|
||||||
|
</div>
|
||||||
|
<p v-if="month.note" class="clothing-note">{{ month.note }}</p>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup>
|
||||||
|
defineProps({
|
||||||
|
month: { type: Object, required: true },
|
||||||
|
})
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="less" scoped>
|
||||||
|
.clothing-card {
|
||||||
|
background: @color-bg-white;
|
||||||
|
border: 1px solid @color-border;
|
||||||
|
border-radius: @border-radius-md;
|
||||||
|
padding: @space-lg;
|
||||||
|
|
||||||
|
&--highlight {
|
||||||
|
border-color: @color-primary-lighter;
|
||||||
|
box-shadow: 0 2px 12px rgba(45, 106, 79, 0.08);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.clothing-header {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: @space-sm;
|
||||||
|
margin-bottom: @space-xs;
|
||||||
|
}
|
||||||
|
|
||||||
|
.clothing-month {
|
||||||
|
font-size: @font-size-base;
|
||||||
|
font-weight: @font-weight-bold;
|
||||||
|
color: @color-primary;
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.clothing-tag {
|
||||||
|
font-size: @font-size-xs;
|
||||||
|
color: @color-accent;
|
||||||
|
font-weight: @font-weight-medium;
|
||||||
|
}
|
||||||
|
|
||||||
|
.clothing-desc {
|
||||||
|
font-size: @font-size-sm;
|
||||||
|
color: @color-text-muted;
|
||||||
|
margin-bottom: @space-sm;
|
||||||
|
}
|
||||||
|
|
||||||
|
.clothing-temps {
|
||||||
|
display: flex;
|
||||||
|
gap: @space-lg;
|
||||||
|
margin-bottom: @space-md;
|
||||||
|
font-size: @font-size-sm;
|
||||||
|
color: @color-text-secondary;
|
||||||
|
|
||||||
|
strong {
|
||||||
|
color: @color-primary;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.clothing-wear {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
gap: @space-xs;
|
||||||
|
}
|
||||||
|
|
||||||
|
.wear-line {
|
||||||
|
font-size: @font-size-sm;
|
||||||
|
color: @color-text-secondary;
|
||||||
|
line-height: @line-height-base;
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.wear-label {
|
||||||
|
display: inline-block;
|
||||||
|
font-weight: @font-weight-medium;
|
||||||
|
color: @color-primary;
|
||||||
|
margin-right: @space-sm;
|
||||||
|
min-width: 48px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.clothing-note {
|
||||||
|
margin-top: @space-md;
|
||||||
|
padding: @space-sm @space-md;
|
||||||
|
background: @color-bg-warm;
|
||||||
|
border-radius: @border-radius-sm;
|
||||||
|
font-size: @font-size-sm;
|
||||||
|
color: @color-accent;
|
||||||
|
line-height: @line-height-base;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
66
components/guides/GuideNav.vue
普通文件
66
components/guides/GuideNav.vue
普通文件
@ -0,0 +1,66 @@
|
|||||||
|
<template>
|
||||||
|
<nav class="guide-nav">
|
||||||
|
<button
|
||||||
|
v-for="section in sections"
|
||||||
|
:key="section.id"
|
||||||
|
class="guide-nav-btn"
|
||||||
|
:class="{ active: active === section.id }"
|
||||||
|
@click="$emit('select', section.id)"
|
||||||
|
>
|
||||||
|
<span class="guide-nav-icon">{{ section.icon }}</span>
|
||||||
|
<span class="guide-nav-text">{{ section.title }}</span>
|
||||||
|
</button>
|
||||||
|
</nav>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup>
|
||||||
|
defineProps({
|
||||||
|
sections: { type: Array, required: true },
|
||||||
|
active: { type: String, default: '' },
|
||||||
|
})
|
||||||
|
defineEmits(['select'])
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="less" scoped>
|
||||||
|
.guide-nav {
|
||||||
|
display: flex;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
gap: @space-sm;
|
||||||
|
margin-bottom: @space-2xl;
|
||||||
|
|
||||||
|
.respond-md({
|
||||||
|
justify-content: center;
|
||||||
|
gap: @space-md;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
.guide-nav-btn {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 6px;
|
||||||
|
padding: @space-sm @space-md;
|
||||||
|
background: @color-bg-white;
|
||||||
|
border: 1px solid @color-border;
|
||||||
|
border-radius: @border-radius-full;
|
||||||
|
cursor: pointer;
|
||||||
|
font-size: @font-size-sm;
|
||||||
|
color: @color-text-secondary;
|
||||||
|
transition: all @transition-fast;
|
||||||
|
white-space: nowrap;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
border-color: @color-primary-light;
|
||||||
|
color: @color-primary;
|
||||||
|
}
|
||||||
|
|
||||||
|
&.active {
|
||||||
|
background: @color-primary;
|
||||||
|
border-color: @color-primary;
|
||||||
|
color: #fff;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.guide-nav-icon {
|
||||||
|
font-size: @font-size-base;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
@ -0,0 +1,246 @@
|
|||||||
|
<template>
|
||||||
|
<div class="toddler-section">
|
||||||
|
<!-- 推荐项目 -->
|
||||||
|
<div class="toddler-group">
|
||||||
|
<h3 class="group-title group-title--green">{{ data.recommended.title }}</h3>
|
||||||
|
<p class="group-desc">{{ data.recommended.desc }}</p>
|
||||||
|
<div class="toddler-items">
|
||||||
|
<div v-for="item in data.recommended.items" :key="item.name" class="toddler-item toddler-item--green">
|
||||||
|
<span class="toddler-item-icon">{{ item.icon }}</span>
|
||||||
|
<div>
|
||||||
|
<strong class="toddler-item-name">{{ item.name }}</strong>
|
||||||
|
<p class="toddler-item-desc">{{ item.desc }}</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- 视情况选择 -->
|
||||||
|
<div class="toddler-group">
|
||||||
|
<h3 class="group-title group-title--amber">{{ data.conditional.title }}</h3>
|
||||||
|
<p class="group-desc">{{ data.conditional.desc }}</p>
|
||||||
|
<div class="toddler-items">
|
||||||
|
<div v-for="item in data.conditional.items" :key="item.name" class="toddler-item toddler-item--amber">
|
||||||
|
<span class="toddler-item-icon">{{ item.icon }}</span>
|
||||||
|
<div>
|
||||||
|
<strong class="toddler-item-name">{{ item.name }}</strong>
|
||||||
|
<p class="toddler-item-desc">{{ item.desc }}</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- 不建议参与 -->
|
||||||
|
<div class="toddler-group">
|
||||||
|
<h3 class="group-title group-title--muted">{{ data.notRecommended.title }}</h3>
|
||||||
|
<p class="group-desc">{{ data.notRecommended.desc }}</p>
|
||||||
|
<div class="toddler-not-items">
|
||||||
|
<div v-for="item in data.notRecommended.items" :key="item.name" class="toddler-not-item">
|
||||||
|
<strong>{{ item.name }}</strong> — {{ item.reason }}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- 装备 -->
|
||||||
|
<div class="toddler-group">
|
||||||
|
<h3 class="group-title group-title--green">宝宝出行装备</h3>
|
||||||
|
<div class="toddler-equip">
|
||||||
|
<div v-for="eq in data.equipment" :key="eq.name" class="equip-item" :class="{ 'equip-item--provided': eq.provided }">
|
||||||
|
<strong class="equip-name">{{ eq.name }}</strong>
|
||||||
|
<span v-if="eq.provided" class="equip-badge">呼籁提供</span>
|
||||||
|
<p class="equip-desc">{{ eq.desc }}</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- 用餐 -->
|
||||||
|
<div class="toddler-group">
|
||||||
|
<h3 class="group-title group-title--green">宝宝用餐小贴士</h3>
|
||||||
|
<ul class="toddler-dining">
|
||||||
|
<li v-for="(tip, i) in data.dining" :key="i">{{ tip }}</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- 温馨提醒 -->
|
||||||
|
<div class="toddler-notes">
|
||||||
|
<div v-for="note in data.notes" :key="note.title" class="toddler-note">
|
||||||
|
<strong>{{ note.title }}</strong>
|
||||||
|
<p>{{ note.content }}</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup>
|
||||||
|
defineProps({
|
||||||
|
data: { type: Object, required: true },
|
||||||
|
})
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="less" scoped>
|
||||||
|
.toddler-section {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
gap: @space-2xl;
|
||||||
|
}
|
||||||
|
|
||||||
|
.toddler-group {
|
||||||
|
// group container
|
||||||
|
}
|
||||||
|
|
||||||
|
.group-title {
|
||||||
|
font-size: @font-size-lg;
|
||||||
|
margin: 0 0 @space-sm;
|
||||||
|
|
||||||
|
&--green { color: @color-primary; }
|
||||||
|
&--amber { color: @color-accent; }
|
||||||
|
&--muted { color: @color-text-muted; }
|
||||||
|
}
|
||||||
|
|
||||||
|
.group-desc {
|
||||||
|
font-size: @font-size-sm;
|
||||||
|
color: @color-text-secondary;
|
||||||
|
margin-bottom: @space-lg;
|
||||||
|
}
|
||||||
|
|
||||||
|
.toddler-items {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
gap: @space-md;
|
||||||
|
}
|
||||||
|
|
||||||
|
.toddler-item {
|
||||||
|
display: flex;
|
||||||
|
gap: @space-md;
|
||||||
|
padding: @space-md @space-lg;
|
||||||
|
background: @color-bg-white;
|
||||||
|
border-radius: @border-radius-md;
|
||||||
|
border-left: 3px solid @color-border;
|
||||||
|
|
||||||
|
&--green { border-left-color: @color-primary; }
|
||||||
|
&--amber { border-left-color: @color-accent; }
|
||||||
|
}
|
||||||
|
|
||||||
|
.toddler-item-icon {
|
||||||
|
font-size: @font-size-lg;
|
||||||
|
flex-shrink: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.toddler-item-name {
|
||||||
|
color: @color-text-primary;
|
||||||
|
font-size: @font-size-base;
|
||||||
|
}
|
||||||
|
|
||||||
|
.toddler-item-desc {
|
||||||
|
font-size: @font-size-sm;
|
||||||
|
color: @color-text-secondary;
|
||||||
|
margin: @space-xs 0 0;
|
||||||
|
line-height: @line-height-base;
|
||||||
|
}
|
||||||
|
|
||||||
|
.toddler-not-items {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
gap: @space-sm;
|
||||||
|
}
|
||||||
|
|
||||||
|
.toddler-not-item {
|
||||||
|
padding: @space-sm @space-md;
|
||||||
|
border-left: 2px solid @color-border;
|
||||||
|
font-size: @font-size-sm;
|
||||||
|
color: @color-text-muted;
|
||||||
|
line-height: @line-height-base;
|
||||||
|
|
||||||
|
strong {
|
||||||
|
color: @color-text-secondary;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.toddler-equip {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
gap: @space-md;
|
||||||
|
}
|
||||||
|
|
||||||
|
.equip-item {
|
||||||
|
background: @color-bg-white;
|
||||||
|
border: 1px solid @color-border;
|
||||||
|
border-radius: @border-radius-md;
|
||||||
|
padding: @space-md @space-lg;
|
||||||
|
|
||||||
|
&--provided {
|
||||||
|
border-top: 3px solid @color-primary;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.equip-name {
|
||||||
|
font-size: @font-size-base;
|
||||||
|
color: @color-primary;
|
||||||
|
}
|
||||||
|
|
||||||
|
.equip-badge {
|
||||||
|
display: inline-block;
|
||||||
|
margin-left: @space-sm;
|
||||||
|
padding: 2px @space-sm;
|
||||||
|
background: @color-primary-bg;
|
||||||
|
color: @color-primary;
|
||||||
|
font-size: @font-size-xs;
|
||||||
|
border-radius: @border-radius-sm;
|
||||||
|
}
|
||||||
|
|
||||||
|
.equip-desc {
|
||||||
|
font-size: @font-size-sm;
|
||||||
|
color: @color-text-secondary;
|
||||||
|
margin: @space-xs 0 0;
|
||||||
|
line-height: @line-height-base;
|
||||||
|
}
|
||||||
|
|
||||||
|
.toddler-dining {
|
||||||
|
padding: 0;
|
||||||
|
margin: 0;
|
||||||
|
list-style: none;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
gap: @space-sm;
|
||||||
|
|
||||||
|
li {
|
||||||
|
font-size: @font-size-sm;
|
||||||
|
color: @color-text-secondary;
|
||||||
|
line-height: @line-height-base;
|
||||||
|
padding-left: @space-md;
|
||||||
|
position: relative;
|
||||||
|
|
||||||
|
&::before {
|
||||||
|
content: '☑';
|
||||||
|
position: absolute;
|
||||||
|
left: 0;
|
||||||
|
color: @color-primary;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.toddler-notes {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
gap: @space-md;
|
||||||
|
}
|
||||||
|
|
||||||
|
.toddler-note {
|
||||||
|
background: @color-bg-white;
|
||||||
|
border: 1px solid @color-border;
|
||||||
|
border-radius: @border-radius-md;
|
||||||
|
padding: @space-md @space-lg;
|
||||||
|
|
||||||
|
strong {
|
||||||
|
color: @color-primary;
|
||||||
|
font-size: @font-size-base;
|
||||||
|
}
|
||||||
|
|
||||||
|
p {
|
||||||
|
font-size: @font-size-sm;
|
||||||
|
color: @color-text-secondary;
|
||||||
|
margin: @space-xs 0 0;
|
||||||
|
line-height: @line-height-base;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
@ -0,0 +1,284 @@
|
|||||||
|
<template>
|
||||||
|
<section class="section">
|
||||||
|
<div class="container">
|
||||||
|
<CommonSectionTitle :title="data.title" :subtitle="data.subtitle" />
|
||||||
|
<p class="compare-intro">{{ data.intro }}</p>
|
||||||
|
|
||||||
|
<!-- 对比表格 -->
|
||||||
|
<div class="compare-table">
|
||||||
|
<!-- 表头:三个目的地 -->
|
||||||
|
<div class="compare-header">
|
||||||
|
<div class="compare-label-col"></div>
|
||||||
|
<div
|
||||||
|
v-for="dest in data.destinations"
|
||||||
|
:key="dest.id"
|
||||||
|
class="compare-dest-col"
|
||||||
|
:class="{ 'compare-dest-col--highlight': dest.highlight }"
|
||||||
|
>
|
||||||
|
<h3 class="dest-name">{{ dest.name }}</h3>
|
||||||
|
<span class="dest-tag">{{ dest.tag }}</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- 对比行 -->
|
||||||
|
<div v-for="dim in data.dimensions" :key="dim.label" class="compare-row">
|
||||||
|
<div class="compare-label-col">
|
||||||
|
<span class="dim-icon">{{ dim.icon }}</span>
|
||||||
|
<span class="dim-label">{{ dim.label }}</span>
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
v-for="(val, i) in dim.values"
|
||||||
|
:key="i"
|
||||||
|
class="compare-value-col"
|
||||||
|
:class="{ 'compare-value-col--highlight': data.destinations[i]?.highlight }"
|
||||||
|
>
|
||||||
|
<span class="dim-label-mobile">{{ dim.icon }} {{ dim.label }}</span>
|
||||||
|
{{ val }}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- 坦诚说明 -->
|
||||||
|
<div class="honest-block">
|
||||||
|
<h3 class="honest-title">{{ data.honestNote.title }}</h3>
|
||||||
|
<p class="honest-subtitle">{{ data.honestNote.subtitle }}</p>
|
||||||
|
<ul class="honest-list">
|
||||||
|
<li v-for="(item, i) in data.honestNote.items" :key="i">{{ item }}</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- 结语 -->
|
||||||
|
<div class="closing-block">
|
||||||
|
<h3 class="closing-title">{{ data.closing.title }}</h3>
|
||||||
|
<p class="closing-text">{{ data.closing.text }}</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- 数据来源 -->
|
||||||
|
<p class="data-source">{{ data.dataSources }}</p>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup>
|
||||||
|
import data from '~/data/destinations.json'
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="less" scoped>
|
||||||
|
.compare-intro {
|
||||||
|
max-width: 800px;
|
||||||
|
margin: 0 auto @space-xl;
|
||||||
|
font-size: @font-size-base;
|
||||||
|
color: @color-text-secondary;
|
||||||
|
line-height: @line-height-loose;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 对比表格
|
||||||
|
.compare-table {
|
||||||
|
margin-bottom: @space-2xl;
|
||||||
|
border: 1px solid @color-border;
|
||||||
|
border-radius: @border-radius-lg;
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
.compare-header {
|
||||||
|
display: none;
|
||||||
|
|
||||||
|
.respond-md({
|
||||||
|
display: grid;
|
||||||
|
grid-template-columns: 120px repeat(3, 1fr);
|
||||||
|
background: @color-bg-gray;
|
||||||
|
border-bottom: 1px solid @color-border;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
.compare-label-col {
|
||||||
|
padding: @space-md @space-lg;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: @space-sm;
|
||||||
|
font-weight: @font-weight-medium;
|
||||||
|
color: @color-text-muted;
|
||||||
|
font-size: @font-size-sm;
|
||||||
|
}
|
||||||
|
|
||||||
|
.compare-dest-col {
|
||||||
|
padding: @space-lg;
|
||||||
|
text-align: center;
|
||||||
|
|
||||||
|
&--highlight {
|
||||||
|
background: @color-primary-bg;
|
||||||
|
position: relative;
|
||||||
|
|
||||||
|
&::after {
|
||||||
|
content: '推荐';
|
||||||
|
position: absolute;
|
||||||
|
top: @space-xs;
|
||||||
|
right: @space-sm;
|
||||||
|
padding: 2px @space-sm;
|
||||||
|
font-size: 11px;
|
||||||
|
font-weight: @font-weight-bold;
|
||||||
|
color: #fff;
|
||||||
|
background: @color-primary;
|
||||||
|
border-radius: @border-radius-sm;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.dest-name {
|
||||||
|
font-size: @font-size-lg;
|
||||||
|
font-weight: @font-weight-bold;
|
||||||
|
color: @color-text-primary;
|
||||||
|
margin-bottom: @space-xs;
|
||||||
|
}
|
||||||
|
|
||||||
|
.dest-tag {
|
||||||
|
font-size: @font-size-xs;
|
||||||
|
color: @color-text-muted;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 对比行
|
||||||
|
.compare-row {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
border-bottom: 1px solid @color-border;
|
||||||
|
|
||||||
|
&:last-child {
|
||||||
|
border-bottom: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.respond-md({
|
||||||
|
display: grid;
|
||||||
|
grid-template-columns: 120px repeat(3, 1fr);
|
||||||
|
flex-direction: row;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
.compare-value-col {
|
||||||
|
padding: @space-md @space-lg;
|
||||||
|
font-size: @font-size-sm;
|
||||||
|
color: @color-text-secondary;
|
||||||
|
line-height: @line-height-base;
|
||||||
|
border-bottom: 1px solid fadeout(@color-border, 50%);
|
||||||
|
|
||||||
|
.respond-md({
|
||||||
|
border-bottom: none;
|
||||||
|
border-left: 1px solid fadeout(@color-border, 50%);
|
||||||
|
});
|
||||||
|
|
||||||
|
&:last-child {
|
||||||
|
border-bottom: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
&--highlight {
|
||||||
|
background: fadeout(@color-primary-bg, 30%);
|
||||||
|
color: @color-text-primary;
|
||||||
|
font-weight: @font-weight-medium;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 移动端:每个值前显示维度标签
|
||||||
|
.dim-label-mobile {
|
||||||
|
display: block;
|
||||||
|
font-size: @font-size-xs;
|
||||||
|
font-weight: @font-weight-bold;
|
||||||
|
color: @color-text-muted;
|
||||||
|
margin-bottom: @space-xs;
|
||||||
|
|
||||||
|
.respond-md({
|
||||||
|
display: none;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
.dim-icon {
|
||||||
|
font-size: @font-size-base;
|
||||||
|
}
|
||||||
|
|
||||||
|
.dim-label {
|
||||||
|
font-size: @font-size-sm;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 移动端隐藏左侧标签列
|
||||||
|
.compare-label-col {
|
||||||
|
display: none;
|
||||||
|
|
||||||
|
.respond-md({
|
||||||
|
display: flex;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// 坦诚说明
|
||||||
|
.honest-block {
|
||||||
|
max-width: 800px;
|
||||||
|
margin: 0 auto @space-xl;
|
||||||
|
padding: @space-xl;
|
||||||
|
background: #FFF7ED;
|
||||||
|
border-radius: @border-radius-lg;
|
||||||
|
border-left: 4px solid #F59E0B;
|
||||||
|
}
|
||||||
|
|
||||||
|
.honest-title {
|
||||||
|
font-size: @font-size-lg;
|
||||||
|
font-weight: @font-weight-bold;
|
||||||
|
color: #B45309;
|
||||||
|
margin-bottom: @space-xs;
|
||||||
|
}
|
||||||
|
|
||||||
|
.honest-subtitle {
|
||||||
|
font-size: @font-size-sm;
|
||||||
|
color: @color-text-muted;
|
||||||
|
margin-bottom: @space-md;
|
||||||
|
}
|
||||||
|
|
||||||
|
.honest-list {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
gap: @space-sm;
|
||||||
|
|
||||||
|
li {
|
||||||
|
font-size: @font-size-sm;
|
||||||
|
color: @color-text-secondary;
|
||||||
|
line-height: @line-height-base;
|
||||||
|
padding-left: @space-md;
|
||||||
|
position: relative;
|
||||||
|
|
||||||
|
&::before {
|
||||||
|
content: '•';
|
||||||
|
position: absolute;
|
||||||
|
left: 0;
|
||||||
|
color: #F59E0B;
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 结语
|
||||||
|
.closing-block {
|
||||||
|
max-width: 800px;
|
||||||
|
margin: 0 auto @space-xl;
|
||||||
|
padding: @space-xl;
|
||||||
|
background: @color-primary-bg;
|
||||||
|
border-radius: @border-radius-lg;
|
||||||
|
border-left: 4px solid @color-primary;
|
||||||
|
}
|
||||||
|
|
||||||
|
.closing-title {
|
||||||
|
font-size: @font-size-lg;
|
||||||
|
font-weight: @font-weight-bold;
|
||||||
|
color: @color-primary;
|
||||||
|
margin-bottom: @space-md;
|
||||||
|
}
|
||||||
|
|
||||||
|
.closing-text {
|
||||||
|
font-size: @font-size-base;
|
||||||
|
color: @color-text-secondary;
|
||||||
|
line-height: @line-height-loose;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 数据来源
|
||||||
|
.data-source {
|
||||||
|
text-align: center;
|
||||||
|
font-size: @font-size-xs;
|
||||||
|
color: @color-text-muted;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
@ -0,0 +1,129 @@
|
|||||||
|
<template>
|
||||||
|
<section class="section section--warm">
|
||||||
|
<div class="container">
|
||||||
|
<CommonSectionTitle title="为什么选择呼籁" label="WHY HULAI" subtitle="不只是包车,是一套成熟的旅行服务体系" />
|
||||||
|
<div class="diff-grid">
|
||||||
|
<div
|
||||||
|
v-for="(item, index) in items"
|
||||||
|
:key="item.title"
|
||||||
|
class="diff-item"
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
v-if="item.image"
|
||||||
|
class="diff-bg"
|
||||||
|
:style="{ backgroundImage: `url(${item.image})` }"
|
||||||
|
/>
|
||||||
|
<div class="diff-content">
|
||||||
|
<div class="diff-icon" v-html="icons[index % icons.length]" />
|
||||||
|
<h3 class="diff-title">{{ item.title }}</h3>
|
||||||
|
<p class="diff-desc">{{ item.description }}</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup>
|
||||||
|
defineProps({
|
||||||
|
items: { type: Array, required: true },
|
||||||
|
})
|
||||||
|
|
||||||
|
// SVG icons for each differentiator
|
||||||
|
const icons = [
|
||||||
|
// 营地
|
||||||
|
'<svg width="32" height="32" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"><path d="M3 21l9-18 9 18"/><path d="M12 3v18"/><path d="M3 21h18"/></svg>',
|
||||||
|
// 车队
|
||||||
|
'<svg width="32" height="32" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"><rect x="1" y="3" width="15" height="13" rx="2"/><polygon points="16 8 20 8 23 11 23 16 16 16 16 8"/><circle cx="5.5" cy="18.5" r="2.5"/><circle cx="18.5" cy="18.5" r="2.5"/></svg>',
|
||||||
|
// 体验
|
||||||
|
'<svg width="32" height="32" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"><path d="M12 2L2 7l10 5 10-5-10-5z"/><path d="M2 17l10 5 10-5"/><path d="M2 12l10 5 10-5"/></svg>',
|
||||||
|
// 旅拍
|
||||||
|
'<svg width="32" height="32" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"><path d="M23 19a2 2 0 01-2 2H3a2 2 0 01-2-2V8a2 2 0 012-2h4l2-3h6l2 3h4a2 2 0 012 2z"/><circle cx="12" cy="13" r="4"/></svg>',
|
||||||
|
// 团队
|
||||||
|
'<svg width="32" height="32" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"><path d="M17 21v-2a4 4 0 00-4-4H5a4 4 0 00-4 4v2"/><circle cx="9" cy="7" r="4"/><path d="M23 21v-2a4 4 0 00-3-3.87"/><path d="M16 3.13a4 4 0 010 7.75"/></svg>',
|
||||||
|
// 研学
|
||||||
|
'<svg width="32" height="32" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"><path d="M2 3h6a4 4 0 014 4v14a3 3 0 00-3-3H2z"/><path d="M22 3h-6a4 4 0 00-4 4v14a3 3 0 013-3h7z"/></svg>',
|
||||||
|
]
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="less" scoped>
|
||||||
|
.diff-grid {
|
||||||
|
display: grid;
|
||||||
|
grid-template-columns: 1fr;
|
||||||
|
gap: @space-lg;
|
||||||
|
|
||||||
|
.respond-md({
|
||||||
|
grid-template-columns: repeat(2, 1fr);
|
||||||
|
});
|
||||||
|
|
||||||
|
.respond-lg({
|
||||||
|
grid-template-columns: repeat(3, 1fr);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
.diff-item {
|
||||||
|
position: relative;
|
||||||
|
border-radius: @border-radius-lg;
|
||||||
|
border: 1px solid @color-border;
|
||||||
|
overflow: hidden;
|
||||||
|
background: @color-bg-white;
|
||||||
|
transition: box-shadow 0.35s cubic-bezier(0.23, 1, 0.32, 1), transform 0.35s cubic-bezier(0.23, 1, 0.32, 1);
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
box-shadow: @shadow-md;
|
||||||
|
transform: translateY(-3px);
|
||||||
|
|
||||||
|
.diff-icon {
|
||||||
|
color: @color-primary;
|
||||||
|
background: @color-primary-bg;
|
||||||
|
}
|
||||||
|
|
||||||
|
.diff-bg {
|
||||||
|
opacity: 0.45;
|
||||||
|
transform: scale(1.05);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.diff-bg {
|
||||||
|
position: absolute;
|
||||||
|
inset: 0;
|
||||||
|
background-size: cover;
|
||||||
|
background-position: center;
|
||||||
|
opacity: 0.35;
|
||||||
|
filter: saturate(0.5) brightness(1.1);
|
||||||
|
transition: opacity 0.5s ease, transform 0.5s ease;
|
||||||
|
}
|
||||||
|
|
||||||
|
.diff-content {
|
||||||
|
position: relative;
|
||||||
|
z-index: 1;
|
||||||
|
padding: @space-xl @space-lg;
|
||||||
|
background: linear-gradient(150deg, rgba(255, 255, 255, 0.97) 30%, rgba(255, 255, 255, 0.85) 60%, rgba(255, 255, 255, 0.65) 100%);
|
||||||
|
}
|
||||||
|
|
||||||
|
.diff-icon {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
width: 56px;
|
||||||
|
height: 56px;
|
||||||
|
border-radius: @border-radius-lg;
|
||||||
|
background: @color-bg-gray;
|
||||||
|
color: @color-primary-light;
|
||||||
|
margin-bottom: @space-lg;
|
||||||
|
transition: color @transition-base, background @transition-base;
|
||||||
|
}
|
||||||
|
|
||||||
|
.diff-title {
|
||||||
|
font-size: @font-size-lg;
|
||||||
|
color: @color-text-primary;
|
||||||
|
margin-bottom: @space-sm;
|
||||||
|
}
|
||||||
|
|
||||||
|
.diff-desc {
|
||||||
|
font-size: @font-size-base;
|
||||||
|
color: @color-text-secondary;
|
||||||
|
line-height: @line-height-relaxed;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
206
components/home/HeroBanner.vue
普通文件
206
components/home/HeroBanner.vue
普通文件
@ -0,0 +1,206 @@
|
|||||||
|
<template>
|
||||||
|
<section class="hero">
|
||||||
|
<div class="hero-bg">
|
||||||
|
<img
|
||||||
|
:src="images.hero.background"
|
||||||
|
alt="呼伦贝尔草原风光 莫日格勒河蜿蜒穿过辽阔草原"
|
||||||
|
class="hero-bg-img"
|
||||||
|
width="1600"
|
||||||
|
height="900"
|
||||||
|
fetchpriority="high"
|
||||||
|
/>
|
||||||
|
<div class="hero-overlay" />
|
||||||
|
</div>
|
||||||
|
<div class="container hero-inner">
|
||||||
|
<h1 class="hero-title">{{ seo.h1 }}</h1>
|
||||||
|
<p class="hero-emotional">{{ brand.slogan.emotional }}</p>
|
||||||
|
<p class="hero-functional">{{ brand.slogan.functional }}</p>
|
||||||
|
<div class="hero-actions">
|
||||||
|
<NuxtLink to="/products" class="hero-btn hero-btn--primary">
|
||||||
|
<span>查看产品</span>
|
||||||
|
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" aria-hidden="true">
|
||||||
|
<path d="M6 3l5 5-5 5" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
|
||||||
|
</svg>
|
||||||
|
</NuxtLink>
|
||||||
|
<NuxtLink to="/faq" class="hero-btn hero-btn--outline">常见问答</NuxtLink>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<!-- 底部弧形裁切 -->
|
||||||
|
<div class="hero-curve">
|
||||||
|
<svg viewBox="0 0 1440 64" fill="none" preserveAspectRatio="none" aria-hidden="true">
|
||||||
|
<path d="M0 64h1440V32C1200 0 240 0 0 32v32z" fill="currentColor" />
|
||||||
|
</svg>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup>
|
||||||
|
import brand from '~/data/brand.json'
|
||||||
|
import images from '~/data/images.json'
|
||||||
|
|
||||||
|
defineProps({
|
||||||
|
seo: { type: Object, required: true },
|
||||||
|
})
|
||||||
|
|
||||||
|
// 仅在首页 preload Hero 图片,避免全站加载
|
||||||
|
useHead({
|
||||||
|
link: [
|
||||||
|
{ rel: 'preload', href: images.hero.background, as: 'image' },
|
||||||
|
],
|
||||||
|
})
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="less" scoped>
|
||||||
|
.hero {
|
||||||
|
position: relative;
|
||||||
|
overflow: hidden;
|
||||||
|
min-height: 480px;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
|
||||||
|
.respond-md({
|
||||||
|
min-height: 580px;
|
||||||
|
});
|
||||||
|
|
||||||
|
.respond-lg({
|
||||||
|
min-height: 640px;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
.hero-bg {
|
||||||
|
position: absolute;
|
||||||
|
inset: 0;
|
||||||
|
z-index: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.hero-bg-img {
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
object-fit: cover;
|
||||||
|
object-position: center 40%;
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 更丰富的渐变遮罩
|
||||||
|
.hero-overlay {
|
||||||
|
position: absolute;
|
||||||
|
inset: 0;
|
||||||
|
background:
|
||||||
|
linear-gradient(180deg, rgba(26, 26, 46, 0.35) 0%, rgba(26, 26, 46, 0.15) 40%, rgba(26, 26, 46, 0.5) 100%),
|
||||||
|
linear-gradient(135deg, rgba(45, 106, 79, 0.3) 0%, transparent 60%);
|
||||||
|
}
|
||||||
|
|
||||||
|
.hero-inner {
|
||||||
|
position: relative;
|
||||||
|
z-index: 1;
|
||||||
|
padding-top: @space-4xl;
|
||||||
|
padding-bottom: 100px;
|
||||||
|
text-align: center;
|
||||||
|
max-width: 720px;
|
||||||
|
margin: 0 auto;
|
||||||
|
|
||||||
|
.respond-md({
|
||||||
|
padding-top: @space-4xl;
|
||||||
|
padding-bottom: 120px;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
.hero-title {
|
||||||
|
color: #FFFFFF;
|
||||||
|
margin-bottom: @space-lg;
|
||||||
|
text-shadow: 0 2px 12px rgba(0, 0, 0, 0.2);
|
||||||
|
letter-spacing: 1px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.hero-emotional {
|
||||||
|
font-size: @font-size-xl;
|
||||||
|
color: rgba(255, 255, 255, 0.95);
|
||||||
|
font-weight: @font-weight-medium;
|
||||||
|
margin-bottom: @space-sm;
|
||||||
|
text-shadow: 0 1px 6px rgba(0, 0, 0, 0.2);
|
||||||
|
|
||||||
|
.respond-md({
|
||||||
|
font-size: @font-size-2xl;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
.hero-functional {
|
||||||
|
font-size: @font-size-md;
|
||||||
|
color: rgba(255, 255, 255, 0.75);
|
||||||
|
margin-bottom: @space-xl;
|
||||||
|
|
||||||
|
.respond-md({
|
||||||
|
font-size: @font-size-lg;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
.hero-actions {
|
||||||
|
display: flex;
|
||||||
|
gap: @space-md;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
justify-content: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.hero-btn {
|
||||||
|
display: inline-flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: @space-sm;
|
||||||
|
padding: 14px 32px;
|
||||||
|
border-radius: @border-radius-full;
|
||||||
|
font-size: @font-size-base;
|
||||||
|
font-weight: @font-weight-medium;
|
||||||
|
text-decoration: none;
|
||||||
|
transition: all 0.3s cubic-bezier(0.23, 1, 0.32, 1);
|
||||||
|
|
||||||
|
.respond-md({
|
||||||
|
padding: 16px 40px;
|
||||||
|
font-size: @font-size-md;
|
||||||
|
});
|
||||||
|
|
||||||
|
&--primary {
|
||||||
|
background: #fff;
|
||||||
|
color: @color-primary;
|
||||||
|
border: 2px solid #fff;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
background: rgba(255, 255, 255, 0.92);
|
||||||
|
transform: translateY(-2px);
|
||||||
|
box-shadow: 0 8px 24px rgba(0, 0, 0, 0.2);
|
||||||
|
color: @color-primary;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&--outline {
|
||||||
|
border: 2px solid rgba(255, 255, 255, 0.5);
|
||||||
|
color: #fff;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
background: rgba(255, 255, 255, 0.15);
|
||||||
|
border-color: rgba(255, 255, 255, 0.8);
|
||||||
|
color: #fff;
|
||||||
|
transform: translateY(-2px);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 底部弧形
|
||||||
|
.hero-curve {
|
||||||
|
position: absolute;
|
||||||
|
bottom: -1px;
|
||||||
|
left: 0;
|
||||||
|
right: 0;
|
||||||
|
z-index: 2;
|
||||||
|
line-height: 0;
|
||||||
|
color: @color-bg-gray;
|
||||||
|
|
||||||
|
svg {
|
||||||
|
width: 100%;
|
||||||
|
height: 40px;
|
||||||
|
|
||||||
|
.respond-md({
|
||||||
|
height: 64px;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
218
components/home/ProductPreview.vue
普通文件
218
components/home/ProductPreview.vue
普通文件
@ -0,0 +1,218 @@
|
|||||||
|
<template>
|
||||||
|
<section class="section">
|
||||||
|
<div class="container">
|
||||||
|
<CommonSectionTitle title="旅行产品" label="PRODUCTS" subtitle="四季不同风景,总有一条线路适合你的家庭" />
|
||||||
|
<div class="product-grid">
|
||||||
|
<NuxtLink v-for="line in productLines" :key="line.id" :to="line.to" class="product-line-card">
|
||||||
|
<div class="line-img-wrap">
|
||||||
|
<img :src="line.image" :alt="line.name + ' ' + line.season + '旅行'" class="line-img" loading="lazy" width="400" height="240" />
|
||||||
|
<span class="line-season-tag" :class="`line-season-tag--${line.theme}`">{{ line.season }}</span>
|
||||||
|
</div>
|
||||||
|
<div class="line-body">
|
||||||
|
<div class="line-meta">
|
||||||
|
<span class="line-duration">{{ line.duration }}</span>
|
||||||
|
</div>
|
||||||
|
<h3 class="line-name">{{ line.name }}</h3>
|
||||||
|
<p class="line-desc">{{ line.description }}</p>
|
||||||
|
<ul class="line-highlights">
|
||||||
|
<li v-for="(h, i) in line.highlights" :key="i">{{ h }}</li>
|
||||||
|
</ul>
|
||||||
|
<span class="line-cta" :class="`line-cta--${line.theme}`">
|
||||||
|
了解详情
|
||||||
|
<svg width="14" height="14" viewBox="0 0 16 16" fill="none" aria-hidden="true"><path d="M6 3l5 5-5 5" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/></svg>
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
</NuxtLink>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup>
|
||||||
|
const productLines = [
|
||||||
|
{
|
||||||
|
id: 'summer',
|
||||||
|
name: '额吉的故乡',
|
||||||
|
season: '夏季',
|
||||||
|
theme: 'summer',
|
||||||
|
duration: '4-7天 · V9系列',
|
||||||
|
to: '/products',
|
||||||
|
image: '/images/seasons/summer-hero.jpg',
|
||||||
|
description: '呼伦贝尔草原家庭定制游,一家一单一车,6个版本适配不同假期',
|
||||||
|
highlights: ['莫日格勒河草原穿越', '专业骑马体验', '呼籁自有营地住宿'],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 'autumn',
|
||||||
|
name: '游牧的森林',
|
||||||
|
season: '秋季',
|
||||||
|
theme: 'autumn',
|
||||||
|
duration: '4-7天 · V3系列',
|
||||||
|
to: '/products/autumn',
|
||||||
|
image: '/images/seasons/autumn-forest.jpg',
|
||||||
|
description: '金秋草原+阿尔山/大兴安岭,南北两线专属私家团',
|
||||||
|
highlights: ['大兴安岭金秋林海', '阿尔山火山天池', '扎罗木得断崖秘境'],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 'winter',
|
||||||
|
name: '嗨冰雪',
|
||||||
|
season: '冬季',
|
||||||
|
theme: 'winter',
|
||||||
|
duration: '5-7天 · V3系列',
|
||||||
|
to: '/products/winter',
|
||||||
|
image: '/images/seasons/winter-hero.jpg',
|
||||||
|
description: '呼伦贝尔冬季定制游,南北两线,冰雪那达慕+驯鹿部落',
|
||||||
|
highlights: ['冰雪那达慕体验', '雪地狼群投喂', '大雪原日出日落'],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 'camp',
|
||||||
|
name: '小蒙马亲子营',
|
||||||
|
season: '夏+冬',
|
||||||
|
theme: 'camp',
|
||||||
|
duration: '夏6天 / 冬7天',
|
||||||
|
to: '/summer-camp',
|
||||||
|
image: '/images/summer-camp/grassland-group.jpg',
|
||||||
|
description: '亲子营模式,每期8组家庭结伴同行,孩子有伙伴大人能放松',
|
||||||
|
highlights: ['专业研学领队带队', '随团摄影师全程跟拍', '草原写生+非遗研学'],
|
||||||
|
},
|
||||||
|
]
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="less" scoped>
|
||||||
|
.product-grid {
|
||||||
|
display: grid;
|
||||||
|
grid-template-columns: 1fr;
|
||||||
|
gap: @space-lg;
|
||||||
|
|
||||||
|
.respond-md({
|
||||||
|
grid-template-columns: repeat(2, 1fr);
|
||||||
|
});
|
||||||
|
|
||||||
|
.respond-lg({
|
||||||
|
grid-template-columns: repeat(4, 1fr);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
.product-line-card {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
background: @color-bg-white;
|
||||||
|
border-radius: @border-radius-lg;
|
||||||
|
overflow: hidden;
|
||||||
|
text-decoration: none;
|
||||||
|
box-shadow: @shadow-card;
|
||||||
|
transition: box-shadow 0.35s cubic-bezier(0.23, 1, 0.32, 1), transform 0.35s cubic-bezier(0.23, 1, 0.32, 1);
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
box-shadow: @shadow-lg;
|
||||||
|
transform: translateY(-6px);
|
||||||
|
|
||||||
|
.line-img {
|
||||||
|
transform: scale(1.05);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.line-img-wrap {
|
||||||
|
position: relative;
|
||||||
|
overflow: hidden;
|
||||||
|
aspect-ratio: 5 / 3;
|
||||||
|
}
|
||||||
|
|
||||||
|
.line-img {
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
object-fit: cover;
|
||||||
|
transition: transform 0.5s cubic-bezier(0.23, 1, 0.32, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
.line-season-tag {
|
||||||
|
position: absolute;
|
||||||
|
top: @space-md;
|
||||||
|
left: @space-md;
|
||||||
|
padding: @space-xs @space-sm;
|
||||||
|
font-size: @font-size-xs;
|
||||||
|
font-weight: @font-weight-bold;
|
||||||
|
border-radius: @border-radius-sm;
|
||||||
|
backdrop-filter: blur(4px);
|
||||||
|
|
||||||
|
&--summer { color: #fff; background: rgba(45, 106, 79, 0.85); }
|
||||||
|
&--autumn { color: #fff; background: rgba(217, 119, 6, 0.85); }
|
||||||
|
&--winter { color: #fff; background: rgba(59, 130, 246, 0.85); }
|
||||||
|
&--camp { color: #fff; background: rgba(139, 92, 246, 0.85); }
|
||||||
|
}
|
||||||
|
|
||||||
|
.line-body {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
padding: @space-lg;
|
||||||
|
flex: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
.line-meta {
|
||||||
|
margin-bottom: @space-sm;
|
||||||
|
}
|
||||||
|
|
||||||
|
.line-duration {
|
||||||
|
font-size: @font-size-xs;
|
||||||
|
color: @color-text-muted;
|
||||||
|
}
|
||||||
|
|
||||||
|
.line-name {
|
||||||
|
font-size: @font-size-xl;
|
||||||
|
font-weight: @font-weight-bold;
|
||||||
|
color: @color-text-primary;
|
||||||
|
margin-bottom: @space-sm;
|
||||||
|
}
|
||||||
|
|
||||||
|
.line-desc {
|
||||||
|
font-size: @font-size-sm;
|
||||||
|
color: @color-text-secondary;
|
||||||
|
line-height: @line-height-base;
|
||||||
|
margin-bottom: @space-md;
|
||||||
|
}
|
||||||
|
|
||||||
|
.line-highlights {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
gap: @space-xs;
|
||||||
|
margin-bottom: @space-lg;
|
||||||
|
flex: 1;
|
||||||
|
|
||||||
|
li {
|
||||||
|
font-size: @font-size-sm;
|
||||||
|
color: @color-text-secondary;
|
||||||
|
padding-left: @space-md;
|
||||||
|
position: relative;
|
||||||
|
|
||||||
|
&::before {
|
||||||
|
content: '';
|
||||||
|
position: absolute;
|
||||||
|
left: 2px;
|
||||||
|
top: 8px;
|
||||||
|
width: 5px;
|
||||||
|
height: 5px;
|
||||||
|
border-radius: 50%;
|
||||||
|
background: @color-primary-lighter;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.line-cta {
|
||||||
|
display: inline-flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: @space-xs;
|
||||||
|
font-size: @font-size-sm;
|
||||||
|
font-weight: @font-weight-medium;
|
||||||
|
margin-top: auto;
|
||||||
|
transition: gap @transition-fast;
|
||||||
|
|
||||||
|
.product-line-card:hover & {
|
||||||
|
gap: @space-sm;
|
||||||
|
}
|
||||||
|
|
||||||
|
&--summer { color: @color-primary; }
|
||||||
|
&--autumn { color: #D97706; }
|
||||||
|
&--winter { color: #3B82F6; }
|
||||||
|
&--camp { color: #8B5CF6; }
|
||||||
|
}
|
||||||
|
</style>
|
||||||
129
components/home/ReviewHighlights.vue
普通文件
129
components/home/ReviewHighlights.vue
普通文件
@ -0,0 +1,129 @@
|
|||||||
|
<template>
|
||||||
|
<section class="section section--gray">
|
||||||
|
<div class="container">
|
||||||
|
<CommonSectionTitle title="客户怎么说" label="REVIEWS" subtitle="来自真实家庭的旅行评价" />
|
||||||
|
<div class="review-grid">
|
||||||
|
<div v-for="r in reviews" :key="r.id" class="review-card">
|
||||||
|
<div class="review-quote-mark">"</div>
|
||||||
|
<blockquote class="review-text">{{ r.content }}</blockquote>
|
||||||
|
<div class="review-footer">
|
||||||
|
<div class="review-avatar">{{ r.nickname.charAt(0) }}</div>
|
||||||
|
<div class="review-info">
|
||||||
|
<span class="review-name">{{ r.nickname }}</span>
|
||||||
|
<span class="review-date">{{ r.travelDate }}</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<p class="review-product">{{ r.productVersion }}</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="review-more">
|
||||||
|
<CommonInternalLink to="/reviews" text="查看更多客户评价" />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup>
|
||||||
|
defineProps({
|
||||||
|
reviews: { type: Array, required: true },
|
||||||
|
})
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="less" scoped>
|
||||||
|
.review-grid {
|
||||||
|
display: grid;
|
||||||
|
grid-template-columns: 1fr;
|
||||||
|
gap: @space-lg;
|
||||||
|
|
||||||
|
.respond-md({
|
||||||
|
grid-template-columns: repeat(2, 1fr);
|
||||||
|
});
|
||||||
|
|
||||||
|
.respond-lg({
|
||||||
|
grid-template-columns: repeat(3, 1fr);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
.review-card {
|
||||||
|
background: @color-bg-white;
|
||||||
|
border-radius: @border-radius-lg;
|
||||||
|
padding: @space-xl;
|
||||||
|
border: 1px solid @color-border;
|
||||||
|
border-left: 3px solid @color-primary-lighter;
|
||||||
|
position: relative;
|
||||||
|
transition: box-shadow 0.35s cubic-bezier(0.23, 1, 0.32, 1), transform 0.35s cubic-bezier(0.23, 1, 0.32, 1);
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
box-shadow: @shadow-md;
|
||||||
|
transform: translateY(-3px);
|
||||||
|
border-left-color: @color-primary;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.review-quote-mark {
|
||||||
|
font-family: Georgia, 'Times New Roman', serif;
|
||||||
|
font-size: 64px;
|
||||||
|
line-height: 1;
|
||||||
|
color: @color-primary-lighter;
|
||||||
|
margin-bottom: -@space-md;
|
||||||
|
user-select: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.review-text {
|
||||||
|
font-size: @font-size-base;
|
||||||
|
color: @color-text-secondary;
|
||||||
|
line-height: @line-height-relaxed;
|
||||||
|
margin-bottom: @space-lg;
|
||||||
|
.text-clamp(4);
|
||||||
|
}
|
||||||
|
|
||||||
|
.review-footer {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: @space-md;
|
||||||
|
}
|
||||||
|
|
||||||
|
.review-avatar {
|
||||||
|
width: 40px;
|
||||||
|
height: 40px;
|
||||||
|
border-radius: 50%;
|
||||||
|
background: linear-gradient(135deg, @color-primary-bg, @color-primary-lighter);
|
||||||
|
color: @color-primary;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
font-size: @font-size-sm;
|
||||||
|
font-weight: @font-weight-bold;
|
||||||
|
flex-shrink: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.review-info {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
gap: 2px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.review-name {
|
||||||
|
font-size: @font-size-sm;
|
||||||
|
color: @color-text-primary;
|
||||||
|
font-weight: @font-weight-medium;
|
||||||
|
}
|
||||||
|
|
||||||
|
.review-date {
|
||||||
|
font-size: @font-size-xs;
|
||||||
|
color: @color-text-muted;
|
||||||
|
}
|
||||||
|
|
||||||
|
.review-product {
|
||||||
|
font-size: @font-size-xs;
|
||||||
|
color: @color-text-muted;
|
||||||
|
margin-top: @space-sm;
|
||||||
|
padding-top: @space-sm;
|
||||||
|
border-top: 1px solid @color-divider;
|
||||||
|
}
|
||||||
|
|
||||||
|
.review-more {
|
||||||
|
text-align: center;
|
||||||
|
margin-top: @space-2xl;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
45
components/home/TrustBar.vue
普通文件
45
components/home/TrustBar.vue
普通文件
@ -0,0 +1,45 @@
|
|||||||
|
<template>
|
||||||
|
<section class="trust-section">
|
||||||
|
<div class="container">
|
||||||
|
<div class="trust-grid">
|
||||||
|
<CommonTrustBadge
|
||||||
|
v-for="stat in stats"
|
||||||
|
:key="stat.label"
|
||||||
|
:value="stat.value"
|
||||||
|
:unit="stat.unit"
|
||||||
|
:label="stat.label"
|
||||||
|
:attribution="stat.attribution"
|
||||||
|
dark
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup>
|
||||||
|
defineProps({
|
||||||
|
stats: { type: Array, required: true },
|
||||||
|
})
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="less" scoped>
|
||||||
|
.trust-section {
|
||||||
|
background: linear-gradient(135deg, @color-primary-dark 0%, @color-primary 100%);
|
||||||
|
padding: @space-xl 0;
|
||||||
|
|
||||||
|
.respond-md({
|
||||||
|
padding: @space-2xl 0;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
.trust-grid {
|
||||||
|
display: grid;
|
||||||
|
grid-template-columns: repeat(2, 1fr);
|
||||||
|
gap: @space-md;
|
||||||
|
|
||||||
|
.respond-md({
|
||||||
|
grid-template-columns: repeat(4, 1fr);
|
||||||
|
gap: @space-xl;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
</style>
|
||||||
204
components/layout/AppFooter.vue
普通文件
204
components/layout/AppFooter.vue
普通文件
@ -0,0 +1,204 @@
|
|||||||
|
<template>
|
||||||
|
<footer class="app-footer">
|
||||||
|
<div class="footer-container">
|
||||||
|
<div class="footer-grid">
|
||||||
|
<!-- 品牌信息 -->
|
||||||
|
<div class="footer-brand">
|
||||||
|
<div class="footer-logo">
|
||||||
|
<img :src="images.logo.main" alt="呼籁旅行" class="footer-logo-img" width="44" height="44" />
|
||||||
|
<div class="footer-logo-text">
|
||||||
|
<span class="logo-text">呼籁旅行</span>
|
||||||
|
<span class="logo-sub">HULAI TRAVEL</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<p class="footer-desc">{{ brand.slogan.functional }}</p>
|
||||||
|
<div class="footer-qr-list">
|
||||||
|
<CommonQRCodeBlock
|
||||||
|
v-for="ch in qrChannels"
|
||||||
|
:key="ch.type"
|
||||||
|
:image="ch.qrImage"
|
||||||
|
:label="ch.label"
|
||||||
|
size="small"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- 导航链接 -->
|
||||||
|
<div v-for="group in footerNav" :key="group.title" class="footer-nav-group">
|
||||||
|
<h4 class="footer-nav-title">{{ group.title }}</h4>
|
||||||
|
<ul class="footer-nav-list">
|
||||||
|
<li v-for="link in group.links" :key="link.to">
|
||||||
|
<NuxtLink :to="link.to" class="footer-nav-link">{{ link.text }}</NuxtLink>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- 底部信息 -->
|
||||||
|
<div class="footer-bottom">
|
||||||
|
<p class="footer-company">旅行服务:内蒙古呼籁国际旅行社有限公司</p>
|
||||||
|
<p class="footer-legal">
|
||||||
|
<a href="https://beian.miit.gov.cn/" target="_blank" rel="noopener" class="footer-icp-link">{{ brand.icp }}</a>
|
||||||
|
<span class="footer-divider">|</span>
|
||||||
|
{{ brand.icpEntity }}
|
||||||
|
</p>
|
||||||
|
<p class="footer-copyright">
|
||||||
|
© {{ new Date().getFullYear() }} {{ brand.fullName }} 版权所有
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</footer>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup>
|
||||||
|
import brand from '~/data/brand.json'
|
||||||
|
import images from '~/data/images.json'
|
||||||
|
import navData from '~/data/navigation.json'
|
||||||
|
import contact from '~/data/contact.json'
|
||||||
|
|
||||||
|
const footerNav = navData.footer
|
||||||
|
const qrChannels = contact.channels.filter(c => c.qrImage && !c.hidden)
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="less" scoped>
|
||||||
|
.app-footer {
|
||||||
|
background: linear-gradient(180deg, @color-primary-dark 0%, #0F2419 100%);
|
||||||
|
color: rgba(255, 255, 255, 0.7);
|
||||||
|
padding: @space-2xl 0 @space-lg;
|
||||||
|
position: relative;
|
||||||
|
|
||||||
|
&::before {
|
||||||
|
content: '';
|
||||||
|
position: absolute;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
right: 0;
|
||||||
|
height: 3px;
|
||||||
|
background: linear-gradient(90deg, @color-primary, @color-accent, @color-primary);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.footer-container {
|
||||||
|
.container();
|
||||||
|
}
|
||||||
|
|
||||||
|
.footer-grid {
|
||||||
|
display: grid;
|
||||||
|
grid-template-columns: 1fr;
|
||||||
|
gap: @space-xl;
|
||||||
|
|
||||||
|
.respond-md({
|
||||||
|
grid-template-columns: 2fr 1fr 1fr 1fr 1fr;
|
||||||
|
gap: @space-xl;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
.footer-brand {
|
||||||
|
margin-bottom: @space-lg;
|
||||||
|
}
|
||||||
|
|
||||||
|
.footer-logo {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: @space-sm;
|
||||||
|
margin-bottom: @space-md;
|
||||||
|
}
|
||||||
|
|
||||||
|
.footer-logo-img {
|
||||||
|
width: 44px;
|
||||||
|
height: 44px;
|
||||||
|
border-radius: 6px;
|
||||||
|
flex-shrink: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.footer-logo-text {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
|
||||||
|
.logo-text {
|
||||||
|
font-size: @font-size-lg;
|
||||||
|
font-weight: @font-weight-bold;
|
||||||
|
color: #fff;
|
||||||
|
}
|
||||||
|
|
||||||
|
.logo-sub {
|
||||||
|
font-size: @font-size-xs;
|
||||||
|
color: rgba(255, 255, 255, 0.4);
|
||||||
|
letter-spacing: 2px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.footer-desc {
|
||||||
|
font-size: @font-size-sm;
|
||||||
|
margin-bottom: @space-lg;
|
||||||
|
color: rgba(255, 255, 255, 0.6);
|
||||||
|
}
|
||||||
|
|
||||||
|
.footer-qr-list {
|
||||||
|
display: flex;
|
||||||
|
gap: @space-lg;
|
||||||
|
}
|
||||||
|
|
||||||
|
.footer-nav-title {
|
||||||
|
font-size: @font-size-base;
|
||||||
|
font-weight: @font-weight-medium;
|
||||||
|
color: #fff;
|
||||||
|
margin-bottom: @space-md;
|
||||||
|
}
|
||||||
|
|
||||||
|
.footer-nav-list {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
gap: @space-sm;
|
||||||
|
}
|
||||||
|
|
||||||
|
.footer-nav-link {
|
||||||
|
font-size: @font-size-sm;
|
||||||
|
color: rgba(255, 255, 255, 0.6);
|
||||||
|
text-decoration: none;
|
||||||
|
transition: color @transition-fast;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
color: #fff;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.footer-bottom {
|
||||||
|
margin-top: @space-2xl;
|
||||||
|
padding-top: @space-lg;
|
||||||
|
border-top: 1px solid rgba(255, 255, 255, 0.1);
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.footer-company {
|
||||||
|
font-size: @font-size-sm;
|
||||||
|
color: rgba(255, 255, 255, 0.6);
|
||||||
|
margin-bottom: @space-xs;
|
||||||
|
}
|
||||||
|
|
||||||
|
.footer-legal {
|
||||||
|
font-size: @font-size-xs;
|
||||||
|
color: rgba(255, 255, 255, 0.5);
|
||||||
|
margin-bottom: @space-xs;
|
||||||
|
}
|
||||||
|
|
||||||
|
.footer-divider {
|
||||||
|
margin: 0 @space-sm;
|
||||||
|
opacity: 0.5;
|
||||||
|
}
|
||||||
|
|
||||||
|
.footer-copyright {
|
||||||
|
font-size: @font-size-xs;
|
||||||
|
color: rgba(255, 255, 255, 0.45);
|
||||||
|
}
|
||||||
|
|
||||||
|
.footer-icp-link {
|
||||||
|
color: rgba(255, 255, 255, 0.5);
|
||||||
|
text-decoration: none;
|
||||||
|
transition: color @transition-fast;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
color: rgba(255, 255, 255, 0.8);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
308
components/layout/AppHeader.vue
普通文件
308
components/layout/AppHeader.vue
普通文件
@ -0,0 +1,308 @@
|
|||||||
|
<template>
|
||||||
|
<header class="app-header">
|
||||||
|
<div class="header-container">
|
||||||
|
<NuxtLink to="/" class="header-logo" aria-label="呼籁旅行首页">
|
||||||
|
<img :src="images.logo.main" alt="呼籁旅行" class="logo-img" width="40" height="40" />
|
||||||
|
<div class="logo-text-group">
|
||||||
|
<span class="logo-text">呼籁旅行</span>
|
||||||
|
<span class="logo-sub">HULAI TRAVEL</span>
|
||||||
|
</div>
|
||||||
|
</NuxtLink>
|
||||||
|
|
||||||
|
<nav class="header-nav" aria-label="主导航">
|
||||||
|
<ul class="nav-list">
|
||||||
|
<li
|
||||||
|
v-for="item in navItems"
|
||||||
|
:key="item.to"
|
||||||
|
class="nav-item"
|
||||||
|
:class="{ 'has-dropdown': item.children }"
|
||||||
|
@mouseenter="item.children && (openDropdown = item.to)"
|
||||||
|
@mouseleave="item.children && (openDropdown = null)"
|
||||||
|
>
|
||||||
|
<NuxtLink :to="item.to" class="nav-link" :class="{ active: isActive(item.to) }">
|
||||||
|
{{ item.text }}
|
||||||
|
<span v-if="item.children" class="nav-arrow">▾</span>
|
||||||
|
</NuxtLink>
|
||||||
|
<!-- 下拉菜单:真实 <a> 链接,SEO 可抓取 -->
|
||||||
|
<ul v-if="item.children" class="nav-dropdown" :class="{ show: openDropdown === item.to }">
|
||||||
|
<li v-for="child in item.children" :key="child.to" class="dropdown-item">
|
||||||
|
<NuxtLink :to="child.to" class="dropdown-link" @click="openDropdown = null">
|
||||||
|
<span class="dropdown-text">{{ child.text }}</span>
|
||||||
|
<span v-if="child.season" class="dropdown-season">{{ child.season }}</span>
|
||||||
|
</NuxtLink>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</nav>
|
||||||
|
|
||||||
|
<button
|
||||||
|
class="mobile-toggle"
|
||||||
|
:aria-expanded="mobileOpen"
|
||||||
|
aria-controls="mobile-nav"
|
||||||
|
aria-label="打开导航菜单"
|
||||||
|
@click="mobileOpen = !mobileOpen"
|
||||||
|
>
|
||||||
|
<span class="toggle-bar" :class="{ open: mobileOpen }"></span>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<LayoutMobileNav :is-open="mobileOpen" :items="navItems" @close="mobileOpen = false" />
|
||||||
|
</header>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup>
|
||||||
|
import { ref } from 'vue'
|
||||||
|
import navData from '~/data/navigation.json'
|
||||||
|
import images from '~/data/images.json'
|
||||||
|
|
||||||
|
const navItems = navData.header
|
||||||
|
const mobileOpen = ref(false)
|
||||||
|
const openDropdown = ref(null)
|
||||||
|
const route = useRoute()
|
||||||
|
|
||||||
|
function isActive(path) {
|
||||||
|
if (path === '/') return route.path === '/'
|
||||||
|
return route.path.startsWith(path)
|
||||||
|
}
|
||||||
|
|
||||||
|
watch(() => route.path, () => {
|
||||||
|
mobileOpen.value = false
|
||||||
|
})
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="less" scoped>
|
||||||
|
.app-header {
|
||||||
|
position: sticky;
|
||||||
|
top: 0;
|
||||||
|
z-index: 100;
|
||||||
|
background: rgba(255, 255, 255, 0.85);
|
||||||
|
backdrop-filter: blur(16px);
|
||||||
|
-webkit-backdrop-filter: blur(16px);
|
||||||
|
border-bottom: 1px solid rgba(0, 0, 0, 0.06);
|
||||||
|
transition: box-shadow @transition-base;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
box-shadow: @shadow-xs;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.header-container {
|
||||||
|
.container();
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: space-between;
|
||||||
|
height: 64px;
|
||||||
|
|
||||||
|
.respond-lg({
|
||||||
|
height: 72px;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
.header-logo {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: @space-sm;
|
||||||
|
text-decoration: none;
|
||||||
|
line-height: 1.2;
|
||||||
|
}
|
||||||
|
|
||||||
|
.logo-img {
|
||||||
|
width: 40px;
|
||||||
|
height: 40px;
|
||||||
|
border-radius: 6px;
|
||||||
|
flex-shrink: 0;
|
||||||
|
|
||||||
|
.respond-lg({
|
||||||
|
width: 44px;
|
||||||
|
height: 44px;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
.logo-text-group {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
}
|
||||||
|
|
||||||
|
.logo-text {
|
||||||
|
font-size: @font-size-lg;
|
||||||
|
font-weight: @font-weight-bold;
|
||||||
|
color: @color-primary;
|
||||||
|
|
||||||
|
.respond-lg({
|
||||||
|
font-size: @font-size-xl;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
.logo-sub {
|
||||||
|
font-size: @font-size-xs;
|
||||||
|
color: @color-text-muted;
|
||||||
|
letter-spacing: 2px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.header-nav {
|
||||||
|
display: none;
|
||||||
|
|
||||||
|
.respond-lg({
|
||||||
|
display: block;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
.nav-list {
|
||||||
|
display: flex;
|
||||||
|
gap: @space-xl;
|
||||||
|
}
|
||||||
|
|
||||||
|
.nav-link {
|
||||||
|
font-size: @font-size-base;
|
||||||
|
color: @color-text-secondary;
|
||||||
|
text-decoration: none;
|
||||||
|
padding: @space-sm 0;
|
||||||
|
border-bottom: 2px solid transparent;
|
||||||
|
transition: color @transition-fast, border-color @transition-fast;
|
||||||
|
|
||||||
|
&:hover,
|
||||||
|
&.active {
|
||||||
|
color: @color-primary;
|
||||||
|
border-bottom-color: @color-primary;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 下拉菜单
|
||||||
|
.has-dropdown {
|
||||||
|
position: relative;
|
||||||
|
}
|
||||||
|
|
||||||
|
.nav-arrow {
|
||||||
|
font-size: 10px;
|
||||||
|
margin-left: 2px;
|
||||||
|
opacity: 0.5;
|
||||||
|
transition: transform @transition-fast;
|
||||||
|
|
||||||
|
.has-dropdown:hover & {
|
||||||
|
transform: rotate(180deg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.nav-dropdown {
|
||||||
|
position: absolute;
|
||||||
|
top: 100%;
|
||||||
|
left: 50%;
|
||||||
|
transform: translateX(-50%);
|
||||||
|
min-width: 180px;
|
||||||
|
background: @color-bg-white;
|
||||||
|
border-radius: @border-radius-md;
|
||||||
|
box-shadow: 0 8px 24px rgba(0, 0, 0, 0.1);
|
||||||
|
padding: @space-sm 0;
|
||||||
|
opacity: 0;
|
||||||
|
visibility: hidden;
|
||||||
|
transition: opacity @transition-fast, visibility @transition-fast;
|
||||||
|
z-index: 10;
|
||||||
|
|
||||||
|
// 防止鼠标移到下拉菜单过程中菜单消失
|
||||||
|
&::before {
|
||||||
|
content: '';
|
||||||
|
position: absolute;
|
||||||
|
top: -8px;
|
||||||
|
left: 0;
|
||||||
|
right: 0;
|
||||||
|
height: 8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
&.show {
|
||||||
|
opacity: 1;
|
||||||
|
visibility: visible;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.dropdown-item {
|
||||||
|
list-style: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.dropdown-link {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: space-between;
|
||||||
|
padding: @space-sm @space-lg;
|
||||||
|
text-decoration: none;
|
||||||
|
color: @color-text-secondary;
|
||||||
|
font-size: @font-size-sm;
|
||||||
|
white-space: nowrap;
|
||||||
|
transition: background @transition-fast, color @transition-fast;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
background: @color-primary-bg;
|
||||||
|
color: @color-primary;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.dropdown-text {
|
||||||
|
flex: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
.dropdown-season {
|
||||||
|
font-size: @font-size-xs;
|
||||||
|
color: @color-text-muted;
|
||||||
|
background: @color-bg-gray;
|
||||||
|
padding: 2px 6px;
|
||||||
|
border-radius: @border-radius-sm;
|
||||||
|
margin-left: @space-sm;
|
||||||
|
}
|
||||||
|
|
||||||
|
.mobile-toggle {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
width: 40px;
|
||||||
|
height: 40px;
|
||||||
|
background: none;
|
||||||
|
border: none;
|
||||||
|
cursor: pointer;
|
||||||
|
|
||||||
|
.respond-lg({
|
||||||
|
display: none;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
.toggle-bar {
|
||||||
|
position: relative;
|
||||||
|
display: block;
|
||||||
|
width: 24px;
|
||||||
|
height: 2px;
|
||||||
|
background: @color-text-primary;
|
||||||
|
transition: background @transition-fast;
|
||||||
|
|
||||||
|
&::before,
|
||||||
|
&::after {
|
||||||
|
content: '';
|
||||||
|
position: absolute;
|
||||||
|
left: 0;
|
||||||
|
width: 24px;
|
||||||
|
height: 2px;
|
||||||
|
background: @color-text-primary;
|
||||||
|
transition: transform @transition-base;
|
||||||
|
}
|
||||||
|
|
||||||
|
&::before {
|
||||||
|
top: -7px;
|
||||||
|
}
|
||||||
|
|
||||||
|
&::after {
|
||||||
|
top: 7px;
|
||||||
|
}
|
||||||
|
|
||||||
|
&.open {
|
||||||
|
background: transparent;
|
||||||
|
|
||||||
|
&::before {
|
||||||
|
top: 0;
|
||||||
|
transform: rotate(45deg);
|
||||||
|
}
|
||||||
|
|
||||||
|
&::after {
|
||||||
|
top: 0;
|
||||||
|
transform: rotate(-45deg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
188
components/layout/MobileNav.vue
普通文件
188
components/layout/MobileNav.vue
普通文件
@ -0,0 +1,188 @@
|
|||||||
|
<template>
|
||||||
|
<Transition name="slide">
|
||||||
|
<div v-if="isOpen" id="mobile-nav" class="mobile-nav" role="dialog" aria-label="导航菜单">
|
||||||
|
<div class="mobile-nav-backdrop" @click="$emit('close')"></div>
|
||||||
|
<nav class="mobile-nav-panel">
|
||||||
|
<ul class="mobile-nav-list">
|
||||||
|
<li v-for="item in items" :key="item.to" class="mobile-nav-item">
|
||||||
|
<!-- 有子菜单的导航项 -->
|
||||||
|
<template v-if="item.children">
|
||||||
|
<button
|
||||||
|
class="mobile-nav-link mobile-nav-toggle"
|
||||||
|
:class="{ expanded: expandedItem === item.to }"
|
||||||
|
@click="toggleExpand(item.to)"
|
||||||
|
>
|
||||||
|
{{ item.text }}
|
||||||
|
<span class="mobile-nav-arrow">›</span>
|
||||||
|
</button>
|
||||||
|
<ul v-show="expandedItem === item.to" class="mobile-sub-list">
|
||||||
|
<li v-for="child in item.children" :key="child.to" class="mobile-sub-item">
|
||||||
|
<NuxtLink :to="child.to" class="mobile-sub-link" @click="$emit('close')">
|
||||||
|
<span>{{ child.text }}</span>
|
||||||
|
<span v-if="child.season" class="mobile-sub-season">{{ child.season }}</span>
|
||||||
|
</NuxtLink>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</template>
|
||||||
|
<!-- 普通导航项 -->
|
||||||
|
<NuxtLink v-else :to="item.to" class="mobile-nav-link" @click="$emit('close')">
|
||||||
|
{{ item.text }}
|
||||||
|
</NuxtLink>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</nav>
|
||||||
|
</div>
|
||||||
|
</Transition>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup>
|
||||||
|
const props = defineProps({
|
||||||
|
isOpen: { type: Boolean, default: false },
|
||||||
|
items: { type: Array, default: () => [] },
|
||||||
|
})
|
||||||
|
|
||||||
|
defineEmits(['close'])
|
||||||
|
|
||||||
|
const expandedItem = ref(null)
|
||||||
|
|
||||||
|
function toggleExpand(key) {
|
||||||
|
expandedItem.value = expandedItem.value === key ? null : key
|
||||||
|
}
|
||||||
|
|
||||||
|
// 关闭菜单时重置展开状态
|
||||||
|
watch(() => props.isOpen, (open) => {
|
||||||
|
if (import.meta.client) {
|
||||||
|
document.body.style.overflow = open ? 'hidden' : ''
|
||||||
|
}
|
||||||
|
if (!open) {
|
||||||
|
expandedItem.value = null
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
onUnmounted(() => {
|
||||||
|
if (import.meta.client) {
|
||||||
|
document.body.style.overflow = ''
|
||||||
|
}
|
||||||
|
})
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="less" scoped>
|
||||||
|
.mobile-nav {
|
||||||
|
position: fixed;
|
||||||
|
inset: 0;
|
||||||
|
z-index: 99;
|
||||||
|
}
|
||||||
|
|
||||||
|
.mobile-nav-backdrop {
|
||||||
|
position: absolute;
|
||||||
|
inset: 0;
|
||||||
|
background: rgba(0, 0, 0, 0.4);
|
||||||
|
}
|
||||||
|
|
||||||
|
.mobile-nav-panel {
|
||||||
|
position: absolute;
|
||||||
|
top: 0;
|
||||||
|
right: 0;
|
||||||
|
width: min(300px, 85vw);
|
||||||
|
height: 100%;
|
||||||
|
background: @color-bg-white;
|
||||||
|
padding: @space-3xl @space-lg @space-lg;
|
||||||
|
overflow-y: auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
.mobile-nav-list {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
gap: @space-xs;
|
||||||
|
}
|
||||||
|
|
||||||
|
.mobile-nav-link {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: space-between;
|
||||||
|
width: 100%;
|
||||||
|
padding: @space-md @space-md;
|
||||||
|
font-size: @font-size-md;
|
||||||
|
color: @color-text-primary;
|
||||||
|
text-decoration: none;
|
||||||
|
border-radius: @border-radius-md;
|
||||||
|
border: none;
|
||||||
|
background: none;
|
||||||
|
cursor: pointer;
|
||||||
|
text-align: left;
|
||||||
|
transition: background @transition-fast;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
background: @color-primary-bg;
|
||||||
|
color: @color-primary;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.mobile-nav-toggle {
|
||||||
|
font-family: inherit;
|
||||||
|
}
|
||||||
|
|
||||||
|
.mobile-nav-arrow {
|
||||||
|
font-size: @font-size-lg;
|
||||||
|
color: @color-text-muted;
|
||||||
|
transition: transform @transition-fast;
|
||||||
|
|
||||||
|
.expanded & {
|
||||||
|
transform: rotate(90deg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.mobile-sub-list {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
padding-left: @space-md;
|
||||||
|
margin-bottom: @space-xs;
|
||||||
|
}
|
||||||
|
|
||||||
|
.mobile-sub-item {
|
||||||
|
list-style: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.mobile-sub-link {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: space-between;
|
||||||
|
padding: @space-sm @space-md;
|
||||||
|
font-size: @font-size-sm;
|
||||||
|
color: @color-text-secondary;
|
||||||
|
text-decoration: none;
|
||||||
|
border-radius: @border-radius-sm;
|
||||||
|
transition: background @transition-fast, color @transition-fast;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
background: @color-primary-bg;
|
||||||
|
color: @color-primary;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.mobile-sub-season {
|
||||||
|
font-size: @font-size-xs;
|
||||||
|
color: @color-text-muted;
|
||||||
|
background: @color-bg-gray;
|
||||||
|
padding: 2px 6px;
|
||||||
|
border-radius: @border-radius-sm;
|
||||||
|
}
|
||||||
|
|
||||||
|
.slide-enter-active,
|
||||||
|
.slide-leave-active {
|
||||||
|
transition: opacity @transition-base;
|
||||||
|
|
||||||
|
.mobile-nav-panel {
|
||||||
|
transition: transform @transition-base;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.slide-enter-from,
|
||||||
|
.slide-leave-to {
|
||||||
|
opacity: 0;
|
||||||
|
|
||||||
|
.mobile-nav-panel {
|
||||||
|
transform: translateX(100%);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
70
components/layout/PageHero.vue
普通文件
70
components/layout/PageHero.vue
普通文件
@ -0,0 +1,70 @@
|
|||||||
|
<template>
|
||||||
|
<section class="page-hero" :class="{ 'page-hero--compact': compact }">
|
||||||
|
<div class="container">
|
||||||
|
<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 48" fill="none" preserveAspectRatio="none" aria-hidden="true">
|
||||||
|
<path d="M0 48h1440V24C1200 0 240 0 0 24v24z" fill="currentColor" />
|
||||||
|
</svg>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup>
|
||||||
|
const props = defineProps({
|
||||||
|
title: { type: String, required: true },
|
||||||
|
subtitle: { type: String, default: '' },
|
||||||
|
compact: { type: Boolean, default: false },
|
||||||
|
breadcrumbs: { type: Array, default: () => [] },
|
||||||
|
})
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="less" scoped>
|
||||||
|
.page-hero {
|
||||||
|
background: linear-gradient(135deg, @color-primary-bg 0%, #E8F3ED 100%);
|
||||||
|
padding: @space-2xl 0 @space-3xl;
|
||||||
|
position: relative;
|
||||||
|
|
||||||
|
.respond-md({
|
||||||
|
padding: @space-3xl 0 @space-4xl;
|
||||||
|
});
|
||||||
|
|
||||||
|
&--compact {
|
||||||
|
padding: @space-xl 0 @space-2xl;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.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: @color-bg-white;
|
||||||
|
|
||||||
|
svg {
|
||||||
|
width: 100%;
|
||||||
|
height: 32px;
|
||||||
|
|
||||||
|
.respond-md({
|
||||||
|
height: 48px;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
@ -0,0 +1,78 @@
|
|||||||
|
<template>
|
||||||
|
<section class="section section--warm">
|
||||||
|
<div class="container">
|
||||||
|
<CommonSectionTitle title="产品进化" subtitle="从V1到V9,每一次更新都是客户反馈驱动" />
|
||||||
|
<div class="evo-stats">
|
||||||
|
<div class="evo-stat">
|
||||||
|
<span class="evo-stat-num">{{ stats.iterations }}</span>
|
||||||
|
<span class="evo-stat-label">次迭代</span>
|
||||||
|
</div>
|
||||||
|
<div class="evo-stat">
|
||||||
|
<span class="evo-stat-num">{{ stats.years }}</span>
|
||||||
|
<span class="evo-stat-label">年打磨</span>
|
||||||
|
</div>
|
||||||
|
<div class="evo-stat">
|
||||||
|
<span class="evo-stat-num">{{ stats.guests }}</span>
|
||||||
|
<span class="evo-stat-label">人次体验</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<p class="evo-intro">2023年3月,呼籁做了一个"反常识"的决定——只做一条路线。不铺量、不贪多,把所有精力集中在打磨一个产品上。三年9次迭代,每一次版本更新背后,都有真实的客户反馈和一线体验数据。</p>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup>
|
||||||
|
defineProps({
|
||||||
|
stats: { type: Object, required: true }
|
||||||
|
})
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="less" scoped>
|
||||||
|
.evo-stats {
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
gap: @space-2xl;
|
||||||
|
margin-bottom: @space-xl;
|
||||||
|
}
|
||||||
|
|
||||||
|
.evo-stat {
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.evo-stat-num {
|
||||||
|
display: inline-block;
|
||||||
|
font-size: @font-size-3xl;
|
||||||
|
font-weight: @font-weight-bold;
|
||||||
|
color: @color-primary;
|
||||||
|
line-height: @line-height-tight;
|
||||||
|
position: relative;
|
||||||
|
|
||||||
|
&::after {
|
||||||
|
content: '';
|
||||||
|
position: absolute;
|
||||||
|
bottom: -2px;
|
||||||
|
left: 10%;
|
||||||
|
right: 10%;
|
||||||
|
height: 3px;
|
||||||
|
background: @color-primary-lighter;
|
||||||
|
border-radius: 2px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.evo-stat-label {
|
||||||
|
display: block;
|
||||||
|
margin-top: @space-sm;
|
||||||
|
font-size: @font-size-sm;
|
||||||
|
color: @color-text-muted;
|
||||||
|
letter-spacing: 1px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.evo-intro {
|
||||||
|
max-width: 700px;
|
||||||
|
margin: 0 auto;
|
||||||
|
text-align: center;
|
||||||
|
font-size: @font-size-base;
|
||||||
|
color: @color-text-secondary;
|
||||||
|
line-height: @line-height-loose;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
@ -0,0 +1,20 @@
|
|||||||
|
<template>
|
||||||
|
<section class="section">
|
||||||
|
<div class="container">
|
||||||
|
<CommonSectionTitle title="关于价格" subtitle="透明、清晰、不套路" />
|
||||||
|
<div class="pricing-content">
|
||||||
|
<p>{{ content }}</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup>
|
||||||
|
defineProps({ content: { type: String, required: true } })
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="less" scoped>
|
||||||
|
.pricing-content { max-width: 800px; margin: 0 auto; padding: @space-xl; background: @color-bg-warm; border-radius: @border-radius-lg;
|
||||||
|
p { font-size: @font-size-md; line-height: @line-height-loose; color: @color-text-secondary; }
|
||||||
|
}
|
||||||
|
</style>
|
||||||
217
components/products/ProductCard.vue
普通文件
217
components/products/ProductCard.vue
普通文件
@ -0,0 +1,217 @@
|
|||||||
|
<template>
|
||||||
|
<article
|
||||||
|
class="product-card"
|
||||||
|
:class="{ 'product-card--popular': isPopular }"
|
||||||
|
itemscope
|
||||||
|
itemtype="https://schema.org/TouristTrip"
|
||||||
|
>
|
||||||
|
<!-- 头部:天数 + 标签 -->
|
||||||
|
<div class="product-header">
|
||||||
|
<div v-if="isPopular" class="popular-badge">推荐</div>
|
||||||
|
<div class="product-duration">
|
||||||
|
<span class="duration-num">{{ product.days }}</span>
|
||||||
|
<span class="duration-unit">天</span>
|
||||||
|
<span class="duration-num">{{ product.nights }}</span>
|
||||||
|
<span class="duration-unit">晚</span>
|
||||||
|
</div>
|
||||||
|
<span class="product-tag">{{ product.tag }}</span>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- 主体 -->
|
||||||
|
<div class="product-body">
|
||||||
|
<h3 class="product-name" itemprop="name">
|
||||||
|
<NuxtLink :to="`/products/${product.id}`" class="product-name-link">{{ shortName }}</NuxtLink>
|
||||||
|
</h3>
|
||||||
|
<p class="product-audience">
|
||||||
|
适合:<span itemprop="touristType">{{ product.audience }}</span>
|
||||||
|
</p>
|
||||||
|
<p class="product-desc" itemprop="description">{{ product.description }}</p>
|
||||||
|
<ul class="product-highlights">
|
||||||
|
<li v-for="(h, i) in product.highlights" :key="i">
|
||||||
|
<span class="highlight-check" aria-hidden="true">✓</span>
|
||||||
|
{{ h }}
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- 底部 CTA -->
|
||||||
|
<NuxtLink to="/contact" class="product-cta">
|
||||||
|
咨询该行程 <span aria-hidden="true">→</span>
|
||||||
|
</NuxtLink>
|
||||||
|
</article>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup>
|
||||||
|
const props = defineProps({ product: { type: Object, required: true } })
|
||||||
|
|
||||||
|
const isPopular = computed(() => props.product.id === 'v9-6d5n-family')
|
||||||
|
|
||||||
|
// 去掉"额吉的故乡V9·"前缀,在标题区域已标明系列
|
||||||
|
const shortName = computed(() => {
|
||||||
|
return props.product.name.replace(/^额吉的故乡V9·/, '')
|
||||||
|
})
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="less" scoped>
|
||||||
|
.product-card {
|
||||||
|
background: @color-bg-white;
|
||||||
|
border: 1px solid @color-border;
|
||||||
|
border-radius: @border-radius-lg;
|
||||||
|
overflow: hidden;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
transition: box-shadow @transition-base, transform @transition-base;
|
||||||
|
position: relative;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
box-shadow: @shadow-lg;
|
||||||
|
transform: translateY(-4px);
|
||||||
|
}
|
||||||
|
|
||||||
|
&--popular {
|
||||||
|
border: 2px solid @color-primary;
|
||||||
|
box-shadow: @shadow-md;
|
||||||
|
|
||||||
|
.product-header {
|
||||||
|
background: @color-primary;
|
||||||
|
}
|
||||||
|
|
||||||
|
.duration-num,
|
||||||
|
.duration-unit,
|
||||||
|
.product-tag {
|
||||||
|
color: #fff;
|
||||||
|
}
|
||||||
|
|
||||||
|
.product-tag {
|
||||||
|
background: rgba(255, 255, 255, 0.2);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 头部
|
||||||
|
.product-header {
|
||||||
|
padding: @space-lg @space-lg @space-md;
|
||||||
|
background: @color-primary-bg;
|
||||||
|
text-align: center;
|
||||||
|
position: relative;
|
||||||
|
}
|
||||||
|
|
||||||
|
.popular-badge {
|
||||||
|
position: absolute;
|
||||||
|
top: @space-sm;
|
||||||
|
right: @space-sm;
|
||||||
|
padding: @space-xs @space-sm;
|
||||||
|
font-size: @font-size-xs;
|
||||||
|
font-weight: @font-weight-bold;
|
||||||
|
color: #fff;
|
||||||
|
background: @color-accent;
|
||||||
|
border-radius: @border-radius-sm;
|
||||||
|
}
|
||||||
|
|
||||||
|
.product-duration {
|
||||||
|
display: flex;
|
||||||
|
align-items: baseline;
|
||||||
|
justify-content: center;
|
||||||
|
gap: 2px;
|
||||||
|
margin-bottom: @space-sm;
|
||||||
|
}
|
||||||
|
|
||||||
|
.duration-num {
|
||||||
|
font-size: @font-size-3xl;
|
||||||
|
font-weight: @font-weight-bold;
|
||||||
|
color: @color-primary;
|
||||||
|
line-height: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
.duration-unit {
|
||||||
|
font-size: @font-size-sm;
|
||||||
|
color: @color-primary;
|
||||||
|
font-weight: @font-weight-medium;
|
||||||
|
}
|
||||||
|
|
||||||
|
.product-tag {
|
||||||
|
display: inline-block;
|
||||||
|
padding: @space-xs @space-md;
|
||||||
|
font-size: @font-size-xs;
|
||||||
|
font-weight: @font-weight-medium;
|
||||||
|
color: @color-primary;
|
||||||
|
background: @color-bg-white;
|
||||||
|
border-radius: @border-radius-full;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 主体
|
||||||
|
.product-body {
|
||||||
|
padding: @space-lg;
|
||||||
|
flex: 1;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
}
|
||||||
|
|
||||||
|
.product-name {
|
||||||
|
font-size: @font-size-lg;
|
||||||
|
font-weight: @font-weight-bold;
|
||||||
|
color: @color-text-primary;
|
||||||
|
margin-bottom: @space-xs;
|
||||||
|
}
|
||||||
|
.product-name-link {
|
||||||
|
color: inherit;
|
||||||
|
text-decoration: none;
|
||||||
|
&:hover { color: @color-primary; }
|
||||||
|
}
|
||||||
|
|
||||||
|
.product-audience {
|
||||||
|
font-size: @font-size-sm;
|
||||||
|
color: @color-text-muted;
|
||||||
|
margin-bottom: @space-md;
|
||||||
|
}
|
||||||
|
|
||||||
|
.product-desc {
|
||||||
|
font-size: @font-size-sm;
|
||||||
|
color: @color-text-secondary;
|
||||||
|
line-height: @line-height-base;
|
||||||
|
margin-bottom: @space-md;
|
||||||
|
.text-clamp(3);
|
||||||
|
}
|
||||||
|
|
||||||
|
.product-highlights {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
gap: @space-sm;
|
||||||
|
margin-top: auto;
|
||||||
|
|
||||||
|
li {
|
||||||
|
display: flex;
|
||||||
|
align-items: flex-start;
|
||||||
|
gap: @space-sm;
|
||||||
|
font-size: @font-size-sm;
|
||||||
|
color: @color-text-secondary;
|
||||||
|
line-height: @line-height-base;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.highlight-check {
|
||||||
|
flex-shrink: 0;
|
||||||
|
color: @color-primary;
|
||||||
|
font-size: @font-size-sm;
|
||||||
|
font-weight: @font-weight-bold;
|
||||||
|
margin-top: 2px;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 底部 CTA
|
||||||
|
.product-cta {
|
||||||
|
display: block;
|
||||||
|
text-align: center;
|
||||||
|
padding: @space-md @space-lg;
|
||||||
|
font-size: @font-size-sm;
|
||||||
|
font-weight: @font-weight-medium;
|
||||||
|
color: @color-primary;
|
||||||
|
background: @color-bg-gray;
|
||||||
|
text-decoration: none;
|
||||||
|
transition: all @transition-fast;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
background: @color-primary;
|
||||||
|
color: #fff;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
@ -0,0 +1,51 @@
|
|||||||
|
<template>
|
||||||
|
<section class="section section--warm">
|
||||||
|
<div class="container">
|
||||||
|
<div class="overview-content">
|
||||||
|
<div class="overview-quote-mark" aria-hidden="true">"</div>
|
||||||
|
<p class="overview-text">{{ narrative }}</p>
|
||||||
|
<div class="overview-line"></div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup>
|
||||||
|
defineProps({ narrative: { type: String, required: true } })
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="less" scoped>
|
||||||
|
.overview-content {
|
||||||
|
max-width: 800px;
|
||||||
|
margin: 0 auto;
|
||||||
|
text-align: center;
|
||||||
|
position: relative;
|
||||||
|
}
|
||||||
|
|
||||||
|
.overview-quote-mark {
|
||||||
|
font-size: 80px;
|
||||||
|
font-weight: @font-weight-bold;
|
||||||
|
color: @color-primary-lighter;
|
||||||
|
line-height: 0.5;
|
||||||
|
margin-bottom: @space-md;
|
||||||
|
font-family: Georgia, serif;
|
||||||
|
}
|
||||||
|
|
||||||
|
.overview-text {
|
||||||
|
font-size: @font-size-md;
|
||||||
|
line-height: @line-height-loose;
|
||||||
|
color: @color-text-secondary;
|
||||||
|
|
||||||
|
.respond-md({
|
||||||
|
font-size: @font-size-lg;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
.overview-line {
|
||||||
|
width: 60px;
|
||||||
|
height: 3px;
|
||||||
|
background: @color-primary;
|
||||||
|
border-radius: 2px;
|
||||||
|
margin: @space-xl auto 0;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
@ -0,0 +1,113 @@
|
|||||||
|
<template>
|
||||||
|
<section id="guide" class="section section--gray">
|
||||||
|
<div class="container">
|
||||||
|
<CommonSectionTitle title="不知道选哪个?" subtitle="按您的情况推荐" />
|
||||||
|
<div class="guide-groups">
|
||||||
|
<div v-for="group in guideGroups" :key="group.title" class="guide-group">
|
||||||
|
<h3 class="guide-group-title">{{ group.title }}</h3>
|
||||||
|
<div class="guide-items">
|
||||||
|
<div v-for="item in group.items" :key="item.condition" class="guide-item">
|
||||||
|
<div class="guide-item-top">
|
||||||
|
<span class="guide-condition">{{ item.condition }}</span>
|
||||||
|
<span class="guide-arrow">→</span>
|
||||||
|
<span class="guide-rec">{{ getProductName(item.recommendation) }}</span>
|
||||||
|
</div>
|
||||||
|
<p class="guide-reason">{{ item.reason }}</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup>
|
||||||
|
const props = defineProps({
|
||||||
|
guide: { type: Object, required: true },
|
||||||
|
versions: { type: Array, required: true },
|
||||||
|
})
|
||||||
|
|
||||||
|
const guideGroups = computed(() => [
|
||||||
|
{ title: '按假期长度', items: props.guide.byVacationLength },
|
||||||
|
{ title: '按孩子年龄', items: props.guide.byChildAge },
|
||||||
|
{ title: '按旅行偏好', items: props.guide.byPreference },
|
||||||
|
])
|
||||||
|
|
||||||
|
function getProductName(id) {
|
||||||
|
if (id === 'summer-camp') return '小蒙马夏令营'
|
||||||
|
const v = props.versions.find(v => v.id === id)
|
||||||
|
return v ? v.name : id
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="less" scoped>
|
||||||
|
.guide-groups {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
gap: @space-2xl;
|
||||||
|
max-width: 800px;
|
||||||
|
margin: 0 auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
.guide-group-title {
|
||||||
|
font-size: @font-size-lg;
|
||||||
|
color: @color-primary;
|
||||||
|
margin-bottom: @space-md;
|
||||||
|
padding-left: @space-md;
|
||||||
|
border-left: 3px solid @color-primary;
|
||||||
|
}
|
||||||
|
|
||||||
|
.guide-items {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
gap: @space-md;
|
||||||
|
}
|
||||||
|
|
||||||
|
.guide-item {
|
||||||
|
padding: @space-lg;
|
||||||
|
background: @color-bg-white;
|
||||||
|
border-radius: @border-radius-md;
|
||||||
|
border: 1px solid @color-border;
|
||||||
|
transition: border-color @transition-fast, box-shadow @transition-fast;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
border-color: @color-primary-lighter;
|
||||||
|
box-shadow: @shadow-sm;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.guide-item-top {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
gap: @space-sm;
|
||||||
|
margin-bottom: @space-xs;
|
||||||
|
}
|
||||||
|
|
||||||
|
.guide-condition {
|
||||||
|
font-weight: @font-weight-medium;
|
||||||
|
color: @color-text-primary;
|
||||||
|
background: @color-bg-gray;
|
||||||
|
padding: @space-xs @space-sm;
|
||||||
|
border-radius: @border-radius-sm;
|
||||||
|
font-size: @font-size-sm;
|
||||||
|
}
|
||||||
|
|
||||||
|
.guide-arrow {
|
||||||
|
color: @color-primary;
|
||||||
|
font-weight: @font-weight-bold;
|
||||||
|
}
|
||||||
|
|
||||||
|
.guide-rec {
|
||||||
|
color: @color-primary;
|
||||||
|
font-weight: @font-weight-bold;
|
||||||
|
font-size: @font-size-base;
|
||||||
|
}
|
||||||
|
|
||||||
|
.guide-reason {
|
||||||
|
font-size: @font-size-sm;
|
||||||
|
color: @color-text-muted;
|
||||||
|
margin: 0;
|
||||||
|
line-height: @line-height-base;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
@ -0,0 +1,82 @@
|
|||||||
|
<template>
|
||||||
|
<section id="summer-camp" class="section section--green">
|
||||||
|
<div class="container">
|
||||||
|
<CommonSectionTitle :title="camp.name" :subtitle="`适合${camp.ageRange}青少年`" />
|
||||||
|
|
||||||
|
<!-- 团宠+简介 -->
|
||||||
|
<div class="camp-hero">
|
||||||
|
<div class="camp-mascot">
|
||||||
|
<img
|
||||||
|
:src="images.mascot.xiaomengma"
|
||||||
|
alt="小蒙马 - 小蒙马夏令营团宠,一只可爱的蒙古小马形象"
|
||||||
|
width="200"
|
||||||
|
height="200"
|
||||||
|
loading="lazy"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div class="camp-intro">
|
||||||
|
<p class="camp-positioning">{{ camp.positioning }}</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="camp-content">
|
||||||
|
<div v-if="camp.coreActivities.length" class="camp-activities">
|
||||||
|
<h3>核心活动</h3>
|
||||||
|
<ul>
|
||||||
|
<li v-for="(a, i) in camp.coreActivities" :key="i">{{ a }}</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
<p class="camp-diff">{{ camp.differenceFromV9 }}</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup>
|
||||||
|
import images from '~/data/images.json'
|
||||||
|
defineProps({ camp: { type: Object, required: true } })
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="less" scoped>
|
||||||
|
.camp-hero {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: center;
|
||||||
|
text-align: center;
|
||||||
|
gap: @space-lg;
|
||||||
|
max-width: 800px;
|
||||||
|
margin: 0 auto @space-xl;
|
||||||
|
|
||||||
|
.respond-md({
|
||||||
|
flex-direction: row;
|
||||||
|
text-align: left;
|
||||||
|
gap: @space-2xl;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
.camp-mascot {
|
||||||
|
flex-shrink: 0;
|
||||||
|
text-align: center;
|
||||||
|
|
||||||
|
img {
|
||||||
|
width: 160px;
|
||||||
|
height: auto;
|
||||||
|
filter: drop-shadow(0 6px 20px rgba(0, 0, 0, 0.08));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.camp-intro {
|
||||||
|
flex: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
.camp-content { max-width: 800px; margin: 0 auto; }
|
||||||
|
.camp-positioning { font-size: @font-size-base; color: @color-text-secondary; line-height: @line-height-loose; }
|
||||||
|
.camp-activities { margin-bottom: @space-lg;
|
||||||
|
h3 { font-size: @font-size-md; margin-bottom: @space-md; }
|
||||||
|
ul { display: flex; flex-direction: column; gap: @space-sm; }
|
||||||
|
li { font-size: @font-size-base; color: @color-text-secondary; padding-left: @space-md; position: relative;
|
||||||
|
&::before { content: '·'; position: absolute; left: 0; color: @color-primary; }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.camp-diff { font-size: @font-size-base; color: @color-text-muted; padding: @space-md; background: @color-bg-white; border-radius: @border-radius-md; }
|
||||||
|
</style>
|
||||||
@ -0,0 +1,93 @@
|
|||||||
|
<template>
|
||||||
|
<section class="section">
|
||||||
|
<div class="container">
|
||||||
|
<CommonSectionTitle title="V8 → V9 升级对比" subtitle="7项关键升级一目了然" />
|
||||||
|
<div class="compare-wrapper">
|
||||||
|
<div class="compare-table">
|
||||||
|
<div class="compare-head">
|
||||||
|
<span class="compare-head-old">{{ compare.headers[0] }}</span>
|
||||||
|
<span class="compare-head-new">{{ compare.headers[1] }}</span>
|
||||||
|
</div>
|
||||||
|
<div v-for="(row, i) in compare.rows" :key="i" class="compare-row">
|
||||||
|
<span class="compare-old">{{ row[0] }}</span>
|
||||||
|
<span class="compare-new">{{ row[1] }}</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup>
|
||||||
|
defineProps({
|
||||||
|
compare: { type: Object, required: true }
|
||||||
|
})
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="less" scoped>
|
||||||
|
.compare-wrapper {
|
||||||
|
max-width: 800px;
|
||||||
|
margin: 0 auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
.compare-table {
|
||||||
|
border-radius: @border-radius-md;
|
||||||
|
overflow: hidden;
|
||||||
|
border: 1px solid @color-border;
|
||||||
|
}
|
||||||
|
|
||||||
|
.compare-head {
|
||||||
|
display: grid;
|
||||||
|
grid-template-columns: 1fr 1fr;
|
||||||
|
}
|
||||||
|
|
||||||
|
.compare-head-old {
|
||||||
|
font-weight: @font-weight-medium;
|
||||||
|
text-align: center;
|
||||||
|
background: @color-bg-gray;
|
||||||
|
color: @color-text-muted;
|
||||||
|
}
|
||||||
|
|
||||||
|
.compare-head-new {
|
||||||
|
font-weight: @font-weight-medium;
|
||||||
|
text-align: center;
|
||||||
|
background: @color-primary;
|
||||||
|
color: #fff;
|
||||||
|
}
|
||||||
|
|
||||||
|
.compare-row {
|
||||||
|
display: grid;
|
||||||
|
grid-template-columns: 1fr 1fr;
|
||||||
|
border-top: 1px solid @color-border;
|
||||||
|
line-height: @line-height-base;
|
||||||
|
}
|
||||||
|
|
||||||
|
.compare-old {
|
||||||
|
color: @color-text-muted;
|
||||||
|
background: @color-bg-white;
|
||||||
|
}
|
||||||
|
|
||||||
|
.compare-new {
|
||||||
|
color: @color-text-primary;
|
||||||
|
background: @color-primary-bg;
|
||||||
|
font-weight: @font-weight-medium;
|
||||||
|
}
|
||||||
|
|
||||||
|
// mobile-first: 小屏紧凑,md 以上舒适
|
||||||
|
.compare-row, .compare-head {
|
||||||
|
font-size: @font-size-xs;
|
||||||
|
|
||||||
|
.respond-md({
|
||||||
|
font-size: @font-size-sm;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
.compare-old, .compare-new,
|
||||||
|
.compare-head-old, .compare-head-new {
|
||||||
|
padding: @space-sm @space-md;
|
||||||
|
|
||||||
|
.respond-md({
|
||||||
|
padding: @space-md @space-lg;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
</style>
|
||||||
@ -0,0 +1,58 @@
|
|||||||
|
<template>
|
||||||
|
<section class="section section--gray">
|
||||||
|
<div class="container">
|
||||||
|
<CommonSectionTitle title="更多V9亮点" subtitle="独家资源 · 自营服务 · 全程无忧" />
|
||||||
|
<div class="highlights-list">
|
||||||
|
<div v-for="item in highlights" :key="item.text" class="highlight-item">
|
||||||
|
<span class="highlight-label">{{ item.label }}</span>
|
||||||
|
<span class="highlight-text">{{ item.text }}</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup>
|
||||||
|
defineProps({
|
||||||
|
highlights: { type: Array, required: true }
|
||||||
|
})
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="less" scoped>
|
||||||
|
.highlights-list {
|
||||||
|
max-width: 800px;
|
||||||
|
margin: 0 auto;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
}
|
||||||
|
|
||||||
|
.highlight-item {
|
||||||
|
display: flex;
|
||||||
|
align-items: baseline;
|
||||||
|
gap: @space-md;
|
||||||
|
padding: @space-md 0;
|
||||||
|
border-bottom: 1px solid @color-border;
|
||||||
|
|
||||||
|
&:last-child {
|
||||||
|
border-bottom: none;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.highlight-label {
|
||||||
|
flex-shrink: 0;
|
||||||
|
font-size: @font-size-xs;
|
||||||
|
font-weight: @font-weight-bold;
|
||||||
|
color: @color-primary;
|
||||||
|
background: @color-primary-bg;
|
||||||
|
padding: @space-xs @space-sm;
|
||||||
|
border-radius: @border-radius-sm;
|
||||||
|
min-width: 42px;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.highlight-text {
|
||||||
|
font-size: @font-size-base;
|
||||||
|
color: @color-text-secondary;
|
||||||
|
line-height: @line-height-base;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
@ -0,0 +1,82 @@
|
|||||||
|
<template>
|
||||||
|
<section class="section">
|
||||||
|
<div class="container">
|
||||||
|
<CommonSectionTitle title="9次迭代背后的产品哲学" subtitle="不是做加法,而是做取舍" />
|
||||||
|
<div class="philosophy-wrapper">
|
||||||
|
<div class="philosophy-list">
|
||||||
|
<div v-for="item in philosophy" :key="item.label" class="philosophy-item">
|
||||||
|
<h4 class="philosophy-label">{{ item.label }}</h4>
|
||||||
|
<p class="philosophy-text">{{ item.text }}</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="quote-block">
|
||||||
|
<p class="quote-text">"{{ quote.text }}"</p>
|
||||||
|
<span class="quote-author">—— {{ quote.author }}</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup>
|
||||||
|
defineProps({
|
||||||
|
philosophy: { type: Array, required: true },
|
||||||
|
quote: { type: Object, required: true }
|
||||||
|
})
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="less" scoped>
|
||||||
|
.philosophy-wrapper {
|
||||||
|
max-width: 800px;
|
||||||
|
margin: 0 auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
.philosophy-list {
|
||||||
|
margin-bottom: @space-2xl;
|
||||||
|
}
|
||||||
|
|
||||||
|
.philosophy-item {
|
||||||
|
padding: @space-lg 0;
|
||||||
|
border-bottom: 1px solid @color-border;
|
||||||
|
|
||||||
|
&:last-child {
|
||||||
|
border-bottom: none;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.philosophy-label {
|
||||||
|
font-size: @font-size-base;
|
||||||
|
font-weight: @font-weight-bold;
|
||||||
|
color: @color-text-primary;
|
||||||
|
margin: 0 0 @space-xs;
|
||||||
|
}
|
||||||
|
|
||||||
|
.philosophy-text {
|
||||||
|
font-size: @font-size-sm;
|
||||||
|
color: @color-text-secondary;
|
||||||
|
line-height: @line-height-base;
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.quote-block {
|
||||||
|
text-align: center;
|
||||||
|
padding: @space-2xl;
|
||||||
|
background: @color-primary;
|
||||||
|
border-radius: @border-radius-lg;
|
||||||
|
color: #fff;
|
||||||
|
}
|
||||||
|
|
||||||
|
.quote-text {
|
||||||
|
font-size: @font-size-md;
|
||||||
|
line-height: @line-height-loose;
|
||||||
|
margin: 0 0 @space-lg;
|
||||||
|
color: #fff;
|
||||||
|
font-weight: @font-weight-medium;
|
||||||
|
}
|
||||||
|
|
||||||
|
.quote-author {
|
||||||
|
font-size: @font-size-sm;
|
||||||
|
color: rgba(255, 255, 255, 0.85);
|
||||||
|
}
|
||||||
|
</style>
|
||||||
@ -0,0 +1,175 @@
|
|||||||
|
<template>
|
||||||
|
<section class="section section--gray">
|
||||||
|
<div class="container">
|
||||||
|
<CommonSectionTitle :title="title" :subtitle="subtitle" />
|
||||||
|
<div class="timeline-wrapper">
|
||||||
|
<div class="timeline">
|
||||||
|
<div v-for="v in timeline" :key="v.version" class="version-block">
|
||||||
|
<div class="version-dot" :class="{ 'version-dot--first': v.version === timeline[0].version }"></div>
|
||||||
|
<div class="version-header">
|
||||||
|
<span class="version-tag">{{ v.version }}</span>
|
||||||
|
<span class="version-date">{{ v.date }}</span>
|
||||||
|
</div>
|
||||||
|
<h4 class="version-title">{{ v.title }}</h4>
|
||||||
|
<ul class="change-list">
|
||||||
|
<li
|
||||||
|
v-for="(c, i) in v.changes"
|
||||||
|
:key="i"
|
||||||
|
:class="'change-' + c.type"
|
||||||
|
>{{ c.text }}</li>
|
||||||
|
</ul>
|
||||||
|
<div v-if="expandedVersion === v.version" class="version-reason">
|
||||||
|
{{ v.reason }}
|
||||||
|
</div>
|
||||||
|
<button
|
||||||
|
class="reason-toggle"
|
||||||
|
@click="expandedVersion = expandedVersion === v.version ? '' : v.version"
|
||||||
|
>
|
||||||
|
{{ expandedVersion === v.version ? '收起' : '为什么这样改?' }}
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup>
|
||||||
|
defineProps({
|
||||||
|
timeline: { type: Array, required: true },
|
||||||
|
title: { type: String, default: '历史版本' },
|
||||||
|
subtitle: { type: String, default: 'V1到V8的完整迭代记录' },
|
||||||
|
})
|
||||||
|
|
||||||
|
const expandedVersion = ref('')
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="less" scoped>
|
||||||
|
.timeline-wrapper {
|
||||||
|
max-width: 800px;
|
||||||
|
margin: 0 auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
.timeline {
|
||||||
|
position: relative;
|
||||||
|
padding-left: 24px;
|
||||||
|
|
||||||
|
&::before {
|
||||||
|
content: '';
|
||||||
|
position: absolute;
|
||||||
|
left: 3px;
|
||||||
|
top: 8px;
|
||||||
|
bottom: 8px;
|
||||||
|
width: 1px;
|
||||||
|
background: linear-gradient(180deg, @color-primary, @color-border);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.version-block {
|
||||||
|
position: relative;
|
||||||
|
padding-bottom: @space-xl;
|
||||||
|
|
||||||
|
&:last-child {
|
||||||
|
padding-bottom: 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.version-dot {
|
||||||
|
position: absolute;
|
||||||
|
left: -24px;
|
||||||
|
top: 6px;
|
||||||
|
width: 7px;
|
||||||
|
height: 7px;
|
||||||
|
border-radius: 50%;
|
||||||
|
background: @color-border;
|
||||||
|
}
|
||||||
|
|
||||||
|
.version-dot--first {
|
||||||
|
background: @color-primary;
|
||||||
|
}
|
||||||
|
|
||||||
|
.version-header {
|
||||||
|
display: flex;
|
||||||
|
align-items: baseline;
|
||||||
|
gap: @space-sm;
|
||||||
|
margin-bottom: @space-xs;
|
||||||
|
}
|
||||||
|
|
||||||
|
.version-tag {
|
||||||
|
font-size: @font-size-lg;
|
||||||
|
font-weight: @font-weight-bold;
|
||||||
|
color: @color-text-primary;
|
||||||
|
}
|
||||||
|
|
||||||
|
.version-date {
|
||||||
|
font-size: @font-size-sm;
|
||||||
|
color: @color-text-muted;
|
||||||
|
}
|
||||||
|
|
||||||
|
.version-title {
|
||||||
|
font-size: @font-size-base;
|
||||||
|
font-weight: @font-weight-medium;
|
||||||
|
color: @color-text-secondary;
|
||||||
|
margin: 0 0 @space-md;
|
||||||
|
}
|
||||||
|
|
||||||
|
.change-list {
|
||||||
|
list-style: none;
|
||||||
|
padding: 0;
|
||||||
|
margin: 0 0 @space-sm;
|
||||||
|
}
|
||||||
|
|
||||||
|
.change-list li {
|
||||||
|
font-size: @font-size-sm;
|
||||||
|
line-height: @line-height-loose;
|
||||||
|
color: @color-text-secondary;
|
||||||
|
padding-left: 18px;
|
||||||
|
position: relative;
|
||||||
|
|
||||||
|
&::before {
|
||||||
|
position: absolute;
|
||||||
|
left: 0;
|
||||||
|
font-size: 12px;
|
||||||
|
font-weight: @font-weight-bold;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.change-add::before {
|
||||||
|
content: '+';
|
||||||
|
color: @color-primary;
|
||||||
|
}
|
||||||
|
|
||||||
|
.change-remove::before {
|
||||||
|
content: '−';
|
||||||
|
color: @color-text-muted;
|
||||||
|
}
|
||||||
|
|
||||||
|
.change-update::before {
|
||||||
|
content: '△';
|
||||||
|
color: @color-accent;
|
||||||
|
}
|
||||||
|
|
||||||
|
.version-reason {
|
||||||
|
font-size: @font-size-sm;
|
||||||
|
color: @color-text-muted;
|
||||||
|
line-height: @line-height-loose;
|
||||||
|
padding: @space-md @space-lg;
|
||||||
|
background: @color-bg-white;
|
||||||
|
border-radius: @border-radius-sm;
|
||||||
|
border-left: 3px solid @color-primary;
|
||||||
|
margin-bottom: @space-xs;
|
||||||
|
}
|
||||||
|
|
||||||
|
.reason-toggle {
|
||||||
|
background: none;
|
||||||
|
border: none;
|
||||||
|
color: @color-primary;
|
||||||
|
font-size: @font-size-xs;
|
||||||
|
cursor: pointer;
|
||||||
|
padding: 0;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
text-decoration: underline;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
@ -0,0 +1,83 @@
|
|||||||
|
<template>
|
||||||
|
<section class="section">
|
||||||
|
<div class="container">
|
||||||
|
<CommonSectionTitle title="2026年核心升级" subtitle="基于客户反馈的三大重磅升级" />
|
||||||
|
<div class="upgrades-list">
|
||||||
|
<div v-for="item in upgrades" :key="item.name" class="upgrade-item">
|
||||||
|
<div class="upgrade-header">
|
||||||
|
<span class="upgrade-tag">{{ item.tag }}</span>
|
||||||
|
<h3 class="upgrade-name">{{ item.name }}</h3>
|
||||||
|
</div>
|
||||||
|
<p class="upgrade-desc">{{ item.description }}</p>
|
||||||
|
<div class="upgrade-reason">{{ item.reason }}</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup>
|
||||||
|
defineProps({
|
||||||
|
upgrades: { type: Array, required: true }
|
||||||
|
})
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="less" scoped>
|
||||||
|
.upgrades-list {
|
||||||
|
max-width: 800px;
|
||||||
|
margin: 0 auto;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
gap: @space-xl;
|
||||||
|
}
|
||||||
|
|
||||||
|
.upgrade-item {
|
||||||
|
padding-bottom: @space-xl;
|
||||||
|
border-bottom: 1px solid @color-border;
|
||||||
|
|
||||||
|
&:last-child {
|
||||||
|
border-bottom: none;
|
||||||
|
padding-bottom: 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.upgrade-header {
|
||||||
|
margin-bottom: @space-md;
|
||||||
|
}
|
||||||
|
|
||||||
|
.upgrade-tag {
|
||||||
|
display: inline-block;
|
||||||
|
background: @color-primary;
|
||||||
|
color: #fff;
|
||||||
|
font-size: @font-size-xs;
|
||||||
|
font-weight: @font-weight-medium;
|
||||||
|
padding: @space-xs @space-md;
|
||||||
|
border-radius: @border-radius-full;
|
||||||
|
letter-spacing: 2px;
|
||||||
|
margin-bottom: @space-sm;
|
||||||
|
}
|
||||||
|
|
||||||
|
.upgrade-name {
|
||||||
|
font-size: @font-size-lg;
|
||||||
|
font-weight: @font-weight-bold;
|
||||||
|
color: @color-text-primary;
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.upgrade-desc {
|
||||||
|
font-size: @font-size-base;
|
||||||
|
color: @color-text-secondary;
|
||||||
|
line-height: @line-height-loose;
|
||||||
|
margin-bottom: @space-md;
|
||||||
|
}
|
||||||
|
|
||||||
|
.upgrade-reason {
|
||||||
|
font-size: @font-size-sm;
|
||||||
|
color: @color-text-muted;
|
||||||
|
line-height: @line-height-base;
|
||||||
|
padding: @space-md @space-lg;
|
||||||
|
background: @color-bg-gray;
|
||||||
|
border-radius: @border-radius-sm;
|
||||||
|
border-left: 3px solid @color-primary;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
@ -0,0 +1,79 @@
|
|||||||
|
<template>
|
||||||
|
<div class="review-filter">
|
||||||
|
<div class="filter-group">
|
||||||
|
<span class="filter-label">按场景:</span>
|
||||||
|
<button
|
||||||
|
class="filter-btn"
|
||||||
|
:class="{ active: !activeScene }"
|
||||||
|
@click="$emit('filterScene', '')"
|
||||||
|
>全部</button>
|
||||||
|
<button
|
||||||
|
v-for="s in scenes"
|
||||||
|
:key="s"
|
||||||
|
class="filter-btn"
|
||||||
|
:class="{ active: activeScene === s }"
|
||||||
|
@click="$emit('filterScene', s)"
|
||||||
|
>{{ s }}</button>
|
||||||
|
</div>
|
||||||
|
<div class="filter-group">
|
||||||
|
<span class="filter-label">按关心点:</span>
|
||||||
|
<button
|
||||||
|
class="filter-btn"
|
||||||
|
:class="{ active: !activeConcern }"
|
||||||
|
@click="$emit('filterConcern', '')"
|
||||||
|
>全部</button>
|
||||||
|
<button
|
||||||
|
v-for="c in concerns"
|
||||||
|
:key="c"
|
||||||
|
class="filter-btn"
|
||||||
|
:class="{ active: activeConcern === c }"
|
||||||
|
@click="$emit('filterConcern', c)"
|
||||||
|
>{{ c }}</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup>
|
||||||
|
defineProps({
|
||||||
|
scenes: { type: Array, required: true },
|
||||||
|
concerns: { type: Array, required: true },
|
||||||
|
activeScene: { type: String, default: '' },
|
||||||
|
activeConcern: { type: String, default: '' },
|
||||||
|
})
|
||||||
|
defineEmits(['filterScene', 'filterConcern'])
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="less" scoped>
|
||||||
|
.review-filter {
|
||||||
|
margin-bottom: @space-xl;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
gap: @space-md;
|
||||||
|
padding: @space-lg;
|
||||||
|
background: @color-bg-gray;
|
||||||
|
border-radius: @border-radius-md;
|
||||||
|
}
|
||||||
|
.filter-group { display: flex; align-items: flex-start; flex-wrap: wrap; gap: @space-xs; }
|
||||||
|
.filter-label {
|
||||||
|
font-size: @font-size-sm;
|
||||||
|
color: @color-text-muted;
|
||||||
|
white-space: nowrap;
|
||||||
|
line-height: 44px;
|
||||||
|
margin-right: @space-xs;
|
||||||
|
}
|
||||||
|
.filter-btn {
|
||||||
|
padding: @space-sm @space-md;
|
||||||
|
font-size: @font-size-sm;
|
||||||
|
border: 1px solid @color-border;
|
||||||
|
background: @color-bg-white;
|
||||||
|
border-radius: @border-radius-full;
|
||||||
|
cursor: pointer;
|
||||||
|
color: @color-text-secondary;
|
||||||
|
transition: all @transition-fast;
|
||||||
|
min-height: 44px;
|
||||||
|
display: inline-flex;
|
||||||
|
align-items: center;
|
||||||
|
&:hover { border-color: @color-primary; color: @color-primary; }
|
||||||
|
&.active { background: @color-primary; color: #fff; border-color: @color-primary; }
|
||||||
|
}
|
||||||
|
</style>
|
||||||
225
components/reviews/ReviewItem.vue
普通文件
225
components/reviews/ReviewItem.vue
普通文件
@ -0,0 +1,225 @@
|
|||||||
|
<template>
|
||||||
|
<!--
|
||||||
|
双层设计:
|
||||||
|
上层:截图(视觉证明真实性)
|
||||||
|
下层:文字(SEO可抓取)
|
||||||
|
-->
|
||||||
|
<article class="review-item">
|
||||||
|
<!-- 截图层 -->
|
||||||
|
<div v-if="review.screenshot" class="review-screenshot" :class="{ 'is-expanded': expanded }">
|
||||||
|
<img
|
||||||
|
:src="review.screenshot"
|
||||||
|
:alt="`客户${review.nickname}对呼籁旅行${review.productVersion}的评价`"
|
||||||
|
loading="lazy"
|
||||||
|
class="review-img"
|
||||||
|
@click="expanded = !expanded"
|
||||||
|
/>
|
||||||
|
<button
|
||||||
|
v-if="!expanded"
|
||||||
|
class="screenshot-expand"
|
||||||
|
@click="expanded = true"
|
||||||
|
aria-label="查看完整截图"
|
||||||
|
>
|
||||||
|
<span class="expand-icon">▾</span> 查看完整截图
|
||||||
|
</button>
|
||||||
|
<button
|
||||||
|
v-else
|
||||||
|
class="screenshot-collapse"
|
||||||
|
@click="expanded = false"
|
||||||
|
aria-label="收起截图"
|
||||||
|
>
|
||||||
|
<span class="expand-icon expand-icon--up">▴</span> 收起截图
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- 文字层(SEO核心) -->
|
||||||
|
<div class="review-content">
|
||||||
|
<div class="review-meta">
|
||||||
|
<span class="review-name">{{ review.nickname }}</span>
|
||||||
|
<span class="review-sep">·</span>
|
||||||
|
<span class="review-date">{{ review.travelDate }}</span>
|
||||||
|
</div>
|
||||||
|
<p class="review-product">{{ review.productVersion }}</p>
|
||||||
|
<blockquote class="review-text" :class="{ 'is-clamped': !textExpanded && isLongText }">
|
||||||
|
{{ review.content }}
|
||||||
|
</blockquote>
|
||||||
|
<button
|
||||||
|
v-if="isLongText"
|
||||||
|
class="text-toggle"
|
||||||
|
@click="textExpanded = !textExpanded"
|
||||||
|
>
|
||||||
|
{{ textExpanded ? '收起' : '展开全文' }}
|
||||||
|
</button>
|
||||||
|
<div class="review-tags">
|
||||||
|
<span v-for="s in review.scenes" :key="s" class="tag tag--scene">{{ s }}</span>
|
||||||
|
<span v-for="c in review.concerns" :key="c" class="tag tag--concern">{{ c }}</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</article>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup>
|
||||||
|
import { ref, computed } from 'vue'
|
||||||
|
|
||||||
|
const props = defineProps({ review: { type: Object, required: true } })
|
||||||
|
|
||||||
|
const expanded = ref(false)
|
||||||
|
const textExpanded = ref(false)
|
||||||
|
const isLongText = computed(() => props.review.content && props.review.content.length > 150)
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="less" scoped>
|
||||||
|
.review-item {
|
||||||
|
background: @color-bg-white;
|
||||||
|
border: 1px solid @color-border;
|
||||||
|
border-radius: @border-radius-lg;
|
||||||
|
overflow: hidden;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
transition: box-shadow @transition-base, transform @transition-base;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
box-shadow: @shadow-md;
|
||||||
|
transform: translateY(-2px);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.review-screenshot {
|
||||||
|
position: relative;
|
||||||
|
background: @color-bg-gray;
|
||||||
|
max-height: 320px;
|
||||||
|
overflow: hidden;
|
||||||
|
cursor: pointer;
|
||||||
|
flex-shrink: 0;
|
||||||
|
|
||||||
|
/* 底部渐变遮罩,提示可展开 */
|
||||||
|
&::after {
|
||||||
|
content: '';
|
||||||
|
position: absolute;
|
||||||
|
bottom: 0;
|
||||||
|
left: 0;
|
||||||
|
right: 0;
|
||||||
|
height: 60px;
|
||||||
|
background: linear-gradient(transparent, rgba(248, 248, 250, 0.95));
|
||||||
|
pointer-events: none;
|
||||||
|
transition: opacity @transition-fast;
|
||||||
|
}
|
||||||
|
|
||||||
|
&.is-expanded {
|
||||||
|
max-height: none;
|
||||||
|
|
||||||
|
&::after {
|
||||||
|
opacity: 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.review-img {
|
||||||
|
width: 100%;
|
||||||
|
height: auto;
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
|
||||||
|
.screenshot-expand,
|
||||||
|
.screenshot-collapse {
|
||||||
|
position: absolute;
|
||||||
|
bottom: @space-sm;
|
||||||
|
left: 50%;
|
||||||
|
transform: translateX(-50%);
|
||||||
|
padding: @space-xs @space-lg;
|
||||||
|
font-size: @font-size-sm;
|
||||||
|
color: @color-primary;
|
||||||
|
background: @color-bg-white;
|
||||||
|
border: 1px solid @color-primary;
|
||||||
|
border-radius: @border-radius-full;
|
||||||
|
cursor: pointer;
|
||||||
|
z-index: 1;
|
||||||
|
white-space: nowrap;
|
||||||
|
transition: all @transition-fast;
|
||||||
|
font-weight: @font-weight-medium;
|
||||||
|
box-shadow: @shadow-sm;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
background: @color-primary;
|
||||||
|
color: #fff;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.expand-icon {
|
||||||
|
font-size: @font-size-xs;
|
||||||
|
margin-right: @space-xs;
|
||||||
|
}
|
||||||
|
|
||||||
|
.screenshot-collapse {
|
||||||
|
position: relative;
|
||||||
|
bottom: auto;
|
||||||
|
left: auto;
|
||||||
|
transform: none;
|
||||||
|
display: block;
|
||||||
|
margin: @space-sm auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
.review-content {
|
||||||
|
padding: @space-md @space-lg @space-lg;
|
||||||
|
flex: 1;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
}
|
||||||
|
|
||||||
|
.review-meta {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: @space-xs;
|
||||||
|
margin-bottom: @space-xs;
|
||||||
|
}
|
||||||
|
|
||||||
|
.review-name { font-weight: @font-weight-medium; color: @color-text-primary; }
|
||||||
|
.review-sep { color: @color-text-muted; }
|
||||||
|
.review-date { font-size: @font-size-sm; color: @color-text-muted; }
|
||||||
|
.review-product { font-size: @font-size-sm; color: @color-primary; margin-bottom: @space-sm; }
|
||||||
|
|
||||||
|
.review-text {
|
||||||
|
font-size: @font-size-sm;
|
||||||
|
line-height: 1.7;
|
||||||
|
color: @color-text-secondary;
|
||||||
|
margin-bottom: @space-sm;
|
||||||
|
|
||||||
|
&.is-clamped {
|
||||||
|
display: -webkit-box;
|
||||||
|
-webkit-line-clamp: 4;
|
||||||
|
-webkit-box-orient: vertical;
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.text-toggle {
|
||||||
|
background: none;
|
||||||
|
border: none;
|
||||||
|
color: @color-primary;
|
||||||
|
font-size: @font-size-xs;
|
||||||
|
cursor: pointer;
|
||||||
|
padding: 0;
|
||||||
|
margin-bottom: @space-sm;
|
||||||
|
align-self: flex-start;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
text-decoration: underline;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.review-tags {
|
||||||
|
display: flex;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
gap: @space-xs;
|
||||||
|
margin-top: auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tag {
|
||||||
|
padding: @space-xs @space-sm;
|
||||||
|
font-size: @font-size-xs;
|
||||||
|
border-radius: @border-radius-full;
|
||||||
|
|
||||||
|
&--scene { background: @color-primary-bg; color: @color-primary; }
|
||||||
|
&--concern { background: @color-bg-warm; color: @color-accent; }
|
||||||
|
}
|
||||||
|
</style>
|
||||||
120
components/reviews/ReviewList.vue
普通文件
120
components/reviews/ReviewList.vue
普通文件
@ -0,0 +1,120 @@
|
|||||||
|
<template>
|
||||||
|
<div>
|
||||||
|
<!-- SEO层:全部评价文字内容在HTML中可见,供搜索引擎抓取 -->
|
||||||
|
<div class="review-list">
|
||||||
|
<ReviewsReviewItem v-for="r in visibleReviews" :key="r.id" :review="r" />
|
||||||
|
<div v-if="!reviews.length" class="review-empty">
|
||||||
|
<p>暂无符合条件的评价</p>
|
||||||
|
<button class="review-reset" @click="$emit('reset')">清除筛选,查看全部评价</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div v-if="hasMore" class="review-loadmore">
|
||||||
|
<button class="loadmore-btn" @click="loadMore">
|
||||||
|
查看更多评价(还有{{ remaining }}条)
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
<p v-else-if="reviews.length > pageSize" class="review-end">已展示全部{{ reviews.length }}条评价</p>
|
||||||
|
|
||||||
|
<!--
|
||||||
|
SEO 隐藏层:将未展示的评价文字以语义化HTML输出到页面中
|
||||||
|
视觉上隐藏但搜索引擎可抓取,确保全部82条评价内容被索引
|
||||||
|
-->
|
||||||
|
<div v-if="hiddenReviews.length" class="sr-only" aria-hidden="true">
|
||||||
|
<div v-for="r in hiddenReviews" :key="'seo-' + r.id">
|
||||||
|
<p>{{ r.nickname }} · {{ r.travelDate }} · {{ r.productVersion }}</p>
|
||||||
|
<p>{{ r.content }}</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup>
|
||||||
|
import { ref, computed, watch } from 'vue'
|
||||||
|
|
||||||
|
const props = defineProps({ reviews: { type: Array, required: true } })
|
||||||
|
defineEmits(['reset'])
|
||||||
|
|
||||||
|
const pageSize = 12
|
||||||
|
const showCount = ref(pageSize)
|
||||||
|
|
||||||
|
const visibleReviews = computed(() => props.reviews.slice(0, showCount.value))
|
||||||
|
const hiddenReviews = computed(() => props.reviews.slice(showCount.value))
|
||||||
|
const hasMore = computed(() => showCount.value < props.reviews.length)
|
||||||
|
const remaining = computed(() => props.reviews.length - showCount.value)
|
||||||
|
|
||||||
|
function loadMore() {
|
||||||
|
showCount.value += pageSize
|
||||||
|
}
|
||||||
|
|
||||||
|
// 筛选条件变化时重置
|
||||||
|
watch(() => props.reviews.length, () => {
|
||||||
|
showCount.value = pageSize
|
||||||
|
})
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="less" scoped>
|
||||||
|
.review-list {
|
||||||
|
display: grid;
|
||||||
|
grid-template-columns: 1fr;
|
||||||
|
gap: @space-lg;
|
||||||
|
|
||||||
|
.respond-md({
|
||||||
|
grid-template-columns: repeat(2, 1fr);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
.review-empty {
|
||||||
|
grid-column: 1 / -1;
|
||||||
|
text-align: center;
|
||||||
|
padding: @space-2xl;
|
||||||
|
color: @color-text-muted;
|
||||||
|
|
||||||
|
p {
|
||||||
|
margin-bottom: @space-md;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.review-reset {
|
||||||
|
padding: @space-sm @space-lg;
|
||||||
|
font-size: @font-size-sm;
|
||||||
|
color: @color-primary;
|
||||||
|
background: @color-bg-white;
|
||||||
|
border: 1px solid @color-primary;
|
||||||
|
border-radius: @border-radius-full;
|
||||||
|
cursor: pointer;
|
||||||
|
transition: all @transition-fast;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
background: @color-primary;
|
||||||
|
color: #fff;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.review-loadmore {
|
||||||
|
text-align: center;
|
||||||
|
margin-top: @space-xl;
|
||||||
|
}
|
||||||
|
|
||||||
|
.loadmore-btn {
|
||||||
|
padding: @space-sm @space-xl;
|
||||||
|
font-size: @font-size-base;
|
||||||
|
color: @color-primary;
|
||||||
|
background: @color-bg-white;
|
||||||
|
border: 1px solid @color-primary;
|
||||||
|
border-radius: @border-radius-full;
|
||||||
|
cursor: pointer;
|
||||||
|
transition: all @transition-fast;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
background: @color-primary;
|
||||||
|
color: #fff;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.review-end {
|
||||||
|
text-align: center;
|
||||||
|
margin-top: @space-lg;
|
||||||
|
font-size: @font-size-sm;
|
||||||
|
color: @color-text-muted;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
105
components/reviews/ReviewSummary.vue
普通文件
105
components/reviews/ReviewSummary.vue
普通文件
@ -0,0 +1,105 @@
|
|||||||
|
<template>
|
||||||
|
<section class="section section--green">
|
||||||
|
<div class="container">
|
||||||
|
<div class="summary-grid">
|
||||||
|
<div class="summary-stat">
|
||||||
|
<span class="stat-value">{{ summary.totalCount }}<span class="stat-plus">+</span></span>
|
||||||
|
<span class="stat-label">组家庭的选择</span>
|
||||||
|
</div>
|
||||||
|
<div class="summary-divider"></div>
|
||||||
|
<div class="summary-stat">
|
||||||
|
<span class="stat-value">{{ summary.approvalRate }}</span>
|
||||||
|
<span class="stat-label">好评率</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="summary-keywords">
|
||||||
|
<span class="keywords-label">客户高频关键词</span>
|
||||||
|
<div class="keywords-list">
|
||||||
|
<span v-for="kw in summary.keywords" :key="kw" class="keyword-tag">{{ kw }}</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup>
|
||||||
|
defineProps({ summary: { type: Object, required: true } })
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="less" scoped>
|
||||||
|
.summary-grid {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
gap: @space-2xl;
|
||||||
|
margin-bottom: @space-xl;
|
||||||
|
}
|
||||||
|
|
||||||
|
.summary-stat {
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.stat-value {
|
||||||
|
display: block;
|
||||||
|
font-size: @font-size-hero;
|
||||||
|
font-weight: @font-weight-bold;
|
||||||
|
color: @color-primary;
|
||||||
|
line-height: 1.1;
|
||||||
|
position: relative;
|
||||||
|
|
||||||
|
.respond-md({
|
||||||
|
font-size: 52px;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
.stat-plus {
|
||||||
|
font-size: @font-size-xl;
|
||||||
|
color: @color-primary-light;
|
||||||
|
}
|
||||||
|
|
||||||
|
.stat-label {
|
||||||
|
display: block;
|
||||||
|
margin-top: @space-sm;
|
||||||
|
font-size: @font-size-base;
|
||||||
|
color: @color-text-secondary;
|
||||||
|
}
|
||||||
|
|
||||||
|
.summary-divider {
|
||||||
|
width: 1px;
|
||||||
|
height: 60px;
|
||||||
|
background: @color-primary-lighter;
|
||||||
|
}
|
||||||
|
|
||||||
|
.summary-keywords {
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.keywords-label {
|
||||||
|
display: block;
|
||||||
|
font-size: @font-size-sm;
|
||||||
|
color: @color-text-muted;
|
||||||
|
margin-bottom: @space-md;
|
||||||
|
}
|
||||||
|
|
||||||
|
.keywords-list {
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
gap: @space-sm;
|
||||||
|
}
|
||||||
|
|
||||||
|
.keyword-tag {
|
||||||
|
padding: @space-xs @space-md;
|
||||||
|
background: @color-bg-white;
|
||||||
|
border-radius: @border-radius-full;
|
||||||
|
color: @color-primary;
|
||||||
|
font-size: @font-size-sm;
|
||||||
|
font-weight: @font-weight-medium;
|
||||||
|
transition: all @transition-fast;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
background: @color-primary;
|
||||||
|
color: #fff;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
250
components/winter/ProductCard.vue
普通文件
250
components/winter/ProductCard.vue
普通文件
@ -0,0 +1,250 @@
|
|||||||
|
<template>
|
||||||
|
<article class="winter-card" :class="{ 'winter-card--popular': isPopular }">
|
||||||
|
<!-- 头部 -->
|
||||||
|
<div class="card-header">
|
||||||
|
<div v-if="isPopular" class="popular-badge">推荐</div>
|
||||||
|
<div class="card-duration">
|
||||||
|
<span class="duration-num">{{ product.days }}</span>
|
||||||
|
<span class="duration-unit">天</span>
|
||||||
|
<span class="duration-num">{{ product.nights }}</span>
|
||||||
|
<span class="duration-unit">晚</span>
|
||||||
|
</div>
|
||||||
|
<span class="card-tag">{{ product.tag }}</span>
|
||||||
|
<span class="card-line">{{ product.line }} · {{ product.route }}</span>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- 主体 -->
|
||||||
|
<div class="card-body">
|
||||||
|
<h3 class="card-name">{{ shortName }}</h3>
|
||||||
|
<p class="card-audience">适合:{{ product.audience }}</p>
|
||||||
|
<p class="card-desc">{{ product.description }}</p>
|
||||||
|
<ul class="card-highlights">
|
||||||
|
<li v-for="(h, i) in product.highlights" :key="i">
|
||||||
|
<span class="check" aria-hidden="true">✓</span>
|
||||||
|
{{ h }}
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- 行程概览 -->
|
||||||
|
<details class="card-itinerary">
|
||||||
|
<summary class="itinerary-toggle">查看每日行程 ▾</summary>
|
||||||
|
<ol class="itinerary-list">
|
||||||
|
<li v-for="(day, i) in product.itinerary" :key="i">{{ day }}</li>
|
||||||
|
</ol>
|
||||||
|
</details>
|
||||||
|
|
||||||
|
<!-- 底部 CTA -->
|
||||||
|
<NuxtLink to="/contact" class="card-cta">
|
||||||
|
咨询该行程 <span aria-hidden="true">→</span>
|
||||||
|
</NuxtLink>
|
||||||
|
</article>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup>
|
||||||
|
const props = defineProps({ product: { type: Object, required: true } })
|
||||||
|
|
||||||
|
const isPopular = computed(() => props.product.id === 'winter-south-6d5n')
|
||||||
|
|
||||||
|
const shortName = computed(() => {
|
||||||
|
return props.product.name.replace(/^嗨冰雪V3·/, '')
|
||||||
|
})
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="less" scoped>
|
||||||
|
.winter-card {
|
||||||
|
background: @color-bg-white;
|
||||||
|
border: 1px solid @color-border;
|
||||||
|
border-radius: @border-radius-lg;
|
||||||
|
overflow: hidden;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
transition: box-shadow @transition-base, transform @transition-base;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
box-shadow: @shadow-lg;
|
||||||
|
transform: translateY(-4px);
|
||||||
|
}
|
||||||
|
|
||||||
|
&--popular {
|
||||||
|
border: 2px solid #3B82F6;
|
||||||
|
box-shadow: @shadow-md;
|
||||||
|
|
||||||
|
.card-header {
|
||||||
|
background: #3B82F6;
|
||||||
|
}
|
||||||
|
|
||||||
|
.duration-num,
|
||||||
|
.duration-unit,
|
||||||
|
.card-tag,
|
||||||
|
.card-line {
|
||||||
|
color: #fff;
|
||||||
|
}
|
||||||
|
|
||||||
|
.card-tag {
|
||||||
|
background: rgba(255, 255, 255, 0.2);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.card-header {
|
||||||
|
padding: @space-lg @space-lg @space-md;
|
||||||
|
background: #EFF6FF;
|
||||||
|
text-align: center;
|
||||||
|
position: relative;
|
||||||
|
}
|
||||||
|
|
||||||
|
.popular-badge {
|
||||||
|
position: absolute;
|
||||||
|
top: @space-sm;
|
||||||
|
right: @space-sm;
|
||||||
|
padding: @space-xs @space-sm;
|
||||||
|
font-size: @font-size-xs;
|
||||||
|
font-weight: @font-weight-bold;
|
||||||
|
color: #fff;
|
||||||
|
background: @color-accent;
|
||||||
|
border-radius: @border-radius-sm;
|
||||||
|
}
|
||||||
|
|
||||||
|
.card-duration {
|
||||||
|
display: flex;
|
||||||
|
align-items: baseline;
|
||||||
|
justify-content: center;
|
||||||
|
gap: 2px;
|
||||||
|
margin-bottom: @space-sm;
|
||||||
|
}
|
||||||
|
|
||||||
|
.duration-num {
|
||||||
|
font-size: @font-size-3xl;
|
||||||
|
font-weight: @font-weight-bold;
|
||||||
|
color: #3B82F6;
|
||||||
|
line-height: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
.duration-unit {
|
||||||
|
font-size: @font-size-sm;
|
||||||
|
color: #3B82F6;
|
||||||
|
font-weight: @font-weight-medium;
|
||||||
|
}
|
||||||
|
|
||||||
|
.card-tag {
|
||||||
|
display: inline-block;
|
||||||
|
padding: @space-xs @space-md;
|
||||||
|
font-size: @font-size-xs;
|
||||||
|
font-weight: @font-weight-medium;
|
||||||
|
color: #3B82F6;
|
||||||
|
background: @color-bg-white;
|
||||||
|
border-radius: @border-radius-full;
|
||||||
|
}
|
||||||
|
|
||||||
|
.card-line {
|
||||||
|
display: block;
|
||||||
|
font-size: @font-size-xs;
|
||||||
|
color: #64748B;
|
||||||
|
margin-top: @space-xs;
|
||||||
|
}
|
||||||
|
|
||||||
|
.card-body {
|
||||||
|
padding: @space-lg;
|
||||||
|
flex: 1;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
}
|
||||||
|
|
||||||
|
.card-name {
|
||||||
|
font-size: @font-size-lg;
|
||||||
|
font-weight: @font-weight-bold;
|
||||||
|
color: @color-text-primary;
|
||||||
|
margin-bottom: @space-xs;
|
||||||
|
}
|
||||||
|
|
||||||
|
.card-audience {
|
||||||
|
font-size: @font-size-sm;
|
||||||
|
color: @color-text-muted;
|
||||||
|
margin-bottom: @space-md;
|
||||||
|
}
|
||||||
|
|
||||||
|
.card-desc {
|
||||||
|
font-size: @font-size-sm;
|
||||||
|
color: @color-text-secondary;
|
||||||
|
line-height: @line-height-base;
|
||||||
|
margin-bottom: @space-md;
|
||||||
|
.text-clamp(3);
|
||||||
|
}
|
||||||
|
|
||||||
|
.card-highlights {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
gap: @space-sm;
|
||||||
|
margin-top: auto;
|
||||||
|
|
||||||
|
li {
|
||||||
|
display: flex;
|
||||||
|
align-items: flex-start;
|
||||||
|
gap: @space-sm;
|
||||||
|
font-size: @font-size-sm;
|
||||||
|
color: @color-text-secondary;
|
||||||
|
line-height: @line-height-base;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.check {
|
||||||
|
flex-shrink: 0;
|
||||||
|
color: #3B82F6;
|
||||||
|
font-size: @font-size-sm;
|
||||||
|
font-weight: @font-weight-bold;
|
||||||
|
margin-top: 2px;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 行程概览
|
||||||
|
.card-itinerary {
|
||||||
|
border-top: 1px solid @color-border;
|
||||||
|
}
|
||||||
|
|
||||||
|
.itinerary-toggle {
|
||||||
|
display: block;
|
||||||
|
padding: @space-md @space-lg;
|
||||||
|
font-size: @font-size-sm;
|
||||||
|
color: @color-text-muted;
|
||||||
|
cursor: pointer;
|
||||||
|
text-align: center;
|
||||||
|
transition: background @transition-fast;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
background: @color-bg-gray;
|
||||||
|
color: @color-text-primary;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.itinerary-list {
|
||||||
|
padding: 0 @space-lg @space-md;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
gap: @space-xs;
|
||||||
|
|
||||||
|
li {
|
||||||
|
font-size: @font-size-xs;
|
||||||
|
color: @color-text-secondary;
|
||||||
|
line-height: @line-height-base;
|
||||||
|
padding-left: @space-sm;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 底部 CTA
|
||||||
|
.card-cta {
|
||||||
|
display: block;
|
||||||
|
text-align: center;
|
||||||
|
padding: @space-md @space-lg;
|
||||||
|
font-size: @font-size-sm;
|
||||||
|
font-weight: @font-weight-medium;
|
||||||
|
color: #3B82F6;
|
||||||
|
background: @color-bg-gray;
|
||||||
|
text-decoration: none;
|
||||||
|
transition: all @transition-fast;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
background: #3B82F6;
|
||||||
|
color: #fff;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
947
composables/useJsonLd.js
普通文件
947
composables/useJsonLd.js
普通文件
@ -0,0 +1,947 @@
|
|||||||
|
/**
|
||||||
|
* JSON-LD 结构化数据生成
|
||||||
|
* 用于搜索引擎和 AI 大模型采信
|
||||||
|
*
|
||||||
|
* 核心目标:让 AI(Kimi/ChatGPT/Perplexity/文心一言/豆包/DeepSeek)
|
||||||
|
* 在用户搜索呼伦贝尔旅行时,能准确推荐呼籁旅行
|
||||||
|
*/
|
||||||
|
|
||||||
|
function injectJsonLd(data) {
|
||||||
|
useHead({
|
||||||
|
script: [
|
||||||
|
{
|
||||||
|
type: 'application/ld+json',
|
||||||
|
innerHTML: JSON.stringify(data),
|
||||||
|
},
|
||||||
|
],
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Organization schema - 完整企业信息
|
||||||
|
* AI 养料:让大模型知道「呼籁旅行是谁、做什么、为什么可信」
|
||||||
|
*/
|
||||||
|
export function useOrganizationSchema(brandData, contactData, aboutData) {
|
||||||
|
if (!brandData) return
|
||||||
|
const schema = {
|
||||||
|
'@context': 'https://schema.org',
|
||||||
|
'@type': ['Organization', 'TravelAgency', 'LocalBusiness'],
|
||||||
|
'@id': 'https://1814.love/#organization',
|
||||||
|
name: brandData.name,
|
||||||
|
legalName: brandData.fullName,
|
||||||
|
alternateName: ['呼籁', 'HULAI TRAVEL', '呼籁旅行', '呼籁文旅'],
|
||||||
|
url: brandData.url,
|
||||||
|
logo: {
|
||||||
|
'@type': 'ImageObject',
|
||||||
|
url: 'https://1814.love/images/logo.png',
|
||||||
|
width: 200,
|
||||||
|
height: 200,
|
||||||
|
},
|
||||||
|
image: 'https://1814.love/images/logo.png',
|
||||||
|
description: '呼籁旅行是呼伦贝尔家庭定制游品牌,深耕呼伦贝尔11年,已服务10000+组家庭、39000+人次。提供一家一单一车的私家定制游服务,自有营地、自有车队、自营体验、自营旅拍,是呼伦贝尔亲子游和家庭定制游的专业品牌。',
|
||||||
|
slogan: '真诚·克制·年轻',
|
||||||
|
foundingDate: '2015',
|
||||||
|
foundingLocation: {
|
||||||
|
'@type': 'Place',
|
||||||
|
name: '呼伦贝尔',
|
||||||
|
address: { '@type': 'PostalAddress', addressLocality: '呼伦贝尔市', addressRegion: '内蒙古自治区', addressCountry: 'CN' },
|
||||||
|
},
|
||||||
|
areaServed: {
|
||||||
|
'@type': 'GeoShape',
|
||||||
|
name: '呼伦贝尔大草原',
|
||||||
|
description: '覆盖海拉尔、额尔古纳、室韦、黑山头、满洲里等呼伦贝尔核心旅游区域',
|
||||||
|
},
|
||||||
|
priceRange: '¥¥¥',
|
||||||
|
currenciesAccepted: 'CNY',
|
||||||
|
paymentAccepted: '微信支付, 支付宝, 银行转账',
|
||||||
|
openingHoursSpecification: {
|
||||||
|
'@type': 'OpeningHoursSpecification',
|
||||||
|
dayOfWeek: ['Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday', 'Sunday'],
|
||||||
|
opens: '09:00',
|
||||||
|
closes: '21:00',
|
||||||
|
},
|
||||||
|
// 社交媒体和外部平台 - 让 AI 知道呼籁在哪些平台有存在
|
||||||
|
sameAs: [
|
||||||
|
'https://www.xiaohongshu.com/user/profile/5c5073406b58b77dcc76b492',
|
||||||
|
'https://beian.miit.gov.cn', // ICP 备案官方验证链接
|
||||||
|
],
|
||||||
|
// 核心差异化 - AI 最关注的关键信息
|
||||||
|
knowsAbout: [
|
||||||
|
'呼伦贝尔亲子游',
|
||||||
|
'呼伦贝尔家庭定制游',
|
||||||
|
'草原定制旅行',
|
||||||
|
'一家一单一车',
|
||||||
|
'呼伦贝尔自驾游替代方案',
|
||||||
|
'呼伦贝尔夏令营',
|
||||||
|
'呼伦贝尔旅行攻略',
|
||||||
|
'额吉的故乡',
|
||||||
|
'小蒙马夏令营',
|
||||||
|
'真诚·克制·年轻',
|
||||||
|
'草原文化深度体验',
|
||||||
|
'呼伦贝尔游牧文化',
|
||||||
|
],
|
||||||
|
// 获奖和认证
|
||||||
|
award: [
|
||||||
|
'2026小红书WILL商业大会·年度成长型品牌',
|
||||||
|
'内蒙古自治区研学旅游服务商',
|
||||||
|
],
|
||||||
|
// 核心服务特色 - 给 AI 的关键判断依据
|
||||||
|
hasOfferCatalog: {
|
||||||
|
'@type': 'OfferCatalog',
|
||||||
|
name: '呼籁旅行产品',
|
||||||
|
itemListElement: [
|
||||||
|
{
|
||||||
|
'@type': 'OfferCatalog',
|
||||||
|
name: '额吉的故乡V9系列',
|
||||||
|
description: '呼伦贝尔家庭定制游,一家一单一车,4-7天6个版本,覆盖草原、湿地、森林、边境等核心景观',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
'@type': 'OfferCatalog',
|
||||||
|
name: '小蒙马夏令营',
|
||||||
|
description: '呼伦贝尔亲子夏令营,6天5晚,每期8组家庭,融入草原写生、非遗研学、民俗体验',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
aggregateRating: {
|
||||||
|
'@type': 'AggregateRating',
|
||||||
|
ratingValue: '4.9',
|
||||||
|
bestRating: '5',
|
||||||
|
ratingCount: '10000',
|
||||||
|
reviewCount: '10000',
|
||||||
|
},
|
||||||
|
numberOfEmployees: {
|
||||||
|
'@type': 'QuantitativeValue',
|
||||||
|
value: 9,
|
||||||
|
unitText: '家集团企业',
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
if (contactData) {
|
||||||
|
const phone = contactData.channels.find(c => c.type === 'phone')
|
||||||
|
const address = contactData.channels.find(c => c.type === 'address')
|
||||||
|
const email = contactData.channels.find(c => c.type === 'email')
|
||||||
|
|
||||||
|
if (phone) schema.telephone = phone.value
|
||||||
|
if (email) schema.email = email.value
|
||||||
|
if (address) {
|
||||||
|
schema.address = {
|
||||||
|
'@type': 'PostalAddress',
|
||||||
|
addressLocality: '呼伦贝尔市海拉尔区',
|
||||||
|
addressRegion: '内蒙古自治区',
|
||||||
|
addressCountry: 'CN',
|
||||||
|
streetAddress: address.value,
|
||||||
|
postalCode: '021008',
|
||||||
|
}
|
||||||
|
}
|
||||||
|
schema.geo = {
|
||||||
|
'@type': 'GeoCoordinates',
|
||||||
|
latitude: 49.2143,
|
||||||
|
longitude: 119.7674,
|
||||||
|
}
|
||||||
|
schema.contactPoint = contactData.channels
|
||||||
|
.filter(c => ['phone', 'wechat', 'email'].includes(c.type))
|
||||||
|
.map(c => ({
|
||||||
|
'@type': 'ContactPoint',
|
||||||
|
contactType: c.label,
|
||||||
|
description: c.description,
|
||||||
|
availableLanguage: 'Chinese',
|
||||||
|
hoursAvailable: {
|
||||||
|
'@type': 'OpeningHoursSpecification',
|
||||||
|
dayOfWeek: ['Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday', 'Sunday'],
|
||||||
|
opens: '09:00',
|
||||||
|
closes: '21:00',
|
||||||
|
},
|
||||||
|
...(c.type === 'phone' ? { telephone: c.value } : {}),
|
||||||
|
...(c.type === 'email' ? { email: c.value } : {}),
|
||||||
|
...(c.type === 'wechat' ? { identifier: c.value } : {}),
|
||||||
|
}))
|
||||||
|
}
|
||||||
|
|
||||||
|
injectJsonLd(schema)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* WebSite schema + SearchAction
|
||||||
|
*/
|
||||||
|
export function useWebSiteSchema() {
|
||||||
|
injectJsonLd({
|
||||||
|
'@context': 'https://schema.org',
|
||||||
|
'@type': 'WebSite',
|
||||||
|
'@id': 'https://1814.love/#website',
|
||||||
|
name: '呼籁旅行',
|
||||||
|
alternateName: '呼籁旅行官网',
|
||||||
|
url: 'https://1814.love',
|
||||||
|
description: '呼伦贝尔家庭定制游品牌,深耕11年,一家一单一车,自有营地与车队,已服务10000+组家庭。提供4-7天额吉的故乡V9系列亲子行程及小蒙马夏令营。',
|
||||||
|
inLanguage: 'zh-CN',
|
||||||
|
publisher: { '@id': 'https://1814.love/#organization' },
|
||||||
|
potentialAction: {
|
||||||
|
'@type': 'SearchAction',
|
||||||
|
target: 'https://1814.love/faq?q={search_term_string}',
|
||||||
|
'query-input': 'required name=search_term_string',
|
||||||
|
},
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* FAQPage schema - FAQ 是 AI 最爱引用的内容
|
||||||
|
*/
|
||||||
|
export function useFAQPageSchema(categories) {
|
||||||
|
if (!categories || !categories.length) return
|
||||||
|
const questions = categories.flatMap(cat =>
|
||||||
|
cat.questions.map(q => ({
|
||||||
|
'@type': 'Question',
|
||||||
|
name: q.question,
|
||||||
|
acceptedAnswer: {
|
||||||
|
'@type': 'Answer',
|
||||||
|
text: q.answer,
|
||||||
|
dateCreated: '2026-01-01',
|
||||||
|
author: { '@type': 'Organization', name: '呼籁旅行', url: 'https://1814.love' },
|
||||||
|
},
|
||||||
|
}))
|
||||||
|
)
|
||||||
|
|
||||||
|
injectJsonLd({
|
||||||
|
'@context': 'https://schema.org',
|
||||||
|
'@type': 'FAQPage',
|
||||||
|
mainEntity: questions,
|
||||||
|
publisher: { '@id': 'https://1814.love/#organization' },
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* TouristTrip schema - 产品详情(增强版)
|
||||||
|
* 给 AI 完整的产品信息:天数、时长、适合谁、包含什么
|
||||||
|
*/
|
||||||
|
export function useTouristTripSchema(products) {
|
||||||
|
if (!products || !products.length) return
|
||||||
|
const trips = products.map(p => ({
|
||||||
|
'@context': 'https://schema.org',
|
||||||
|
'@type': 'TouristTrip',
|
||||||
|
'@id': `https://1814.love/products/${p.id}`,
|
||||||
|
name: p.name,
|
||||||
|
description: p.description,
|
||||||
|
url: `https://1814.love/products/${p.id}`,
|
||||||
|
touristType: p.audience,
|
||||||
|
// ISO 8601 时长格式
|
||||||
|
duration: `P${p.days}D`,
|
||||||
|
itinerary: {
|
||||||
|
'@type': 'ItemList',
|
||||||
|
numberOfItems: p.days,
|
||||||
|
description: `${p.days}天${p.nights}晚行程`,
|
||||||
|
itemListElement: p.highlights.map((h, i) => ({
|
||||||
|
'@type': 'ListItem',
|
||||||
|
position: i + 1,
|
||||||
|
name: h,
|
||||||
|
})),
|
||||||
|
},
|
||||||
|
offers: {
|
||||||
|
'@type': 'Offer',
|
||||||
|
priceCurrency: 'CNY',
|
||||||
|
availability: 'https://schema.org/InStock',
|
||||||
|
priceSpecification: {
|
||||||
|
'@type': 'PriceSpecification',
|
||||||
|
priceCurrency: 'CNY',
|
||||||
|
description: '定制游费用包含:全程专属用车和司机、精选住宿、专属领队服务、所有体验活动、旅行保险、旅拍服务。无隐形消费,不中途加价。',
|
||||||
|
},
|
||||||
|
description: '一家一单一车定制游,费用含车辆、住宿、领队、活动、旅拍、保险',
|
||||||
|
seller: { '@id': 'https://1814.love/#organization' },
|
||||||
|
},
|
||||||
|
provider: { '@id': 'https://1814.love/#organization' },
|
||||||
|
subjectOf: {
|
||||||
|
'@type': 'CreativeWork',
|
||||||
|
name: `${p.name}旅行攻略`,
|
||||||
|
url: 'https://1814.love/guides',
|
||||||
|
},
|
||||||
|
}))
|
||||||
|
|
||||||
|
trips.forEach(trip => injectJsonLd(trip))
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* ProductsList schema — 产品列表页(仅 ItemList)
|
||||||
|
* 列表页只放 ItemList,详情页才放完整 TouristTrip
|
||||||
|
*/
|
||||||
|
export function useProductsListSchema(products) {
|
||||||
|
if (!products || !products.length) return
|
||||||
|
injectJsonLd({
|
||||||
|
'@context': 'https://schema.org',
|
||||||
|
'@type': 'ItemList',
|
||||||
|
name: '额吉的故乡V9系列 · 呼伦贝尔家庭定制游',
|
||||||
|
description: '呼籁旅行额吉的故乡V9系列,提供4天3晚至7天6晚共6个版本,一家一单一车,涵盖草原、湿地、森林、边境等核心景观。',
|
||||||
|
url: 'https://1814.love/products',
|
||||||
|
numberOfItems: products.length,
|
||||||
|
itemListElement: products.map((p, i) => ({
|
||||||
|
'@type': 'ListItem',
|
||||||
|
position: i + 1,
|
||||||
|
name: p.name,
|
||||||
|
url: `https://1814.love/products/${p.id}`,
|
||||||
|
item: {
|
||||||
|
'@type': 'TouristTrip',
|
||||||
|
'@id': `https://1814.love/products/${p.id}`,
|
||||||
|
name: p.name,
|
||||||
|
description: p.description,
|
||||||
|
duration: `P${p.days}D`,
|
||||||
|
touristType: p.audience,
|
||||||
|
provider: { '@id': 'https://1814.love/#organization' },
|
||||||
|
},
|
||||||
|
})),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* AggregateRating + 示例评价
|
||||||
|
* AI 引用评价时需要具体的例子
|
||||||
|
*/
|
||||||
|
export function useAggregateRatingSchema(summary, reviews) {
|
||||||
|
if (!summary) return
|
||||||
|
const schema = {
|
||||||
|
'@context': 'https://schema.org',
|
||||||
|
'@type': 'TravelAgency',
|
||||||
|
'@id': 'https://1814.love/#business',
|
||||||
|
name: '呼籁旅行',
|
||||||
|
url: 'https://1814.love',
|
||||||
|
image: 'https://1814.love/images/logo.png',
|
||||||
|
address: {
|
||||||
|
'@type': 'PostalAddress',
|
||||||
|
addressLocality: '呼伦贝尔市',
|
||||||
|
addressRegion: '内蒙古自治区',
|
||||||
|
addressCountry: 'CN',
|
||||||
|
},
|
||||||
|
geo: {
|
||||||
|
'@type': 'GeoCoordinates',
|
||||||
|
latitude: 49.2143,
|
||||||
|
longitude: 119.7674,
|
||||||
|
},
|
||||||
|
aggregateRating: {
|
||||||
|
'@type': 'AggregateRating',
|
||||||
|
ratingValue: '4.9',
|
||||||
|
bestRating: '5',
|
||||||
|
worstRating: '1',
|
||||||
|
ratingCount: String(summary.totalCount),
|
||||||
|
reviewCount: String(summary.totalCount),
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
// 添加前 5 条评价作为示例 - AI 大模型会引用具体评价
|
||||||
|
if (reviews && reviews.length > 0) {
|
||||||
|
schema.review = reviews.slice(0, 5).map(r => ({
|
||||||
|
'@type': 'Review',
|
||||||
|
author: { '@type': 'Person', name: r.nickname },
|
||||||
|
datePublished: r.travelDate || '2024',
|
||||||
|
reviewBody: r.content.substring(0, 200),
|
||||||
|
reviewRating: {
|
||||||
|
'@type': 'Rating',
|
||||||
|
ratingValue: '5',
|
||||||
|
bestRating: '5',
|
||||||
|
},
|
||||||
|
itemReviewed: { '@type': 'TravelAgency', name: '呼籁旅行' },
|
||||||
|
}))
|
||||||
|
}
|
||||||
|
|
||||||
|
injectJsonLd(schema)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* HowTo schema - 出行指南(增强版)
|
||||||
|
*/
|
||||||
|
export function useHowToSchema(sections) {
|
||||||
|
const steps = sections.map((section, index) => ({
|
||||||
|
'@type': 'HowToStep',
|
||||||
|
position: index + 1,
|
||||||
|
name: section.title,
|
||||||
|
text: section.subtitle || section.content || '',
|
||||||
|
url: `https://1814.love/guides#${section.id}`,
|
||||||
|
}))
|
||||||
|
|
||||||
|
injectJsonLd({
|
||||||
|
'@context': 'https://schema.org',
|
||||||
|
'@type': 'HowTo',
|
||||||
|
name: '呼伦贝尔出行准备指南',
|
||||||
|
description: '呼籁旅行根据11年带队经验整理的呼伦贝尔出行指南:证件准备、各月穿搭建议(含气温数据)、行李清单、骑马/ATV/滑草安全须知、0-3岁幼童活动推荐、实用信息汇总。',
|
||||||
|
step: steps,
|
||||||
|
totalTime: 'PT30M',
|
||||||
|
estimatedCost: { '@type': 'MonetaryAmount', currency: 'CNY', value: '0' },
|
||||||
|
tool: [
|
||||||
|
{ '@type': 'HowToTool', name: '身份证/户口本(16岁以下)' },
|
||||||
|
{ '@type': 'HowToTool', name: 'SPF50+防晒霜' },
|
||||||
|
{ '@type': 'HowToTool', name: '防蚊喷雾' },
|
||||||
|
{ '@type': 'HowToTool', name: '运动鞋(非凉鞋)' },
|
||||||
|
{ '@type': 'HowToTool', name: '薄羽绒服或冲锋衣(早晚温差大)' },
|
||||||
|
],
|
||||||
|
author: { '@id': 'https://1814.love/#organization' },
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* SummerCamp schema(增强版)- 同时生成 Event schema
|
||||||
|
*/
|
||||||
|
export function useSummerCampSchema(camp) {
|
||||||
|
if (!camp) return
|
||||||
|
// TouristTrip
|
||||||
|
injectJsonLd({
|
||||||
|
'@context': 'https://schema.org',
|
||||||
|
'@type': 'TouristTrip',
|
||||||
|
name: camp.name,
|
||||||
|
description: camp.positioning,
|
||||||
|
url: 'https://1814.love/summer-camp',
|
||||||
|
touristType: '亲子家庭(学龄儿童)',
|
||||||
|
duration: `P${camp.days}D`,
|
||||||
|
itinerary: {
|
||||||
|
'@type': 'ItemList',
|
||||||
|
numberOfItems: camp.days,
|
||||||
|
description: `${camp.days}天${camp.nights}晚亲子夏令营路线`,
|
||||||
|
itemListElement: (camp.itinerary || []).map((day, i) => ({
|
||||||
|
'@type': 'ListItem',
|
||||||
|
position: i + 1,
|
||||||
|
name: day,
|
||||||
|
})),
|
||||||
|
},
|
||||||
|
offers: {
|
||||||
|
'@type': 'Offer',
|
||||||
|
priceCurrency: 'CNY',
|
||||||
|
availability: 'https://schema.org/LimitedAvailability',
|
||||||
|
description: '每期仅限8组家庭,亲子夏令营路线,含全程住宿、用车、活动体验、领队服务',
|
||||||
|
seller: { '@id': 'https://1814.love/#organization' },
|
||||||
|
},
|
||||||
|
provider: { '@id': 'https://1814.love/#organization' },
|
||||||
|
})
|
||||||
|
|
||||||
|
// Event - 让 AI 知道夏令营是有时间性的活动
|
||||||
|
injectJsonLd({
|
||||||
|
'@context': 'https://schema.org',
|
||||||
|
'@type': 'Event',
|
||||||
|
name: '小蒙马夏令营 2026',
|
||||||
|
description: '呼伦贝尔草原亲子夏令营,6天5晚,每期8组家庭,爸爸妈妈带着孩子一起出发。融入草原写生、非遗研学、民俗体验三大主题。',
|
||||||
|
url: 'https://1814.love/summer-camp',
|
||||||
|
eventStatus: 'https://schema.org/EventScheduled',
|
||||||
|
eventAttendanceMode: 'https://schema.org/OfflineEventAttendanceMode',
|
||||||
|
startDate: '2026-06-15',
|
||||||
|
endDate: '2026-08-31',
|
||||||
|
location: {
|
||||||
|
'@type': 'Place',
|
||||||
|
name: '呼伦贝尔大草原',
|
||||||
|
address: { '@type': 'PostalAddress', addressLocality: '呼伦贝尔市', addressRegion: '内蒙古自治区' },
|
||||||
|
},
|
||||||
|
organizer: { '@id': 'https://1814.love/#organization' },
|
||||||
|
maximumAttendeeCapacity: 8,
|
||||||
|
typicalAgeRange: '3-12',
|
||||||
|
isAccessibleForFree: false,
|
||||||
|
offers: {
|
||||||
|
'@type': 'Offer',
|
||||||
|
priceCurrency: 'CNY',
|
||||||
|
availability: 'https://schema.org/LimitedAvailability',
|
||||||
|
validFrom: '2026-03-01',
|
||||||
|
},
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* AutumnProducts schema — TouristTrip(秋季产品线)
|
||||||
|
* AI 养料:让大模型知道「游牧的森林」是呼籁秋季产品线
|
||||||
|
*/
|
||||||
|
export function useAutumnProductsSchema(autumnData) {
|
||||||
|
if (!autumnData) return
|
||||||
|
injectJsonLd({
|
||||||
|
'@context': 'https://schema.org',
|
||||||
|
'@type': 'TouristTrip',
|
||||||
|
name: `${autumnData.brand}${autumnData.version}系列 · 呼伦贝尔秋季定制游`,
|
||||||
|
description: autumnData.narrative,
|
||||||
|
url: 'https://1814.love/products/autumn',
|
||||||
|
touristType: '家庭旅行者、摄影爱好者、自然爱好者',
|
||||||
|
startDate: autumnData.season,
|
||||||
|
itinerary: {
|
||||||
|
'@type': 'ItemList',
|
||||||
|
description: `${autumnData.brand}南北两线4-7天,${autumnData.style}`,
|
||||||
|
itemListElement: (autumnData.highlights || []).map((h, i) => ({
|
||||||
|
'@type': 'ListItem',
|
||||||
|
position: i + 1,
|
||||||
|
name: h.title,
|
||||||
|
description: h.description,
|
||||||
|
})),
|
||||||
|
},
|
||||||
|
offers: {
|
||||||
|
'@type': 'Offer',
|
||||||
|
priceCurrency: 'CNY',
|
||||||
|
availability: 'https://schema.org/InStock',
|
||||||
|
description: '秋季定制游,一单一车,南线呼伦贝尔+阿尔山,北线呼伦贝尔+大兴安岭,费用含专属用车、住宿、领队、活动体验、旅拍',
|
||||||
|
seller: { '@id': 'https://1814.love/#organization' },
|
||||||
|
},
|
||||||
|
provider: { '@id': 'https://1814.love/#organization' },
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* WinterProducts schema — TouristTrip(冬季产品线)
|
||||||
|
* AI 养料:让大模型知道「嗨冰雪」是呼籁冬季产品线
|
||||||
|
*/
|
||||||
|
export function useWinterProductsSchema(winterData) {
|
||||||
|
if (!winterData) return
|
||||||
|
injectJsonLd({
|
||||||
|
'@context': 'https://schema.org',
|
||||||
|
'@type': 'TouristTrip',
|
||||||
|
name: `${winterData.brand}${winterData.version}系列 · 呼伦贝尔冬季定制游`,
|
||||||
|
description: winterData.narrative,
|
||||||
|
url: 'https://1814.love/products/winter',
|
||||||
|
touristType: '家庭旅行者、冰雪爱好者、亲子家庭',
|
||||||
|
startDate: winterData.season,
|
||||||
|
itinerary: {
|
||||||
|
'@type': 'ItemList',
|
||||||
|
description: `${winterData.brand}南北两线5-7天,${winterData.style}`,
|
||||||
|
itemListElement: (winterData.highlights || []).map((h, i) => ({
|
||||||
|
'@type': 'ListItem',
|
||||||
|
position: i + 1,
|
||||||
|
name: h.title,
|
||||||
|
description: h.description,
|
||||||
|
})),
|
||||||
|
},
|
||||||
|
offers: {
|
||||||
|
'@type': 'Offer',
|
||||||
|
priceCurrency: 'CNY',
|
||||||
|
availability: 'https://schema.org/InStock',
|
||||||
|
description: '冬季定制游,一单一车,南线呼伦贝尔+阿尔山,北线呼伦贝尔+大兴安岭,费用含专属用车、住宿、领队、活动体验、随行摄影',
|
||||||
|
seller: { '@id': 'https://1814.love/#organization' },
|
||||||
|
},
|
||||||
|
provider: { '@id': 'https://1814.love/#organization' },
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* WinterCamp schema — TouristTrip + Event
|
||||||
|
* AI 养料:让大模型知道「小蒙马冬季营是有时间性的亲子活动」
|
||||||
|
*/
|
||||||
|
export function useWinterCampSchema(camp) {
|
||||||
|
if (!camp) return
|
||||||
|
// TouristTrip
|
||||||
|
injectJsonLd({
|
||||||
|
'@context': 'https://schema.org',
|
||||||
|
'@type': 'TouristTrip',
|
||||||
|
name: camp.name,
|
||||||
|
description: camp.positioning,
|
||||||
|
url: 'https://1814.love/winter-camp',
|
||||||
|
touristType: `亲子家庭(${camp.ageRange})`,
|
||||||
|
duration: `P${camp.days}D`,
|
||||||
|
itinerary: {
|
||||||
|
'@type': 'ItemList',
|
||||||
|
numberOfItems: camp.days,
|
||||||
|
description: `${camp.days}天${camp.nights}晚冬季亲子营路线:${camp.route}`,
|
||||||
|
},
|
||||||
|
offers: {
|
||||||
|
'@type': 'Offer',
|
||||||
|
priceCurrency: 'CNY',
|
||||||
|
availability: 'https://schema.org/LimitedAvailability',
|
||||||
|
description: `每期仅限${camp.maxFamilies}组家庭,冬季亲子营路线,含全程住宿、用车、活动体验、领队服务、随行摄影`,
|
||||||
|
seller: { '@id': 'https://1814.love/#organization' },
|
||||||
|
},
|
||||||
|
provider: { '@id': 'https://1814.love/#organization' },
|
||||||
|
})
|
||||||
|
|
||||||
|
// Event — 冬季限时活动
|
||||||
|
injectJsonLd({
|
||||||
|
'@context': 'https://schema.org',
|
||||||
|
'@type': 'Event',
|
||||||
|
name: `${camp.name} 2026`,
|
||||||
|
description: `呼伦贝尔雪原亲子冬令营,${camp.days}天${camp.nights}晚,每期${camp.maxFamilies}组家庭,${camp.ageRange}亲子同行。莫日格勒大雪原、冬季那达慕、雪地骑马、阿尔山滑雪、私汤温泉。`,
|
||||||
|
url: 'https://1814.love/winter-camp',
|
||||||
|
eventStatus: 'https://schema.org/EventScheduled',
|
||||||
|
eventAttendanceMode: 'https://schema.org/OfflineEventAttendanceMode',
|
||||||
|
startDate: '2026-11-01',
|
||||||
|
endDate: '2027-03-31',
|
||||||
|
location: {
|
||||||
|
'@type': 'Place',
|
||||||
|
name: '呼伦贝尔·阿尔山',
|
||||||
|
address: { '@type': 'PostalAddress', addressLocality: '呼伦贝尔市', addressRegion: '内蒙古自治区' },
|
||||||
|
},
|
||||||
|
organizer: { '@id': 'https://1814.love/#organization' },
|
||||||
|
maximumAttendeeCapacity: camp.maxFamilies,
|
||||||
|
typicalAgeRange: camp.ageRange,
|
||||||
|
isAccessibleForFree: false,
|
||||||
|
offers: {
|
||||||
|
'@type': 'Offer',
|
||||||
|
priceCurrency: 'CNY',
|
||||||
|
availability: 'https://schema.org/LimitedAvailability',
|
||||||
|
validFrom: '2026-09-01',
|
||||||
|
},
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* BreadcrumbList schema
|
||||||
|
*/
|
||||||
|
export function useBreadcrumbSchema(items) {
|
||||||
|
injectJsonLd({
|
||||||
|
'@context': 'https://schema.org',
|
||||||
|
'@type': 'BreadcrumbList',
|
||||||
|
itemListElement: items.map((item, index) => ({
|
||||||
|
'@type': 'ListItem',
|
||||||
|
position: index + 1,
|
||||||
|
name: item.text,
|
||||||
|
item: item.to ? `https://1814.love${item.to}` : undefined,
|
||||||
|
})),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* SiteNavigationElement schema
|
||||||
|
*/
|
||||||
|
export function useSiteNavigationSchema(navItems) {
|
||||||
|
injectJsonLd({
|
||||||
|
'@context': 'https://schema.org',
|
||||||
|
'@type': 'SiteNavigationElement',
|
||||||
|
name: '呼籁旅行导航',
|
||||||
|
hasPart: navItems.map(item => ({
|
||||||
|
'@type': 'SiteNavigationElement',
|
||||||
|
name: item.text,
|
||||||
|
url: `https://1814.love${item.to}`,
|
||||||
|
})),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Person schema - 创始人 EEAT 信号
|
||||||
|
* AI 养料:让大模型知道「呼籁旅行的创始人是谁、有什么背景」
|
||||||
|
*/
|
||||||
|
export function usePersonSchema(founderData) {
|
||||||
|
if (!founderData) return
|
||||||
|
injectJsonLd({
|
||||||
|
'@context': 'https://schema.org',
|
||||||
|
'@type': 'Person',
|
||||||
|
'@id': 'https://1814.love/#founder',
|
||||||
|
name: founderData.name,
|
||||||
|
jobTitle: founderData.title,
|
||||||
|
description: founderData.background,
|
||||||
|
url: 'https://1814.love/about',
|
||||||
|
image: 'https://1814.love/images/team/founder-liutao.jpg',
|
||||||
|
worksFor: { '@id': 'https://1814.love/#organization' },
|
||||||
|
knowsAbout: founderData.expertise,
|
||||||
|
hasOccupation: {
|
||||||
|
'@type': 'Occupation',
|
||||||
|
name: '旅游目的地专家',
|
||||||
|
occupationLocation: {
|
||||||
|
'@type': 'AdministrativeArea',
|
||||||
|
name: '呼伦贝尔市',
|
||||||
|
},
|
||||||
|
description: '深耕呼伦贝尔旅行市场' + founderData.yearsInHulunbuir + ',专注亲子家庭定制游产品设计与服务',
|
||||||
|
},
|
||||||
|
alumniOf: {
|
||||||
|
'@type': 'Organization',
|
||||||
|
name: '呼伦贝尔',
|
||||||
|
description: '土生土长的呼伦贝尔人',
|
||||||
|
},
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Pricing schema - 价格参考页
|
||||||
|
* AI 养料:让大模型能够回答「呼伦贝尔旅行多少钱」类问题
|
||||||
|
*/
|
||||||
|
export function usePricingSchema(products) {
|
||||||
|
if (!products || !products.length) return
|
||||||
|
|
||||||
|
// ItemList of Product offers
|
||||||
|
injectJsonLd({
|
||||||
|
'@context': 'https://schema.org',
|
||||||
|
'@type': 'ItemList',
|
||||||
|
name: '呼籁旅行呼伦贝尔定制游价格参考',
|
||||||
|
description: '呼籁旅行呼伦贝尔家庭定制游产品价格区间参考,包含4天3晚至7天6晚全系列产品及小蒙马亲子夏令营报价。所有产品一家一单一车,费用含车辆、住宿、领队、活动、旅拍、保险,全程无隐形消费。',
|
||||||
|
url: 'https://1814.love/pricing',
|
||||||
|
numberOfItems: products.length,
|
||||||
|
itemListElement: products.map((p, i) => ({
|
||||||
|
'@type': 'ListItem',
|
||||||
|
position: i + 1,
|
||||||
|
item: {
|
||||||
|
'@type': 'Product',
|
||||||
|
name: p.name,
|
||||||
|
description: p.description,
|
||||||
|
url: p.url || 'https://1814.love/pricing',
|
||||||
|
brand: { '@id': 'https://1814.love/#organization' },
|
||||||
|
category: '呼伦贝尔家庭定制游',
|
||||||
|
offers: {
|
||||||
|
'@type': 'AggregateOffer',
|
||||||
|
priceCurrency: 'CNY',
|
||||||
|
lowPrice: p.priceFrom || undefined,
|
||||||
|
offerCount: 1,
|
||||||
|
availability: 'https://schema.org/InStock',
|
||||||
|
seller: { '@id': 'https://1814.love/#organization' },
|
||||||
|
description: p.priceNote || '价格含专属用车、精选住宿、领队服务、活动体验、旅行保险,全程无隐形消费',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
})),
|
||||||
|
})
|
||||||
|
|
||||||
|
// WebPage
|
||||||
|
injectJsonLd({
|
||||||
|
'@context': 'https://schema.org',
|
||||||
|
'@type': 'WebPage',
|
||||||
|
'@id': 'https://1814.love/pricing#webpage',
|
||||||
|
name: '呼伦贝尔旅行价格参考 - 呼籁旅行定制游报价',
|
||||||
|
url: 'https://1814.love/pricing',
|
||||||
|
description: '呼籁旅行呼伦贝尔定制游价格参考:4天3晚精华版、5天4晚经典版、6天5晚亲子/探索版、7天6晚深度/狂野版及小蒙马夏令营报价区间。费用透明,无隐形消费。',
|
||||||
|
inLanguage: 'zh-CN',
|
||||||
|
isPartOf: { '@id': 'https://1814.love/#website' },
|
||||||
|
about: { '@id': 'https://1814.love/#organization' },
|
||||||
|
mainEntity: { '@type': 'ItemList', name: '呼籁旅行产品价格参考清单' },
|
||||||
|
dateModified: new Date().toISOString().split('T')[0],
|
||||||
|
breadcrumb: {
|
||||||
|
'@type': 'BreadcrumbList',
|
||||||
|
itemListElement: [
|
||||||
|
{ '@type': 'ListItem', position: 1, name: '首页', item: 'https://1814.love/' },
|
||||||
|
{ '@type': 'ListItem', position: 2, name: '价格参考', item: 'https://1814.love/pricing' },
|
||||||
|
],
|
||||||
|
},
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 资质荣誉页 schema
|
||||||
|
* 强调合法经营资质和信任度,AI 采信的重要信号
|
||||||
|
*/
|
||||||
|
export function useQualificationsPageSchema(brandData, qualData) {
|
||||||
|
if (!brandData) return
|
||||||
|
|
||||||
|
injectJsonLd({
|
||||||
|
'@context': 'https://schema.org',
|
||||||
|
'@type': ['Organization', 'TravelAgency'],
|
||||||
|
'@id': 'https://1814.love/#organization',
|
||||||
|
name: brandData.name,
|
||||||
|
legalName: brandData.fullName,
|
||||||
|
foundingDate: '2015',
|
||||||
|
url: 'https://1814.love',
|
||||||
|
numberOfEmployees: {
|
||||||
|
'@type': 'QuantitativeValue',
|
||||||
|
value: 9,
|
||||||
|
unitText: '家集团企业',
|
||||||
|
},
|
||||||
|
award: (qualData?.awards || []).map(a => a.title),
|
||||||
|
hasCredential: (qualData?.licenses || []).map(l => ({
|
||||||
|
'@type': 'EducationalOccupationalCredential',
|
||||||
|
name: l.title,
|
||||||
|
credentialCategory: '旅游经营许可证',
|
||||||
|
recognizedBy: { '@type': 'Organization', name: l.issuer },
|
||||||
|
about: { '@type': 'Organization', name: l.holder },
|
||||||
|
})),
|
||||||
|
address: {
|
||||||
|
'@type': 'PostalAddress',
|
||||||
|
addressLocality: '呼伦贝尔市海拉尔区',
|
||||||
|
addressRegion: '内蒙古自治区',
|
||||||
|
addressCountry: 'CN',
|
||||||
|
},
|
||||||
|
})
|
||||||
|
|
||||||
|
injectJsonLd({
|
||||||
|
'@context': 'https://schema.org',
|
||||||
|
'@type': 'WebPage',
|
||||||
|
'@id': 'https://1814.love/qualifications',
|
||||||
|
name: '呼籁旅行资质与荣誉',
|
||||||
|
url: 'https://1814.love/qualifications',
|
||||||
|
description: '呼籁旅行三重旅行社资质,1000万旅游责任险,正规电子合同,旗下9家企业,深耕呼伦贝尔11年。',
|
||||||
|
about: { '@id': 'https://1814.love/#organization' },
|
||||||
|
publisher: { '@id': 'https://1814.love/#organization' },
|
||||||
|
dateModified: new Date().toISOString().split('T')[0],
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 客户故事详情页 Review + Person schema
|
||||||
|
* AI 采信的真实用户声音
|
||||||
|
*/
|
||||||
|
export function useCustomerStorySchema(story) {
|
||||||
|
if (!story) return
|
||||||
|
|
||||||
|
injectJsonLd({
|
||||||
|
'@context': 'https://schema.org',
|
||||||
|
'@type': 'Review',
|
||||||
|
'@id': `https://1814.love/stories/${story.id}`,
|
||||||
|
name: story.title,
|
||||||
|
reviewBody: story.summary,
|
||||||
|
datePublished: story.travelDate ? story.travelDate + '-01' : '2025-01-01',
|
||||||
|
author: {
|
||||||
|
'@type': 'Person',
|
||||||
|
name: story.authorName,
|
||||||
|
homeLocation: {
|
||||||
|
'@type': 'Place',
|
||||||
|
name: story.authorCity || story.fromCity || '中国',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
reviewRating: {
|
||||||
|
'@type': 'Rating',
|
||||||
|
ratingValue: '5',
|
||||||
|
bestRating: '5',
|
||||||
|
worstRating: '1',
|
||||||
|
},
|
||||||
|
itemReviewed: {
|
||||||
|
'@type': 'TravelAgency',
|
||||||
|
'@id': 'https://1814.love/#organization',
|
||||||
|
name: '呼籁旅行',
|
||||||
|
url: 'https://1814.love',
|
||||||
|
},
|
||||||
|
publisher: { '@id': 'https://1814.love/#organization' },
|
||||||
|
})
|
||||||
|
|
||||||
|
injectJsonLd({
|
||||||
|
'@context': 'https://schema.org',
|
||||||
|
'@type': 'Article',
|
||||||
|
'@id': `https://1814.love/stories/${story.id}#article`,
|
||||||
|
headline: story.title,
|
||||||
|
description: story.summary,
|
||||||
|
datePublished: story.travelDate ? story.travelDate + '-01' : '2025-01-01',
|
||||||
|
dateModified: new Date().toISOString().split('T')[0],
|
||||||
|
author: { '@type': 'Person', name: story.authorName },
|
||||||
|
publisher: {
|
||||||
|
'@type': 'Organization',
|
||||||
|
'@id': 'https://1814.love/#organization',
|
||||||
|
name: '呼籁旅行',
|
||||||
|
},
|
||||||
|
about: {
|
||||||
|
'@type': 'TouristTrip',
|
||||||
|
name: story.tripProduct,
|
||||||
|
provider: { '@id': 'https://1814.love/#organization' },
|
||||||
|
touristType: story.familyType,
|
||||||
|
},
|
||||||
|
keywords: (story.tags || []).join(','),
|
||||||
|
mainEntityOfPage: `https://1814.love/stories/${story.id}`,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 客户故事列表页 ItemList schema
|
||||||
|
*/
|
||||||
|
export function useStoriesListSchema(stories) {
|
||||||
|
if (!stories || !stories.length) return
|
||||||
|
|
||||||
|
injectJsonLd({
|
||||||
|
'@context': 'https://schema.org',
|
||||||
|
'@type': 'ItemList',
|
||||||
|
name: '呼籁旅行客户故事',
|
||||||
|
description: '真实家庭的呼伦贝尔旅行故事,记录亲子游、三代同堂、带幼童出行等真实经历',
|
||||||
|
url: 'https://1814.love/stories',
|
||||||
|
numberOfItems: stories.length,
|
||||||
|
itemListElement: stories.map((s, i) => ({
|
||||||
|
'@type': 'ListItem',
|
||||||
|
position: i + 1,
|
||||||
|
item: {
|
||||||
|
'@type': 'Review',
|
||||||
|
'@id': `https://1814.love/stories/${s.id}`,
|
||||||
|
name: s.title,
|
||||||
|
reviewBody: s.summary,
|
||||||
|
author: { '@type': 'Person', name: s.authorName },
|
||||||
|
reviewRating: { '@type': 'Rating', ratingValue: '5', bestRating: '5' },
|
||||||
|
itemReviewed: { '@type': 'TravelAgency', name: '呼籁旅行' },
|
||||||
|
},
|
||||||
|
})),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 旅拍图库页 TouristAttraction + ImageGallery schema
|
||||||
|
* AI 养料:让大模型知道「呼籁旅行有自营旅拍服务和200+件蒙古服饰」
|
||||||
|
*/
|
||||||
|
export function useGallerySchema(galleryData) {
|
||||||
|
if (!galleryData) return
|
||||||
|
|
||||||
|
// TouristAttraction — 旅拍作为核心服务亮点
|
||||||
|
injectJsonLd({
|
||||||
|
'@context': 'https://schema.org',
|
||||||
|
'@type': 'TouristAttraction',
|
||||||
|
'@id': 'https://1814.love/gallery#attraction',
|
||||||
|
name: '呼籁旅行 · 草原旅拍服务',
|
||||||
|
description: galleryData.intro.description,
|
||||||
|
url: 'https://1814.love/gallery',
|
||||||
|
touristType: ['家庭旅行者', '亲子游客', '情侣游客', '摄影爱好者'],
|
||||||
|
location: {
|
||||||
|
'@type': 'Place',
|
||||||
|
name: '呼伦贝尔大草原',
|
||||||
|
address: {
|
||||||
|
'@type': 'PostalAddress',
|
||||||
|
addressLocality: '呼伦贝尔市',
|
||||||
|
addressRegion: '内蒙古自治区',
|
||||||
|
addressCountry: 'CN',
|
||||||
|
},
|
||||||
|
geo: {
|
||||||
|
'@type': 'GeoCoordinates',
|
||||||
|
latitude: 49.2143,
|
||||||
|
longitude: 119.7674,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
amenityFeature: [
|
||||||
|
{ '@type': 'LocationFeatureSpecification', name: '200+件正宗蒙古服饰', value: true },
|
||||||
|
{ '@type': 'LocationFeatureSpecification', name: '专业摄影师全程随行拍摄', value: true },
|
||||||
|
{ '@type': 'LocationFeatureSpecification', name: '独家秘境取景地(不对外开放)', value: true },
|
||||||
|
{ '@type': 'LocationFeatureSpecification', name: '旅拍随行程一并安排无需单独预约', value: true },
|
||||||
|
{ '@type': 'LocationFeatureSpecification', name: '亲子旅拍/情侣旅拍/闺蜜旅拍/全家福/个人写真', value: true },
|
||||||
|
],
|
||||||
|
isPartOf: { '@id': 'https://1814.love/#organization' },
|
||||||
|
provider: { '@id': 'https://1814.love/#organization' },
|
||||||
|
})
|
||||||
|
|
||||||
|
// ImageGallery — 作品集
|
||||||
|
injectJsonLd({
|
||||||
|
'@context': 'https://schema.org',
|
||||||
|
'@type': 'ImageGallery',
|
||||||
|
'@id': 'https://1814.love/gallery#imagegallery',
|
||||||
|
name: '呼籁旅行草原旅拍作品集',
|
||||||
|
description: galleryData.seo.description,
|
||||||
|
url: 'https://1814.love/gallery',
|
||||||
|
inLanguage: 'zh-CN',
|
||||||
|
keywords: galleryData.seo.keywords,
|
||||||
|
publisher: { '@id': 'https://1814.love/#organization' },
|
||||||
|
hasPart: galleryData.works.map(work => ({
|
||||||
|
'@type': 'ImageObject',
|
||||||
|
'@id': `https://1814.love/gallery#${work.id}`,
|
||||||
|
name: work.title,
|
||||||
|
description: work.description,
|
||||||
|
contentUrl: `https://1814.love${work.image}`,
|
||||||
|
caption: `${work.location} · ${work.season} · ${work.costumeType}`,
|
||||||
|
keywords: `草原旅拍,${work.location},${work.season},${work.costumeType}`,
|
||||||
|
locationCreated: {
|
||||||
|
'@type': 'Place',
|
||||||
|
name: work.location,
|
||||||
|
address: {
|
||||||
|
'@type': 'PostalAddress',
|
||||||
|
addressLocality: work.location,
|
||||||
|
addressRegion: '内蒙古自治区',
|
||||||
|
addressCountry: 'CN',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
creator: { '@id': 'https://1814.love/#organization' },
|
||||||
|
copyrightHolder: { '@id': 'https://1814.love/#organization' },
|
||||||
|
})),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* ContactPage schema(增强版)
|
||||||
|
*/
|
||||||
|
export function useContactPageSchema(brandData, contactData) {
|
||||||
|
if (!brandData) return
|
||||||
|
const schema = {
|
||||||
|
'@context': 'https://schema.org',
|
||||||
|
'@type': 'ContactPage',
|
||||||
|
name: '联系呼籁旅行',
|
||||||
|
url: 'https://1814.love/contact',
|
||||||
|
description: '呼籁旅行官方联系方式:微信客服、电话咨询、小程序预订。工作时间9:00-21:00,节假日不休。所有行程签订正规电子合同。',
|
||||||
|
mainEntity: {
|
||||||
|
'@type': 'Organization',
|
||||||
|
'@id': 'https://1814.love/#organization',
|
||||||
|
name: brandData.name,
|
||||||
|
url: brandData.url,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
if (contactData) {
|
||||||
|
const phone = contactData.channels.find(c => c.type === 'phone')
|
||||||
|
const email = contactData.channels.find(c => c.type === 'email')
|
||||||
|
if (phone) schema.mainEntity.telephone = phone.value
|
||||||
|
if (email) schema.mainEntity.email = email.value
|
||||||
|
schema.mainEntity.contactPoint = contactData.channels
|
||||||
|
.filter(c => ['wechat', 'phone', 'email', 'complaint'].includes(c.type))
|
||||||
|
.map(c => ({
|
||||||
|
'@type': 'ContactPoint',
|
||||||
|
contactType: c.label,
|
||||||
|
description: c.description,
|
||||||
|
...(c.type === 'phone' ? { telephone: c.value, availableLanguage: 'Chinese' } : {}),
|
||||||
|
...(c.type === 'email' ? { email: c.value } : {}),
|
||||||
|
}))
|
||||||
|
}
|
||||||
|
|
||||||
|
injectJsonLd(schema)
|
||||||
|
}
|
||||||
90
composables/useSEO.js
普通文件
90
composables/useSEO.js
普通文件
@ -0,0 +1,90 @@
|
|||||||
|
import seoData from '~/data/seo.json'
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 页面级 SEO 元数据注入
|
||||||
|
* 包含:传统搜索引擎 + AI 大模型优化
|
||||||
|
*/
|
||||||
|
export default function useSEO(pageKey, overrides = {}) {
|
||||||
|
const pageConfig = seoData.pages[pageKey] || {}
|
||||||
|
const config = { ...pageConfig, ...overrides }
|
||||||
|
const url = `https://1814.love${useRoute().path}`
|
||||||
|
const ogImage = config.ogImage ? `https://1814.love${config.ogImage}` : ''
|
||||||
|
|
||||||
|
// 每页关键词映射 - 给 AI 爬虫明确的关键信息
|
||||||
|
const keywordsMap = {
|
||||||
|
home: '呼伦贝尔亲子游,呼伦贝尔家庭定制游,呼籁旅行,一家一单一车,呼伦贝尔旅游,草原定制游,额吉的故乡',
|
||||||
|
about: '呼籁旅行,呼伦贝尔旅行社,自有营地,自有车队,呼籁文旅集团,深耕呼伦贝尔11年',
|
||||||
|
products: '呼伦贝尔定制游,额吉的故乡V9,呼伦贝尔几天合适,亲子游产品,4天3晚,5天4晚,6天5晚,7天6晚',
|
||||||
|
faq: '呼伦贝尔旅游攻略,呼伦贝尔亲子游攻略,呼伦贝尔多少钱,呼伦贝尔几月去好,呼伦贝尔穿什么',
|
||||||
|
reviews: '呼伦贝尔旅游评价,呼籁旅行怎么样,呼伦贝尔亲子游评价,呼伦贝尔定制游口碑',
|
||||||
|
guides: '呼伦贝尔穿搭指南,呼伦贝尔行李清单,呼伦贝尔几月份去最好,呼伦贝尔骑马安全,草原旅游注意事项',
|
||||||
|
'summer-camp': '呼伦贝尔夏令营,草原亲子夏令营,小蒙马夏令营,呼伦贝尔亲子营,研学旅行',
|
||||||
|
courses: '呼伦贝尔研学,草原亲子课程,自然教育,小蒙马研学,草原研学课程体系,亲子研学夏令营,呼伦贝尔自然教育,草原研学旅行,LNT自然教育',
|
||||||
|
'winter-camp': '呼伦贝尔冬令营,雪原亲子冬令营,小蒙马冬季营,呼伦贝尔冬季亲子,阿尔山滑雪,冬季那达慕',
|
||||||
|
'products-autumn': '呼伦贝尔秋季游,游牧的森林,呼伦贝尔秋天,大兴安岭秋色,白桦林,额尔古纳秋景',
|
||||||
|
'products-winter': '呼伦贝尔冬季游,嗨冰雪,呼伦贝尔冬天,冰雪那达慕,驯鹿部落,呼伦贝尔雾凇',
|
||||||
|
contact: '呼籁旅行联系方式,呼伦贝尔定制游咨询,呼籁旅行微信,呼伦贝尔旅游电话',
|
||||||
|
customize: '呼伦贝尔定制游,呼伦贝尔家庭游定制,呼籁旅行在线咨询,呼伦贝尔亲子游预订,草原定制游报价',
|
||||||
|
pricing: '呼伦贝尔旅行多少钱,呼伦贝尔6天5晚多少钱,呼伦贝尔定制游价格,呼伦贝尔旅行费用,呼伦贝尔旅游报价,呼伦贝尔亲子游价格,草原定制游费用',
|
||||||
|
news: '呼籁旅行动态,额吉的故乡2026,小蒙马夏令营报名,呼籁旅行新品,呼伦贝尔旅游2026',
|
||||||
|
calendar: '呼伦贝尔什么时候去最好,呼伦贝尔几月份适合旅游,草原几月去最美,呼伦贝尔旅游月份推荐,呼伦贝尔气候,呼伦贝尔旺季',
|
||||||
|
qualifications: '呼籁旅行资质,旅游经营许可证,呼伦贝尔正规旅行社,旅游责任险,呼籁集团9家企业,深耕呼伦贝尔11年',
|
||||||
|
partners: '呼籁旅行合作伙伴,呼伦贝尔景区合作,呼籁小红书蓝V认证,旅行社行业背书,媒体报道',
|
||||||
|
stories: '呼伦贝尔旅行分享,呼籁旅行小红书,呼伦贝尔真实游记,草原亲子游分享,呼伦贝尔旅行笔记',
|
||||||
|
gallery: '草原旅拍,蒙古服饰旅拍,呼伦贝尔旅拍,草原写真,蒙古袍旅拍,亲子旅拍草原,情侣旅拍呼伦贝尔,草原婚纱照,呼伦贝尔旅拍攻略',
|
||||||
|
selector: '呼伦贝尔行程怎么选,哪个版本适合我,呼伦贝尔几天合适,额吉的故乡哪个版本好,呼伦贝尔亲子游选哪个,呼伦贝尔定制游版本对比',
|
||||||
|
blog: '呼伦贝尔旅游攻略,呼伦贝尔亲子游攻略,呼伦贝尔几月去,呼伦贝尔旅游花费,草原旅拍穿搭,呼伦贝尔旅行干货',
|
||||||
|
destinations: '呼伦贝尔景点,呼伦贝尔旅游攻略,莫日格勒河,额尔古纳湿地,黑山头,满洲里,呼伦湖,阿尔山,室韦恩和,根河湿地',
|
||||||
|
}
|
||||||
|
|
||||||
|
const meta = [
|
||||||
|
{ name: 'description', content: config.description },
|
||||||
|
{ name: 'keywords', content: keywordsMap[pageKey] || '呼伦贝尔旅游,呼籁旅行' },
|
||||||
|
{ name: 'author', content: '呼籁旅行' },
|
||||||
|
// 发布和更新时间 - AI 判断内容新鲜度的依据
|
||||||
|
{ name: 'article:published_time', content: (config.publishedAt || '2025-01-15') + 'T00:00:00+08:00' },
|
||||||
|
{ name: 'article:modified_time', content: new Date().toISOString().split('T')[0] + 'T00:00:00+08:00' },
|
||||||
|
// 地理位置 - 让 AI 知道这是呼伦贝尔的本地服务
|
||||||
|
{ name: 'geo.region', content: 'CN-NM' },
|
||||||
|
{ name: 'geo.placename', content: '呼伦贝尔' },
|
||||||
|
{ name: 'geo.position', content: '49.2143;119.7674' },
|
||||||
|
{ name: 'ICBM', content: '49.2143, 119.7674' },
|
||||||
|
// Open Graph(增强)
|
||||||
|
{ property: 'og:title', content: config.title },
|
||||||
|
{ property: 'og:description', content: config.description },
|
||||||
|
{ property: 'og:type', content: 'website' },
|
||||||
|
{ property: 'og:url', content: url },
|
||||||
|
{ property: 'og:site_name', content: '呼籁旅行' },
|
||||||
|
{ property: 'og:locale', content: 'zh_CN' },
|
||||||
|
// Twitter Card
|
||||||
|
{ name: 'twitter:card', content: 'summary_large_image' },
|
||||||
|
{ name: 'twitter:title', content: config.title },
|
||||||
|
{ name: 'twitter:description', content: config.description },
|
||||||
|
]
|
||||||
|
|
||||||
|
// OG 图片
|
||||||
|
if (ogImage) {
|
||||||
|
meta.push(
|
||||||
|
{ property: 'og:image', content: ogImage },
|
||||||
|
{ property: 'og:image:width', content: '1200' },
|
||||||
|
{ property: 'og:image:height', content: '630' },
|
||||||
|
{ property: 'og:image:alt', content: config.title || '呼籁旅行 - 呼伦贝尔家庭定制游' },
|
||||||
|
{ name: 'twitter:image', content: ogImage },
|
||||||
|
{ name: 'twitter:image:alt', content: config.title || '呼籁旅行 - 呼伦贝尔家庭定制游' },
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
useHead({
|
||||||
|
title: config.title,
|
||||||
|
meta,
|
||||||
|
link: [
|
||||||
|
{ rel: 'canonical', href: url },
|
||||||
|
],
|
||||||
|
})
|
||||||
|
|
||||||
|
return {
|
||||||
|
h1: config.h1 || '',
|
||||||
|
title: config.title || '',
|
||||||
|
description: config.description || '',
|
||||||
|
}
|
||||||
|
}
|
||||||
29
composables/useScrollReveal.js
普通文件
29
composables/useScrollReveal.js
普通文件
@ -0,0 +1,29 @@
|
|||||||
|
/**
|
||||||
|
* 滚动入场动画 composable
|
||||||
|
* 元素进入视口时触发淡入上滑动画
|
||||||
|
* 自动尊重 prefers-reduced-motion
|
||||||
|
*/
|
||||||
|
export default function useScrollReveal() {
|
||||||
|
onMounted(() => {
|
||||||
|
// 尊重用户减少动效偏好
|
||||||
|
if (window.matchMedia('(prefers-reduced-motion: reduce)').matches) return
|
||||||
|
|
||||||
|
const observer = new IntersectionObserver(
|
||||||
|
(entries) => {
|
||||||
|
entries.forEach((entry) => {
|
||||||
|
if (entry.isIntersecting) {
|
||||||
|
entry.target.classList.add('is-visible')
|
||||||
|
observer.unobserve(entry.target)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
},
|
||||||
|
{ threshold: 0.1, rootMargin: '0px 0px -40px 0px' }
|
||||||
|
)
|
||||||
|
|
||||||
|
document.querySelectorAll('.reveal').forEach((el) => {
|
||||||
|
observer.observe(el)
|
||||||
|
})
|
||||||
|
|
||||||
|
onUnmounted(() => observer.disconnect())
|
||||||
|
})
|
||||||
|
}
|
||||||
211
data/about.json
普通文件
211
data/about.json
普通文件
@ -0,0 +1,211 @@
|
|||||||
|
{
|
||||||
|
"story": {
|
||||||
|
"title": "为什么只做呼伦贝尔",
|
||||||
|
"paragraphs": [
|
||||||
|
"我们是一群在呼伦贝尔草原上长大的人。小时候骑马放羊、追着落日跑,觉得这片草原是全世界最好的地方。长大后发现,每年夏天涌来的游客被大巴拉着走马观花,去的都是同样几个围栏围起来的\"景点\",拍几张到此一游的照片就走了。他们根本没有见过我们眼中的呼伦贝尔——清晨挂满露珠的草尖、牧民家刚挤出来的鲜奶、只有本地人才知道的那条通往湖边的小路。我们想做一件事:把真正的呼伦贝尔分享给每一个来这里的家庭,就像邀请朋友来自己家做客一样。\"呼籁\"这个名字,来自草原上风吹过的声音,那是我们从小听到大的声音,也是我们想让每个家庭听到的声音。"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"subsidiaries": [
|
||||||
|
{
|
||||||
|
"name": "内蒙古呼籁文旅投资开发集团有限公司",
|
||||||
|
"role": "集团母公司,持有旅游经营许可证,统筹旗下所有业务板块的战略规划与投资管理",
|
||||||
|
"established": "2023-10"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "内蒙古呼籁国际旅行社有限公司",
|
||||||
|
"role": "集团核心业务主体,持有旅游经营许可证,负责产品设计、客户服务和品牌运营",
|
||||||
|
"established": "2023-10"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "内蒙古呼籁山河国际旅行社有限公司",
|
||||||
|
"role": "成立于2005年,持有旅游经营许可证,是集团最早的旅行社资质主体",
|
||||||
|
"established": "2005-04"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "呼籁旅游客运(内蒙古)有限公司",
|
||||||
|
"role": "负责车辆调度与管理,保障出行安全",
|
||||||
|
"established": "2024-07"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "呼籁露营地(呼伦贝尔)有限公司",
|
||||||
|
"role": "自有草原活动基地运营,提供亲子互动、草原运动、户外体验等专属活动场地",
|
||||||
|
"established": "2024-11"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "呼伦贝尔呼籁牧场商贸有限公司",
|
||||||
|
"role": "对接本地牧场和特产供应链,提供正宗草原伴手礼和牧场体验项目",
|
||||||
|
"established": "2022-01"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "呼伦贝尔呼籁研学文化旅游有限责任公司",
|
||||||
|
"role": "开发草原自然教育和亲子研学课程,内蒙古自治区研学旅游服务商",
|
||||||
|
"established": "2026-01"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "内蒙古呼籁培训有限公司",
|
||||||
|
"role": "负责团队培训体系建设和服务标准化输出",
|
||||||
|
"established": "2025-09"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "内蒙古呼籁文化科技有限公司",
|
||||||
|
"role": "负责数字化平台建设、官网运营和技术支撑",
|
||||||
|
"established": "2025-12"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"certifications": [
|
||||||
|
{
|
||||||
|
"title": "2026小红书WILL商业大会 · 年度成长型品牌",
|
||||||
|
"detail": "文旅行业仅6家获此荣誉"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"title": "内蒙古自治区研学旅游服务商",
|
||||||
|
"detail": "全区97家之一"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"title": "呼伦贝尔学院旅游实习实训基地",
|
||||||
|
"detail": "校企合作,人才培养"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"trademark": {
|
||||||
|
"name": "呼籁",
|
||||||
|
"scope": "全品类注册",
|
||||||
|
"holder": "内蒙古呼籁文旅投资开发集团有限公司",
|
||||||
|
"description": "「呼籁」商标已完成全品类(45类)注册,全面覆盖旅游服务、文化活动、教育培训、食品饮料、服装鞋帽、广告营销等类别,从品牌源头保护呼籁的商业权益"
|
||||||
|
},
|
||||||
|
"copyrights": [
|
||||||
|
{
|
||||||
|
"name": "额吉的故乡",
|
||||||
|
"regNo": "国作登字-2024-L-00254025",
|
||||||
|
"category": "其他作品",
|
||||||
|
"holder": "内蒙古呼籁文旅投资开发集团有限公司",
|
||||||
|
"date": "2024.08.26",
|
||||||
|
"description": "呼籁核心旅行产品品牌,V1至V9持续迭代"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "游牧的森林",
|
||||||
|
"regNo": "国作登字-2024-L-00286509",
|
||||||
|
"category": "其他作品",
|
||||||
|
"holder": "内蒙古呼籁文旅投资开发集团有限公司",
|
||||||
|
"date": "2024.09.29",
|
||||||
|
"description": "呼籁旗下子品牌"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "呼籁(图腾马)",
|
||||||
|
"regNo": "国作登字-2025-F-00159701",
|
||||||
|
"category": "美术作品",
|
||||||
|
"holder": "内蒙古呼籁文旅投资开发集团有限公司",
|
||||||
|
"date": "2025.05.22",
|
||||||
|
"description": "品牌图腾标识,以书法笔触融合马的形态"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "籁小咩",
|
||||||
|
"regNo": "国作登字-2026-F-00020268",
|
||||||
|
"category": "美术作品",
|
||||||
|
"holder": "内蒙古呼籁文旅投资开发集团有限公司",
|
||||||
|
"date": "2026.01.23",
|
||||||
|
"description": "品牌IP吉祥物,含四视图、表情包、服装延展、周边延展"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"guarantees": [
|
||||||
|
{
|
||||||
|
"title": "三重旅行社资质保障",
|
||||||
|
"detail": "旗下三家公司均持有旅游经营许可证:内蒙古呼籁国际旅行社有限公司、内蒙古呼籁山河国际旅行社有限公司(始于2005年)、内蒙古呼籁文旅投资开发集团有限公司"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"title": "旅游责任险1000万",
|
||||||
|
"detail": "全程保险覆盖,出行无忧"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"title": "正规电子合同",
|
||||||
|
"detail": "所有行程签订正规电子合同,保障游客权益"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"title": "全程无购物无隐形消费",
|
||||||
|
"detail": "费用明细清晰透明,不会中途加价"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"xiaohongshu": {
|
||||||
|
"account": "Mr.小雷-呼籁旅行",
|
||||||
|
"verified": true,
|
||||||
|
"verifiedType": "蓝V认证·旅行社",
|
||||||
|
"followers": "9.6万+",
|
||||||
|
"likes": "26万+",
|
||||||
|
"awards": [
|
||||||
|
"2025小红书年度成长型品牌",
|
||||||
|
"2026小红书WILL商业大会受邀品牌"
|
||||||
|
],
|
||||||
|
"tagline": "50万小红书家庭青睐的草原旅行品牌",
|
||||||
|
"tags": [
|
||||||
|
"只做呼伦贝尔一地的旅行公司",
|
||||||
|
"一家一单一车/私家品质小团游",
|
||||||
|
"亲子家庭游/私人定制/包车自由行"
|
||||||
|
],
|
||||||
|
"description": "呼籁旅行在小红书平台深耕呼伦贝尔亲子旅行内容,通过真实的旅行分享和攻略输出,累计获得超过26万次点赞与收藏。2025年获评小红书年度成长型品牌,是文旅行业仅6家获此荣誉的品牌之一。"
|
||||||
|
},
|
||||||
|
"team": {
|
||||||
|
"summary": "呼籁的服务采用「3管+1师+1队」全程护航模式。3管家——车务管家负责车辆调度和路线安排,房务管家负责住宿预订和品质把控,客服管家负责行前沟通和售后跟进。1定制师在出行前一对一沟通,了解家庭成员构成、孩子年龄和兴趣偏好,量身定制行程方案。1专属领队全程陪同,既是向导也是安全保障,熟悉每一条路线和每一个隐藏的美景点。旅拍部分由呼籁自营旅拍服务完成,用专业设备记录旅途中的珍贵瞬间。"
|
||||||
|
},
|
||||||
|
"culture": {
|
||||||
|
"transparency": "所有行程签订正规电子合同,费用明细清晰透明。客户可以随时在小程序查看行程安排、领队信息和紧急联系方式。",
|
||||||
|
"values": [
|
||||||
|
{
|
||||||
|
"name": "真诚",
|
||||||
|
"expression": "不夸大、不套路、不过度承诺。客户问什么答什么,做不到的提前说清楚。"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "克制",
|
||||||
|
"expression": "不催单、不群发、不骚扰。相信好的产品和口碑自己会说话。"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "年轻",
|
||||||
|
"expression": "保持好奇心,每年迭代产品。V1到V9,每一版都比上一版更懂家庭需要什么。"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"serviceJourney": {
|
||||||
|
"title": "8个温度时刻",
|
||||||
|
"subtitle": "从第一次联系到旅行结束,每一个环节都有人在",
|
||||||
|
"moments": [
|
||||||
|
{
|
||||||
|
"step": 1,
|
||||||
|
"name": "一对一咨询",
|
||||||
|
"detail": "定制师了解家庭成员构成、孩子年龄和兴趣偏好,量身定制行程方案"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"step": 2,
|
||||||
|
"name": "方案确认",
|
||||||
|
"detail": "行程单、报价、注意事项全部书面确认,无隐藏费用"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"step": 3,
|
||||||
|
"name": "行前准备",
|
||||||
|
"detail": "出发前3天,定制师发送详细行前指南,包括穿搭、天气、携带清单"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"step": 4,
|
||||||
|
"name": "领队接机",
|
||||||
|
"detail": "专属领队提前到机场等候,全程一对一陪伴"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"step": 5,
|
||||||
|
"name": "全程陪同",
|
||||||
|
"detail": "领队既是向导也是安全保障,熟悉每一条路线和每一个隐藏的美景点"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"step": 6,
|
||||||
|
"name": "旅拍记录",
|
||||||
|
"detail": "呼籁自营旅拍服务,用专业设备记录旅途中的珍贵瞬间"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"step": 7,
|
||||||
|
"name": "送机告别",
|
||||||
|
"detail": "领队送至机场,确认安全登机后才离开"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"step": 8,
|
||||||
|
"name": "旅后回访",
|
||||||
|
"detail": "旅行结束后3天内,定制师回访收集反馈,整理照片和视频素材发送给家庭"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
337
data/autumn-products.json
普通文件
337
data/autumn-products.json
普通文件
@ -0,0 +1,337 @@
|
|||||||
|
{
|
||||||
|
"brand": "游牧的森林",
|
||||||
|
"version": "V3",
|
||||||
|
"season": "秋季(9月中旬-10月中旬)",
|
||||||
|
"narrative": "呼伦贝尔+阿尔山,是很多人一生的梦想。这里是每年中国境内最早入秋的地方之一——森林、草原、湿地、公路,绝美、震撼、火山天池、林区民俗……但很多人一生也只能来一次而已!期待通过大兴安岭秋季南北线之旅,让您和家人也爱上我的家乡,留下一生美好的回忆。",
|
||||||
|
"style": "独立成团不拼团 · 一单一车 · 随走随停 · 不错过每处风景",
|
||||||
|
"versions": [
|
||||||
|
{
|
||||||
|
"id": "autumn-south-4d3n",
|
||||||
|
"name": "游牧的森林V3·南线4天3晚",
|
||||||
|
"days": 4,
|
||||||
|
"nights": 3,
|
||||||
|
"tag": "短途版",
|
||||||
|
"line": "南线",
|
||||||
|
"route": "呼伦贝尔+阿尔山",
|
||||||
|
"audience": "假期极短但想看秋色的旅行者",
|
||||||
|
"description": "秋季南线短途版,4天时间串联呼伦贝尔草原与阿尔山秋色精华。牧云山顶赏莫日格勒河、扎罗木得断崖秋色、阿尔山国家森林公园,核心秋景一个不少。行程紧凑高效,适合假期极短但不想错过大兴安岭秋色的旅行者。",
|
||||||
|
"highlights": [
|
||||||
|
"牧云山顶赏莫日格勒河九曲十八弯",
|
||||||
|
"扎罗木得断崖秋色,24年新发掘的小众秘境",
|
||||||
|
"阿尔山国家森林公园AAAAA级景区"
|
||||||
|
],
|
||||||
|
"itinerary": []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "autumn-south-5d4n",
|
||||||
|
"name": "游牧的森林V3·南线5天4晚",
|
||||||
|
"days": 5,
|
||||||
|
"nights": 4,
|
||||||
|
"tag": "经典版",
|
||||||
|
"line": "南线",
|
||||||
|
"route": "呼伦贝尔+阿尔山",
|
||||||
|
"audience": "想深度体验阿尔山秋色的家庭",
|
||||||
|
"description": "秋季南线经典版本,5天4晚从容走遍呼伦贝尔草原与阿尔山秋色。扎罗木得断崖秋野素拍、童话之城阿尔山、阿尔山国家森林公园AAAAA级、ATV卡丁车森林穿越、白狼峰日落,核心秋景与深度体验兼顾。适合想深度体验阿尔山秋色的家庭。",
|
||||||
|
"highlights": [
|
||||||
|
"扎罗木得断崖+秋野素拍,定格秋日最美瞬间",
|
||||||
|
"童话之城阿尔山+阿尔山国家森林公园AAAAA级",
|
||||||
|
"ATV卡丁车森林穿越+白狼峰日落"
|
||||||
|
],
|
||||||
|
"itinerary": [
|
||||||
|
"D1 各地→海拉尔(接机+自由闲逛)",
|
||||||
|
"D2 牧云山顶-莫日格勒河-扎罗木得断崖-秋野素拍-额尔古纳",
|
||||||
|
"D3 额尔古纳-黑山头骑马赏日落-ATV穿越湿地-阿尔山",
|
||||||
|
"D4 阿尔山国家森林公园-天池-驼峰岭天池-不冻河-白狼峰日落-阿尔山",
|
||||||
|
"D5 阿尔山-ATV卡丁车森林穿越-伊敏河湿地-海拉尔-返程"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "autumn-south-7d6n",
|
||||||
|
"name": "游牧的森林V3·南线7天6晚",
|
||||||
|
"days": 7,
|
||||||
|
"nights": 6,
|
||||||
|
"tag": "深度版",
|
||||||
|
"line": "南线",
|
||||||
|
"route": "呼伦贝尔+阿尔山",
|
||||||
|
"audience": "假期充足想深度探索秋色的家庭",
|
||||||
|
"description": "秋季南线主推版本,7天6晚从容走遍呼伦贝尔草原与阿尔山秋色全部精华。在经典版基础上增加白桦林喂驯鹿、恩和骑马做列巴等深度体验,节奏更从容舒适。注:2025年因柴河段修路无法通行,柴河月亮天池暂不包含在V3行程中,2026年V4版本将重新纳入柴河及蘑阿公路为重点线路。",
|
||||||
|
"highlights": [
|
||||||
|
"全部南线精华+更从容节奏,秋季主推版本",
|
||||||
|
"白桦林喂驯鹿+恩和骑马+做列巴",
|
||||||
|
"阿尔山国家森林公园AAAAA级+白狼峰日落"
|
||||||
|
],
|
||||||
|
"itinerary": [
|
||||||
|
"D1 各地→海拉尔",
|
||||||
|
"D2 牧云山顶-莫日格勒河-扎罗木得断崖-秋野素拍-额尔古纳",
|
||||||
|
"D3 额尔古纳-白桦林喂驯鹿-恩和骑马-画套娃做列巴-恩和",
|
||||||
|
"D4 恩和-黑山头骑马赏日落-ATV穿越五彩湿地-额尔古纳",
|
||||||
|
"D5 额尔古纳-伊敏河湿地-阿尔山",
|
||||||
|
"D6 阿尔山国家森林公园-天池-驼峰岭天池-不冻河-白狼峰日落-阿尔山",
|
||||||
|
"D7 阿尔山-ATV卡丁车森林穿越-海拉尔-返程"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "autumn-manzhouli-south-7d6n",
|
||||||
|
"name": "游牧的森林V3·满洲里+南线7天6晚",
|
||||||
|
"days": 7,
|
||||||
|
"nights": 6,
|
||||||
|
"tag": "满洲里+南线",
|
||||||
|
"line": "满洲里+南线",
|
||||||
|
"route": "呼伦贝尔+满洲里+阿尔山",
|
||||||
|
"audience": "想同时看边境风情和阿尔山秋色的家庭",
|
||||||
|
"description": "满洲里与南线的完美结合,7天6晚同时体验中俄蒙边境风情与阿尔山金秋。满洲里套娃广场+边境风情+阿尔山秋色一网打尽,适合想一次旅行看遍呼伦贝尔秋季精华的家庭。",
|
||||||
|
"highlights": [
|
||||||
|
"满洲里套娃广场+边境异域风情",
|
||||||
|
"阿尔山国家森林公园+火山天池秋色",
|
||||||
|
"扎罗木得断崖+秋野素拍+骑马赏日落"
|
||||||
|
],
|
||||||
|
"itinerary": []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "autumn-north-5d4n",
|
||||||
|
"name": "游牧的森林V3·北线5天4晚",
|
||||||
|
"days": 5,
|
||||||
|
"nights": 4,
|
||||||
|
"tag": "北线经典",
|
||||||
|
"line": "北线",
|
||||||
|
"route": "呼伦贝尔+大兴安岭",
|
||||||
|
"audience": "想深入大兴安岭腹地赏秋的旅行者",
|
||||||
|
"description": "秋季北线经典版,5天4晚深入大兴安岭腹地赏秋。大兴安岭绝美公路根白路、龙岩山公园三体雷达峰、大兴安岭深处驯鹿园、太平川古村落,感受大兴安岭最原始的秋色。适合想深入大兴安岭腹地赏秋的旅行者。",
|
||||||
|
"highlights": [
|
||||||
|
"大兴安岭绝美公路根白路,人在车中坐车在画中游",
|
||||||
|
"龙岩山公园三体雷达峰,俯瞰林区小镇全貌",
|
||||||
|
"大兴安岭深处驯鹿园+太平川古村落"
|
||||||
|
],
|
||||||
|
"itinerary": [
|
||||||
|
"D1 各地→海拉尔",
|
||||||
|
"D2 牧云山顶-莫日格勒河-扎罗木得断崖-秋野素拍-额尔古纳",
|
||||||
|
"D3 额尔古纳-白桦林喂驯鹿-恩和骑马-恩和",
|
||||||
|
"D4 恩和-室韦-太平川古村落-莫尔道嘎-龙岩山公园三体雷达峰-莫尔道嘎",
|
||||||
|
"D5 莫尔道嘎-根白路-敖鲁古雅驯鹿园-海拉尔-返程"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "autumn-north-6d5n",
|
||||||
|
"name": "游牧的森林V3·北线6天5晚",
|
||||||
|
"days": 6,
|
||||||
|
"nights": 5,
|
||||||
|
"tag": "北线深度",
|
||||||
|
"line": "北线",
|
||||||
|
"route": "呼伦贝尔+大兴安岭",
|
||||||
|
"audience": "假期充足想更深度走北线的家庭",
|
||||||
|
"description": "秋季北线深度版,6天5晚更从容地深入大兴安岭。在北线5天基础上增加更多深度体验,节奏更舒适,每一处秋色都能细细品味。适合假期充足想更深度走北线的家庭。",
|
||||||
|
"highlights": [
|
||||||
|
"在北线5天基础上更从容,节奏更舒适",
|
||||||
|
"增加更多深度体验,细品大兴安岭秋色",
|
||||||
|
"根白路+龙岩山+驯鹿园+太平川古村落"
|
||||||
|
],
|
||||||
|
"itinerary": []
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"highlights": [
|
||||||
|
{
|
||||||
|
"title": "《语文》课本中的大兴安岭",
|
||||||
|
"description": "中国境内最早入秋的地方,每年9-10月变成一片金黄色的海洋。"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"title": "童话之城阿尔山",
|
||||||
|
"description": "不是山,风景却美过任何一座山,大兴安岭腹地,有人说这里是「东方瑞士」。"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"title": "扎罗木得断崖",
|
||||||
|
"description": "呼伦贝尔秋季最亮丽的名片,兼顾草原、湿地和白桦林等多种风景于一体,24年才被发掘的私密小众景点。"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"title": "秋野素拍",
|
||||||
|
"description": "专业户外人像摄影师提供素拍服务,在草原、湿地和白桦林中定格秋日美好。"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"title": "黑山头骑马赏日落",
|
||||||
|
"description": "呼伦贝尔旅游的一张名片,秋天的这里绝美,脚下就是壮观的额尔古纳湿地五彩斑斓。"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"title": "呼伦贝尔大草原",
|
||||||
|
"description": "秋季的草原别有一番韵味,满眼金黄色的牧草,牛羊成群,草原人少可以独享宁静。"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"title": "牧云山顶赏莫日格勒河最佳视角",
|
||||||
|
"description": "九曲十八弯尽收眼底,同时享用精致下午茶。"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"title": "ATV卡丁车穿越湿地",
|
||||||
|
"description": "穿越亚洲最大的原生草本湿地,在黑山头圣地开展穿越草原、湿地、河流、森林的极致之旅。"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"title": "白桦林里喂驯鹿",
|
||||||
|
"description": "敖鲁古雅使鹿鄂温克,零距离喂苔藓,与森林中的驯鹿精灵合拍(限10.7日前)。"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"title": "一半茫茫林海一半火山天池",
|
||||||
|
"description": "阿尔山火山带,兴安天池(状如心形)、驼峰岭天池(上帝留在大兴安岭的蓝眼泪)。2026年V4版本将新增柴河月亮天池及蘑阿公路为重点线路。"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"title": "阿尔山国家森林公园",
|
||||||
|
"description": "内蒙古东部地区唯一的国家AAAAA级景区,森林覆盖率高达80%,秋季是阿尔山最美的时节。"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"southHighlights": [
|
||||||
|
{
|
||||||
|
"title": "ATV卡丁车森林穿越",
|
||||||
|
"description": "在阿尔山安排一场秋日里的ATV穿越之旅,约50分钟,充分感受秋日森林的旖旎风光。"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"title": "人间仙境白狼日落",
|
||||||
|
"description": "白狼峰海拔1500米,藏在林海深处的小众宝藏地,每逢秋季变成一片黄色的海洋,蔚为壮观。"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"title": "打卡中国最小火车站",
|
||||||
|
"description": "始建于1937年东洋风格的日式建筑,中国最美的火车站,秋天的列车缓缓驶向远方。"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"northHighlights": [
|
||||||
|
{
|
||||||
|
"title": "大兴安岭北部林区绝美公路根白路",
|
||||||
|
"description": "乘车穿越在金黄色的海洋中,人在车中坐,车在画中游。"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"title": "龙岩山公园三体雷达峰",
|
||||||
|
"description": "在大兴安岭深处的莫尔道嘎小镇,登高望远俯瞰整个林区小镇,酷似三体书中的信号接收站。"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"title": "大兴安岭深处驯鹿园",
|
||||||
|
"description": "敖鲁古雅使鹿鄂温克,中国最后的狩猎部落,零距离喂苔藓。"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"title": "大兴安岭中的古村落太平川",
|
||||||
|
"description": "散发着原始氛围的小村庄,位于大兴安岭深山腹地之中,宛如世外桃源,有百年历史的老屋。"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"timeline": [
|
||||||
|
{
|
||||||
|
"version": "V4(预告)",
|
||||||
|
"date": "2026.09",
|
||||||
|
"title": "柴河+蘑阿公路将成为游牧的森林重点线路",
|
||||||
|
"changes": [
|
||||||
|
{
|
||||||
|
"text": "蘑阿公路——大兴安岭最美秋季公路正式纳入行程",
|
||||||
|
"type": "add"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"text": "2025年因柴河段修路无法通行,2026年道路修复后将全面升级南线行程",
|
||||||
|
"type": "update"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"reason": "柴河-蘑阿公路是大兴安岭秋季最壮观的公路之一,2025年修路期间暂时无法安排,2026年道路修复后将成为游牧的森林V4的核心亮点。"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"version": "V3",
|
||||||
|
"date": "2025.09",
|
||||||
|
"title": "新增短途版+满洲里版,北线扩展6天版,全线升级素拍",
|
||||||
|
"changes": [
|
||||||
|
{
|
||||||
|
"text": "南线新增4天3晚短途版,假期极短也能体验秋色精华",
|
||||||
|
"type": "add"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"text": "新增满洲里+南线7天6晚版,边境风情与阿尔山秋色一网打尽",
|
||||||
|
"type": "add"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"text": "北线增加6天5晚深度版,更从容地深入大兴安岭",
|
||||||
|
"type": "add"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"text": "2025年因柴河段修路,南线行程暂不包含柴河月亮天池",
|
||||||
|
"type": "remove"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"text": "全线升级素拍服务,专业户外人像摄影师定格秋日美好",
|
||||||
|
"type": "update"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"reason": "V2版本产品线较少,无法满足不同假期长度的客户需求。V3新增短途版和满洲里版扩大覆盖面,北线增加深度版,同时全线升级素拍服务提升体验。"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"version": "V2(南线)",
|
||||||
|
"date": "2024.08",
|
||||||
|
"title": "新增扎罗木得断崖,升级随车备品",
|
||||||
|
"changes": [
|
||||||
|
{
|
||||||
|
"text": "取消牙克石凤凰山庄景区",
|
||||||
|
"type": "remove"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"text": "增加扎罗木得断崖观赏点,24年新发掘的小众秘境",
|
||||||
|
"type": "add"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"text": "增加备品三件套,提升旅途舒适度",
|
||||||
|
"type": "add"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"reason": "牙克石凤凰山庄景区体验一般,替换为24年新发掘的扎罗木得断崖,兼顾草原、湿地和白桦林多种风景,成为秋季最亮丽的名片。"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"version": "V1",
|
||||||
|
"date": "2023.09",
|
||||||
|
"title": "游牧的森林首发·南线呼伦贝尔+阿尔山",
|
||||||
|
"changes": [
|
||||||
|
{
|
||||||
|
"text": "首发线路,南线呼伦贝尔+阿尔山",
|
||||||
|
"type": "add"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"text": "白桦林喂驯鹿,与森林中的驯鹿精灵合拍",
|
||||||
|
"type": "add"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"text": "阿尔山国家森林公园,大兴安岭腹地AAAAA级景区",
|
||||||
|
"type": "add"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"text": "白狼峰日落,藏在林海深处的小众宝藏地",
|
||||||
|
"type": "add"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"text": "ATV穿越湿地,穿越亚洲最大的原生草本湿地",
|
||||||
|
"type": "add"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"reason": "呼籁深耕呼伦贝尔多年后首次推出秋季产品线。南线串联草原秋色与阿尔山火山天池,让大兴安岭的金秋不再只是一个遥远的梦想。"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"selectionGuide": {
|
||||||
|
"byVacationLength": [
|
||||||
|
{
|
||||||
|
"reason": "精华浓缩",
|
||||||
|
"condition": "4天假期",
|
||||||
|
"recommendation": "autumn-south-4d3n"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"reason": "南线经典",
|
||||||
|
"condition": "5天假期想看阿尔山",
|
||||||
|
"recommendation": "autumn-south-5d4n"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"reason": "北线经典",
|
||||||
|
"condition": "5天假期想看大兴安岭",
|
||||||
|
"recommendation": "autumn-north-5d4n"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"reason": "北线深度",
|
||||||
|
"condition": "6天假期深入大兴安岭",
|
||||||
|
"recommendation": "autumn-north-6d5n"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"reason": "南线深度",
|
||||||
|
"condition": "7天假期看阿尔山",
|
||||||
|
"recommendation": "autumn-south-7d6n"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"reason": "满洲里+南线",
|
||||||
|
"condition": "7天想看边境+阿尔山",
|
||||||
|
"recommendation": "autumn-manzhouli-south-7d6n"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
140
data/blog.json
普通文件
140
data/blog.json
普通文件
@ -0,0 +1,140 @@
|
|||||||
|
{
|
||||||
|
"articles": [
|
||||||
|
{
|
||||||
|
"id": "hulunbuir-travel-guide-2026",
|
||||||
|
"title": "2026年呼伦贝尔旅游攻略:第一次去必看",
|
||||||
|
"subtitle": "第一次去呼伦贝尔?这篇是你需要的第一篇攻略。最佳季节、核心景点、行程天数建议、自驾vs包车对比、预算参考——全在这里,帮你少走弯路。",
|
||||||
|
"author": "呼籁旅行",
|
||||||
|
"date": "2026-03-10",
|
||||||
|
"category": "攻略",
|
||||||
|
"summary": "第一次去呼伦贝尔?这篇是你需要的第一篇攻略。最佳季节、核心景点、行程天数建议、自驾vs包车对比、预算参考——全在这里,帮你少走弯路。",
|
||||||
|
"coverImage": "/images/team/hero-grassland.jpg",
|
||||||
|
"tags": [
|
||||||
|
"呼伦贝尔攻略",
|
||||||
|
"首次出行",
|
||||||
|
"行程规划",
|
||||||
|
"呼伦贝尔旅游"
|
||||||
|
],
|
||||||
|
"content": "<h2>为什么要去呼伦贝尔?</h2><p>呼伦贝尔是中国最大的地级市,面积约25.3万平方公里,拥有中国保存最完好的天然草原之一。这里有莫日格勒河的九曲弯,有额尔古纳湿地的晨雾,有边境公路的无尽延伸,有根河的驯鹿文化。每年6月至8月,这里是真正意义上的「绿色乌托邦」。</p><h2>最佳出行时间</h2><p>呼伦贝尔一年四季各有特色,但对于第一次来的游客,<strong>6月下旬至8月下旬</strong>是最推荐的时间窗口。这个阶段草原最绿、天气最稳定、活动最丰富。</p><ul><li><strong>6月下旬</strong>:草原刚进入旺季,游客相对少,价格较优惠,野花盛开</li><li><strong>7月全月</strong>:高峰期,景色最美,那达慕民俗活动丰富,但需提前预订</li><li><strong>8月</strong>:草场依然翠绿,进入收尾期,性价比高</li></ul><p>如果你喜欢秋色,9月的白桦林和湿地同样值得一来;冬季则适合雪原探险和冰雪那达慕。</p><h2>核心景点不能错过</h2><p>呼伦贝尔幅员辽阔,景点分布分散。以下是第一次来必须打卡的核心区域:</p><ul><li><strong>莫日格勒河</strong>:被誉为「天下第一曲水」,九曲十八弯,日出时拍照是摄影人的圣地</li><li><strong>额尔古纳湿地</strong>:国家级自然保护区,晨雾中的湿地有梦幻感</li><li><strong>中俄边境公路</strong>:沿黑山头到室韦的边境线驾车,一侧是额尔古纳河,对岸是俄罗斯</li><li><strong>呼伦湖</strong>:中国北方第一大淡水湖,落日景色壮美</li><li><strong>根河敖鲁古雅</strong>:驯鹿文化保护区,感受鄂温克族最原始的游牧生活</li></ul><h2>行程天数怎么定</h2><p>呼伦贝尔不是一个「走马观花」的目的地,建议最少安排<strong>5天4晚</strong>。如果带孩子或希望深度体验,6-7天更从容。4天3晚适合二刷或时间紧张的朋友,只能走精华线路。</p><h2>交通方式</h2><p>从北京/上海/成都等主要城市均有直飞海拉尔(呼伦贝尔市区机场)的航班。到达后,建议选择<strong>专业包车+本地领队</strong>的方式,原因是:</p><ul><li>景点间距离动辄100-200公里,自驾路况复杂</li><li>本地领队熟悉隐藏景点和最佳拍摄时机</li><li>草原上部分区域手机信号差,导航不可靠</li></ul><h2>第一次去的注意事项</h2><p>草原的紫外线强度是城市的2-3倍,防晒是第一要务。早晚温差可达15-20℃,即使夏天也要带一件厚外套。草原上蚊虫活跃,防虫喷雾不可少。如果带孩子,骑马等活动要确认安全规范后再参与。</p><h2>预订建议</h2><p>7月旺季的行程和住宿至少提前<strong>2-3个月</strong>预订,热门日期可能更早售罄。选择有资质的本地旅行社,签订正规电子合同,避免行程缩水或临时换车换导游。呼籁旅行深耕呼伦贝尔11年,一家一单一车,是家庭出行的可靠选择。</p>"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "hulunbuir-family-travel-guide",
|
||||||
|
"title": "呼伦贝尔亲子游完全指南:带娃怎么玩",
|
||||||
|
"subtitle": "带孩子去呼伦贝尔草原,什么年龄合适?哪些活动安全?怎么选行程?呼籁旅行11年亲子游经验,帮你把每一个细节都想清楚。",
|
||||||
|
"author": "呼籁旅行",
|
||||||
|
"date": "2026-03-05",
|
||||||
|
"category": "亲子",
|
||||||
|
"summary": "带孩子去呼伦贝尔草原,什么年龄合适?哪些活动安全?怎么选行程?呼籁旅行11年亲子游经验,帮你把每一个细节都想清楚。",
|
||||||
|
"coverImage": "/images/team/hero-family.jpg",
|
||||||
|
"tags": [
|
||||||
|
"亲子游",
|
||||||
|
"带娃旅行",
|
||||||
|
"草原亲子",
|
||||||
|
"家庭出游"
|
||||||
|
],
|
||||||
|
"content": "<h2>呼伦贝尔适合多大孩子?</h2><p>这是父母们最常问的问题。答案是:<strong>基本上没有年龄下限</strong>,但不同年龄段的体验侧重点不同。我们服务过最小3个月的宝宝,也服务过带14岁少年来「二刷」的家庭。</p><ul><li><strong>0-2岁</strong>:以草原感受为主,大自然的声音、空气和视野对宝宝的感官发育有积极意义。骑马等活动不参与,以看为主。</li><li><strong>3-5岁</strong>:可以体验套马杆、接触马匹、参与奶制品制作,是最容易被草原「征服」的年龄段。</li><li><strong>6-10岁</strong>:黄金亲子年龄,骑马、越野车、篝火晚会、学蒙古语,每个环节都充满好奇心和参与热情。</li><li><strong>11岁以上</strong>:体力充沛,可以挑战ATV、越野徒步,独立拍照,开始建立属于自己的旅行记忆。</li></ul><h2>亲子游必体验活动TOP 5</h2><p><strong>1. 草原骑马</strong><br/>这是孩子们最期待的活动。建议选择有专业牵马师陪同的体验,而非放任独骑。正规的亲子骑马会为孩子配备头盔和安全背心,牵马师全程陪伴。</p><p><strong>2. 挤牛奶·做奶制品</strong><br/>去牧民家体验传统奶制品制作:手工奶酪、酸奶、黄油。孩子通过亲手操作,理解食物从哪里来,是自然教育的绝佳场景。</p><p><strong>3. 篝火晚会</strong><br/>夏夜草原的篝火晚会是行程高潮。蒙古族歌手现场演唱,孩子们学跳安代舞,手持火把绕圈,黑色天幕和满天星辰——这个画面,孩子长大后不会忘。</p><p><strong>4. 捡牛粪·认植物</strong><br/>这是我们专为亲子家庭设计的自然教育环节。草原上有200余种野花,牧民带孩子认识常见草本植物,讲解草原生态。</p><p><strong>5. 边境公路探秘</strong><br/>从室韦到黑山头的边境公路全程约200公里,孩子趴在车窗上看对岸的俄罗斯小屋,听领队讲两岸的历史故事,地理课在真实场景中发生。</p><h2>亲子行程怎么选</h2><p>建议带孩子至少安排<strong>6天5晚</strong>,这样行程节奏从容,孩子不会因赶路而疲惫。7天6晚亲子版则可以增加深度体验环节,例如驯鹿基地参观和湿地探秘。</p><p>避免选择强调「效率」的快行程,草原旅行的意义在于让孩子有足够时间在一片草地上发呆、跑动、和牧民家的狗玩耍——这些「无意义」的时间,往往是他们记忆最深的片段。</p><h2>住宿与饮食</h2><p>呼籁旅行的自有营地提供亲子友好的蒙古包住宿,内置独立卫浴,不必担心如厕问题。营地备有儿童餐,对食材过敏的家庭请提前告知定制师。草原的饮食以牛羊肉为主,挑食的孩子可以准备一些备用零食。</p><h2>安全保障</h2><p>选择有资质的旅行社是保障安全的第一步。呼籁旅行为每位游客购买旅行意外险,专业领队均接受过急救培训,骑马等高风险活动全程配备专业人员。草原紫外线强,儿童防晒霜建议每2小时补涂一次。</p>"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "hulunbuir-best-month-to-visit",
|
||||||
|
"title": "呼伦贝尔几月份去最好?月份对比全解析",
|
||||||
|
"subtitle": "春夏秋冬各有千秋,但不同月份的差异远比你想象得大。本文用数据说话,帮你选出最适合自己的出行时间。",
|
||||||
|
"author": "呼籁旅行",
|
||||||
|
"date": "2026-02-28",
|
||||||
|
"category": "攻略",
|
||||||
|
"summary": "春夏秋冬各有千秋,但不同月份的差异远比你想象得大。本文用数据说话,帮你选出最适合自己的出行时间。",
|
||||||
|
"coverImage": "/images/team/hero-grassland.jpg",
|
||||||
|
"tags": [
|
||||||
|
"出行时间",
|
||||||
|
"季节推荐",
|
||||||
|
"气候攻略",
|
||||||
|
"呼伦贝尔旅游"
|
||||||
|
],
|
||||||
|
"content": "<h2>一句话结论</h2><p>如果只能给一个答案:<strong>7月中旬至8月上旬</strong>是综合体验最好的时间段——草最绿、天最蓝、活动最丰富。但这也是最贵、最挤的时候。根据你的出行目的、预算和喜好,不同月份各有优势。</p><h2>各月份详细解析</h2><h3>5月:草原刚苏醒,人少价低</h3><p>5月气温回升,草原开始泛绿,但草色尚浅,偶尔还有寒潮。适合摄影爱好者追逐「初绿」感,以及预算有限的旅行者。日均气温10-18℃,晚上仍需厚外套。</p><h3>6月:野花最盛,性价比之王</h3><p>6月草原进入盛放期,各色野花铺满大地,是全年最适合摄影的月份之一。游客量约为7月的60%,价格相对低15-20%。日均气温18-24℃,天气舒适。<strong>强烈推荐</strong>不赶热闹、喜欢自然的旅行者。</p><h3>7月:旺季高峰,景色最美</h3><p>7月草原达到一年中最高颜值。7月中下旬那达慕期间民俗活动丰富,是体验蒙古族文化的最佳时机。日均气温22-28℃。缺点:预订需提前2-3个月,价格为全年最高。</p><h3>8月:旺季收尾,从容出行</h3><p>8月上旬草色仍旺,中旬开始草色转黄。游客量逐渐减少,各类资源预订难度下降。日均气温18-25℃。适合不想在旺季挤着玩又想看到绿草的家庭。</p><h3>9月:秋叶金黄,大兴安岭最美</h3><p>9月呼伦贝尔的重心从草原转向森林。大兴安岭白桦林金黄,额尔古纳湿地芦苇变金,莫尔道嘎国家森林公园层林尽染。是秋色爱好者和摄影人的推荐月份。气温10-18℃,早晚凉,穿着要比夏季厚一层。</p><h3>10月:初雪来临,草原转入休眠</h3><p>10月中下旬开始降雪,草原景观结束,进入「雪原模式」。适合喜欢人迹罕至、想看初雪草原的探险旅行者。非常规旅游旺季,部分营地已关闭。</p><h3>11月至次年2月:冰雪季,另一个呼伦贝尔</h3><p>呼伦贝尔冬季最低气温可达-40℃,是中国最冷地区之一。但这里也是国内冰雪体验最丰富的目的地:冰雪那达慕、驯鹿文化、雾凇奇景、冰上车队。适合追求极致体验、耐寒能力强的旅行者。</p><h3>3-4月:不推荐</h3><p>春季融雪期,道路泥泞,草原泥泞,景色荒芜,是一年中最不适合旅游的时段。</p><h2>按人群推荐</h2><ul><li><strong>亲子家庭(6-12岁孩子)</strong>:7月旺季,活动最丰富</li><li><strong>亲子家庭(3-5岁孩子)</strong>:6月末或8月,天气舒适节奏慢</li><li><strong>摄影爱好者</strong>:6月野花期或9月秋色期</li><li><strong>预算有限</strong>:6月上旬或8月下旬</li><li><strong>冰雪体验</strong>:1月,冰雪活动最丰富</li><li><strong>避开人群</strong>:6月上旬,景美人少</li></ul><h2>总结</h2><p>没有「最好」的月份,只有「最适合你」的月份。建议结合自己的行程安排、孩子年龄和旅行目的综合判断。如果拿不定主意,欢迎联系呼籁旅行的定制师,我们会根据你的具体情况给出最适合的建议。</p>"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "hulunbuir-self-drive-vs-chartered-bus",
|
||||||
|
"title": "呼伦贝尔自驾vs包车:哪种方式更适合你",
|
||||||
|
"subtitle": "呼伦贝尔自驾还是包车,这个问题困扰着大多数第一次去的旅行者。本文从路况、费用、自由度、安全性四个维度全面对比。",
|
||||||
|
"author": "呼籁旅行",
|
||||||
|
"date": "2026-02-20",
|
||||||
|
"category": "攻略",
|
||||||
|
"summary": "呼伦贝尔自驾还是包车,这个问题困扰着大多数第一次去的旅行者。本文从路况、费用、自由度、安全性四个维度全面对比。",
|
||||||
|
"coverImage": "/images/team/hero-grassland.jpg",
|
||||||
|
"tags": [
|
||||||
|
"自驾攻略",
|
||||||
|
"包车攻略",
|
||||||
|
"交通方式",
|
||||||
|
"呼伦贝尔旅游"
|
||||||
|
],
|
||||||
|
"content": "<h2>先说结论</h2><p>对于第一次去呼伦贝尔、带有孩子或老人的家庭旅行者,<strong>包车+本地领队</strong>是更优解。有越野经验、团队人数较多(6人以上)、追求极致自由的旅行者可以考虑自驾。</p><h2>路况:草原路不是你想象的样子</h2><p>很多人以为呼伦贝尔只是开车在草原上走走,实际上情况复杂得多:</p><ul><li>海拉尔到草原核心区的距离超过150公里,全程以国省道为主,部分路段没有护栏</li><li>莫日格勒河观景台需要走无导航的草地便道,雨后极易陷车</li><li>从室韦到黑山头的边境公路全长约200公里,途中加油站极少</li><li>9月以后部分路段开始结冰,对驾驶技术要求高</li><li>草原无信号区域手机导航失效,需要提前下载离线地图</li></ul><p>这些问题对有经验的自驾游客不构成障碍,但对普通家庭旅行者而言风险较高。</p><h2>费用对比</h2><p><strong>自驾费用</strong>(以5天为例,2大2小):</p><ul><li>租车费:约600-900元/天,5天约3000-4500元</li><li>油费:约800-1200元</li><li>停车+景区内摆渡车:约500元</li><li>合计约4300-6200元(不含住宿餐饮)</li></ul><p><strong>包车费用</strong>(同等行程):</p><ul><li>含专业领队+7座商务车:约800-1200元/天,5天约4000-6000元</li><li>包含:全程接送、景区讲解、行程规划、应急协调</li></ul><p>费用相差不大,但包车额外包含了专业服务价值。</p><h2>自由度</h2><p>自驾最大的优势是时间完全自由——想在哪个路边停就停,想在哪个景点多待就多待,不必配合其他人的节奏。这对摄影发烧友尤其重要,追光追云需要极大的时间弹性。</p><p>但包车并非完全不自由。选择优质旅行社的私家包车(一家一单),你同样可以提出自己的节奏要求,领队会配合调整。</p><h2>安全性</h2><p>草原上的安全隐患不止于交通。本地领队了解哪片草场近期有狼群活动,知道哪个景点的悬崖边栏杆不稳,在应急情况下(陷车、孩子受伤、天气突变)能快速调动本地资源。这是任何导航软件都无法替代的本地经验。</p><h2>适合自驾的情况</h2><ul><li>旅行团有越野车经验丰富的驾驶员</li><li>人数6人以上,摊薄成本</li><li>行程以摄影为主,需要极大的时间弹性</li><li>有呼伦贝尔旅行经验(二刷以上)</li></ul><h2>适合包车的情况</h2><ul><li>第一次去,不熟悉路线</li><li>带孩子或老人,安全优先</li><li>行程天数有限,希望效率最高</li><li>想深度了解本地文化,需要领队讲解</li><li>4人以下家庭,自驾反而更贵</li></ul><h2>选包车的关键:怎么选靠谱的</h2><p>包车最大的坑在于「人头团」——名义上包车,实际上拼车,或者中途换车换领队。选择包车要注意:签订正规合同、确认是否一家一单、确认车辆型号和领队信息。呼籁旅行提供「一家一单一车」的私家定制,从签约到结束同一个领队全程陪同,这是我们的核心承诺。</p>"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "hulunbuir-travel-cost-breakdown",
|
||||||
|
"title": "呼伦贝尔旅行花费明细:玩一趟到底要多少钱",
|
||||||
|
"subtitle": "呼伦贝尔一趟到底花多少钱?本文拆解机票、住宿、交通、餐饮、活动、购物各项费用,给出高中低三档真实预算参考。",
|
||||||
|
"author": "呼籁旅行",
|
||||||
|
"date": "2026-02-15",
|
||||||
|
"category": "攻略",
|
||||||
|
"summary": "呼伦贝尔一趟到底花多少钱?本文拆解机票、住宿、交通、餐饮、活动、购物各项费用,给出高中低三档真实预算参考。",
|
||||||
|
"coverImage": "/images/team/hero-family.jpg",
|
||||||
|
"tags": [
|
||||||
|
"旅游花费",
|
||||||
|
"预算攻略",
|
||||||
|
"性价比",
|
||||||
|
"呼伦贝尔费用"
|
||||||
|
],
|
||||||
|
"content": "<h2>先说总数</h2><p>以2大2小(4-10岁孩子)5天4晚为例,<strong>中档出行总预算约15000-22000元</strong>,人均约3750-5500元。预算差异主要来自机票舱位、住宿档次和是否选择旺季出行。</p><h2>机票费用</h2><p>北京/上海至海拉尔(HLD)直飞约2.5小时,无直飞城市需转机。</p><ul><li><strong>经济舱</strong>:北京出发来回约800-1500元/人,视旺淡季波动较大</li><li><strong>商务舱</strong>:约3000-5000元/人</li><li><strong>提前预订建议</strong>:7月旺季至少提前2个月订票,可省20-30%</li><li>4人家庭机票合计约3200-6000元(经济舱)</li></ul><h2>定制游套餐费用</h2><p>选择呼籁旅行的定制游套餐,包含车辆、领队、大部分景区门票和营地住宿:</p><ul><li><strong>4天3晚</strong>:约5800-7200元/人(视版本和人数)</li><li><strong>5天4晚</strong>:约7000-8500元/人</li><li><strong>6天5晚亲子版</strong>:约8500-10000元/人</li></ul><p>套餐包含:专属领队、7座商务车、自有营地住宿(含早餐)、主要景区门票、部分活动费用。</p><h2>额外活动费用</h2><p>套餐外的自费活动参考价(旺季):</p><ul><li>骑马体验(30分钟):80-150元/人</li><li>ATV/越野摩托:200-400元/组</li><li>热气球(部分区域):400-600元/人</li><li>驯鹿基地参观:80元/人</li></ul><p>建议提前了解套餐包含哪些活动,避免到现场发现核心项目都要单独付费。</p><h2>餐饮费用</h2><p>草原上的饮食选择相对有限。住宿套餐一般含早餐,午晚餐需自理或选择套餐附带版本。</p><ul><li>牧民家就餐(手把肉+奶茶+各类奶制品):约100-150元/人</li><li>海拉尔市区餐厅:约60-100元/人</li><li>景区附近餐厅:质量参差,约80-120元/人</li><li>5天餐饮合计(午晚餐):约1500-2500元(4人家庭)</li></ul><h2>购物费用</h2><p>呼伦贝尔特产推荐:风干牛肉、马奶酒、风干羊腿、各类奶制品、蒙古族手工艺品。预算控制在500-1500元较为合理,注意辨别正规商家,避免购买过度加工的旅游纪念品。</p><h2>三档预算汇总(4人家庭,5天4晚)</h2><ul><li><strong>经济档</strong>(淡季6月,拼房/民宿):约12000-16000元</li><li><strong>舒适档</strong>(旺季7月,包车定制游):约18000-25000元</li><li><strong>品质档</strong>(旺季7月,商务舱+高端住宿):约30000-40000元</li></ul><h2>省钱小技巧</h2><ul><li>淡旺季差价约20-30%,6月或8月出行可节省不少</li><li>提前3个月预订机票,通常比临时订便宜30%以上</li><li>儿童优惠:大部分景区12岁以下半价或免票,提前了解政策</li><li>选择套餐含活动的版本,比散拼更划算</li></ul>"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "hulunbuir-travel-with-toddlers-4-6",
|
||||||
|
"title": "带4-6岁孩子去草原的注意事项",
|
||||||
|
"subtitle": "4-6岁是孩子最适合初次体验草原的年龄段,好奇心旺盛但自我保护能力弱。这篇文章总结了11年来服务这个年龄段孩子的所有注意事项。",
|
||||||
|
"author": "呼籁旅行",
|
||||||
|
"date": "2026-02-10",
|
||||||
|
"category": "亲子",
|
||||||
|
"summary": "4-6岁是孩子最适合初次体验草原的年龄段,好奇心旺盛但自我保护能力弱。这篇文章总结了11年来服务这个年龄段孩子的所有注意事项。",
|
||||||
|
"coverImage": "/images/team/hero-family.jpg",
|
||||||
|
"tags": [
|
||||||
|
"4-6岁",
|
||||||
|
"幼童旅行",
|
||||||
|
"亲子注意事项",
|
||||||
|
"安全出行"
|
||||||
|
],
|
||||||
|
"content": "<h2>为什么4-6岁特别适合草原初体验</h2><p>心理学研究表明,3-6岁是儿童自然依恋期的关键窗口。在这个阶段接触大自然,对孩子的感知发育、情绪调节和环境认知有深远影响。草原的开阔空间、野生动植物、以及与城市截然不同的生活方式,对这个年龄段的孩子有天然的吸引力。但同时,4-6岁孩子的自我保护意识尚未成熟,需要大人更细心的陪伴和防护。</p><h2>安全第一:哪些活动可以参与</h2><p><strong>推荐参与:</strong></p><ul><li>骑马体验(由专业牵马师全程陪同,配备儿童头盔和安全背心)</li><li>接触牧民家的温顺马匹和羊群</li><li>奶制品制作体验</li><li>草地自由玩耍、捉昆虫、认植物</li><li>篝火晚会观看(距火堆保持2米以上)</li><li>湿地木栈道参观</li></ul><p><strong>不推荐参与:</strong></p><ul><li>ATV全地形越野车(最低年龄要求通常为12岁)</li><li>快速骑马(无牵马师陪同的自由骑乘)</li><li>深水区游泳</li><li>夜间单独户外活动</li></ul><h2>防晒是头等大事</h2><p>草原海拔约600-800米,加上没有城市遮蔽物,紫外线强度是城市的2-3倍。4-6岁孩子皮肤薄、防晒能力弱,晒伤在草原上非常常见。</p><ul><li>选择SPF50+、PA+++的儿童专用防晒霜</li><li>每隔2小时补涂一次,游泳或出汗后立即补涂</li><li>上午10点至下午3点是UV最强时段,尽量避免长时间在无遮蔽处活动</li><li>备好遮阳帽(大帽沿款)、防晒衣、太阳镜(儿童专用UV防护款)</li></ul><h2>饮食注意事项</h2><p>草原的饮食以牛羊肉为主,酸奶、奶茶、奶豆腐等奶制品是当地特色。几点注意:</p><ul><li>如果孩子对牛奶蛋白过敏,务必提前告知领队</li><li>蒙古奶茶含有奶和砖茶,首次尝试给孩子少量品尝</li><li>草原上的生水不可饮用,全程饮用瓶装水或自带滤水</li><li>备好孩子平时爱吃的零食,避免因不适应当地食物而挨饿</li><li>手把肉(煮羊腿)是当地特色,可以让孩子尝试,但注意骨头</li></ul><h2>行程节奏的把握</h2><p>4-6岁孩子每天有效活动时间约4-6小时,之后需要午休。建议行程安排:</p><ul><li>上午安排主要景点或活动(精力最旺盛)</li><li>下午安排轻松项目或营地自由活动</li><li>避免连续多天长途驾车(每天车程控制在3小时以内)</li><li>每天保证10小时左右睡眠(草原空气好,孩子睡得深)</li></ul><h2>常见突发状况处理</h2><p><strong>蚊虫叮咬</strong>:草原蚊虫活跃,出发前涂抹含DEET或派卡瑞丁的儿童驱蚊产品。被叮咬后用冰块冷敷,切勿让孩子抓挠。</p><p><strong>感冒发烧</strong>:早晚温差大,备好儿童退烧药和感冒药。若发烧超过38.5℃,需及时就医(海拉尔有三甲医院)。</p><p><strong>晕车</strong>:草原路颠簸,晕车的孩子出发前1小时服用晕车药,行程中准备好塑料袋。</p><p><strong>皮肤过敏</strong>:草原花粉较多,有过敏体质的孩子备好抗组胺药物,出门戴口罩。</p><h2>一句话总结</h2><p>带4-6岁孩子去草原,做好防晒、管好饮食、控制节奏,其余的交给草原——孩子对自然的好奇心会帮你完成剩下的事情。</p>"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "hulunbuir-travel-tips-avoid-pitfalls",
|
||||||
|
"title": "呼伦贝尔避坑指南:这些坑千万别踩",
|
||||||
|
"subtitle": "呼伦贝尔旅游的坑不少:强制购物、人头拼团、低价陷阱、景区宰客……这篇避坑指南帮你把雷都踩在出发之前。",
|
||||||
|
"author": "呼籁旅行",
|
||||||
|
"date": "2026-01-25",
|
||||||
|
"category": "避坑",
|
||||||
|
"summary": "呼伦贝尔旅游的坑不少:强制购物、人头拼团、低价陷阱、景区宰客……这篇避坑指南帮你把雷都踩在出发之前。",
|
||||||
|
"coverImage": "/images/team/hero-grassland.jpg",
|
||||||
|
"tags": [
|
||||||
|
"避坑指南",
|
||||||
|
"旅游陷阱",
|
||||||
|
"消费提醒",
|
||||||
|
"呼伦贝尔旅游"
|
||||||
|
],
|
||||||
|
"content": "<h2>坑一:低价团,行程缩水</h2><p>在各大平台搜索「呼伦贝尔旅游」,会出现标价极低的产品,比市场均价低30-50%。这类产品的常见套路:</p><ul><li>核心景点(如边境公路、室韦)被删减</li><li>住宿缩水,从营地换成郊区普通宾馆</li><li>强制购物停留时间长、自费活动多</li><li>领队专业度差,纯跑路</li></ul><p><strong>辨别方法</strong>:对比行程中是否包含室韦/黑山头边境公路、自有营地住宿、额尔古纳湿地等核心节点。正规套餐不会比市场均价低超过15%。</p><h2>坑二:人头拼团,冒充私家团</h2><p>很多旅行社打着「私家包车」的旗号,实际是把多组家庭拼在同一辆车上,变成了效率低、节奏不一的大团。辨别方式:在合同中明确写入「一家一单,不拼团,同一辆车只接待本组家庭」,并注明车辆型号和领队姓名。</p><h2>坑三:景区内宰客</h2><p>草原上部分非正规马场、摄影点、手工艺品摊位存在漫天要价的情况。常见场景:骑马前未谈好价格,骑完被要天价;照相「免费」,洗出来才知道每张100元以上。</p><p><strong>应对方法</strong>:任何消费前先确认价格并口头确认,有争议项目拍视频留证据。选择有本地领队陪同的出行方式,领队通常会提前提醒这类情况。</p><h2>坑四:住宿虚假宣传</h2><p>部分民宿或营地在网上发布的照片与实际差距悬殊:图片是高级帐篷,实际是没有卫浴的简易蒙古包;宣传「草原深处」,实际在城郊农家乐。</p><p><strong>辨别方法</strong>:要求提供真实照片(不修图)、卫浴配置、与草原核心区的距离。呼籁旅行的自有营地提供真实照片和视频参考,可在预订前查看。</p><h2>坑五:旺季一房难求</h2><p>7月草原旺季,优质营地和酒店经常提前2个月以上售罄。若临时决定出行,只能选择剩余的低品质住宿,严重影响体验。<strong>教训</strong>:确定要去就立刻预订,尤其是7月15日至8月5日的黄金期。</p><h2>坑六:不签合同,口头承诺</h2><p>小作坊式的旅行社常见问题:仅口头承诺行程,不提供书面合同;出现问题无凭据。正规旅行社必须签订包含行程细节、退改条款、投诉渠道的正式旅游合同(电子版也算)。无合同,不出发。</p><h2>坑七:天气原因无法赔偿</h2><p>草原天气变化快,有时会遭遇大雨导致部分景点无法前往。部分旅行社在合同中以「不可抗力」条款免除一切责任。查看合同时重点关注:因天气原因导致行程调整,旅行社如何补偿或安排替代方案。</p><h2>坑八:购物停留时间过长</h2><p>部分旅行社与当地购物点有合作,在行程中安排1-2小时甚至更长的购物时间,以「体验当地文化」为名实为强制购物。选择旅行社时直接问:行程中是否有购物环节?是否有强制购物?获得明确承诺后写入合同。</p><h2>坑九:活动安全保障不足</h2><p>草原上的骑马、ATV等活动存在一定风险。不规范的活动场地:无头盔提供、马匹未经专业训练、无安全员陪同。参与任何体力活动前确认安全装备是否齐全,拒绝没有安全保障的项目。</p><h2>坑十:以为草原哪里都一样</h2><p>这不是「坑」,但是认知偏差。呼伦贝尔最精华的景点高度分散,如果只在海拉尔周边转,会错过所有核心风景。行程规划时确认包含:莫日格勒河、额尔古纳湿地、边境公路(室韦-黑山头段)这三个核心节点,否则相当于白跑一趟。</p>"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "grassland-photography-outfit-guide",
|
||||||
|
"title": "草原旅拍穿搭指南:怎么拍出大片感",
|
||||||
|
"subtitle": "去草原不知道穿什么?本文从色系选择、服装款式、配件搭配到拍摄时机,手把手教你在呼伦贝尔草原拍出大片感。",
|
||||||
|
"author": "呼籁旅行",
|
||||||
|
"date": "2026-01-18",
|
||||||
|
"category": "穿搭",
|
||||||
|
"summary": "去草原不知道穿什么?本文从色系选择、服装款式、配件搭配到拍摄时机,手把手教你在呼伦贝尔草原拍出大片感。",
|
||||||
|
"coverImage": "/images/team/hero-grassland.jpg",
|
||||||
|
"tags": [
|
||||||
|
"草原穿搭",
|
||||||
|
"旅拍穿搭",
|
||||||
|
"拍照技巧",
|
||||||
|
"呼伦贝尔摄影"
|
||||||
|
],
|
||||||
|
"content": "<h2>草原拍照的核心逻辑</h2><p>草原摄影不同于城市街拍,背景是无边绿色+蓝天白云的极简组合,这意味着<strong>服装颜色是决定出片质量的第一要素</strong>。颜色选对了,随手一拍都是大片;颜色选错了,专业摄影师也救不回来。</p><h2>色系选择:哪些颜色最出片</h2><p><strong>最推荐:</strong></p><ul><li><strong>白色</strong>:与绿草蓝天形成最强反差,任何角度都好看,是草原拍照的王者色</li><li><strong>米黄/驼色</strong>:低饱和度的暖色调与草原泥土色系天然融合,不抢镜,任何构图都好看</li><li><strong>天蓝/浅蓝</strong>:呼应天空色,融入感强,有「天人合一」的意境</li><li><strong>民族风红色</strong>:蒙古族传统服装色,与草原文化契合,但面积不宜过大</li></ul><p><strong>慎用:</strong></p><ul><li>深绿色:与背景融合,人会「消失」在草原中</li><li>印花/格纹:在草原简洁背景下显得杂乱</li><li>荧光色:显眼但不好看,适合纪念照不适合大片</li></ul><h2>推荐款式</h2><p><strong>女生首选:</strong></p><ul><li>飘逸长裙(纯色或简约印花):风吹裙摆是草原专属画面,必备</li><li>蒙古族传统袍子(可在当地租借):文化感拉满,适合正式纪念照</li><li>衬衫+高腰阔腿裤:干净清爽,适合日常旅行拍摄</li></ul><p><strong>男生推荐:</strong></p><ul><li>白色或浅色衬衫:简单好配,不会抢镜</li><li>户外风系列(防晒衣+功能裤):既实用又有探险感</li><li>蒙古族传统服装:非常出片,可在当地租用</li></ul><p><strong>亲子家庭:</strong></p><ul><li>建议全家选择同一色系,而非相同颜色</li><li>经典组合:爸爸白衬衫+妈妈白裙+孩子蓝色或黄色(补色点亮画面)</li><li>孩子适合亮色系,活泼的黄色、红色最出片</li></ul><h2>配件不可少</h2><ul><li><strong>帽子</strong>:草原必备,功能性(防晒)和美观性兼顾。草帽、白色棒球帽、蒙古风毡帽都很适合</li><li><strong>马术靴</strong>:穿上骑马靴整个人气质立刻不同,也很安全</li><li><strong>腰带/腰封</strong>:长裙加一条民族风腰带,层次感立刻出来</li></ul><h2>最佳拍摄时机</h2><p>草原光线变化极大,拍摄时机比服装更重要:</p><ul><li><strong>黄金时刻(Golden Hour)</strong>:日出后1小时(约6:00-7:30)和日落前1小时(约20:00-21:30)。此时光线暖黄,阴影柔和,任何构图都好看</li><li><strong>蓝调时刻</strong>:日出前和日落后15分钟,天空呈深蓝色,适合营地或蒙古包的夜景拍摄</li><li><strong>正午慎拍</strong>:10:00-16:00阳光直射,阴影浓重,容易曝光过度,此时建议在阴影处或营地内拍摄</li></ul><h2>拍摄构图小技巧</h2><ul><li><strong>低角度仰拍</strong>:把相机/手机放到腰部高度向上拍,以草地为前景,人物和天空占画面的上2/3,草原感最强</li><li><strong>留白天空</strong>:草原的天空是最好的背景,让人物处于画面下1/3,上方大面积留白</li><li><strong>奔跑/回眸</strong>:让被拍摄者做动态动作,避免生硬站立</li><li><strong>利用道路</strong>:边境公路的笔直道路是天然的透视线,站在道路中央拍摄有延伸感</li></ul><h2>实用建议</h2><p>带至少2套不同颜色的外出服装,根据当天景点背景灵活切换。在营地可以借穿当地蒙古族传统服装,通常收费50-100元/套,非常值得体验。草原风大,长裙拍摄时顺风站立,裙摆自然飘起效果最好。最后,记得在出发前充满手机电量,草原上充电不方便,备一个移动电源是必要的。</p>"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
62
data/brand.json
普通文件
62
data/brand.json
普通文件
@ -0,0 +1,62 @@
|
|||||||
|
{
|
||||||
|
"name": "呼籁旅行",
|
||||||
|
"fullName": "内蒙古呼籁文旅投资开发集团有限公司",
|
||||||
|
"domain": "1814.love",
|
||||||
|
"url": "https://1814.love",
|
||||||
|
"slogan": {
|
||||||
|
"emotional": "带孩子回到母亲的故乡",
|
||||||
|
"functional": "呼伦贝尔家庭定制游·一家一单一车"
|
||||||
|
},
|
||||||
|
"trustStats": [
|
||||||
|
{
|
||||||
|
"value": "10000+",
|
||||||
|
"unit": "组",
|
||||||
|
"label": "已服务家庭"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"value": "39000+",
|
||||||
|
"unit": "人次",
|
||||||
|
"label": "累计服务人次"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"value": "11",
|
||||||
|
"unit": "年",
|
||||||
|
"label": "深耕呼伦贝尔"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"value": "9",
|
||||||
|
"unit": "家",
|
||||||
|
"label": "旗下企业"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"differentiators": [
|
||||||
|
{
|
||||||
|
"title": "自有营地",
|
||||||
|
"description": "呼籁自有草原活动基地,亲子互动、草原运动、户外体验的专属场地,不是拼团景点"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"title": "自有车队",
|
||||||
|
"description": "呼籁旅游客运有限公司自营车队,不转卖客人给第三方,每一程都是呼籁自己的车、自己的师傅"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"title": "自营体验",
|
||||||
|
"description": "呼籁营地、白桦林研学、黑山头研学、寻龙诀全地形越野车等核心体验项目均为呼籁自营,品质自己把控"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"title": "自营旅拍",
|
||||||
|
"description": "呼籁自营旅拍团队,200+服饰可选,在呼籁营地定点旅拍,记录全家最自然的瞬间"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"title": "专业团队",
|
||||||
|
"description": "3管家(车务+房务+客服)+ 1定制师 + 1专属领队,全程只服务您一个家庭"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"title": "研学基地",
|
||||||
|
"description": "黑山头自有蒙古族文化研学基地,孩子在草原上动手体验、学习成长,不是走马观花"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"icpEntity": "内蒙古呼籁文化科技有限公司",
|
||||||
|
"icp": "蒙ICP备2025033324号-2",
|
||||||
|
"icpUrl": "https://beian.miit.gov.cn",
|
||||||
|
"eContract": "所有行程签订正规电子合同"
|
||||||
|
}
|
||||||
187
data/calendar.json
普通文件
187
data/calendar.json
普通文件
@ -0,0 +1,187 @@
|
|||||||
|
{
|
||||||
|
"meta": {
|
||||||
|
"pageTitle": "呼伦贝尔最佳出行月份",
|
||||||
|
"pageIntro": "11年、39000+人次、每一个月份都送过客人出发——哪个月最值得去、哪个月要避开、带孩子选什么时间,我们用真实数据告诉你",
|
||||||
|
"bestTime": "6月~9月",
|
||||||
|
"quickRecommendations": [
|
||||||
|
{
|
||||||
|
"label": "草原最美",
|
||||||
|
"months": "6—8月",
|
||||||
|
"reason": "绿草如茵,天高云淡,那达慕节庆"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"label": "秋色绝景",
|
||||||
|
"months": "9月",
|
||||||
|
"reason": "白桦金黄,草原秋色,摄影圣地"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"label": "错峰推荐",
|
||||||
|
"months": "5月 / 10月",
|
||||||
|
"reason": "人少价优,各有特色,舒适出行"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"label": "冬季探险",
|
||||||
|
"months": "12—2月",
|
||||||
|
"reason": "冰雪那达慕,极寒体验,雪原驰骋"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"months": [
|
||||||
|
{
|
||||||
|
"month": 1,
|
||||||
|
"name": "一月",
|
||||||
|
"season": "winter",
|
||||||
|
"ratingStars": 2,
|
||||||
|
"tempRange": "-30°C ~ -15°C",
|
||||||
|
"weatherFeature": "极寒晴朗,万里冰封,呼伦贝尔最寒冷的月份",
|
||||||
|
"highlights": ["呼伦湖冰雪那达慕", "冰钓体验", "雪地徒步穿越", "零下30度的极寒星空"],
|
||||||
|
"clothingTips": "鹅绒羽绒服(-30°C标准)+ 羊毛打底 + 防风冲锋裤 + 保暖雪地靴",
|
||||||
|
"isPeakSeason": false,
|
||||||
|
"recommendedProducts": ["嗨冰雪", "小蒙马冬季营"],
|
||||||
|
"tagline": "极寒秘境,勇者专属"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"month": 2,
|
||||||
|
"name": "二月",
|
||||||
|
"season": "winter",
|
||||||
|
"ratingStars": 2,
|
||||||
|
"tempRange": "-28°C ~ -10°C",
|
||||||
|
"weatherFeature": "银装素裹,冰雪节庆,气温略有回升但仍属严冬",
|
||||||
|
"highlights": ["冰雪节庆活动", "驯鹿部落探访", "雪地骑马", "室韦冰上体验"],
|
||||||
|
"clothingTips": "同一月装备:鹅绒羽绒全套 + 防水手套 + 护目镜(防雪反光)",
|
||||||
|
"isPeakSeason": false,
|
||||||
|
"recommendedProducts": ["嗨冰雪"],
|
||||||
|
"tagline": "冰雪盛宴,雪原驰骋"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"month": 3,
|
||||||
|
"name": "三月",
|
||||||
|
"season": "spring",
|
||||||
|
"ratingStars": 1,
|
||||||
|
"tempRange": "-15°C ~ 2°C",
|
||||||
|
"weatherFeature": "冬末春初,大风频繁,草原仍是枯黄,不宜出行",
|
||||||
|
"highlights": ["草原雪与枯草交替", "候鸟初归迹象"],
|
||||||
|
"clothingTips": "厚羽绒 + 防风冲锋衣 + 围巾,防大风为主",
|
||||||
|
"isPeakSeason": false,
|
||||||
|
"recommendedProducts": [],
|
||||||
|
"tagline": "大风过境,建议避开"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"month": 4,
|
||||||
|
"name": "四月",
|
||||||
|
"season": "spring",
|
||||||
|
"ratingStars": 2,
|
||||||
|
"tempRange": "-5°C ~ 12°C",
|
||||||
|
"weatherFeature": "春风回暖,草原返青初期,风沙偶有,人迹稀少",
|
||||||
|
"highlights": ["草原返青初期嫩绿", "候鸟大规模归来", "冰消湖泊倒影", "错峰出行几乎无游客"],
|
||||||
|
"clothingTips": "冲锋衣 + 厚毛衣 + 秋裤,防风为主,备防沙巾",
|
||||||
|
"isPeakSeason": false,
|
||||||
|
"recommendedProducts": ["额吉的故乡V9(错峰)"],
|
||||||
|
"tagline": "人少路宽,草原新生"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"month": 5,
|
||||||
|
"name": "五月",
|
||||||
|
"season": "spring",
|
||||||
|
"ratingStars": 4,
|
||||||
|
"tempRange": "5°C ~ 22°C",
|
||||||
|
"weatherFeature": "春风怡人,绿草铺地,野花盛放,气候舒适,游客尚少",
|
||||||
|
"highlights": ["草原野花漫山盛开", "绿草渐浓如毯", "候鸟迁徙壮观", "白天长达16小时"],
|
||||||
|
"clothingTips": "冲锋衣 + 长袖 + 防晒,早晚加绒衣一件",
|
||||||
|
"isPeakSeason": false,
|
||||||
|
"recommendedProducts": ["额吉的故乡V9"],
|
||||||
|
"tagline": "错峰推荐,花开无边"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"month": 6,
|
||||||
|
"name": "六月",
|
||||||
|
"season": "summer",
|
||||||
|
"ratingStars": 5,
|
||||||
|
"tempRange": "15°C ~ 28°C",
|
||||||
|
"weatherFeature": "气候宜人,草原进入翠绿全盛期,是全年最美时节之一",
|
||||||
|
"highlights": ["莫日格勒河嫩绿如画", "一望无际的绿色草原", "骑马体验最舒适", "北疆夏至日长达17小时"],
|
||||||
|
"clothingTips": "薄外套 + 防晒衣 + 长裤,早晚加薄羽绒,备雨衣",
|
||||||
|
"isPeakSeason": true,
|
||||||
|
"recommendedProducts": ["额吉的故乡V9", "小蒙马夏令营"],
|
||||||
|
"tagline": "最美时节,绿意盎然"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"month": 7,
|
||||||
|
"name": "七月",
|
||||||
|
"season": "summer",
|
||||||
|
"ratingStars": 5,
|
||||||
|
"tempRange": "18°C ~ 30°C",
|
||||||
|
"weatherFeature": "全年最热,草原旺季巅峰,那达慕节庆最集中,需提前3个月预订",
|
||||||
|
"highlights": ["那达慕传统节庆", "草原鲜花盛放至极", "额尔古纳湿地最美", "民俗体验最丰富"],
|
||||||
|
"clothingTips": "轻薄长袖 + 防晒 + 备风衣,中午注意防暑,水分补充充足",
|
||||||
|
"isPeakSeason": true,
|
||||||
|
"recommendedProducts": ["额吉的故乡V9", "小蒙马夏令营"],
|
||||||
|
"tagline": "旺季巅峰,提前3个月预订"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"month": 8,
|
||||||
|
"name": "八月",
|
||||||
|
"season": "summer",
|
||||||
|
"ratingStars": 5,
|
||||||
|
"tempRange": "15°C ~ 28°C",
|
||||||
|
"weatherFeature": "夏末渐凉,草原仍绿,早晚清爽宜人,雨后彩虹频现",
|
||||||
|
"highlights": ["草原仍绿意盎然", "早晚清凉舒适", "夕阳草原最美角度", "雨后彩虹奇景常见"],
|
||||||
|
"clothingTips": "薄外套 + 长裤,备一件薄羽绒,早晚温差8-10°C不可忽视",
|
||||||
|
"isPeakSeason": true,
|
||||||
|
"recommendedProducts": ["额吉的故乡V9", "小蒙马夏令营"],
|
||||||
|
"tagline": "旺季尾声,舒爽清凉"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"month": 9,
|
||||||
|
"name": "九月",
|
||||||
|
"season": "autumn",
|
||||||
|
"ratingStars": 5,
|
||||||
|
"tempRange": "5°C ~ 20°C",
|
||||||
|
"weatherFeature": "草原金秋,色彩由绿转金,白桦林绝景,摄影爱好者公认圣地",
|
||||||
|
"highlights": ["白桦林一片金黄", "草原由绿转秋色", "额尔古纳湿地倒影绝美", "牧民秋季转场壮观"],
|
||||||
|
"clothingTips": "冲锋衣 + 毛衣,早晚加薄羽绒,温差显著需分层穿搭",
|
||||||
|
"isPeakSeason": true,
|
||||||
|
"recommendedProducts": ["游牧的森林(秋季)"],
|
||||||
|
"tagline": "秋景无双,摄影圣地"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"month": 10,
|
||||||
|
"name": "十月",
|
||||||
|
"season": "autumn",
|
||||||
|
"ratingStars": 3,
|
||||||
|
"tempRange": "-5°C ~ 10°C",
|
||||||
|
"weatherFeature": "深秋落叶,气温骤降,草原苍茫辽阔,初雪可能出现",
|
||||||
|
"highlights": ["白桦林落叶金色", "大雁南飞壮观景象", "霜降草原别样美", "初雪概率渐增"],
|
||||||
|
"clothingTips": "厚羽绒 + 毛衣 + 防风裤,做好充分保暖准备",
|
||||||
|
"isPeakSeason": false,
|
||||||
|
"recommendedProducts": ["游牧的森林(秋季)"],
|
||||||
|
"tagline": "秋尽初冬,苍茫别致"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"month": 11,
|
||||||
|
"name": "十一月",
|
||||||
|
"season": "winter",
|
||||||
|
"ratingStars": 2,
|
||||||
|
"tempRange": "-20°C ~ -5°C",
|
||||||
|
"weatherFeature": "初冬降雪,河流结冰,草原进入冰封准备期,游客稀少",
|
||||||
|
"highlights": ["初雪草原独特美景", "河流开始结冰", "人迹罕至的静谧旷野"],
|
||||||
|
"clothingTips": "厚羽绒全套 + 防风裤 + 保暖靴,防寒为第一优先",
|
||||||
|
"isPeakSeason": false,
|
||||||
|
"recommendedProducts": [],
|
||||||
|
"tagline": "初冬雪景,静谧独特"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"month": 12,
|
||||||
|
"name": "十二月",
|
||||||
|
"season": "winter",
|
||||||
|
"ratingStars": 3,
|
||||||
|
"tempRange": "-30°C ~ -15°C",
|
||||||
|
"weatherFeature": "冰雪全封,冬景壮美,冰雪活动赛季正式开启",
|
||||||
|
"highlights": ["呼伦湖完全冰封", "冰雪那达慕开幕", "雾凇奇景绽放", "冰钓与雪地越野"],
|
||||||
|
"clothingTips": "零下30°C专业装备:鹅绒 + 羊毛打底 + 防风冲锋套装",
|
||||||
|
"isPeakSeason": false,
|
||||||
|
"recommendedProducts": ["嗨冰雪", "小蒙马冬季营"],
|
||||||
|
"tagline": "壮美冬景,冰雪探险"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
50
data/contact.json
普通文件
50
data/contact.json
普通文件
@ -0,0 +1,50 @@
|
|||||||
|
{
|
||||||
|
"channels": [
|
||||||
|
{
|
||||||
|
"type": "wechat",
|
||||||
|
"label": "微信客服",
|
||||||
|
"value": "hulai1814",
|
||||||
|
"qrImage": "/images/contact/qrcode-wechat.jpg",
|
||||||
|
"primary": true,
|
||||||
|
"description": "添加微信,一对一沟通行程需求"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "miniprogram",
|
||||||
|
"label": "预订小程序",
|
||||||
|
"value": "呼籁旅行",
|
||||||
|
"qrImage": "/images/qrcode-miniprogram.png",
|
||||||
|
"description": "微信扫码进入小程序,在线了解和预订"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "phone",
|
||||||
|
"label": "电话咨询",
|
||||||
|
"value": "4000881814",
|
||||||
|
"description": "工作时间9:00-21:00,节假日不休"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "address",
|
||||||
|
"label": "公司地址",
|
||||||
|
"value": "内蒙古自治区呼伦贝尔市海拉尔区奋斗镇学府路煤校3号楼",
|
||||||
|
"description": "欢迎来公司实地考察"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "email",
|
||||||
|
"label": "商务合作",
|
||||||
|
"value": "bd@1814.love",
|
||||||
|
"description": "媒体合作、异业合作请邮件联系"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "complaint",
|
||||||
|
"label": "投诉建议",
|
||||||
|
"value": "tousu@1814.love",
|
||||||
|
"description": "您的反馈是我们进步的动力,24小时内回复"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "hr",
|
||||||
|
"label": "加入我们",
|
||||||
|
"value": "hr@1814.love",
|
||||||
|
"description": "期待热爱旅行的你,简历请投递至此邮箱"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"securityNotice": "请认准官方渠道,谨防假冒。所有行程均签订正规电子合同,您的权益受法律保护。"
|
||||||
|
}
|
||||||
257
data/courses.json
普通文件
257
data/courses.json
普通文件
@ -0,0 +1,257 @@
|
|||||||
|
{
|
||||||
|
"modules": [
|
||||||
|
{
|
||||||
|
"id": "ecology",
|
||||||
|
"icon": "🌿",
|
||||||
|
"name": "草原生态课",
|
||||||
|
"ageRange": "3-12岁",
|
||||||
|
"duration": "每次90分钟",
|
||||||
|
"shortDesc": "认识草原上的植物、昆虫、鸟类,理解食物链和生态系统的基本关系。",
|
||||||
|
"activities": [
|
||||||
|
"植物标本采集与图鉴比对(仅采集枯叶,不伤害活株)",
|
||||||
|
"夜观星空:认识北斗七星和银河,了解游牧民如何用星星导航",
|
||||||
|
"草原土壤采样:观察不同深度的土壤颜色和生物",
|
||||||
|
"鸟类观察:用望远镜记录草原鸟类活动"
|
||||||
|
],
|
||||||
|
"objectives": [
|
||||||
|
"能识别5种以上草原常见植物(如羊草、针茅、狼毒花)",
|
||||||
|
"了解草原食物链:草→鼠→鹰的完整链条",
|
||||||
|
"理解游牧民与草原之间的共生关系",
|
||||||
|
"培养对自然生命的敬畏与保护意识"
|
||||||
|
],
|
||||||
|
"philosophy": "生态教育不是在课堂里讲生物课,而是让孩子蹲下来,安静地看一只草原蚂蚱如何生活。"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "horse",
|
||||||
|
"icon": "🐎",
|
||||||
|
"name": "马术体验课",
|
||||||
|
"ageRange": "4-12岁",
|
||||||
|
"duration": "每次60分钟",
|
||||||
|
"shortDesc": "从认识马、与马建立信任,到基础骑乘,体验游牧民族与马之间的独特情感纽带。",
|
||||||
|
"activities": [
|
||||||
|
"认识马:马的身体结构、情绪表达方式、安全距离",
|
||||||
|
"与马建立信任:喂草、轻抚、眼神交流练习",
|
||||||
|
"基础骑乘体验:领队牵马在指定草地范围内步行骑行",
|
||||||
|
"马术文化课:蒙古族马文化、那达慕赛马传统讲解"
|
||||||
|
],
|
||||||
|
"objectives": [
|
||||||
|
"了解蒙古马的品种特点和历史文化地位",
|
||||||
|
"掌握马匹日常照料基础:喂食、刷毛、缰绳系法",
|
||||||
|
"完成有领队陪同的基础骑乘(步行圈乘)",
|
||||||
|
"建立对动物的尊重与责任感"
|
||||||
|
],
|
||||||
|
"philosophy": "马是蒙古族最亲密的伙伴。让孩子第一次坐上马背,是与这片草原文明的真实连接。"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "nomad",
|
||||||
|
"icon": "🏕️",
|
||||||
|
"name": "游牧文化课",
|
||||||
|
"ageRange": "5-12岁",
|
||||||
|
"duration": "每次120分钟",
|
||||||
|
"shortDesc": "走进蒙古包,跟牧民家庭学习搭建、拆卸、日常生活,体验真实的游牧文化。",
|
||||||
|
"activities": [
|
||||||
|
"蒙古包DIY:亲手参与搭建小号教学蒙古包",
|
||||||
|
"牧民厨房:在牧民阿妈指导下制作奶茶和炒米",
|
||||||
|
"游牧乐器体验:马头琴听讲和简单节奏感知",
|
||||||
|
"传统服装体验:穿上蒙古袍,了解每个装饰的含义"
|
||||||
|
],
|
||||||
|
"objectives": [
|
||||||
|
"了解蒙古包的结构和搭建原理(与自然的关系)",
|
||||||
|
"体验游牧生活的基本技能:挤奶、制奶茶、晾奶豆腐",
|
||||||
|
"理解游牧文化中「迁徙」的生态智慧",
|
||||||
|
"尊重并欣赏不同民族的生活方式"
|
||||||
|
],
|
||||||
|
"philosophy": "游牧文明是人类与自然最和谐的相处方式之一。让孩子亲身体验,比任何课本都更有说服力。"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "art",
|
||||||
|
"icon": "🎨",
|
||||||
|
"name": "自然艺术课",
|
||||||
|
"ageRange": "3-12岁",
|
||||||
|
"duration": "每次90分钟",
|
||||||
|
"shortDesc": "用草原上捡到的材料创作艺术,让孩子用创意表达对自然的感受。",
|
||||||
|
"activities": [
|
||||||
|
"大地艺术:在草地上用天然材料拼出图案",
|
||||||
|
"自然笔记:用画笔记录今天观察到的一种植物或动物",
|
||||||
|
"石头彩绘:将草原上拾到的石头画成小动物",
|
||||||
|
"草编基础:学习蒙古族传统草编工艺的简单入门"
|
||||||
|
],
|
||||||
|
"objectives": [
|
||||||
|
"用自然材料(石头、枯草、羽毛)完成一件艺术作品",
|
||||||
|
"学会用线条和颜色记录自然观察(自然笔记)",
|
||||||
|
"理解「取之自然、用之有度」的创作伦理",
|
||||||
|
"建立个人审美和创意表达能力"
|
||||||
|
],
|
||||||
|
"philosophy": "最好的画布就是大地。最好的颜料就是孩子对这片草原的情感。"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "team",
|
||||||
|
"icon": "🤝",
|
||||||
|
"name": "团队成长课",
|
||||||
|
"ageRange": "6-12岁",
|
||||||
|
"duration": "每次120分钟",
|
||||||
|
"shortDesc": "通过草原场景中的团队挑战,培养沟通、合作和领导力。",
|
||||||
|
"activities": [
|
||||||
|
"草原寻宝:分组完成地图导航和线索解谜任务",
|
||||||
|
"搭建营地:6人小组在规定时间内搭建遮蔽所",
|
||||||
|
"信任盲走:蒙眼在队友引导下完成草地穿越",
|
||||||
|
"故事圈:每晚围营火分享今天最有挑战的时刻"
|
||||||
|
],
|
||||||
|
"objectives": [
|
||||||
|
"在陌生环境中主动建立与同伴的信任",
|
||||||
|
"学会在团队任务中有效分工和沟通",
|
||||||
|
"体验挫折并找到解决问题的方法",
|
||||||
|
"认识自己在团队中的角色和贡献"
|
||||||
|
],
|
||||||
|
"philosophy": "草原没有捷径,但有方向。团队成长课教的不是竞争,是如何在未知中互相支持。"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "lnt",
|
||||||
|
"icon": "🌍",
|
||||||
|
"name": "LNT无痕环保课",
|
||||||
|
"ageRange": "5-12岁",
|
||||||
|
"duration": "每次60分钟",
|
||||||
|
"shortDesc": "学习「Leave No Trace」无痕山野七大原则,培养真正的环保行动力。",
|
||||||
|
"activities": [
|
||||||
|
"无痕营地实践:检查营地,发现并修复对环境的微小影响",
|
||||||
|
"垃圾分类挑战:在草原场景中完成垃圾分类和正确处理",
|
||||||
|
"足迹科学:测量并计算小组活动对草地的踩踏面积",
|
||||||
|
"环保承诺卡:写下回家后的一个环保行动并拍照留念"
|
||||||
|
],
|
||||||
|
"objectives": [
|
||||||
|
"了解LNT无痕山野七大原则及其原因",
|
||||||
|
"掌握草原环境中的无痕宿营实践方法",
|
||||||
|
"理解人类活动对草原生态的实际影响",
|
||||||
|
"回家后能把LNT理念传递给身边的人"
|
||||||
|
],
|
||||||
|
"philosophy": "最好的环保教育不是告诉孩子'不能做什么',而是让他们亲眼看到,亲手感受,然后自己做出选择。"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"ageGroups": [
|
||||||
|
{
|
||||||
|
"id": "toddler",
|
||||||
|
"emoji": "🐣",
|
||||||
|
"focus": "感知与好奇",
|
||||||
|
"label": "探索组 3-5岁",
|
||||||
|
"headline": "用感官探索草原的一切",
|
||||||
|
"highlights": [
|
||||||
|
"父母全程陪同,亲子共探",
|
||||||
|
"以触摸、嗅觉、听觉为主要学习方式",
|
||||||
|
"每次活动不超过45分钟,符合专注力发展",
|
||||||
|
"强调安全感和情绪表达,不强迫参与任何活动",
|
||||||
|
"结营获得个人草原探索小书"
|
||||||
|
],
|
||||||
|
"description": "3-5岁的孩子处于感知世界的黄金期。这个年龄段的课程以感官体验为主——摸、闻、看、听,不强调知识记忆,强调情感连接。父母全程陪同,亲子共同探索。",
|
||||||
|
"recommendedModules": [
|
||||||
|
"ecology",
|
||||||
|
"art",
|
||||||
|
"lnt"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "child",
|
||||||
|
"emoji": "🌟",
|
||||||
|
"focus": "体验与探索",
|
||||||
|
"label": "探险组 6-8岁",
|
||||||
|
"headline": "在探险中建立自信与好奇",
|
||||||
|
"highlights": [
|
||||||
|
"每天1个独立完成的小任务",
|
||||||
|
"开始学习简单的自然科学观察方法",
|
||||||
|
"基础马术体验(有领队全程陪同)",
|
||||||
|
"参与游牧文化DIY活动",
|
||||||
|
"结营获得个人成长记录手册和技能徽章"
|
||||||
|
],
|
||||||
|
"description": "6-8岁是自信心和独立性快速发展的阶段。探险组的课程设计鼓励孩子在安全范围内独立完成小任务,并开始理解自然系统背后的逻辑。每天有明确的小挑战和成就感积累。",
|
||||||
|
"recommendedModules": [
|
||||||
|
"ecology",
|
||||||
|
"horse",
|
||||||
|
"nomad",
|
||||||
|
"art",
|
||||||
|
"lnt"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "teen",
|
||||||
|
"emoji": "🏔️",
|
||||||
|
"focus": "思考与领导",
|
||||||
|
"label": "领袖组 9-12岁",
|
||||||
|
"headline": "从体验者到探索者的转变",
|
||||||
|
"highlights": [
|
||||||
|
"参与团队领导力挑战项目",
|
||||||
|
"完成一份完整的草原生态观察报告",
|
||||||
|
"深度游牧文化课:与牧民家庭进行真实交流",
|
||||||
|
"LNT实地项目:为营地制定一份环保改进方案",
|
||||||
|
"结营获得自然探索认证和个人成长评估报告"
|
||||||
|
],
|
||||||
|
"description": "9-12岁的孩子已经具备抽象思维能力,能够理解生态系统、文化传承等复杂概念。领袖组课程加入更多挑战性任务、团队决策场景和深度文化探究,鼓励孩子提问和批判性思考。",
|
||||||
|
"recommendedModules": [
|
||||||
|
"ecology",
|
||||||
|
"horse",
|
||||||
|
"nomad",
|
||||||
|
"team",
|
||||||
|
"lnt"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"faq": [
|
||||||
|
{
|
||||||
|
"a": "完全安全。马术课使用的是经过专门训练的温顺蒙古马,全程由有5年以上经验的专业领队牵马陪同,孩子不会独自骑行。4岁以上孩子即可参与步行体验,强调与马建立信任,不强调技巧。活动前有完整的安全讲解和装备检查。",
|
||||||
|
"q": "孩子没有骑过马,马术课安全吗?"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"a": "大部分课程在户外进行,这是我们设计的核心。天气预备方案:小雨不影响户外活动(雨天草原更美),中雨以上会转移到蒙古包室内进行游牧文化课、自然艺术课等室内模块。我们始终保证每天的课程质量,而不是简单'取消'。",
|
||||||
|
"q": "课程全部是户外吗?下雨天怎么办?"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"a": "请在报名时如实填写孩子的过敏情况。我们的医疗联络人会根据营期草原的具体植被情况给出评估意见。通常7月下旬至8月中旬是花粉高峰期,建议过敏体质孩子选择6月或9月的营期,同时随行携带必备药物。",
|
||||||
|
"q": "孩子有严重花粉过敏,能参加吗?"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"a": "取决于年龄段。3-5岁探索组需要家长全程陪同参与。6-8岁探险组和9-12岁领袖组,我们建议孩子独立参营(父母在附近的营地等待),这有助于孩子建立真正的自信和独立性——但家长也可以选择陪同,我们有亲子共营版本。",
|
||||||
|
"q": "父母可以全程陪同吗?还是需要独立参营?"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"a": "每期最多16个孩子,确保每4个孩子配备1名自然教育导师,同时配备1名当地专业领队。师生比不超过1:4,这是我们的底线。小班制是小蒙马研学的核心承诺之一,我们不会为了多收费而扩大营地规模。",
|
||||||
|
"q": "每期招多少孩子?师生比例是多少?"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"philosophy": {
|
||||||
|
"headline": "在自然中学习,在游戏中成长",
|
||||||
|
"tagline": "草原是最好的教室,大自然是最好的老师",
|
||||||
|
"description": "呼籁小蒙马研学课程以LNT(Leave No Trace)自然教育理念为核心,结合呼伦贝尔草原、森林、湿地等多种生态系统,设计了覆盖3-15岁全年龄段的系统化自然教育课程体系。每门课程均由自然教育专家和儿童教育专家共同开发,注重动手实践、启发式引导和深度体验。",
|
||||||
|
"values": [
|
||||||
|
{
|
||||||
|
"label": "自然启蒙",
|
||||||
|
"desc": "在真实的草原环境中建立对自然的认知和情感连接"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"label": "动手实践",
|
||||||
|
"desc": "以行动为中心的学习,不只是看和听,而是真正去做"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"label": "年龄分层",
|
||||||
|
"desc": "针对不同年龄段认知特点,定制学习深度和表达方式"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"label": "家庭共学",
|
||||||
|
"desc": "父母与孩子共同参与,在旅途中建立珍贵的家庭记忆"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"instructors": {
|
||||||
|
"placeholder": [
|
||||||
|
{
|
||||||
|
"name": "自然教育师(招募中)",
|
||||||
|
"title": "LNT认证自然教育师",
|
||||||
|
"credentials": "LNT认证 · 儿童自然教育专业培训",
|
||||||
|
"bio": "我们正在招募有热情的自然教育师加入小蒙马团队,如果你热爱草原、热爱孩子,欢迎联系我们。"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "草原向导 · 牧民老师",
|
||||||
|
"title": "本地牧民导师",
|
||||||
|
"credentials": "世居牧民家庭 · 草原生活实践者",
|
||||||
|
"bio": "来自呼伦贝尔的牧民老师,用最真实的草原生活经验教孩子认识马、牛、羊,以及草原上的动植物。"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
91
data/customize.json
普通文件
91
data/customize.json
普通文件
@ -0,0 +1,91 @@
|
|||||||
|
{
|
||||||
|
"trustStats": [],
|
||||||
|
"durations": [
|
||||||
|
{
|
||||||
|
"label": "4天3晚(精华版)",
|
||||||
|
"value": "4天3晚"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"label": "5天4晚(经典版)",
|
||||||
|
"value": "5天4晚"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"label": "6天5晚(亲子/探索版)",
|
||||||
|
"value": "6天5晚"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"label": "7天6晚(深度/狂野版)",
|
||||||
|
"value": "7天6晚"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"activities": [
|
||||||
|
{
|
||||||
|
"label": "亲子活动",
|
||||||
|
"value": "亲子活动"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"label": "旅拍",
|
||||||
|
"value": "旅拍"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"label": "骑马",
|
||||||
|
"value": "骑马"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"label": "蒙古包住宿",
|
||||||
|
"value": "蒙古包住宿"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"label": "草原露营",
|
||||||
|
"value": "草原露营"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"label": "私人牧场",
|
||||||
|
"value": "私人牧场"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"budgets": [
|
||||||
|
{
|
||||||
|
"label": "5,000 元以下",
|
||||||
|
"value": "5000元以下"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"label": "5,000 — 8,000 元",
|
||||||
|
"value": "5000-8000元"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"label": "8,000 — 12,000 元",
|
||||||
|
"value": "8000-12000元"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"label": "12,000 元以上",
|
||||||
|
"value": "12000元以上"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"label": "不限预算",
|
||||||
|
"value": "不限预算"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"process": [
|
||||||
|
{
|
||||||
|
"desc": "告诉我们几口人、想玩几天、有没有特别的期待",
|
||||||
|
"title": "填写需求"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"desc": "专属定制师通过微信联系您,0元咨询费",
|
||||||
|
"title": "2小时内回复"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"desc": "行程、住宿、费用明细一次说清,所有细节写进合同",
|
||||||
|
"title": "拿到专属方案"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"desc": "一家一单一车,全程只服务你们一个家庭",
|
||||||
|
"title": "出发,只属于你家"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"contact": {
|
||||||
|
"tip": "工作时间 09:00 — 21:00,节假日不休",
|
||||||
|
"wechat": "扫码添加微信"
|
||||||
|
}
|
||||||
|
}
|
||||||
286
data/destinations-detail.json
普通文件
286
data/destinations-detail.json
普通文件
@ -0,0 +1,286 @@
|
|||||||
|
{
|
||||||
|
"destinations": [
|
||||||
|
{
|
||||||
|
"id": "moriguole",
|
||||||
|
"name": "莫日格勒河",
|
||||||
|
"subtitle": "天下第一曲水 · 老舍笔下的草原河曲",
|
||||||
|
"tag": "草原核心",
|
||||||
|
"description": "1961年老舍来这儿考察,脱口而出「天下第一曲水」,这名号就此传开。河本身不宽,有些河段窄到你觉得一步就能跨过去,但它在三百公里的草原上拐出了上千个弯。从牧云山顶或断崖制高点往下看,河道的S弯一层套一层,两岸吃草的牛羊像散落的棋子,那种辽阔感是照片拍不出来的。呼籁旅行的自营营地就扎在莫日格勒河畔,早起出帐篷两分钟走到河边,晨雾配合日出光线,出片率极高。草原深处没手机信号,跟着我们的车队走才不会迷路。",
|
||||||
|
"highlights": [
|
||||||
|
"牧云山顶/断崖俯瞰河曲全景——目前公认最佳机位,比金帐汗那边角度好",
|
||||||
|
"沿河岸骑马漫步,牛羊就在身边,比黑山头骑马更有草原腹地的感觉",
|
||||||
|
"呼籁自营营地入住,河边BBQ、旅拍、看星空一条龙",
|
||||||
|
"清晨河面起雾时拍大片,日出前后1小时是黄金时间",
|
||||||
|
"穿越草原腹地到营地的路本身就是体验——便道、牛群、无信号"
|
||||||
|
],
|
||||||
|
"bestSeason": {
|
||||||
|
"primary": "7月-8月"
|
||||||
|
},
|
||||||
|
"heroImage": "/images/destinations/moriguole.jpg",
|
||||||
|
"seasons": [
|
||||||
|
"summer"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "eergunashire",
|
||||||
|
"name": "额尔古纳湿地",
|
||||||
|
"subtitle": "亚洲第一湿地 · 根河的Ω形大弯",
|
||||||
|
"tag": "生态景观",
|
||||||
|
"description": "号称「亚洲第一湿地」,从额尔古纳市区开车3公里就到,不算远。核心体验就是爬到海拔720米的主峰观景台往下看——根河拐出的一个完美Ω形大弯和一个形状像树叶的湖心岛,绿色铺到天际线,河道像大地的血管蜿蜒其中。说实话,走到山顶那一刻确实被震住了。木栈道下山一路视角不断变化,每一段都值得停下来。秋季9月下旬到10月初来最震撼,湿地从绿变黄变红,颜色层次极其丰富。",
|
||||||
|
"highlights": [
|
||||||
|
"登顶观景台看Ω形河弯和叶形湖心岛——所有宣传照都是这个角度",
|
||||||
|
"木栈道下山一路看湿地层次变化,每段视角都不同",
|
||||||
|
"秋季色彩爆发——9月下旬到10月初,黄红绿三色交织",
|
||||||
|
"早晨6点前到,雾气在河面和树丛间弥漫,比中午去好十倍",
|
||||||
|
"河里有鱼、岸边有水鸟,运气好能看到丹顶鹤"
|
||||||
|
],
|
||||||
|
"bestSeason": {
|
||||||
|
"primary": "9月中旬-10月初"
|
||||||
|
},
|
||||||
|
"heroImage": "/images/destinations/eergunashire.jpg",
|
||||||
|
"seasons": [
|
||||||
|
"summer"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "baihualin",
|
||||||
|
"name": "白桦林",
|
||||||
|
"subtitle": "国内面积最大的纯生白桦林 · 亲子拍照圣地",
|
||||||
|
"tag": "森林体验",
|
||||||
|
"description": "在额尔古纳到恩和的省道边上,将近1000公顷的纯生白桦林,国内面积最大的。树干白得发亮,阳光透过树冠洒下来确实好看。景区开发得比较成熟,分了好几个主题区,不算原生态体验,但胜在拍照出片率高,带孩子来也有地方玩。呼籁安排的行程里,白桦林有非遗传承人现场教桦树皮画,按年龄分层体验——这个才是这里最值得的环节。秋季9月底白桦叶变金黄,配白色树干,随手拍都是大片。",
|
||||||
|
"highlights": [
|
||||||
|
"非遗传承人现场教桦树皮画,按孩子年龄分层体验",
|
||||||
|
"空中栈道——架在树冠层的步道,从上往下看白桦林感觉不一样",
|
||||||
|
"驯鹿苑——景区养了驯鹿可以近距离喂食,孩子最爱的环节",
|
||||||
|
"秋季金黄白桦叶配白色树干,随手拍都是大片",
|
||||||
|
"全地形越野车穿越白桦林——往返12公里自由驰骋"
|
||||||
|
],
|
||||||
|
"bestSeason": {
|
||||||
|
"primary": "9月下旬-10月初"
|
||||||
|
},
|
||||||
|
"heroImage": "/images/destinations/baihualin.jpg",
|
||||||
|
"seasons": [
|
||||||
|
"summer",
|
||||||
|
"autumn"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "enhe-shiwei",
|
||||||
|
"name": "恩和·室韦",
|
||||||
|
"subtitle": "华俄后裔的木刻楞村落 · 边境安宁小镇",
|
||||||
|
"tag": "民族文化",
|
||||||
|
"description": "两个村子离得不远但气质不同。室韦开发早,主街热闹,商业化明显;恩和安静得多,蒙语意思就是「和平安宁」,入选了中国传统村落名录。居民都是华俄后裔,长着混血面孔说着东北话,住的是俄式木刻楞房子,冬暖夏凉。最有意思的体验是去列巴坊看大妈现烤列巴面包,配上自家腌的酸黄瓜和蓝莓酱,再喝杯俄式果茶。呼籁的行程安排在恩和骑马穿越——穿越草原、湿地、森林、河流四种地形,和其他地方骑马感受完全不同。",
|
||||||
|
"highlights": [
|
||||||
|
"恩和沉浸式骑马穿越——草原、湿地、森林、河流四种地形",
|
||||||
|
"木刻楞民居——原木垒成的俄式传统木屋,走进去能闻到木头香",
|
||||||
|
"热尼亚列巴坊手作体验——看列巴烤制全过程,现烤现吃",
|
||||||
|
"额尔古纳河边看对岸俄罗斯——河对面就是俄罗斯村庄",
|
||||||
|
"画套娃、做列巴、品俄式果茶——沉浸式文化体验"
|
||||||
|
],
|
||||||
|
"bestSeason": {
|
||||||
|
"primary": "7月-8月"
|
||||||
|
},
|
||||||
|
"heroImage": "/images/destinations/shiwei.jpg",
|
||||||
|
"seasons": [
|
||||||
|
"summer",
|
||||||
|
"autumn"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "heishantou",
|
||||||
|
"name": "黑山头",
|
||||||
|
"subtitle": "呼伦贝尔骑马首选地 · 边境日落",
|
||||||
|
"tag": "骑马体验",
|
||||||
|
"description": "黑山头是呼伦贝尔公认的骑马最佳地点,原因很简单——这边草原特别开阔平坦,视野好,马场多且正规。不是景区里牵着走一小圈的那种,而是马倌带路你自己控马在草原上跑,大圈下来一个多小时。傍晚一定要去日落山,看夕阳把额尔古纳河和整片草原湿地染成金色。呼籁的探索版行程安排了恩和+黑山头两次骑马——白桦林间漫步和草原驰骋完全不同的体验。",
|
||||||
|
"highlights": [
|
||||||
|
"草原骑马穿越——自己控马不是牵马,大圈1-1.5小时真实骑行",
|
||||||
|
"日落山观日落——看额尔古纳河湿地被夕阳染金,呼伦贝尔最美日落之一",
|
||||||
|
"中俄边防公路——左边是额尔古纳河和俄罗斯,右边是无边草原,路本身就是景",
|
||||||
|
"ATV穿越湿地——秋季五彩湿地中驾驶全地形车穿行",
|
||||||
|
"牧户家访——进蒙古包挤牛奶、喂小羊、喝奶茶"
|
||||||
|
],
|
||||||
|
"bestSeason": {
|
||||||
|
"primary": "7月-8月"
|
||||||
|
},
|
||||||
|
"heroImage": "/images/destinations/heishantou.jpg",
|
||||||
|
"seasons": [
|
||||||
|
"summer",
|
||||||
|
"autumn"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "manzhouli",
|
||||||
|
"name": "满洲里",
|
||||||
|
"subtitle": "中俄蒙三国交汇的异域边城",
|
||||||
|
"tag": "边境文化",
|
||||||
|
"description": "满洲里不像一个中国城市,更像是把俄罗斯小城搬了一半过来。街上到处是俄文招牌,餐厅菜单有俄文版,路上能碰到真正的俄罗斯人来采购。套娃广场那个巨型套娃建筑里面其实是个酒店,周围大大小小的套娃到了晚上全亮灯,效果很梦幻。国门景区能看到对面俄罗斯的后贝加尔斯克小镇。带孩子来最好——满洲里是少有的能让小孩主动问问题的地方:那个大套娃里面住着谁?对面河那边是哪个国家?",
|
||||||
|
"highlights": [
|
||||||
|
"套娃广场夜景——晚上亮灯后整个广场变成童话世界,白天别去",
|
||||||
|
"国门景区——第五代国门,一侧中国一侧俄罗斯",
|
||||||
|
"俄罗斯大马戏——驯兽、空中飞人,欧式巴洛克风格剧场",
|
||||||
|
"套娃酒店入住——冬季北线行程安排住这里,体验异域风情",
|
||||||
|
"俄式餐厅——红菜汤和手工列巴味道正宗"
|
||||||
|
],
|
||||||
|
"bestSeason": {
|
||||||
|
"primary": "6月-8月"
|
||||||
|
},
|
||||||
|
"heroImage": "/images/destinations/manzhouli.jpg",
|
||||||
|
"seasons": [
|
||||||
|
"summer",
|
||||||
|
"autumn",
|
||||||
|
"winter"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "aershan",
|
||||||
|
"name": "阿尔山国家森林公园",
|
||||||
|
"subtitle": "AAAAA级 · 火山天池群 · 温泉之都",
|
||||||
|
"tag": "地质奇观",
|
||||||
|
"description": "阿尔山不是一座山,是一座小城,蒙语意思是「热的圣水」,说的就是温泉。森林公园是AAAAA级加世界地质公园,面积10万公顷,里面有50多座火山锥、19个火山口、8个天池。一天根本逛不完,门票可以两天内重复进园。必须去的是驼峰岭天池——火山口积水形成的湖,蓝得不真实,需要爬山但不高。杜鹃湖也值得,月牙形湖面春天周围开满杜鹃花。冬季的阿尔山是嗨冰雪线路的核心——白狼峰日出、不冻河、百里雾凇画廊、泡温泉,都安排在这。",
|
||||||
|
"highlights": [
|
||||||
|
"驼峰岭天池——阿尔山天池群中最大最深的,蓝得不真实",
|
||||||
|
"白狼峰日出+泼水成冰——冬季必玩,零下三十度的视觉冲击",
|
||||||
|
"不冻河——零下几十度依然流淌,岸边雾凇配河面蒸腾雾气",
|
||||||
|
"石塘林——火山喷发岩浆凝固的石林,像外星地表",
|
||||||
|
"ATV卡丁车森林穿越——在林间小道上驾驶全地形车"
|
||||||
|
],
|
||||||
|
"bestSeason": {
|
||||||
|
"primary": "9月中旬(秋色)"
|
||||||
|
},
|
||||||
|
"heroImage": "/images/destinations/aershan.jpg",
|
||||||
|
"seasons": [
|
||||||
|
"autumn",
|
||||||
|
"winter"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "shiwei",
|
||||||
|
"name": "室韦·恩和",
|
||||||
|
"subtitle": "中国俄罗斯族第一村 · 边境秘境",
|
||||||
|
"tag": "民族文化",
|
||||||
|
"description": "室韦和恩和是额尔古纳河畔两座毗邻的边境小村,也是中国俄罗斯族聚居最集中的地方,被誉为「中国俄罗斯族第一村」。这里的居民多为中俄混血后裔,至今保留着俄罗斯族的生活习俗:木刻楞民居、手工列巴面包、俄式点心……走进村子,仿佛置身于西伯利亚的某个小村落。额尔古纳河在村前流淌,对岸便是俄罗斯,中俄两国鸡犬相闻的奇特景象在这里真实上演。室韦的夜晚宁静安详,星空灿烂如宝石,是厌倦城市喧嚣、寻求深度旅行体验的家庭的理想目的地。",
|
||||||
|
"highlights": [
|
||||||
|
"参观俄罗斯族木刻楞民居,了解中俄混血文化的独特生活方式",
|
||||||
|
"品尝手工列巴和俄式点心,体验正宗俄罗斯族传统美食",
|
||||||
|
"额尔古纳河边远眺对岸俄罗斯,感受中俄边境的历史沧桑",
|
||||||
|
"室韦星空观测,远离城市光污染的绝佳观星胜地",
|
||||||
|
"骑马穿越边境草原,感受额尔古纳河流域独特的自然风光"
|
||||||
|
],
|
||||||
|
"bestSeason": {
|
||||||
|
"primary": "7月-8月",
|
||||||
|
"secondary": "9月",
|
||||||
|
"description": "夏季绿意最浓,骑马和额尔古纳河景色最佳。9月秋色开始,边防公路两侧层林尽染。"
|
||||||
|
},
|
||||||
|
"heroImage": "/images/destinations/shiwei.jpg",
|
||||||
|
"seasons": [
|
||||||
|
"summer",
|
||||||
|
"autumn"
|
||||||
|
],
|
||||||
|
"tips": [
|
||||||
|
"室韦开发较早商业气息浓,恩和更安静有生活气息,推荐两个都去",
|
||||||
|
"额尔古纳河边可以望对岸俄罗斯村庄,注意不要越境",
|
||||||
|
"列巴面包上午去买,下午基本售罄",
|
||||||
|
"夜里气温低,即使夏天也要带薄外套"
|
||||||
|
],
|
||||||
|
"relatedProducts": [
|
||||||
|
"v9-5d4n",
|
||||||
|
"v9-6d5n-family",
|
||||||
|
"v9-7d6n-family",
|
||||||
|
"v9-7d6n-wild"
|
||||||
|
],
|
||||||
|
"seo": {
|
||||||
|
"title": "室韦·恩和旅游攻略 - 中国俄罗斯族第一村 | 呼籁旅行",
|
||||||
|
"description": "室韦恩和是华俄后裔聚居的边境秘境,木刻楞民居、手工列巴、额尔古纳河边望俄罗斯。呼籁旅行带你深度体验这片独特的中俄边境风情。",
|
||||||
|
"keywords": "室韦,恩和,中国俄罗斯族,木刻楞,列巴,额尔古纳河,边境旅游"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "daxinganling",
|
||||||
|
"name": "大兴安岭·莫尔道嘎",
|
||||||
|
"subtitle": "中国最后一片寒温带原始森林 · 森林小火车",
|
||||||
|
"tag": "森林探秘",
|
||||||
|
"description": "莫尔道嘎国家森林公园是中国最后一片寒温带明亮针叶原始森林,森林覆盖率94.97%。最大的卖点是森林观光小火车——三节车厢全程9.87公里,时速15公里,绕公园一圈大约一个半小时。小火车穿行在林海里确实有童话感,沿途设了几个站可以下车拍照。最后一站有野生小松鼠和可以喂的小鹿,孩子特别开心。呼籁夏季亲子版行程安排了森林小火车+兴安神鹿园喂驯鹿,从草原走进森林,一路风景完全不同。",
|
||||||
|
"highlights": [
|
||||||
|
"森林小火车穿行原始森林——全程9.87公里,每站可下车游览拍照",
|
||||||
|
"兴安神鹿园零距离喂驯鹿——大兴安岭深处的亲子亮点",
|
||||||
|
"樟子松林观景台——从这里看出去就是无尽的「林海」",
|
||||||
|
"秋季层林尽染——9月底到10月初目光所及都是色彩",
|
||||||
|
"原始森林徒步——空气负氧离子含量极高,真正的森林浴"
|
||||||
|
],
|
||||||
|
"bestSeason": {
|
||||||
|
"primary": "9月底-10月初"
|
||||||
|
},
|
||||||
|
"heroImage": "/images/destinations/daxinganling.jpg",
|
||||||
|
"seasons": [
|
||||||
|
"summer",
|
||||||
|
"autumn"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "hulunhu",
|
||||||
|
"name": "呼伦湖",
|
||||||
|
"subtitle": "北方第一大湖 · 冬季穿越蓝冰",
|
||||||
|
"tag": "湖泊景观",
|
||||||
|
"description": "呼伦湖是内蒙古最大的湖泊,面积约2339平方公里。夏季碧波万顷,岸线蜿蜒800多公里,和草原连成一片,日落时分整个湖面被染成金色。但真正让人印象深刻的反而是冬季——呼伦湖结冰后形成壮观的蓝冰,嗨冰雪北线行程安排了穿越呼伦湖蓝冰,在冰面上行走的体验完全不一样。湖里产鲤鱼、鲫鱼、白鱼,现捕现做的全鱼宴是来这儿的必吃项目。",
|
||||||
|
"highlights": [
|
||||||
|
"冬季穿越蓝冰——呼伦湖结冰后形成的蓝冰奇观,嗨冰雪北线核心体验",
|
||||||
|
"湖边看日落——金色夕阳映照万顷碧波,草原与湖水连成一片",
|
||||||
|
"现捕现做全鱼宴——湖里的鲤鱼鲫鱼白鱼新鲜到桌",
|
||||||
|
"春秋候鸟迁徙——数万候鸟栖息湖面的壮观景象",
|
||||||
|
"风车公路——通往呼伦湖的公路两侧风力发电机阵列"
|
||||||
|
],
|
||||||
|
"bestSeason": {
|
||||||
|
"primary": "7月-8月"
|
||||||
|
},
|
||||||
|
"heroImage": "/images/destinations/hulunhu.jpg",
|
||||||
|
"seasons": [
|
||||||
|
"summer",
|
||||||
|
"autumn"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "aoluguya",
|
||||||
|
"name": "敖鲁古雅驯鹿部落",
|
||||||
|
"subtitle": "中国唯一的驯鹿民族 · 鄂温克使鹿文化",
|
||||||
|
"tag": "民族探访",
|
||||||
|
"description": "这是中国唯一的驯鹿部落,鄂温克族是中国仅存的游猎民族。但说实话:现在游客去的「敖鲁古雅」是政府修建的旅游景区,不是真正的猎民营地——真正的鄂温克猎民和驯鹿生活在150公里外的深山密林里。景区里能喂驯鹿、看博物馆、了解桦皮文化和萨满文化,商业化程度不低但如果调整好预期带孩子来还是很有教育意义的。冬季嗨冰雪北线安排了深入根河方向的布冬霞驯鹿部落,坐驯鹿雪橇、穿鄂温克民族服饰,体验更真实一些。",
|
||||||
|
"highlights": [
|
||||||
|
"近距离喂驯鹿——买苔藓喂食拍照,驯鹿很温顺",
|
||||||
|
"鄂温克博物馆——了解驯鹿文化、狩猎文化、桦皮文化和萨满文化",
|
||||||
|
"撮罗子体验——鄂温克传统圆锥形住所,可以进去坐坐",
|
||||||
|
"冬季驯鹿雪橇——嗨冰雪北线安排的布冬霞驯鹿部落体验",
|
||||||
|
"鄂温克民族服饰体验——穿上传统服饰在雪地里拍照"
|
||||||
|
],
|
||||||
|
"bestSeason": {
|
||||||
|
"primary": "7月-8月"
|
||||||
|
},
|
||||||
|
"heroImage": "/images/destinations/aoluguya.jpg",
|
||||||
|
"seasons": [
|
||||||
|
"summer",
|
||||||
|
"autumn",
|
||||||
|
"winter"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "genhe",
|
||||||
|
"name": "根河·中国冷极",
|
||||||
|
"subtitle": "历史最低温-58°C · 不冻河奇观",
|
||||||
|
"tag": "冷极探秘",
|
||||||
|
"description": "根河是中国官方认定的最冷城市,历史最低温零下58度。但大多数游客不是冬天来的——夏天的根河其实是个避暑胜地,七八月也就20度出头。冬天来的话,泼水成冰是必玩项目:零下三四十度往空中泼热水瞬间变成冰晶散开,怎么拍怎么好看。嗨冰雪北线的行程最后安排在根河——布冬霞驯鹿部落喂驯鹿、铁锹烤肉、鄂温克民族服饰体验,然后从根河返回海拉尔。",
|
||||||
|
"highlights": [
|
||||||
|
"泼水成冰——零下三四十度的经典打卡体验,怎么拍怎么好看",
|
||||||
|
"不冻河——零下几十度依然流淌,河面蒸腾的雾气配岸边雾凇",
|
||||||
|
"冷极碑打卡——标注「-58°C」的地标,冬季来必拍",
|
||||||
|
"铁锹烤肉——用真铁锹当烤盘,根河特色美食",
|
||||||
|
"夏季避暑——七八月白天20度左右,原始森林负氧离子爆表"
|
||||||
|
],
|
||||||
|
"bestSeason": {
|
||||||
|
"primary": "12月-2月"
|
||||||
|
},
|
||||||
|
"heroImage": "/images/destinations/genhe.jpg",
|
||||||
|
"seasons": [
|
||||||
|
"winter"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
111
data/destinations.json
普通文件
111
data/destinations.json
普通文件
@ -0,0 +1,111 @@
|
|||||||
|
{
|
||||||
|
"title": "亲子游目的地怎么选?",
|
||||||
|
"subtitle": "一份客观对比,帮你找到最适合全家的那个答案",
|
||||||
|
"intro": "很多家庭在规划暑假亲子游时,会在呼伦贝尔、新疆北疆和呼和浩特周边草原之间犹豫。三个目的地各有魅力,以下是我们基于真实数据的客观对比,不贬低任何目的地,只帮你找到最适合带孩子去的那个。",
|
||||||
|
"destinations": [
|
||||||
|
{
|
||||||
|
"highlight": true,
|
||||||
|
"id": "hulunbuir",
|
||||||
|
"name": "呼伦贝尔",
|
||||||
|
"tag": "草原+森林+湿地"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "xinjiang",
|
||||||
|
"name": "北疆",
|
||||||
|
"tag": "雪山+草甸+湖泊"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "west-inner-mongolia",
|
||||||
|
"name": "呼和浩特周边",
|
||||||
|
"tag": "希拉穆仁+辉腾锡勒+响沙湾"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"dimensions": [
|
||||||
|
{
|
||||||
|
"label": "夏季气温",
|
||||||
|
"icon": "🌡️",
|
||||||
|
"values": [
|
||||||
|
"均温20-21°C,天然避暑胜地",
|
||||||
|
"21-31°C,部分地区可达35°C+",
|
||||||
|
"呼和浩特17-28°C,响沙湾沙漠区域体感更热"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"label": "日均车程",
|
||||||
|
"icon": "🚗",
|
||||||
|
"values": [
|
||||||
|
"2-3小时,日行150-250km",
|
||||||
|
"6-8小时,日行400-600km",
|
||||||
|
"景点集中,希拉穆仁80km、辉腾锡勒110km、响沙湾180km,3-4天可走完"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"label": "海拔",
|
||||||
|
"icon": "⛰️",
|
||||||
|
"values": [
|
||||||
|
"600-770m,零高反风险",
|
||||||
|
"赛里木湖2072m、巴音布鲁克2500m,有轻微高反可能",
|
||||||
|
"呼和浩特1050m,辉腾锡勒1800-2100m,整体无高反风险"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"label": "景观密度",
|
||||||
|
"icon": "🏞️",
|
||||||
|
"values": [
|
||||||
|
"草原+森林+湿地+河流+湖泊+边境小镇,紧凑环线一次体验",
|
||||||
|
"雪山+高山草甸+峡谷+湖泊极其壮美,但景点间距极大",
|
||||||
|
"草原+沙漠两种体验可兼得,行程紧凑高效,但草原辽阔感不如呼伦贝尔"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"label": "游客密度",
|
||||||
|
"icon": "👥",
|
||||||
|
"values": [
|
||||||
|
"2024年全年3443万人次,区域25.3万km²,体感不拥挤",
|
||||||
|
"2024年全年3.02亿人次,独库公路日通车超2万辆",
|
||||||
|
"希拉穆仁暑期团队游较多,响沙湾人气旺但设施成熟不用排太久"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"label": "亲子适配",
|
||||||
|
"icon": "👨👩👧",
|
||||||
|
"values": [
|
||||||
|
"地势平坦安全,成熟亲子营+研学体系,孩子跑得开",
|
||||||
|
"长途车程对孩子不友好,山路+高海拔有一定风险",
|
||||||
|
"响沙湾沙漠项目丰富孩子爱玩,草原部分体验较浅,适合首次体验草原+沙漠的家庭"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"label": "费用参考",
|
||||||
|
"icon": "💰",
|
||||||
|
"values": [
|
||||||
|
"家庭4人5-7天约1-1.7万(含北京出发机票)",
|
||||||
|
"家庭4人7-10天约1.8-3.5万(距离远天数多)",
|
||||||
|
"家庭4人3-4天约0.5-1万,行程短费用低,性价比高"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"label": "文化体验",
|
||||||
|
"icon": "🎭",
|
||||||
|
"values": [
|
||||||
|
"蒙古族+俄罗斯族+鄂温克族,三重文化交融",
|
||||||
|
"哈萨克族+维吾尔族+丝路历史,多民族风情",
|
||||||
|
"蒙古族文化+沙漠娱乐,适合短途初体验,深度稍浅"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"honestNote": {
|
||||||
|
"title": "我们的坦诚",
|
||||||
|
"subtitle": "呼伦贝尔也有不完美的地方",
|
||||||
|
"items": [
|
||||||
|
"旺季房紧:7月中旬至8月中旬住宿紧张且价格上浮,建议提前1-2个月预订",
|
||||||
|
"南方航班少:广州、深圳出发直飞航班有限,可能需要中转",
|
||||||
|
"壮观度:呼伦贝尔的风景是辽阔舒展型的,不如新疆雪山峡谷那般「震撼」"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"closing": {
|
||||||
|
"title": "为什么呼籁只做呼伦贝尔?",
|
||||||
|
"text": "新疆壮美,呼和浩特周边方便,每个目的地都有自己的好。但我们选择只做呼伦贝尔,是因为11年的深耕让我们确信:如果你有5-7天假期,想带孩子看真正辽阔的草原、穿越森林湿地、体验多民族文化——呼伦贝尔是综合最优解。我们把所有精力放在一个地方,才能把每一条路线、每一个营地、每一位领队都打磨到最好。不是其他地方不好,而是对家庭亲子游这件事,呼伦贝尔真的很合适,而我们恰好最懂它。"
|
||||||
|
},
|
||||||
|
"dataSources": "气温数据来源:中国气象局;旅游人次数据来源:呼伦贝尔市2024年统计公报、新疆维吾尔自治区文旅厅;距离数据来源:高德地图实测"
|
||||||
|
}
|
||||||
313
data/faq.json
普通文件
313
data/faq.json
普通文件
@ -0,0 +1,313 @@
|
|||||||
|
{
|
||||||
|
"categories": [
|
||||||
|
{
|
||||||
|
"id": "product",
|
||||||
|
"name": "产品类",
|
||||||
|
"questions": [
|
||||||
|
{
|
||||||
|
"id": "what-is-eqi",
|
||||||
|
"question": "额吉的故乡是什么?",
|
||||||
|
"answer": "额吉的故乡是呼籁旅行的核心产品系列,目前已迭代至V9版本。「额吉」在蒙古语中是「母亲」的意思,这个名字承载着呼籁对呼伦贝尔这片土地的深厚感情——希望每个来到这里的家庭,都能感受到草原如母亲般的温暖和包容。产品采用一家一单一车的定制模式,涵盖4天3晚到7天6晚多个版本,满足不同家庭的假期安排和出行需求。",
|
||||||
|
"relatedLinks": [
|
||||||
|
{
|
||||||
|
"url": "/products",
|
||||||
|
"text": "查看所有产品版本"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "what-products",
|
||||||
|
"question": "呼籁有哪些产品?",
|
||||||
|
"answer": "呼籁旅行目前有两大产品线:额吉的故乡V9系列和小蒙马夏令营。额吉的故乡V9系列是家庭定制游产品,一家一单一车,提供4天3晚至7天6晚共6个版本,适合不同假期和偏好的家庭。小蒙马夏令营是亲子夏令营路线,6天5晚,每期8组家庭同行,爸爸妈妈带着孩子一起出发,融入草原写生、非遗研学、民俗体验三大主题。两大产品线都走呼伦贝尔核心线路,区别在于形式:额吉的故乡是私家定制,小蒙马是亲子夏令营。",
|
||||||
|
"relatedLinks": [
|
||||||
|
{
|
||||||
|
"url": "/products",
|
||||||
|
"text": "查看产品详情"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "price-6d5n",
|
||||||
|
"question": "呼伦贝尔6天5晚多少钱?",
|
||||||
|
"answer": "呼籁旅行不在官网公示具体价格,因为每个家庭的人数、出行时间、住宿偏好不同,最终价格会有差异。但可以说清楚价格包含什么:全程专属用车和司机、精选住宿、专属领队服务、所有体验活动费用、旅行保险、呼籁自营旅拍服务等,没有隐形消费,不会中途加价。呼籁的价格确实比拼团游高,因为是一家一单一车的定制服务,品质和体验完全不同。建议直接联系定制师,根据您的具体需求获取详细报价。",
|
||||||
|
"relatedLinks": [
|
||||||
|
{
|
||||||
|
"url": "/contact",
|
||||||
|
"text": "联系定制师获取报价"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "vs-group-tour",
|
||||||
|
"question": "亲子游和普通跟团什么区别?",
|
||||||
|
"answer": "区别主要在三个方面。第一,出行方式不同——跟团是几十人大巴统一行动,呼籁是一家一单一车,自由度完全不同。第二,行程设计不同——跟团走标准景点打卡路线,呼籁的行程专门为家庭和孩子设计,节奏更合理,体验活动更丰富,包含骑马、草原滑草、ATV、观日出日落、访牧户等。第三,服务配置不同——跟团只有导游,呼籁配备3管家(车务+房务+客服)+ 定制师 + 专属领队,全程只服务您一个家庭。",
|
||||||
|
"relatedLinks": [
|
||||||
|
{
|
||||||
|
"url": "/products",
|
||||||
|
"text": "了解呼籁的产品"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "how-many-days-with-kids",
|
||||||
|
"question": "带小孩子选几天合适?",
|
||||||
|
"answer": "如果孩子在3-5岁,建议选6天5晚亲子版,行程节奏专门为小朋友设计,不会太赶。如果孩子在6岁以上,7天6晚深度版体验更完整,孩子的体力和好奇心都跟得上。假期有限的话,4天3晚精华版也能涵盖草原核心体验。总的来说,6天是大多数家庭的选择,时间和体验的平衡比较理想。出发前呼籁的定制师会根据孩子年龄推荐合适版本。",
|
||||||
|
"relatedLinks": [
|
||||||
|
{
|
||||||
|
"url": "/products#guide",
|
||||||
|
"text": "按孩子年龄选产品"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "summer-camp-age",
|
||||||
|
"question": "小蒙马夏令营适合几岁?",
|
||||||
|
"answer": "小蒙马夏令营是亲子夏令营,爸爸妈妈带着孩子一起参加,适合有学龄儿童的家庭。行程中的活动会根据孩子年龄适配难度,比如骑马教练会匹配合适的马匹,绘画老师会按基础指导,非遗手工也简单易操作。小蒙马和额吉的故乡的区别在于:额吉的故乡是一家一单一车的私家定制游,小蒙马是每期8组家庭一起出发的亲子夏令营,孩子有伙伴一起玩,大人也能在团队氛围里放松。小蒙马还贴心设计了「爸妈托管」时段,专业工作人员带孩子做游戏,家长可以短暂休息。",
|
||||||
|
"relatedLinks": [
|
||||||
|
{
|
||||||
|
"url": "/summer-camp",
|
||||||
|
"text": "了解小蒙马夏令营"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "preparation",
|
||||||
|
"name": "出行准备类",
|
||||||
|
"questions": [
|
||||||
|
{
|
||||||
|
"id": "what-to-wear",
|
||||||
|
"question": "去呼伦贝尔穿什么带什么?",
|
||||||
|
"answer": "呼伦贝尔早晚温差大,核心原则是洋葱式穿搭、层层叠加。7月白天16-34°C可以穿短袖短裤,但早晚只有十几度需要薄外套;5月和9月则需要厚外套甚至薄羽绒服。必带物品:SPF50+防晒霜(草原紫外线远比城市强,每2小时补涂)、含DEET成分的防蚊喷雾、宽檐帽+UV400墨镜、充电宝(必须有3C认证,不超过27000mAh)、耳塞和遮光眼罩(夏季凌晨3-4点天亮)、保温杯(多喝温水,不要饮用生水)、肠胃药和益生菌。鞋子以运动鞋为主,建议带两双换穿。拍照穿浅色、白色、红色、鹅黄色在草原上很出片。不用带矿泉水和方便面,海拉尔超市齐全。呼籁会提供哈达、儿童安全座椅、一次性雨衣、骑马手套、防蚊喷雾等物品,出发前管家会发详细行前清单。更多穿搭和行李细节请查看出行指南。",
|
||||||
|
"relatedLinks": [
|
||||||
|
{
|
||||||
|
"url": "/guides",
|
||||||
|
"text": "查看完整出行指南"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "best-month",
|
||||||
|
"question": "呼伦贝尔几月去最好?",
|
||||||
|
"answer": "呼伦贝尔夏季旅游季节是5-10月,各月体验不同。5月草刚返青,白天5-26°C、夜间可低至-6°C,需厚外套甚至羽绒服,游客极少适合错峰。6月上旬草原开始变绿,下旬油菜花开放,白天13-28°C,体感舒适。7月是最旺季,草原最美,满眼绿色加野花,白天可达34°C但不闷热,是大多数家庭的选择。8月暑假高峰,下旬渐有秋意。9月白桦林开始变黄,秋色渐浓,蚊虫基本没了,早晚已经很凉需要厚外套。国庆期间秋末接近入冬,部分年份可能飘雪。冬季12-2月可以体验雪原风光。如果时间灵活,6月中下旬和9月初的体验也非常好,且价格更友好。更多各月穿搭建议请查看出行指南。",
|
||||||
|
"relatedLinks": [
|
||||||
|
{
|
||||||
|
"url": "/guides",
|
||||||
|
"text": "查看各月穿搭指南"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "bugs-prevention",
|
||||||
|
"question": "蚊虫多吗?防蚊怎么做?",
|
||||||
|
"answer": "草原上6-8月确实有蚊虫,湿地区域7月中旬为高峰期,日出前和日落后蚊虫最活跃。但做好防护就没什么大问题。建议带含DEET成分的防蚊喷雾,穿浅色长袖长裤效果最好(深色衣服反而容易招蚊子)。另外需要注意蜱虫防护:户外活动时扎紧裤脚和袖口,每天活动结束后检查皮肤(尤其腋下、腰部、发际线、耳后),万一发现蜱虫叮咬不要用手硬拽,用尖头镊子贴近皮肤夹住蜱虫头部垂直拔出,然后碘伏消毒。呼籁的领队随车备有蚊不叮和防蚊喷雾,也携带急救包。大部分家庭反馈蚊虫影响可控,不必过度担心。",
|
||||||
|
"relatedLinks": [
|
||||||
|
{
|
||||||
|
"url": "/guides",
|
||||||
|
"text": "查看完整出行指南"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "altitude-sickness",
|
||||||
|
"question": "呼伦贝尔有高原反应吗?",
|
||||||
|
"answer": "没有。呼伦贝尔的平均海拔在600-800米左右,属于平原地区,不会产生高原反应。这也是呼伦贝尔特别适合亲子游的原因之一——老人和小孩都不需要担心海拔问题,身体没有额外负担。唯一需要注意的是昼夜温差较大,注意增减衣物即可。",
|
||||||
|
"relatedLinks": [
|
||||||
|
{
|
||||||
|
"url": "/guides",
|
||||||
|
"text": "查看穿搭与出行指南"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "kids-safety",
|
||||||
|
"question": "带孩子去安全吗?",
|
||||||
|
"answer": "安全是呼籁最重视的事项。首先,呼籁的车辆和司机都有严格管理,车况定期检查,车辆配备儿童安全座椅。其次,呼籁配备专业领队,每天的活动都有安全评估和应急预案,领队随身携带急救包。第三,所有行程均购买旅游责任险(保额1000万),签订正规电子合同。各项活动都有明确的安全规范:骑马穿越全程有专业马师随行,年龄较小的孩子由马师牵引或抱着骑;ATV越野车2人一车系安全带,12岁以下需家长陪同;草原滑草要求身高1.2米以上独立乘坐,不足1.2米可和大人一起坐。0-3岁幼童有专属活动推荐,不建议参与骑马穿越和ATV等项目。呼籁已服务超过10000组家庭、累计近4万人次出行,安全记录良好。",
|
||||||
|
"relatedLinks": [
|
||||||
|
{
|
||||||
|
"url": "/reviews",
|
||||||
|
"text": "查看其他家庭的评价"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "trust",
|
||||||
|
"name": "信任类",
|
||||||
|
"questions": [
|
||||||
|
{
|
||||||
|
"id": "is-reliable",
|
||||||
|
"question": "呼籁旅行怎么样靠谱吗?",
|
||||||
|
"answer": "呼籁旅行是呼伦贝尔本地品牌,隶属内蒙古呼籁文旅投资开发集团有限公司,旗下9家企业。集团核心旅行社主体——呼籁山河国旅成立于2005年,深耕呼伦贝尔11年。呼籁拥有自有车队、自有营地、自营旅拍团队,已服务超过10000组家庭、累计近4万人次。所有行程签订正规电子合同,旅游责任险保额1000万,全程无购物无隐形消费。您可以在客户评价页面查看真实的出行反馈。",
|
||||||
|
"relatedLinks": [
|
||||||
|
{
|
||||||
|
"url": "/reviews",
|
||||||
|
"text": "查看客户真实评价"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"url": "/about",
|
||||||
|
"text": "了解呼籁的资质"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "is-legal",
|
||||||
|
"question": "呼籁是正规旅行社吗?",
|
||||||
|
"answer": "是的。呼籁旅行集团旗下的呼籁山河国旅,成立于2005年,持有正规旅行社经营许可证,所有行程均签订正规电子合同,缴纳旅行社质量保证金,受旅游管理部门监管。呼籁集团旗下9家企业,包括自有车队和营地,具备完整的旅行服务链条。旅游责任险保额1000万。选择有资质的旅行社,是出行安全的第一道保障。",
|
||||||
|
"relatedLinks": [
|
||||||
|
{
|
||||||
|
"url": "/about",
|
||||||
|
"text": "了解呼籁集团"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "refund-policy",
|
||||||
|
"question": "退改政策是什么?",
|
||||||
|
"answer": "呼籁的退改政策写在电子合同里,清晰透明。定金在出行前可申请退还,具体退改比例以合同条款为准。如果因为不可抗力(如极端天气等)无法出行,呼籁会协商妥善处理,可以选择改期或退款。所有费用和退改条款均在合同中明确约定,受法律保护。建议确认行程后联系定制师了解详细退改条款。",
|
||||||
|
"relatedLinks": [
|
||||||
|
{
|
||||||
|
"url": "/contact",
|
||||||
|
"text": "联系定制师了解详情"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "hidden-cost",
|
||||||
|
"question": "费用含什么?有隐形消费吗?",
|
||||||
|
"answer": "呼籁的报价包含:全程专属用车、司机、住宿、专属领队服务、行程内所有体验活动、旅行保险、呼籁自营旅拍服务。不包含的项目会在合同中明确列出,通常是往返大交通(机票/火车票)和个人消费。呼籁承诺没有隐形消费,不会在行程中推销购物店或加价项目。所有费用明细在签订合同时一目了然,让每一分钱都花在体验上。",
|
||||||
|
"relatedLinks": [
|
||||||
|
{
|
||||||
|
"url": "/products",
|
||||||
|
"text": "了解产品详情"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "how-to-contact",
|
||||||
|
"question": "如何联系呼籁旅行?",
|
||||||
|
"answer": "联系呼籁最方便的方式是添加微信客服,可以直接沟通行程需求并获取定制方案。您也可以通过官网 1814.love 在线咨询,或拨打客服电话。所有官方联系方式均在「联系我们」页面公示,请认准官方渠道,谨防假冒。呼籁的定制师会根据您的家庭情况和假期安排,推荐合适的产品版本。",
|
||||||
|
"relatedLinks": [
|
||||||
|
{
|
||||||
|
"url": "/contact",
|
||||||
|
"text": "查看所有联系方式"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "experience",
|
||||||
|
"name": "体验类",
|
||||||
|
"questions": [
|
||||||
|
{
|
||||||
|
"id": "accommodation",
|
||||||
|
"question": "呼伦贝尔住哪里比较好?",
|
||||||
|
"answer": "呼伦贝尔的住宿选择比较多样:城区有星级酒店,草原上有蒙古包和特色民宿,还有呼籁自有的营地住宿。呼籁会根据行程路线精选住宿,确保干净舒适。如果选择探索版行程,住宿标准会进一步升级。需要说明的是,草原上的住宿条件和城市有差距,但这也是草原体验的一部分。呼籁会提前告知住宿标准,让您有合理预期。",
|
||||||
|
"relatedLinks": [
|
||||||
|
{
|
||||||
|
"url": "/products",
|
||||||
|
"text": "查看探索版行程"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "horse-riding",
|
||||||
|
"question": "能骑马吗?孩子能骑吗?",
|
||||||
|
"answer": "可以骑马,这是呼伦贝尔最受家庭欢迎的体验之一。骑马穿越往返约1小时,马匹都是经过训练的温顺马,全程有专业马师随行陪同。如果不太敢骑或不熟练,马师会牵着马走,不额外收费;年龄较小的孩子由马师抱着骑。请穿长裤和运动鞋,呼籁会提前准备骑马手套。骑马时双手握住缰绳、身体放松,不要站在马的后面。0-3岁幼童不建议参与沉浸式骑马穿越,但可以体验喂小羊、营地儿童游乐架、轮胎秋千等温和活动。除骑马外,行程中还可体验草原滑草(身高1.2米以上可独立乘坐)、ATV越野(2人一车)等多种户外活动。",
|
||||||
|
"relatedLinks": [
|
||||||
|
{
|
||||||
|
"url": "/guides#activities",
|
||||||
|
"text": "查看活动安全须知"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "charter-vs-group",
|
||||||
|
"question": "包车自由行和拼团哪个好?",
|
||||||
|
"answer": "这取决于您的需求和预算。拼团价格更低,但行程固定、同行人员不可控、自由度很低。呼籁做的是一家一单一车的定制游,价格高于拼团,但一家一车,行程可调整,只和自己家人在一起,体验完全不同。特别是带孩子出行,定制游的优势很明显——孩子需要休息可以随时停,想多玩一会儿也没人催。如果预算允许,带孩子出行建议选定制游。",
|
||||||
|
"relatedLinks": [
|
||||||
|
{
|
||||||
|
"url": "/products",
|
||||||
|
"text": "查看定制游产品"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "how-many-days-best",
|
||||||
|
"question": "呼伦贝尔玩几天合适?",
|
||||||
|
"answer": "如果时间允许,建议至少5天以上。4天能看到核心风光,但节奏会比较紧凑;5-6天是大多数家庭的选择,体验较为完整;7天能深入探索,包括牧云山顶、寻龙诀秘境等独家资源点。呼籁提供4-7天的多个版本,可以根据假期灵活选择。第一次来呼伦贝尔的家庭,6天5晚是比较推荐的时长,时间和体验的平衡较好。",
|
||||||
|
"relatedLinks": [
|
||||||
|
{
|
||||||
|
"url": "/products#guide",
|
||||||
|
"text": "按假期长度选产品"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "popular",
|
||||||
|
"name": "高频咨询类",
|
||||||
|
"questions": [
|
||||||
|
{
|
||||||
|
"id": "driver-guide-quality",
|
||||||
|
"question": "司机和领队怎么样?",
|
||||||
|
"answer": "呼籁的司机都经过严格筛选、培训和考核,熟悉呼伦贝尔的每条路线。领队都是经过呼籁体系化培训和严格考核的,统一服务标准。额吉的故乡等一单一团产品配备3管家(车务管家+房务管家+客服管家)+ 1定制师 + 1专属领队,全程只服务您一个家庭,旅拍部分含呼籁自营旅拍服务。小蒙马夏令营配备全程2位亲子领队 + 1位跟拍摄影师 + 专属司机。很多回头客会指定同一位领队,就是因为服务到位、值得信赖。在客户评价中,司机和领队是被提及频率很高的好评项。",
|
||||||
|
"relatedLinks": [
|
||||||
|
{
|
||||||
|
"url": "/reviews",
|
||||||
|
"text": "看客户怎么评价"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "rainy-day-plan",
|
||||||
|
"question": "下雨怎么办?有备用方案吗?",
|
||||||
|
"answer": "呼伦贝尔夏天的天气变化较快,局部阵雨是常有的事。呼籁的每条行程都有备用方案,如果户外活动受天气影响,领队会及时调整安排替代活动或调换行程顺序。草原的雨通常来得快去得也快,很少影响一整天的行程。建议随身带一件轻便雨衣,比打伞方便。呼籁的领队经验丰富,会根据实时天气灵活应对,确保行程体验不打折扣。",
|
||||||
|
"relatedLinks": [
|
||||||
|
{
|
||||||
|
"url": "/guides#clothing",
|
||||||
|
"text": "查看各月天气与穿搭建议"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "multi-family",
|
||||||
|
"question": "能不能两家或三家一起出行?",
|
||||||
|
"answer": "当然可以,多家庭同行是呼籁很受欢迎的出行方式。呼籁会根据家庭数量安排合适的车辆配置(可以多车同行),孩子们在一起玩更开心,大人也能互相搭把手。费用可以按家庭分摊,性价比更高。建议多家庭出行时选6天5晚亲子版,活动设计特别适合孩子们一起参与。具体方案可以联系定制师沟通。",
|
||||||
|
"relatedLinks": [
|
||||||
|
{
|
||||||
|
"url": "/contact",
|
||||||
|
"text": "联系定制师规划行程"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "custom-itinerary",
|
||||||
|
"question": "行程能根据需求调整吗?",
|
||||||
|
"answer": "可以,这正是定制游的意义——行程不是固定的模板。在呼籁的标准版本基础上,您可以和定制师沟通调整:想多留半天在某个地方、想去某个特定的点、想安排特别的体验活动,都可以讨论。定制师会根据路线合理性和时间给出专业建议。大幅度调整可能影响报价,具体以沟通结果为准。呼籁已迭代至V9版本,标准行程本身经过多年优化,适合绝大多数家庭。",
|
||||||
|
"relatedLinks": [
|
||||||
|
{
|
||||||
|
"url": "/contact",
|
||||||
|
"text": "联系定制师"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "vs-other-charter",
|
||||||
|
"question": "和其他呼伦贝尔包车有什么区别?",
|
||||||
|
"answer": "呼伦贝尔做包车的很多,但呼籁不只是包车。区别在于:第一,呼籁是正规旅行社(旗下呼籁山河国旅成立于2005年),签正规电子合同,旅游责任险1000万,有法律保障;很多包车是个人或无资质的车队。第二,呼籁提供完整的服务团队(3管家+定制师+专属领队),不只是一个司机带路。第三,呼籁有自有营地、自有车队、牧云山顶和寻龙诀秘境等独家体验资源,这些是普通包车司机给不了的。第四,呼籁的行程经过专业设计和9次迭代优化,是一套成熟的旅行服务体系。",
|
||||||
|
"relatedLinks": [
|
||||||
|
{
|
||||||
|
"url": "/about",
|
||||||
|
"text": "了解呼籁的实力"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
242
data/gallery.json
普通文件
242
data/gallery.json
普通文件
@ -0,0 +1,242 @@
|
|||||||
|
{
|
||||||
|
"works": [
|
||||||
|
{
|
||||||
|
"id": "gallery-001",
|
||||||
|
"title": "莫日格勒河畔·蒙古袍亲子写真",
|
||||||
|
"category": "family",
|
||||||
|
"location": "莫日格勒河",
|
||||||
|
"description": "清晨的莫日格勒河,河湾处光线最柔和。一家三口身着蒙古袍,是草原上最美的风景。",
|
||||||
|
"image": "/images/gallery/gallery-001.jpg"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "gallery-013",
|
||||||
|
"title": "父子蒙古袍·营地合影",
|
||||||
|
"category": "family",
|
||||||
|
"location": "呼籁营地",
|
||||||
|
"description": "父子俩身着蓝色蒙古袍,在呼籁营地指示牌前开心合影。",
|
||||||
|
"image": "/旅拍照片/IMG_1244.JPG"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "gallery-002",
|
||||||
|
"title": "额尔古纳湿地·情侣旅拍",
|
||||||
|
"category": "couple",
|
||||||
|
"location": "额尔古纳湿地",
|
||||||
|
"description": "湿地栈道尽头,两人相视而笑。蒙古族礼服在阳光下格外耀眼,湿地的翠绿是最好的背景。",
|
||||||
|
"image": "/images/gallery/gallery-002.jpg"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "gallery-014",
|
||||||
|
"title": "父子草原奔跑",
|
||||||
|
"category": "family",
|
||||||
|
"location": "呼籁营地",
|
||||||
|
"description": "穿着蒙古袍的父子俩在草原上并肩奔跑,笑容灿烂。",
|
||||||
|
"image": "/旅拍照片/IMG_1245.JPG"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "gallery-003",
|
||||||
|
"title": "白桦林间·闺蜜写真",
|
||||||
|
"category": "friends",
|
||||||
|
"location": "额尔古纳白桦林",
|
||||||
|
"description": "金秋的白桦林是最天然的摄影棚。三位闺蜜身着不同颜色的蒙古盛装,在金叶飘落中留下了这组写真。",
|
||||||
|
"image": "/images/gallery/gallery-003.jpg"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "gallery-015",
|
||||||
|
"title": "骑在爸爸肩上",
|
||||||
|
"category": "family",
|
||||||
|
"location": "呼籁营地",
|
||||||
|
"description": "儿子骑在爸爸肩膀上,父子同穿蓝色蒙古袍,蓝天绿草间的温馨瞬间。",
|
||||||
|
"image": "/旅拍照片/IMG_1246.JPG"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "gallery-004",
|
||||||
|
"title": "黑山头草原·三代同堂全家福",
|
||||||
|
"category": "group",
|
||||||
|
"location": "黑山头",
|
||||||
|
"description": "祖孙三代,一家十口,同穿蒙古袍站在草原最高处。他们说这张照片挂在客厅最显眼的地方。",
|
||||||
|
"image": "/images/gallery/gallery-004.jpg"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "gallery-016",
|
||||||
|
"title": "一家三口草地游戏",
|
||||||
|
"category": "family",
|
||||||
|
"location": "呼籁营地",
|
||||||
|
"description": "爸爸、妈妈和女儿围坐在草地上玩拍手游戏,女儿笑得合不拢嘴。",
|
||||||
|
"image": "/旅拍照片/IMG_1247.JPG"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "gallery-005",
|
||||||
|
"title": "草原深处·骑马个人写真",
|
||||||
|
"category": "portrait",
|
||||||
|
"location": "莫日格勒河源头",
|
||||||
|
"description": "骑马奔驰在无人草原,风吹起头饰上的流苏。这一刻,她成了草原上最自由的人。",
|
||||||
|
"image": "/images/gallery/gallery-005.jpg"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "gallery-017",
|
||||||
|
"title": "爸爸扛起小公主",
|
||||||
|
"category": "family",
|
||||||
|
"location": "呼籁营地",
|
||||||
|
"description": "爸爸把穿着蓝色蒙古裙的女儿扛在肩上奔跑,蓝天下尽情欢笑。",
|
||||||
|
"image": "/旅拍照片/IMG_1248.JPG"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "gallery-006",
|
||||||
|
"title": "呼伦湖畔·亲子骑马留影",
|
||||||
|
"category": "family",
|
||||||
|
"location": "呼伦湖",
|
||||||
|
"description": "湖边的夕阳把天空染成橙红,孩子骑在马背上,爸爸牵着缰绳。这张照片定格了一个家庭最美的时光。",
|
||||||
|
"image": "/images/gallery/gallery-006.jpg"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "gallery-018",
|
||||||
|
"title": "父女温馨时刻",
|
||||||
|
"category": "family",
|
||||||
|
"location": "呼籁营地",
|
||||||
|
"description": "小女儿调皮地捏爸爸的鼻子,穿蒙古袍的爸爸笑着配合,温馨又可爱。",
|
||||||
|
"image": "/旅拍照片/IMG_1249.JPG"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "gallery-007",
|
||||||
|
"title": "秋日白桦·情侣婚纱旅拍",
|
||||||
|
"category": "couple",
|
||||||
|
"location": "室韦白桦林",
|
||||||
|
"description": "他们把婚纱照拍到了室韦。金色白桦叶飘落,蒙古婚礼盛装在秋光中更显华美。这是他们说过最满意的照片。",
|
||||||
|
"image": "/images/gallery/gallery-007.jpg"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "gallery-019",
|
||||||
|
"title": "父女草原追逐",
|
||||||
|
"category": "family",
|
||||||
|
"location": "呼籁营地",
|
||||||
|
"description": "穿着蓝色裙子的女儿和蒙古袍爸爸在草原上开心追逐奔跑。",
|
||||||
|
"image": "/旅拍照片/IMG_1250.JPG"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "gallery-008",
|
||||||
|
"title": "冬日雪原·个人写真",
|
||||||
|
"category": "portrait",
|
||||||
|
"location": "海拉尔草原",
|
||||||
|
"description": "零下三十度的冬日草原,她穿着厚重的皮袍站在雪地里,背后是无垠的白色世界。沉静而有力量。",
|
||||||
|
"image": "/images/gallery/gallery-008.jpg"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "gallery-020",
|
||||||
|
"title": "一家三口·小推车",
|
||||||
|
"category": "family",
|
||||||
|
"location": "呼籁营地",
|
||||||
|
"description": "爸爸拉着绿色小推车载着女儿飞奔,妈妈在后面张开双臂追赶,快乐溢出画面。",
|
||||||
|
"image": "/旅拍照片/IMG_1251.JPG"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "gallery-009",
|
||||||
|
"title": "营地花海·闺蜜团写真",
|
||||||
|
"category": "friends",
|
||||||
|
"location": "呼籁自营营地",
|
||||||
|
"description": "营地的格桑花开了整个夏天。四个闺蜜相约来草原,在花海里留下了这组让她们争相转发的写真。",
|
||||||
|
"image": "/images/gallery/gallery-009.jpg"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "gallery-021",
|
||||||
|
"title": "粉色蒙古盛装·旗帜前",
|
||||||
|
"category": "solo",
|
||||||
|
"location": "呼籁营地",
|
||||||
|
"description": "小女孩穿着精美的粉色蒙古盛装,在呼伦贝尔旗帜前巧笑嫣然。",
|
||||||
|
"image": "/旅拍照片/IMG_1252.JPG"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "gallery-010",
|
||||||
|
"title": "莫日格勒·同学聚会全家福",
|
||||||
|
"category": "group",
|
||||||
|
"location": "莫日格勒河",
|
||||||
|
"description": "同学聚会选择了草原,十五个人浩浩荡荡,每个人都穿上了不同颜色的蒙古袍,笑得合不拢嘴。",
|
||||||
|
"image": "/images/gallery/gallery-010.jpg"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "gallery-022",
|
||||||
|
"title": "草原上的旋转舞",
|
||||||
|
"category": "solo",
|
||||||
|
"location": "呼籁营地",
|
||||||
|
"description": "小女孩穿粉色蒙古盛装在草原上翩翩旋转,裙摆飞扬。",
|
||||||
|
"image": "/旅拍照片/IMG_1253.JPG"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "gallery-011",
|
||||||
|
"title": "额尔古纳秋色·母女亲子写真",
|
||||||
|
"category": "family",
|
||||||
|
"location": "额尔古纳湿地",
|
||||||
|
"description": "妈妈和女儿穿着撞色亲子蒙古袍,在湿地木栈道上相互依偎。秋光洒下来,温柔又好看。",
|
||||||
|
"image": "/images/gallery/gallery-011.jpg"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "gallery-023",
|
||||||
|
"title": "草原上的飞踢",
|
||||||
|
"category": "solo",
|
||||||
|
"location": "呼籁营地",
|
||||||
|
"description": "小女孩穿着粉色蒙古盛装在草原上踢腿跳跃,活力四射。",
|
||||||
|
"image": "/旅拍照片/IMG_1254.JPG"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "gallery-012",
|
||||||
|
"title": "冬季那达慕·节日盛装写真",
|
||||||
|
"category": "portrait",
|
||||||
|
"location": "呼伦贝尔冬季那达慕",
|
||||||
|
"description": "冬季那达慕现场,他穿上节日盛装,背后是策马奔腾的骑手。整组照片充满了草原特有的力量感。",
|
||||||
|
"image": "/images/gallery/gallery-012.jpg"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "gallery-024",
|
||||||
|
"title": "奔跑的背影",
|
||||||
|
"category": "solo",
|
||||||
|
"location": "呼籁营地",
|
||||||
|
"description": "粉色蒙古盛装的小女孩在草原上奔跑,辫子和裙摆随风飞扬的背影。",
|
||||||
|
"image": "/旅拍照片/IMG_1255.JPG"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "gallery-025",
|
||||||
|
"title": "白裙俏皮少女",
|
||||||
|
"category": "solo",
|
||||||
|
"location": "呼籁营地",
|
||||||
|
"description": "小女孩穿着白色蒙古裙搭配棕色马靴,在草原上俏皮摆pose。",
|
||||||
|
"image": "/旅拍照片/IMG_1256.JPG"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "gallery-026",
|
||||||
|
"title": "草原笑脸·蒙古头饰",
|
||||||
|
"category": "solo",
|
||||||
|
"location": "呼籁营地",
|
||||||
|
"description": "戴着精美蒙古族头饰的小女孩对着镜头伸出双手,笑容灿烂无比。",
|
||||||
|
"image": "/旅拍照片/IMG_1258.JPG"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "gallery-027",
|
||||||
|
"title": "母女牵手·草原漫步",
|
||||||
|
"category": "family",
|
||||||
|
"location": "呼籁营地",
|
||||||
|
"description": "妈妈和女儿穿着白色长裙手牵手漫步在草原上,温柔而美好。",
|
||||||
|
"image": "/旅拍照片/IMG_1259.JPG"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"intro": {
|
||||||
|
"description": "呼籁旅行提供专业草原旅拍服务,200+件正宗蒙古袍,专业摄影师全程随行,营地即景即拍。",
|
||||||
|
"stats": [
|
||||||
|
{
|
||||||
|
"value": "200+",
|
||||||
|
"label": "套蒙古服饰"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"value": "11年",
|
||||||
|
"label": "深耕草原"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"value": "3000+",
|
||||||
|
"label": "旅拍家庭"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"seo": {
|
||||||
|
"title": "呼籁草原旅拍 - 蒙古袍旅拍|呼伦贝尔专业旅拍服务",
|
||||||
|
"description": "呼籁旅行提供呼伦贝尔草原专业旅拍服务,200+套正宗蒙古袍,专业摄影师随行,营地即景即拍。亲子旅拍/情侣旅拍/全家福,3000+家庭选择。",
|
||||||
|
"keywords": "草原旅拍,蒙古袍旅拍,呼伦贝尔旅拍,亲子旅拍,情侣旅拍,全家福,呼籁旅拍"
|
||||||
|
}
|
||||||
|
}
|
||||||
522
data/guides.json
普通文件
522
data/guides.json
普通文件
@ -0,0 +1,522 @@
|
|||||||
|
{
|
||||||
|
"pageIntro": "这份指南是呼籁团队根据多年带队经验整理的,从穿什么衣服、带什么东西、到各项活动的注意事项,帮您轻松准备呼伦贝尔之行。",
|
||||||
|
"sections": [
|
||||||
|
{
|
||||||
|
"id": "documents",
|
||||||
|
"title": "证件准备",
|
||||||
|
"subtitle": "出发前第一件事",
|
||||||
|
"icon": "📋",
|
||||||
|
"content": "别的都能补,证件忘了真回不了头。出发前一晚,请全家人把证件放在一起,拍张照存手机里备用。",
|
||||||
|
"tips": [
|
||||||
|
"建议把证件拍照存手机相册,万一遗失可以应急。电子身份证在部分场景也可以使用。"
|
||||||
|
],
|
||||||
|
"items": [
|
||||||
|
{
|
||||||
|
"text": "身份证(成人必带)",
|
||||||
|
"important": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"text": "户口本(16周岁以下儿童必带)",
|
||||||
|
"important": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"text": "优惠证件(如有):学生证、教师资格证、军官证、残疾证、老年证等,部分景点可享门票减免",
|
||||||
|
"important": false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"text": "医保卡或商业保险卡(以防万一)",
|
||||||
|
"important": false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"text": "少量现金(大部分地方支持手机支付,但偏远牧区备一点更安心)",
|
||||||
|
"important": false
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "clothing",
|
||||||
|
"title": "穿搭建议",
|
||||||
|
"subtitle": "洋葱式穿搭,层层叠加,随时增减",
|
||||||
|
"icon": "👔",
|
||||||
|
"content": "呼伦贝尔昼夜温差大,不同月份差异也大。不管哪个月来,包里永远塞一件外套。",
|
||||||
|
"months": [
|
||||||
|
{
|
||||||
|
"desc": "草刚返青,花还没全开,游客少,适合错峰出行",
|
||||||
|
"name": "5月",
|
||||||
|
"tempDay": "5~26°C",
|
||||||
|
"kidsWear": "比大人多加一层,薄羽绒服随身带,晚上活动一定穿上",
|
||||||
|
"adultWear": "长袖打底+厚外套(冲锋衣或抓绒),早晚穿羽绒服,怕冷的备秋裤",
|
||||||
|
"highlight": false,
|
||||||
|
"tempNight": "-6~10°C"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"desc": "草原开始变绿,野花初开,气温回升但早晚仍凉",
|
||||||
|
"name": "6月上旬",
|
||||||
|
"tempDay": "10~26°C",
|
||||||
|
"kidsWear": "薄卫衣+可脱卸的外套,书包里塞一件薄羽绒应急",
|
||||||
|
"adultWear": "白天长袖/薄卫衣+轻薄外套,早晚加抓绒衫或薄羽绒,怕晒的备防晒衣",
|
||||||
|
"highlight": false,
|
||||||
|
"tempNight": "1~14°C"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"desc": "草原进入最绿的时候,油菜花陆续开放,白天舒适宜人",
|
||||||
|
"name": "6月下旬",
|
||||||
|
"tempDay": "13~28°C",
|
||||||
|
"kidsWear": "短袖+薄外套,晚上篝火活动加一件长袖",
|
||||||
|
"adultWear": "短袖/T恤+薄外套或防晒衫,早晚加一件卫衣就够了",
|
||||||
|
"highlight": false,
|
||||||
|
"tempNight": "5~18°C"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"desc": "草原最美的季节,满眼绿色+野花,中午会有点晒但不闷热",
|
||||||
|
"name": "7月(最旺季)",
|
||||||
|
"note": "7月中下旬满洲里白天可达34°C,但早晚温差大,出门随身带件外套准没错",
|
||||||
|
"tempDay": "16~34°C",
|
||||||
|
"kidsWear": "短袖+薄长裤(草地上跑建议穿长裤防蚊虫),备一件拉链卫衣随时穿脱",
|
||||||
|
"adultWear": "短袖短裤+防晒衣,早晚加一件薄外套或卫衣。中午紫外线强,帽子墨镜防晒霜三件套必备",
|
||||||
|
"highlight": true,
|
||||||
|
"tempNight": "10~24°C"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"desc": "暑假高峰,下旬起草原渐有秋意,偶有阵雨,雨后特别清爽",
|
||||||
|
"name": "8月",
|
||||||
|
"tempDay": "14~30°C",
|
||||||
|
"kidsWear": "短袖+薄外套,8月下旬出行的建议带一件抓绒",
|
||||||
|
"adultWear": "短袖+轻便外套,下旬建议多带一件厚一点的外套",
|
||||||
|
"highlight": false,
|
||||||
|
"tempNight": "6~20°C"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"desc": "秋色渐浓,白桦林开始变黄,蚊虫基本没了,早晚已经很凉",
|
||||||
|
"name": "9月",
|
||||||
|
"tempDay": "6~24°C",
|
||||||
|
"kidsWear": "长袖+厚外套,薄羽绒必备,帽子手套也建议带着",
|
||||||
|
"adultWear": "长袖+厚外套(冲锋衣或呢大衣),早晚穿薄羽绒或抓绒,围巾也可以带上",
|
||||||
|
"highlight": false,
|
||||||
|
"tempNight": "-4~12°C"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"desc": "秋末接近入冬,部分年份可能飘雪,但秋色也最浓烈",
|
||||||
|
"name": "国庆(10.1-10.7)",
|
||||||
|
"tempDay": "0~18°C",
|
||||||
|
"kidsWear": "同样按冬天标准,注意保暖帽和手套,风大时口罩也带上",
|
||||||
|
"adultWear": "按冬天穿——保暖内衣+毛衣+羽绒服+秋裤,帽子围巾手套齐上",
|
||||||
|
"highlight": false,
|
||||||
|
"tempNight": "-10~6°C"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"extraTips": [
|
||||||
|
"阿尔山海拔较高(约1000米),整体比海拉尔低4-6°C,即使7月晚间也需要外套。走阿尔山线路的客人请额外多带一件保暖衣物。",
|
||||||
|
"鞋子以运动鞋为主,建议带两双换穿。万一踩湿了弄脏了,换着穿不耽误事。不建议穿新鞋出行。高跟鞋、凉鞋在草地上走不了。",
|
||||||
|
"拍照穿浅色、白色、红色、鹅黄色效果好。连衣裙、民族风披肩适合营地晚会和旅拍。带小朋友的家庭可以准备一套亲子装。"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "packing",
|
||||||
|
"title": "行李清单",
|
||||||
|
"subtitle": "该带什么、不该带什么,一目了然",
|
||||||
|
"icon": "🎒",
|
||||||
|
"content": "",
|
||||||
|
"tips": [
|
||||||
|
"出发前记得清理手机存储空间,草原上拍照量很大,很多人到第三天手机就满了。",
|
||||||
|
"部分酒店有洗衣服务,呼籁也会备洗衣液,行程中换洗衣物不用太担心。"
|
||||||
|
],
|
||||||
|
"provided": {
|
||||||
|
"items": "哈达、儿童安全座椅、一次性拖鞋、一次性雨衣+鞋套、骑马手套、一次性马桶垫、蚊不叮、防蚊喷雾、创口贴、洗衣液、卫生巾、牙签线、扑克、指甲刀、头绳、晕车贴、口罩、棉签等",
|
||||||
|
"title": "这些我们已经帮您准备好了",
|
||||||
|
"description": "以下物品不需要自己带,我们会在旅途中为每位客人提供:"
|
||||||
|
},
|
||||||
|
"dontBring": [
|
||||||
|
"大行李箱(车上空间有限,建议1个中号箱+1个随身小包)",
|
||||||
|
"过多现金(手机支付基本全覆盖)",
|
||||||
|
"矿泉水、方便面等日用品(海拉尔超市齐全,不用寄)"
|
||||||
|
],
|
||||||
|
"categories": [
|
||||||
|
{
|
||||||
|
"name": "防晒与护肤",
|
||||||
|
"note": "草原紫外线远比城市里强,防晒不是选做题",
|
||||||
|
"items": [
|
||||||
|
{
|
||||||
|
"text": "防晒霜 SPF50+ PA++++(每隔2小时补涂一次)",
|
||||||
|
"important": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"text": "宽檐帽(帽檐建议10cm以上,渔夫帽最实用)+ UV400墨镜",
|
||||||
|
"important": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"text": "冰袖 + 防晒衣或披肩",
|
||||||
|
"important": false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"text": "保湿面霜 + 润唇膏(草原干燥,嘴唇容易裂)",
|
||||||
|
"important": false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"text": "补水面膜(呼伦贝尔气候偏干,晚上敷一片补补水)",
|
||||||
|
"important": false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"text": "折叠晴雨伞(防晒遮阳、突遇阵雨都能用)",
|
||||||
|
"important": false
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "健康防护",
|
||||||
|
"note": "",
|
||||||
|
"items": [
|
||||||
|
{
|
||||||
|
"text": "防蚊液(6-8月草原蚊虫较多,户外必备)",
|
||||||
|
"important": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"text": "肠胃药 + 益生菌(换了水土,有备无患)",
|
||||||
|
"important": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"text": "晕车药或晕车贴(部分路段弯道较多,提前贴好)",
|
||||||
|
"important": false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"text": "保温杯(多喝温水少喝生水,自带保温杯随时能喝上热水)",
|
||||||
|
"important": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"text": "过敏药/特殊用药(呼伦贝尔当地药店品种有限,请务必从家里带齐)",
|
||||||
|
"important": true
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "电子设备",
|
||||||
|
"note": "",
|
||||||
|
"items": [
|
||||||
|
{
|
||||||
|
"text": "充电宝(必备!请携带有3C认证标志的,不超过27000mAh,乘机需随身携带不可托运)",
|
||||||
|
"important": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"text": "自拍杆或小三脚架",
|
||||||
|
"important": false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"text": "数据线(多带一根备用)",
|
||||||
|
"important": false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"text": "无人机(如有。注意:海拉尔市区、满洲里、室韦、边防公路沿线严禁飞行)",
|
||||||
|
"important": false
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "睡眠相关",
|
||||||
|
"note": "",
|
||||||
|
"items": [
|
||||||
|
{
|
||||||
|
"text": "耳塞或隔音耳罩(蒙古包和木刻楞隔音一般)",
|
||||||
|
"important": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"text": "遮光眼罩(夏季凌晨3-4点天就亮了)",
|
||||||
|
"important": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"text": "U型头枕(车程较长,路上补觉用得上)",
|
||||||
|
"important": false
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "个人洗护",
|
||||||
|
"note": "",
|
||||||
|
"items": [
|
||||||
|
{
|
||||||
|
"text": "自用洗浴拖鞋",
|
||||||
|
"important": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"text": "一次性内衣内裤(旅途中换洗不方便,多备几套)",
|
||||||
|
"important": false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"text": "洗脸巾(一次性的,比酒店毛巾放心)",
|
||||||
|
"important": false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"text": "儿童洗漱用品(当地酒店儿童洗漱用品不太齐全,建议自带)",
|
||||||
|
"important": true
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "activities",
|
||||||
|
"title": "活动安全须知",
|
||||||
|
"subtitle": "各项体验活动的安全要点",
|
||||||
|
"icon": "🛡️",
|
||||||
|
"content": "各项目对儿童的年龄和身高要求不同,具体以领队现场说明为准。有疑问可以提前问客服。",
|
||||||
|
"activities": [
|
||||||
|
{
|
||||||
|
"icon": "🐴",
|
||||||
|
"name": "骑马穿越",
|
||||||
|
"points": [
|
||||||
|
"往返约1小时,马匹都是经过训练的温顺马,全程有专业马师随行",
|
||||||
|
"不太敢骑或不熟练,马师会牵着马走,不额外收费。年龄较小的孩子由马师抱着骑",
|
||||||
|
"请穿长裤和运动鞋,不要穿裙子或拖鞋。呼籁会提前准备骑马手套",
|
||||||
|
"骑马时双手握住缰绳,身体放松,不要大声喊叫或突然拍打马匹",
|
||||||
|
"不要站在马的后面,马匹受惊时可能后踢,请始终从侧面靠近",
|
||||||
|
"请听从马师指引,不要自行策马奔腾"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"icon": "🚙",
|
||||||
|
"name": "ATV全地形越野车",
|
||||||
|
"points": [
|
||||||
|
"每辆车2人一车,请系好安全带,听从教练指引",
|
||||||
|
"行驶中双手紧握扶手,不要将身体任何部位伸出车外",
|
||||||
|
"整队一起行驶,跟紧前车,不要超车、不要脱离队伍",
|
||||||
|
"孕妇、心脏病患者、严重腰椎颈椎疾病者不建议乘坐",
|
||||||
|
"12周岁以下儿童需由家长陪同乘坐",
|
||||||
|
"雨天前后路面泥泞,建议额外备一套换洗衣物"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"icon": "🛝",
|
||||||
|
"name": "滑草(乌兰山景区)",
|
||||||
|
"points": [
|
||||||
|
"不限次数,单次体验约1分钟,很刺激也很过瘾",
|
||||||
|
"身高1.2m以上、体重190斤以内可独立乘坐。身高不足1.2m可和大人一起坐,两人体重相加不超190斤",
|
||||||
|
"请穿运动鞋、长裤,滑行途中不可中途跳车",
|
||||||
|
"请勿佩戴无系绳帽子,高速滑行时帽子飞掉容易遮挡视线",
|
||||||
|
"有心脏病、高血压、关节疾病的客人请量力而行",
|
||||||
|
"大风、下雨等特殊天气时景区娱乐项目暂停开放"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"icon": "🏕️",
|
||||||
|
"name": "呼籁营地",
|
||||||
|
"points": [
|
||||||
|
"营地位于敖包相会景区内,天下第一敖包旁,可俯瞰伊敏河湿地",
|
||||||
|
"营地活动包括旅拍、BBQ等,注意脚下草原坑洼",
|
||||||
|
"营地下方是湿地有一定坡度,请看管好小朋友,不要靠近坡边",
|
||||||
|
"BBQ用餐时注意火源安全,不要让小朋友独自靠近烤炉",
|
||||||
|
"敖包上的石头、经幡和哈达是祭祀物品,请不要随意取走或踩踏",
|
||||||
|
"想添石祈福可以从地上捡一块石头轻轻放上去,顺时针绕敖包走三圈"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"icon": "🐄",
|
||||||
|
"name": "牧场体验",
|
||||||
|
"points": [
|
||||||
|
"包含喂羊、挤牛奶、做奶制品等互动项目",
|
||||||
|
"接触动物后请及时洗手",
|
||||||
|
"不要从动物背后靠近,动作轻柔,避免惊吓到牲畜"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "practical",
|
||||||
|
"title": "实用信息",
|
||||||
|
"subtitle": "几件小事,提前知道更安心",
|
||||||
|
"icon": "💡",
|
||||||
|
"content": "",
|
||||||
|
"apps": [
|
||||||
|
{
|
||||||
|
"names": "巧摄、莉景天气",
|
||||||
|
"category": "查日出日落"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"names": "醒图、Snapseed",
|
||||||
|
"category": "修图"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"names": "美图秀秀、轻颜相机、POCO相机",
|
||||||
|
"category": "拍照美颜"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"names": "天文通(查银河+光污染地图)、Star Walk",
|
||||||
|
"category": "看星空"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"names": "花伴侣、形色,或微信搜「花草日记植物识别」小程序",
|
||||||
|
"category": "认花草"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"names": "一刻相册(出发前同步照片,腾出手机空间)",
|
||||||
|
"category": "腾空间"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"topics": [
|
||||||
|
{
|
||||||
|
"name": "关于保险",
|
||||||
|
"content": "呼籁会提前为每位客人统一购买旅游保险,覆盖骑马、越野车等行程中的活动项目。保单会在出发前发到服务群里,不用自己操心。"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "关于航班",
|
||||||
|
"content": "建议下载「飞常准」或「航旅纵横」App关注航班动态。呼伦贝尔(海拉尔东山机场)直飞航线有限,很多城市需要中转。优先选择经停航班(中途经停但不换飞机)或联程航班(行李可直挂到目的地)。中转注意:确保在同一个机场中转(如北京首都/大兴、上海虹桥/浦东),两段航班之间至少预留2小时以上间隔。"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "关于车程",
|
||||||
|
"content": "呼伦贝尔面积相当于山东省,景点之间距离较远,单日车程在2-5小时不等。不过沿途风景很美,草原、湿地、白桦林不断变换。带小朋友的家庭建议准备iPad、故事书、小零食,车上配有充电接口。"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "关于信号",
|
||||||
|
"content": "大部分路段有4G信号,营地WiFi正常。深入草原腹地时部分路段信号会弱,建议提前下载好离线地图和娱乐内容。"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "关于打车和外卖",
|
||||||
|
"content": "海拉尔、额尔古纳、满洲里市区内滴滴、高德打车都很方便,也可以叫外卖。恩和、莫尔道嘎、黑山头等小镇打车和外卖不太方便。海拉尔市区出租车热线:0470-8898888,白天起步价6元/2公里,夜间6.8元/2公里。"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "关于饮食",
|
||||||
|
"content": "当地饮食以牛羊肉和奶制品为主,口味偏咸香。肠胃敏感的客人头两天建议少量尝试。如果有忌口或特殊饮食需求(回民餐、素食、海鲜过敏、儿童忌辣等),请提前告知客服和领队。"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "关于蚊虫",
|
||||||
|
"content": "6-8月户外活动时会有蚊虫,湿地区域7月中旬为高峰期。日出前和日落后蚊虫最活跃。穿浅色长袖长裤效果最好,深色衣服反而容易招蚊子。呼籁随车备有蚊不叮和防蚊喷雾。"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "关于蜱虫",
|
||||||
|
"content": "草原上偶尔会有蜱虫,户外活动时穿长袖长裤、扎紧裤脚和袖口。每天活动结束后仔细检查皮肤(尤其腋下、腰部、发际线、耳后)。万一发现蜱虫叮咬,不要用手硬拽,用尖头镊子贴近皮肤夹住蜱虫头部垂直拔出,碘伏消毒。如有不适及时就医,领队随身携带急救包。"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "关于草原天气",
|
||||||
|
"content": "呼伦贝尔平均海拔600-800米,不会高反,老人小朋友都可以放心来。草原夏季降雨以短暂阵雨为主,来得快去得也快,雨后容易遇到彩虹和晚霞。白天可能接近或超过30°C,但高温只集中在中午前后,行程会避开最热时段。"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"appNote": "草原日出约凌晨3:30-4:30,日落约19:00-20:30(不同月份有差异)。夏季银河肉眼可见。"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "toddler",
|
||||||
|
"title": "0-3岁幼童专属指南",
|
||||||
|
"subtitle": "孩子小,不代表无法旅行,而是应该被更细致地呵护",
|
||||||
|
"icon": "👶",
|
||||||
|
"content": "为了让小宝宝也能轻松融入旅程,根据项目特点和幼童安全需求整理了这份指南。请结合孩子当天的状态灵活安排,不必每个项目都参与。",
|
||||||
|
"notes": [
|
||||||
|
{
|
||||||
|
"title": "关于费用",
|
||||||
|
"content": "幼童仅收取500元费用,不强制参与任何项目。如参与项目产生额外成本,均由呼籁承担。"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"title": "关于灵活调整",
|
||||||
|
"content": "行程安排灵活,如宝宝临时不适,可随时与领队协商调整节奏或选择暂时休息。"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"title": "关于家庭陪伴",
|
||||||
|
"content": "所有活动均考虑了家庭陪伴场景设计,父母可轮流参与,不必担心一人抱娃一人玩的情况。"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"dining": [
|
||||||
|
"行程中多数用餐点提供热水,方便冲泡奶粉或加热辅食",
|
||||||
|
"BBQ为自助形式,可灵活选择适合宝宝的食材(蔬菜、软面包等),避免辛辣和过硬食物",
|
||||||
|
"如宝宝有特殊饮食需求(过敏、素食等),报名时备注,提前与餐厅沟通",
|
||||||
|
"建议自带少量宝宝常吃的零食和辅食"
|
||||||
|
],
|
||||||
|
"equipment": [
|
||||||
|
{
|
||||||
|
"desc": "呼籁车辆可提供,报名时告知定制师孩子的年龄和体重",
|
||||||
|
"name": "儿童安全座椅",
|
||||||
|
"provided": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"desc": "呼籁提供,需提前7天预约(旺季数量有限)",
|
||||||
|
"name": "儿童床围栏",
|
||||||
|
"provided": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"desc": "奶瓶、辅食工具、常用药品、保温杯、轻便推车(草原建议大轮款)、防晒帽、薄外套",
|
||||||
|
"name": "建议自带物品",
|
||||||
|
"provided": false
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"conditional": {
|
||||||
|
"desc": "建议现场评估孩子状态后再决定",
|
||||||
|
"items": [
|
||||||
|
{
|
||||||
|
"desc": "自助式可灵活安排用餐节奏,注意让孩子远离烤架区域。",
|
||||||
|
"icon": "🍖",
|
||||||
|
"name": "呼籁BBQ"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"desc": "场地较大、人流较多。若宝宝易紧张或对声音敏感,可在边缘观赏或提前离场。",
|
||||||
|
"icon": "🎪",
|
||||||
|
"name": "套娃广场/马之舞"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"desc": "部分设备有身高限制,建议家长到现场后根据实际情况选择合适项目。",
|
||||||
|
"icon": "🎠",
|
||||||
|
"name": "满洲里梦幻游乐"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"title": "视情况选择的项目"
|
||||||
|
},
|
||||||
|
"recommended": {
|
||||||
|
"desc": "适合陪伴式参与或安静观赏,温和、安全、有互动感",
|
||||||
|
"items": [
|
||||||
|
{
|
||||||
|
"desc": "温和安全,可抱着孩子亲密互动。营地环境安静,适合低龄宝宝放松玩耍。",
|
||||||
|
"icon": "🐑",
|
||||||
|
"name": "营地喂小羊"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"desc": "家庭旅拍可抱娃合影,服装也有宝宝尺码,可自由选择是否换装。",
|
||||||
|
"icon": "📸",
|
||||||
|
"name": "呼籁旅拍"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"desc": "安排专属时间段,宝宝可在家长陪同下安全观赏和投喂(已含饲料)。",
|
||||||
|
"icon": "🦌",
|
||||||
|
"name": "白桦林驯鹿"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"desc": "草原景观舒适安静,适合家长轮流照看孩子,轻松拍照休息。",
|
||||||
|
"icon": "☕",
|
||||||
|
"name": "牧云山顶下午茶"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"desc": "环节温和,适合亲子共创。2岁以下建议由家长陪同操作。",
|
||||||
|
"icon": "🎨",
|
||||||
|
"name": "DIY套娃/做列巴"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"desc": "彩色顶棚遮阳游乐设施,配有小滑梯和安全围栏,宝宝可在家长陪同下自由攀爬玩耍。",
|
||||||
|
"icon": "🎪",
|
||||||
|
"name": "营地儿童游乐架"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"desc": "晃动幅度温和,适合家长抱着宝宝一起荡。",
|
||||||
|
"icon": "🛞",
|
||||||
|
"name": "草原轮胎秋千"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"title": "推荐参与的项目"
|
||||||
|
},
|
||||||
|
"notRecommended": {
|
||||||
|
"desc": "对低龄宝宝安全性或体验感不佳,建议家长自行体验,宝宝由另一位家长陪伴",
|
||||||
|
"items": [
|
||||||
|
{
|
||||||
|
"name": "沉浸式骑马穿越",
|
||||||
|
"reason": "路线含草原、森林、河流、坡地,幼儿无法独立骑乘"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "ATV越野车穿越",
|
||||||
|
"reason": "震动强烈、地形不平,不适合2岁以下宝宝"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "乌兰山千米滑草",
|
||||||
|
"reason": "速度较快且有坡度,若孩子容易害怕不建议参加"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "射箭/油桶火车",
|
||||||
|
"reason": "存在晃动、冲击风险,宝宝无法安全控制身体平衡"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"title": "不建议参与的项目"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
46
data/images.json
普通文件
46
data/images.json
普通文件
@ -0,0 +1,46 @@
|
|||||||
|
{
|
||||||
|
"brandStory": {
|
||||||
|
"photo": "/images/team/hero-family.jpg"
|
||||||
|
},
|
||||||
|
"hero": {
|
||||||
|
"background": "/images/team/hero-grassland.jpg"
|
||||||
|
},
|
||||||
|
"logo": {
|
||||||
|
"main": "/images/logo.png",
|
||||||
|
"square": "/images/logo-square.png"
|
||||||
|
},
|
||||||
|
"mascot": {
|
||||||
|
"banner": "/images/mascot/mascot-banner.png",
|
||||||
|
"front": "/images/mascot/mascot-front.png",
|
||||||
|
"stickerQr": "/images/mascot-sticker-qr.png",
|
||||||
|
"xiaomengma": "/images/mascot/xiaomengma.png"
|
||||||
|
},
|
||||||
|
"seasons": {
|
||||||
|
"autumn-forest": "/images/seasons/autumn-forest.jpg",
|
||||||
|
"autumn-hero": "/images/seasons/autumn-hero.jpg",
|
||||||
|
"autumn-tianchi": "/images/seasons/autumn-tianchi.jpg",
|
||||||
|
"autumn-train": "/images/seasons/autumn-train.jpg",
|
||||||
|
"summer-car": "/images/seasons/summer-car.jpg",
|
||||||
|
"summer-hero": "/images/seasons/summer-hero.jpg",
|
||||||
|
"summer-river": "/images/seasons/summer-river.jpg",
|
||||||
|
"winter-frost": "/images/seasons/winter-frost.jpg",
|
||||||
|
"winter-hero": "/images/seasons/winter-hero.jpg",
|
||||||
|
"winter-tree": "/images/seasons/winter-tree.jpg",
|
||||||
|
"winter-yurt": "/images/seasons/winter-yurt.jpg"
|
||||||
|
},
|
||||||
|
"summerCamp": {
|
||||||
|
"birch": "/images/summer-camp/birch-group.jpg",
|
||||||
|
"graduation": "/images/summer-camp/camp-graduation.jpg",
|
||||||
|
"grassland": "/images/summer-camp/grassland-group.jpg",
|
||||||
|
"river": "/images/summer-camp/river-banner.jpg"
|
||||||
|
},
|
||||||
|
"team": {
|
||||||
|
"guideGroup": "/images/team/guide-group.jpg",
|
||||||
|
"guideTraining": "/images/team/guide-training.jpg",
|
||||||
|
"ranchStore": "/images/team/ranch-store.jpg",
|
||||||
|
"routeSurvey": "/images/team/route-survey-2025.jpg"
|
||||||
|
},
|
||||||
|
"xiaohongshu": {
|
||||||
|
"storefront": "/images/xiaohongshu/storefront.jpg"
|
||||||
|
}
|
||||||
|
}
|
||||||
124
data/navigation.json
普通文件
124
data/navigation.json
普通文件
@ -0,0 +1,124 @@
|
|||||||
|
{
|
||||||
|
"header": [
|
||||||
|
{
|
||||||
|
"text": "首页",
|
||||||
|
"to": "/"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"text": "产品线",
|
||||||
|
"to": "/products",
|
||||||
|
"children": [
|
||||||
|
{
|
||||||
|
"to": "/products",
|
||||||
|
"text": "额吉的故乡",
|
||||||
|
"season": "夏"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"to": "/products/autumn",
|
||||||
|
"text": "游牧的森林",
|
||||||
|
"season": "秋"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"to": "/products/winter",
|
||||||
|
"text": "嗨冰雪",
|
||||||
|
"season": "冬"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"to": "/summer-camp",
|
||||||
|
"text": "小蒙马夏令营",
|
||||||
|
"season": "夏"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"to": "/winter-camp",
|
||||||
|
"text": "小蒙马冬季营",
|
||||||
|
"season": "冬"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"text": "客户评价",
|
||||||
|
"to": "/reviews"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"text": "出行指南",
|
||||||
|
"to": "/guides"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"text": "常见问答",
|
||||||
|
"to": "/faq"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"text": "关于我们",
|
||||||
|
"to": "/about"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"text": "联系我们",
|
||||||
|
"to": "/contact"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"footer": [
|
||||||
|
{
|
||||||
|
"title": "了解呼籁",
|
||||||
|
"links": [
|
||||||
|
{
|
||||||
|
"text": "关于我们",
|
||||||
|
"to": "/about"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"text": "品牌故事",
|
||||||
|
"to": "/about#story"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"text": "团队介绍",
|
||||||
|
"to": "/about#team"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"title": "旅行产品",
|
||||||
|
"links": [
|
||||||
|
{
|
||||||
|
"text": "额吉的故乡",
|
||||||
|
"to": "/products"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"text": "游牧的森林",
|
||||||
|
"to": "/products/autumn"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"text": "嗨冰雪",
|
||||||
|
"to": "/products/winter"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"text": "小蒙马夏令营",
|
||||||
|
"to": "/summer-camp"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"text": "小蒙马冬季营",
|
||||||
|
"to": "/winter-camp"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"title": "帮助中心",
|
||||||
|
"links": [
|
||||||
|
{
|
||||||
|
"text": "出行指南",
|
||||||
|
"to": "/guides"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"text": "常见问答",
|
||||||
|
"to": "/faq"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"text": "客户评价",
|
||||||
|
"to": "/reviews"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"text": "联系我们",
|
||||||
|
"to": "/contact"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
44
data/news.json
普通文件
44
data/news.json
普通文件
@ -0,0 +1,44 @@
|
|||||||
|
{
|
||||||
|
"articles": [
|
||||||
|
{
|
||||||
|
"id": "news-3",
|
||||||
|
"title": "额吉的故乡V9正式发布:三大升级,一家一车",
|
||||||
|
"date": "2026-03-08",
|
||||||
|
"category": null,
|
||||||
|
"summary": "呼籁旅行2026夏季旗舰产品「额吉的故乡V9」正式发布。V9在V8基础上完成三大升级:营地迁入敖包召回景区、白桦林新增非遗传承人课程、深度合作云牧场。6天5晚,一家一车,5月开始接待。",
|
||||||
|
"content": "2026年3月7-8日,呼籁旅行2026夏季旗舰产品「额吉的故乡V9」正式对外发布。V9是额吉的故乡系列的第9次迭代,从2023年V1上线至今,已服务超过10000组家庭、39000余人次。本次V9在V8基础上完成三大核心升级:一、营地升级——呼籁自营营地迁入敖包召回景区,在景区内拥有独立空间,上午安排营地烧烤和旅拍,避开下午客流高峰;二、非遗研学升级——白桦林增设非遗传承人专属课程,按年龄分层设计体验内容;三、牧场升级——与云牧场达成深度合作,体验近距离牧场互动,同时在附近自营空间安排蒙古包体验、捡牛粪、酥油茶、手工毡等活动。产品为6天5晚行程,分舒适套餐和尊享套餐两个版本,全程一家一单一车、独立成团。预售期间下单享早鸟优惠,5月正式开始接待。"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "news-4",
|
||||||
|
"title": "2026小蒙马亲子夏令营开放报名",
|
||||||
|
"date": "2026-02-20",
|
||||||
|
"category": null,
|
||||||
|
"summary": "2026年小蒙马亲子夏令营正式开放报名,7天6晚,每期最多8组家庭,涵盖草原、森林、湿地三大研学模块,全程路虎头等舱车队、专属摄影师跟拍。",
|
||||||
|
"content": "2026年小蒙马亲子夏令营正式开放报名。小蒙马是呼籁旅行专为家庭设计的深度营地产品,行程7天6晚,每期最多8组家庭同行。课程围绕草原、森林、湿地三大研学模块设计,包含恩和骑马、乌兰山滑草、ATV越野、面包DIY、兰旗果舍等体验。全程配备路虎头等舱车队,每组家庭配专属摄影师全程跟拍。2026年夏季计划开设9期,名额有限,报名请联系定制师获取详细方案和排期。"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "news-5",
|
||||||
|
"title": "呼籁营地迁入敖包召回景区,2026赛季全面升级",
|
||||||
|
"date": "2026-02-10",
|
||||||
|
"category": null,
|
||||||
|
"summary": "呼籁自营营地正式迁入敖包召回景区,签约5年(2026-2030),在景区内拥有独立空间和品牌IP,2026年5月正式开营。",
|
||||||
|
"content": "呼籁旅行自营营地已完成选址升级,正式迁入敖包召回景区。此次合作签约5年(2026-2030),呼籁在景区内拥有独立运营空间,品牌IP归呼籁所有。新营地的核心优势是行程节奏的优化:上午在营地完成旅拍和烧烤,下午再进入莫日格勒河景区,避开游客高峰时段。营地将于2026年5月正式开营,届时将配合额吉的故乡V9产品一同投入使用。"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "news-6",
|
||||||
|
"title": "呼籁2025年度回顾:累计服务家庭突破10000组",
|
||||||
|
"date": "2026-01-15",
|
||||||
|
"category": null,
|
||||||
|
"summary": "呼籁旅行2025年度接待约18000人次,自2015年创立以来,累计服务家庭突破10000组、39000余人次。感谢每一个信任呼籁的家庭。",
|
||||||
|
"content": "回顾2025年,呼籁旅行全年接待约18000人次。自2015年创立以来,呼籁累计服务家庭已突破10000组,共计39000余人次踏上呼伦贝尔草原。这一年,额吉的故乡从V8迭代到V9,小蒙马亲子夏令营正式上线,自有车队和自营营地投入运营——这些变化的背后,是每一个选择信任呼籁的家庭给了我们持续投入的底气。2026年,我们会继续深耕呼伦贝尔家庭定制游,把更多精力放在服务本身。"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "news-7",
|
||||||
|
"title": "呼籁荣获小红书WILL商业大会「年度成长型品牌」",
|
||||||
|
"date": "2026-01-05",
|
||||||
|
"category": null,
|
||||||
|
"summary": "呼籁旅行在2026小红书WILL商业大会上荣获「年度成长型品牌」,全国文旅行业仅6家品牌获此荣誉。6家品牌中,呼籁是深耕单一目的地的本地品牌代表。",
|
||||||
|
"content": "在2026年小红书WILL商业大会上,呼籁旅行荣获「年度成长型品牌」称号。全国文旅行业仅6家品牌入选,6家品牌中,呼籁是深耕单一目的地的本地品牌代表。呼籁小红书账号「Mr.小雷-呼籁旅行」由联合创始人孙雷运营,目前拥有9.5万+粉丝。这份荣誉属于每一位愿意在小红书分享呼伦贝尔旅行故事的客户和伙伴。"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
56
data/partners.json
普通文件
56
data/partners.json
普通文件
@ -0,0 +1,56 @@
|
|||||||
|
{
|
||||||
|
"govPartners": [
|
||||||
|
{
|
||||||
|
"name": "测试合作伙伴",
|
||||||
|
"description": "合作描述",
|
||||||
|
"website": null,
|
||||||
|
"verified": true
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"associations": [
|
||||||
|
{
|
||||||
|
"name": "内蒙古自治区文化和旅游厅",
|
||||||
|
"description": "政府主管部门|颁发旅游经营许可证·认定研学旅游服务商",
|
||||||
|
"website": null,
|
||||||
|
"verified": true
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"academicCoops": [
|
||||||
|
{
|
||||||
|
"name": "呼伦贝尔学院",
|
||||||
|
"description": "高校合作|旅游实习实训基地|校企合作,共同培养旅游管理专业人才,实践教学基地|合作始于:2024",
|
||||||
|
"website": null,
|
||||||
|
"verified": true
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"scenicPartners": [
|
||||||
|
{
|
||||||
|
"name": "莫日格勒河景区",
|
||||||
|
"description": "呼籁行程核心目的地,提供专属通道和深度体验项目",
|
||||||
|
"website": null,
|
||||||
|
"verified": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "额尔古纳湿地公园",
|
||||||
|
"description": "国家级自然保护区,呼籁行程必经目的地",
|
||||||
|
"website": null,
|
||||||
|
"verified": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "黑山头景区",
|
||||||
|
"description": "呼籁自有骑马营地所在地,独家草原骑马体验",
|
||||||
|
"website": null,
|
||||||
|
"verified": true
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"hotelPartners": [],
|
||||||
|
"platformEndorsements": [
|
||||||
|
{
|
||||||
|
"name": "小红书",
|
||||||
|
"description": "2025年度成长型品牌·2026 WILL商业大会受邀品牌|蓝V认证·旅行社|粉丝:9.5万+|账号:Mr.小雷-呼籁旅行",
|
||||||
|
"website": null,
|
||||||
|
"verified": true
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"mediaReports": []
|
||||||
|
}
|
||||||
164
data/pricing.json
普通文件
164
data/pricing.json
普通文件
@ -0,0 +1,164 @@
|
|||||||
|
{
|
||||||
|
"products": [
|
||||||
|
{
|
||||||
|
"id": "v9-4d3n",
|
||||||
|
"name": "额吉的故乡V9·4天3晚 精华版",
|
||||||
|
"priceLabel": "详询定制师",
|
||||||
|
"priceNote": "价格因人数、住宿选择和出行季节有所不同,请联系定制师获取专属报价",
|
||||||
|
"highlights": [
|
||||||
|
"莫日格勒河草原深度穿越",
|
||||||
|
"黑山头骑马",
|
||||||
|
"走访蒙古族牧户家庭"
|
||||||
|
],
|
||||||
|
"url": "/products/v9-4d3n"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "v9-5d4n-forest",
|
||||||
|
"name": "额吉的故乡V9·5天4晚 森林版",
|
||||||
|
"priceLabel": "2580元起",
|
||||||
|
"priceNote": "舒适套餐2580-4780元/人,高档套餐3380-5880元/人,价格因出行日期和住宿等级不同",
|
||||||
|
"highlights": [
|
||||||
|
"草原+大兴安岭森林双线深度",
|
||||||
|
"森林小火车+兴安神鹿园",
|
||||||
|
"恩和骑马+全地形越野车"
|
||||||
|
],
|
||||||
|
"url": "/products/v9-5d4n"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "v9-5d4n-prairie",
|
||||||
|
"name": "额吉的故乡V9·5天4晚 草原版",
|
||||||
|
"priceLabel": "2580元起",
|
||||||
|
"priceNote": "舒适套餐2580-4780元/人,高档套餐3380-5880元/人,价格因出行日期和住宿等级不同",
|
||||||
|
"highlights": [
|
||||||
|
"草原+边境+满洲里不进森林",
|
||||||
|
"寻龙诀秘境+套娃大马戏",
|
||||||
|
"巴尔虎马之舞实景演出"
|
||||||
|
],
|
||||||
|
"url": "/products/v9-5d4n"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "v9-5d4n",
|
||||||
|
"name": "额吉的故乡V9·5天4晚 经典版",
|
||||||
|
"priceLabel": "详询定制师",
|
||||||
|
"priceNote": "最受欢迎的版本,报价需结合家庭人数和住宿等级,请联系定制师",
|
||||||
|
"highlights": [
|
||||||
|
"额尔古纳湿地全景",
|
||||||
|
"白桦林漫步",
|
||||||
|
"中俄边境公路"
|
||||||
|
],
|
||||||
|
"url": "/products/v9-5d4n"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "v9-6d5n-family",
|
||||||
|
"name": "额吉的故乡V9·6天5晚 亲子版",
|
||||||
|
"priceLabel": "详询定制师",
|
||||||
|
"priceNote": "包含旅拍服务,具体报价根据孩子年龄和活动需求定制,请联系定制师",
|
||||||
|
"highlights": [
|
||||||
|
"草原营地亲子活动",
|
||||||
|
"蒙古族手工体验",
|
||||||
|
"旅拍服务200+服饰"
|
||||||
|
],
|
||||||
|
"url": "/products/v9-6d5n-family"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "v9-6d5n-explore",
|
||||||
|
"name": "额吉的故乡V9·6天5晚 探索版",
|
||||||
|
"priceLabel": "2980元起",
|
||||||
|
"priceNote": "舒适套餐2980-5480元/人,高档套餐3980-6980元/人,含自有营地旅拍+两次骑马",
|
||||||
|
"highlights": [
|
||||||
|
"自有营地旅拍+大力山穿越",
|
||||||
|
"恩和+黑山头两次骑马",
|
||||||
|
"寻龙诀秘境+满洲里国门"
|
||||||
|
],
|
||||||
|
"url": "/products/v9-6d5n-comfort"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "v9-7d6n-family",
|
||||||
|
"name": "额吉的故乡V9·7天6晚 亲子版",
|
||||||
|
"priceLabel": "3680元起",
|
||||||
|
"priceNote": "舒适套餐3680-6280元/人,高档套餐4580-7980元/人,最完整亲子深度版",
|
||||||
|
"highlights": [
|
||||||
|
"自有营地旅拍+非遗传承人授课",
|
||||||
|
"森林小火车+驯鹿+蒙古文化",
|
||||||
|
"寻龙诀秘境+套娃+马之舞"
|
||||||
|
],
|
||||||
|
"url": "/products/v9-7d6n-family"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "v9-6d5n-comfort",
|
||||||
|
"name": "额吉的故乡V9·6天5晚 探索版",
|
||||||
|
"priceLabel": "详询定制师",
|
||||||
|
"priceNote": "全程精选品质酒店,住宿标准提升,请联系定制师获取报价",
|
||||||
|
"highlights": [
|
||||||
|
"全程精选品质酒店",
|
||||||
|
"休闲节奏设计",
|
||||||
|
"深度体验不赶路"
|
||||||
|
],
|
||||||
|
"url": "/products/v9-6d5n-comfort"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "v9-7d6n-wild",
|
||||||
|
"name": "额吉的故乡V9·7天6晚 旷野版",
|
||||||
|
"priceLabel": "6480元起",
|
||||||
|
"priceNote": "高端套餐6480-8680元/人,含装甲车穿越+湿地漂流+帐篷营地+航拍",
|
||||||
|
"highlights": [
|
||||||
|
"装甲车穿越+湿地漂流",
|
||||||
|
"帐篷营地+草原木屋特色住宿",
|
||||||
|
"寻龙诀秘境+专业航拍"
|
||||||
|
],
|
||||||
|
"url": "/products/v9-7d6n-wild"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "summer-camp",
|
||||||
|
"name": "小蒙马夏令营",
|
||||||
|
"priceLabel": "详询定制师",
|
||||||
|
"priceNote": "每期仅限8组家庭,名额有限,请提前联系定制师了解营期和报名方式",
|
||||||
|
"highlights": [
|
||||||
|
"草原写生·非遗研学·民俗体验",
|
||||||
|
"每期仅限8组家庭",
|
||||||
|
"含爸妈托管时段"
|
||||||
|
],
|
||||||
|
"url": "/summer-camp"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "autumn",
|
||||||
|
"name": "游牧的森林·秋季产品",
|
||||||
|
"priceLabel": "详询定制师",
|
||||||
|
"priceNote": "秋季产品根据出行日期和人数定制,请联系定制师获取最新报价",
|
||||||
|
"highlights": [
|
||||||
|
"大兴安岭秋色",
|
||||||
|
"白桦林金黄",
|
||||||
|
"额尔古纳秋景"
|
||||||
|
],
|
||||||
|
"url": "/products/autumn"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"intro": "呼籁旅行定制游按家庭整体报价,非人头计费。报价包含全程住宿、餐饮、景区交通、领队服务,不含大交通(飞机/火车)和个人消费。签正规电子合同,购买1000万旅游责任险,报价后2小时内回复。",
|
||||||
|
"included": [
|
||||||
|
"全程住宿(3-4星精选酒店/特色民宿/营地帐篷)",
|
||||||
|
"全程餐饮(特色草原餐、营地BBQ)",
|
||||||
|
"全程专属车辆(商务车/越野车)",
|
||||||
|
"专职领队全程陪同服务",
|
||||||
|
"核心景点门票(含呼籁自营营地体验)",
|
||||||
|
"旅游意外险 + 1000万旅游责任险",
|
||||||
|
"行程期间24小时紧急服务"
|
||||||
|
],
|
||||||
|
"excluded": [
|
||||||
|
"往返大交通(飞机/高铁/火车票)",
|
||||||
|
"个人消费(纪念品、自选活动等)",
|
||||||
|
"部分自费景点(如需要单独购票的景区)",
|
||||||
|
"护照、签注等证件费用"
|
||||||
|
],
|
||||||
|
"philosophy": {
|
||||||
|
"title": "价格透明,不绕弯子",
|
||||||
|
"honestNote": "我们不做低价吸引再加收各种费用的事。报价就是总价。",
|
||||||
|
"content": "报价后会详细说明包含和不包含的项目,没有任何隐形消费。定制游按家庭整体报价,一个家庭无论几口人都是统一价,不按人头收费。不同住宿等级价格有差异,我们会提供几档方案供选择。",
|
||||||
|
"promise": "对报价有任何疑问,欢迎直接问。我们的定制师会在2小时内详细回复。"
|
||||||
|
},
|
||||||
|
"cta": {
|
||||||
|
"title": "获取专属报价",
|
||||||
|
"description": "告诉我们家庭人数、出行时间、大概预算,定制师2小时内给出详细方案",
|
||||||
|
"to": "/contact",
|
||||||
|
"button": "联系定制师获取报价"
|
||||||
|
}
|
||||||
|
}
|
||||||
202
data/products.json
普通文件
202
data/products.json
普通文件
@ -0,0 +1,202 @@
|
|||||||
|
{
|
||||||
|
"narrative": "「额吉的故乡」是蒙古语中对母亲故土的深情称呼。这条定制游产品线从2023年诞生至今,已经迭代到了第9个版本。我们根据不同家庭的假期长度、孩子年龄和旅行偏好,打磨出6个版本——不是简单地增减天数,而是针对每一类家庭的需求重新设计节奏、线路和体验内容。每一个版本都遵循同一个承诺:一家一单一车,全程私家定制游,您的假期只属于您的家庭。",
|
||||||
|
"versions": [
|
||||||
|
{
|
||||||
|
"id": "v9-4d3n",
|
||||||
|
"name": "额吉的故乡V9·4天3晚",
|
||||||
|
"days": 4,
|
||||||
|
"nights": 3,
|
||||||
|
"audience": "假期有限的家庭、初次体验草原",
|
||||||
|
"description": "呼伦贝尔定制游精华浓缩版,用4天时间串联最核心的风光与体验。一家一单一车,从海拉尔出发,穿越莫日格勒河草原腹地,抵达中俄边境小镇室韦,途经黑山头骑马,最终在满洲里收官。行程紧凑但不赶路,每一天都有记忆点。",
|
||||||
|
"highlights": [
|
||||||
|
"莫日格勒河草原深度穿越,走进\"天下第一曲水\"的怀抱",
|
||||||
|
"黑山头专业马场骑马体验,在草原上策马奔腾",
|
||||||
|
"走访蒙古族牧户家庭,亲手挤牛奶、品尝手工奶制品"
|
||||||
|
],
|
||||||
|
"tag": "精华版"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "v9-5d4n",
|
||||||
|
"name": "额吉的故乡V9·5天4晚",
|
||||||
|
"days": 5,
|
||||||
|
"nights": 4,
|
||||||
|
"audience": "希望深度体验又兼顾时间的家庭",
|
||||||
|
"description": "最受欢迎的经典版本,5天4晚覆盖呼伦贝尔精华景观和核心体验。在精华版基础上,增加了额尔古纳湿地、白桦林和中俄边境公路等标志性内容,体验层次更丰富,行程节奏刚刚好——既不浪费假期,也不走马观花。",
|
||||||
|
"highlights": [
|
||||||
|
"登临额尔古纳湿地——\"亚洲第一湿地\"的壮阔全景尽收眼底",
|
||||||
|
"漫步白桦林,感受大兴安岭林区的静谧与诗意",
|
||||||
|
"驰骋中俄边境公路,一侧草原一侧界河,风景绝美"
|
||||||
|
],
|
||||||
|
"tag": "经典版"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "v9-6d5n-family",
|
||||||
|
"name": "额吉的故乡V9·6天5晚亲子版",
|
||||||
|
"days": 6,
|
||||||
|
"nights": 5,
|
||||||
|
"audience": "带3-10岁孩子的家庭",
|
||||||
|
"description": "呼伦贝尔亲子定制游的代表版本,行程节奏配合孩子的体能和注意力,每天安排适龄的互动体验。一家一单一车,营地活动、亲子手工、草原游戏穿插其中,让孩子不只是「跟着走」,而是真正参与到旅行中来。同时配备旅拍服务,为全家留下草原上最自然的影像记录。",
|
||||||
|
"highlights": [
|
||||||
|
"草原营地活动——放风筝、踢足球、搭帐篷,孩子撒欢的天堂",
|
||||||
|
"亲子互动体验——蒙古族手工制作、奶制品DIY、草原寻宝",
|
||||||
|
"呼籁营地定点旅拍,200+服饰可选,定格全家最自然的欢笑"
|
||||||
|
],
|
||||||
|
"tag": "亲子版"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "v9-6d5n-comfort",
|
||||||
|
"name": "额吉的故乡V9·6天5晚探索版",
|
||||||
|
"days": 6,
|
||||||
|
"nights": 5,
|
||||||
|
"audience": "注重住宿品质的家庭、带老人出行",
|
||||||
|
"description": "同样的定制游线路精华,更从容的旅行节奏。一家一单一车,全程精选当地品质酒店,每天行车时间控制在合理范围,留出充足的休息和自由活动时间。适合对住宿有要求的家庭、带老人同行的家庭,或者只是想让旅行更松弛一些的人。少赶一段路,多看一会儿风景。",
|
||||||
|
"highlights": [
|
||||||
|
"全程精选品质酒店,告别标准化快捷酒店,每晚都住得舒心",
|
||||||
|
"休闲节奏设计,每天行车不超额,留足时间享受当下",
|
||||||
|
"深度体验优先——不追求打卡数量,每个地方都停够、看够、感受够"
|
||||||
|
],
|
||||||
|
"tag": "探索版"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "v9-7d6n-family",
|
||||||
|
"name": "额吉的故乡V9·7天6晚亲子版",
|
||||||
|
"days": 7,
|
||||||
|
"nights": 6,
|
||||||
|
"audience": "假期充足、希望深度探索的亲子家庭",
|
||||||
|
"description": "最完整的亲子深度版本,7天时间从容走遍呼伦贝尔精华,每一天都有不同主题的体验。草原、森林、湿地、边境小镇——多元地貌轮番呈现,活动内容从骑马到手工到自然探索一应俱全,配合全程摄影跟拍,是送给孩子最好的暑假礼物。",
|
||||||
|
"highlights": [
|
||||||
|
"全程深度不赶路,7天覆盖草原、湿地、森林、边境四大主题",
|
||||||
|
"多元活动贯穿全程——骑马、射箭、手工、自然课堂,天天有新鲜",
|
||||||
|
"专业摄影师全程跟拍,旅行结束即获精修家庭影像大片"
|
||||||
|
],
|
||||||
|
"tag": "深度亲子版"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "v9-7d6n-wild",
|
||||||
|
"name": "额吉的故乡V9·7天6晚狂野版",
|
||||||
|
"days": 7,
|
||||||
|
"nights": 6,
|
||||||
|
"audience": "追求深度体验、热爱户外的家庭",
|
||||||
|
"description": "为热爱户外探索的家庭量身定制的硬核版本。一家一单一车,解锁牧云山顶日落、ATV草原穿越、寻龙诀秘境等独家体验,深入常规线路到不了的地方。适合孩子年龄稍大、体能较好的家庭,也适合二刷呼伦贝尔想要全新体验的老朋友。",
|
||||||
|
"highlights": [
|
||||||
|
"牧云山顶看日落——登上草原最高处,360度金色草海尽收眼底",
|
||||||
|
"ATV全地形车草原穿越,肾上腺素拉满的草原越野体验",
|
||||||
|
"寻龙诀秘境探秘,深入人迹罕至的草原腹地,发现隐藏风景"
|
||||||
|
],
|
||||||
|
"tag": "狂野版"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"summerCamp": {
|
||||||
|
"name": "小蒙马夏令营",
|
||||||
|
"positioning": "孩子在探索世界,你也在找回自己。小蒙马是呼籁旅行打造的呼伦贝尔草原亲子夏令营路线,6天5晚,每期仅限8组家庭同行,爸爸妈妈带着孩子一起出发,行程融入草原写生、非遗研学、民俗体验三大主题,孩子沉浸式学习成长,大人也能真正被照顾、被理解,找回属于自己的节奏。",
|
||||||
|
"days": 6,
|
||||||
|
"nights": 5,
|
||||||
|
"sessions": {
|
||||||
|
"2025": 11,
|
||||||
|
"2026plan": 30
|
||||||
|
},
|
||||||
|
"principles": [
|
||||||
|
"住得好、不赶路",
|
||||||
|
"玩得深、有特色",
|
||||||
|
"大人孩子都照顾",
|
||||||
|
"走心不走马观花"
|
||||||
|
],
|
||||||
|
"coreActivities": [],
|
||||||
|
"itinerary": [
|
||||||
|
"Day1 全国→海拉尔|接机入住,调整状态",
|
||||||
|
"Day2 海拉尔→牧云山顶音乐会→图嘎营地亲子破冰+游戏互动|爸妈托管时间",
|
||||||
|
"Day3 图嘎→莫尔格勒河写生→白桦林非遗研学+喂驯鹿→望见林悦|连住两晚不搬家",
|
||||||
|
"Day4 望见林悦→恩和骑马→华俄后裔家做列巴→UTV→河边烧烤",
|
||||||
|
"Day5 望见林悦→乌兰山滑草→越野车穿越→民族服饰拍照→烤全羊+篝火晚会",
|
||||||
|
"Day6 呼籁牧场非遗羊毛毡+蒙古族民俗体验+云朵牧场→午餐后返程"
|
||||||
|
],
|
||||||
|
"faq": [
|
||||||
|
{
|
||||||
|
"question": "小蒙马夏令营需要家长陪同吗?",
|
||||||
|
"answer": "是的,小蒙马是亲子夏令营,爸爸妈妈带着孩子一起出发。行程中既有全家共同参与的活动(骑马、写生、做列巴),也贴心设计了「爸妈托管」时段——专业工作人员陪同孩子做游戏,家长可以短暂放松休息。特别适合一个人带孩子出行的妈妈,行程有人安排,孩子有人带着玩,你也能真正歇一歇。"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"question": "小蒙马和额吉的故乡有什么区别?",
|
||||||
|
"answer": "两者都是呼籁出品,都走呼伦贝尔核心线路。核心区别在于形式:额吉的故乡是一家一单一车的私家定制游,您的家庭独享车和领队,行程灵活自由。小蒙马是亲子夏令营,每期8组家庭一起出发,融入草原写生、非遗研学、民俗体验三大主题,孩子有伙伴一起学一起玩,大人也能在团队氛围里放松社交。"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"question": "行程会不会太赶?孩子体力跟得上吗?",
|
||||||
|
"answer": "不会。小蒙马的行程设计遵循「舒适适配」原则,充分考虑孩子的体能和注意力。比如牧云山顶音乐会安排在上午精力充沛时段,住宿安排连住两晚减少搬家奔波,每天的活动节奏都留有休息缓冲时间。所有户外活动也会根据孩子年龄适配难度,确保参与感和安全性。"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"question": "夏令营一般什么时候开营?怎么报名?",
|
||||||
|
"answer": "小蒙马夏令营在每年暑假期间开营,具体开营时间和营期安排会在每年春季公布。2025年成功举办11期,2026年计划开设30期。建议关注呼籁旅行小红书账号或添加微信客服获取最新营期信息和报名方式。"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"differenceFromV9": "小蒙马和额吉的故乡都是呼籁出品,都走呼伦贝尔核心线路,很多体验项目也是同一套标准。核心区别在于形式和节奏:额吉的故乡是一家一单一车的私家定制游,您的家庭独享一辆车和一位领队,行程灵活自由。小蒙马是亲子夏令营形式,每期8组家庭一起出发,融入草原写生、非遗研学、民俗体验三大主题,孩子有伙伴一起学一起玩,大人也能在团队氛围里放松社交。小蒙马还贴心设计了「爸妈托管」时段——专业工作人员陪同孩子做游戏,家长可以短暂放松休息。特别适合一个人带孩子出行的妈妈。"
|
||||||
|
},
|
||||||
|
"selectionGuide": {
|
||||||
|
"byVacationLength": [
|
||||||
|
{
|
||||||
|
"reason": "精华浓缩,不浪费一天",
|
||||||
|
"condition": "3-4天假期",
|
||||||
|
"recommendation": "v9-4d3n"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"reason": "经典线路,体验最全",
|
||||||
|
"condition": "5天假期",
|
||||||
|
"recommendation": "v9-5d4n"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"reason": "节奏从容,适合带娃",
|
||||||
|
"condition": "6天假期",
|
||||||
|
"recommendation": "v9-6d5n-family"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"reason": "深度探索,不留遗憾",
|
||||||
|
"condition": "7天以上",
|
||||||
|
"recommendation": "v9-7d6n-family"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"byChildAge": [
|
||||||
|
{
|
||||||
|
"reason": "亲子版节奏舒缓,活动适龄",
|
||||||
|
"condition": "3-5岁幼儿",
|
||||||
|
"recommendation": "v9-6d5n-family"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"reason": "深度版活动丰富,孩子最开心",
|
||||||
|
"condition": "6-10岁儿童",
|
||||||
|
"recommendation": "v9-7d6n-family"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"reason": "小蒙马夏令营,8组家庭同行",
|
||||||
|
"condition": "亲子夏令营",
|
||||||
|
"recommendation": "summer-camp"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"reason": "狂野版户外体验更刺激",
|
||||||
|
"condition": "10岁以上",
|
||||||
|
"recommendation": "v9-7d6n-wild"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"byPreference": [
|
||||||
|
{
|
||||||
|
"reason": "精选住宿,行程不赶",
|
||||||
|
"condition": "追求舒适",
|
||||||
|
"recommendation": "v9-6d5n-comfort"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"reason": "小众秘境,深入草原",
|
||||||
|
"condition": "追求深度",
|
||||||
|
"recommendation": "v9-7d6n-wild"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"reason": "探索版最适合全家出行",
|
||||||
|
"condition": "带老人同行",
|
||||||
|
"recommendation": "v9-6d5n-comfort"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"reason": "亲子版孩子们可以结伴玩耍",
|
||||||
|
"condition": "多家庭同行",
|
||||||
|
"recommendation": "v9-6d5n-family"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"pricingPhilosophy": "呼籁定制游的价格包含了车辆、住宿、领队服务、活动体验、旅行摄影和保险。看起来比拼团贵,但每一分钱都花在了体验上——没有购物店、没有隐形消费、没有赶场式行程。一家一单一车的定制游模式意味着所有资源都是为您的家庭专属调配的:您的领队只服务您一家,您的车只拉您一家,您的行程可以根据实际情况灵活调整。这不是高价版的跟团游,而是完全不同的旅行方式。这是呼籁对品质的坚持,也是我们9年来口碑积累的底气。"
|
||||||
|
}
|
||||||
137
data/qualifications.json
普通文件
137
data/qualifications.json
普通文件
@ -0,0 +1,137 @@
|
|||||||
|
{
|
||||||
|
"licenses": [
|
||||||
|
{
|
||||||
|
"title": "旅游经营许可证",
|
||||||
|
"issuer": "内蒙古自治区文化和旅游厅",
|
||||||
|
"description": "证件号:L-NMG-101453|持证主体:内蒙古呼籁文旅投资开发集团有限公司|法人:刘涛|经营范围:境内旅游业务、入境旅游业务|统一信用代码:91150702MACYA3MN0U|集团母公司,统筹旗下所有业务板块"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"title": "旅游经营许可证",
|
||||||
|
"issuer": "内蒙古自治区文化和旅游厅",
|
||||||
|
"description": "证件号:L-NMG00210|持证主体:内蒙古呼籁山河国际旅行社有限公司|法人:刘涛|经营范围:境内旅游业务、入境旅游业务|统一信用代码:911507007722296570|成立于2005年,集团旅行社资质中历史最悠久的主体"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"insurance": {
|
||||||
|
"title": "旅游责任险 · 1000万保障",
|
||||||
|
"issuer": null,
|
||||||
|
"description": "全程旅游责任险覆盖,出行安全有兜底。保单号:6203130180266250001337,保额10,000,000.00元,有效期2026年01月01日至2026年12月31日。|"
|
||||||
|
},
|
||||||
|
"awards": [
|
||||||
|
{
|
||||||
|
"title": "2026小红书WILL商业大会·年度成长型品牌",
|
||||||
|
"issuer": "小红书",
|
||||||
|
"year": 2026,
|
||||||
|
"description": "文旅行业仅6家品牌获此荣誉,是平台对呼籁内容质量与品牌成长的认可"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"title": "内蒙古自治区研学旅游服务商",
|
||||||
|
"issuer": "内蒙古自治区文化和旅游厅",
|
||||||
|
"year": 2026,
|
||||||
|
"description": "全区97家之一,具备官方认可的研学服务资质,可承接中小学研学项目"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"title": "呼伦贝尔学院旅游实习实训基地",
|
||||||
|
"issuer": "呼伦贝尔学院",
|
||||||
|
"year": 2024,
|
||||||
|
"description": "校企合作,共同培养旅游管理人才,呼籁每年接收旅游管理专业实习生"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"heritage": {
|
||||||
|
"title": "品牌资历:11年深耕呼伦贝尔",
|
||||||
|
"description": "|2005年:内蒙古呼籁山河国际旅行社有限公司成立,取得旅游经营许可证,开始深耕呼伦贝尔旅游市场;2015年:呼籁品牌创立,开始专注于家庭定制游和深度体验型旅游产品;2022年:呼伦贝尔呼籁牧场商贸有限公司成立,打通本地牧场和特产供应链;2023年:内蒙古呼籁文旅投资开发集团有限公司成立,完成集团化布局;内蒙古呼籁国际旅行社有限公司同年成立;2024年:呼籁旅游客运公司、呼籁露营地公司相继成立,实现自有车队+自有营地双重保障;2025年:获评小红书2025年度成长型品牌;内蒙古呼籁培训有限公司、内蒙古呼籁文化科技有限公司相继成立;2026年:呼伦贝尔呼籁研学文化旅游有限责任公司成立;入选小红书WILL商业大会·年度成长型品牌(文旅行业仅6家)"
|
||||||
|
},
|
||||||
|
"safetyGuarantees": [
|
||||||
|
{
|
||||||
|
"title": "三重旅行社资质",
|
||||||
|
"detail": "旗下三家主体均持有旅游经营许可证"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"title": "1000万旅游责任险",
|
||||||
|
"detail": "每单行程全程覆盖旅游意外责任"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"title": "「呼籁」注册商标",
|
||||||
|
"detail": "第39类旅游服务注册商标持有方"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"title": "深耕呼伦贝尔11年",
|
||||||
|
"detail": "2015年创立,本地团队深耕运营"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"enterpriseMatrix": {
|
||||||
|
"totalCount": 9,
|
||||||
|
"description": "呼籁集团旗下覆盖旅行社、营地、车队、牧场等多业态企业",
|
||||||
|
"companies": [
|
||||||
|
{
|
||||||
|
"name": "呼伦贝尔呼籁旅行社有限公司",
|
||||||
|
"type": "旅行社",
|
||||||
|
"license": "旅游经营许可证"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "呼籁旅游有限公司",
|
||||||
|
"type": "旅行社",
|
||||||
|
"license": "旅游经营许可证"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "嘎查旅行社有限公司",
|
||||||
|
"type": "旅行社",
|
||||||
|
"license": "旅游经营许可证"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "呼籁旅游客运有限公司",
|
||||||
|
"type": "旅游客运",
|
||||||
|
"license": "道路运输许可证"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "呼籁草原营地",
|
||||||
|
"type": "营地运营",
|
||||||
|
"license": "营地经营许可"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "呼籁牧场商贸有限公司",
|
||||||
|
"type": "农牧产品",
|
||||||
|
"license": "营业执照"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "呼籁研学教育有限公司",
|
||||||
|
"type": "研学教育",
|
||||||
|
"license": "营业执照"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "额吉的故乡文化传媒有限公司",
|
||||||
|
"type": "文化传媒",
|
||||||
|
"license": "营业执照"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "呼籁科技有限公司",
|
||||||
|
"type": "互联网科技",
|
||||||
|
"license": "营业执照"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"intellectualProperty": {
|
||||||
|
"trademark": {
|
||||||
|
"name": "呼籁",
|
||||||
|
"scope": "第39类旅游、旅行社、交通运输服务",
|
||||||
|
"holder": "呼伦贝尔呼籁旅行社有限公司",
|
||||||
|
"description": "「呼籁」商标已在国家知识产权局完成注册,保护呼伦贝尔旅游定制服务领域的核心品牌权益。"
|
||||||
|
},
|
||||||
|
"copyrights": [
|
||||||
|
{
|
||||||
|
"title": "呼籁旅行官方网站",
|
||||||
|
"type": "软件著作权",
|
||||||
|
"year": "2024"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"title": "额吉的故乡旅游产品系列",
|
||||||
|
"type": "文字作品著作权",
|
||||||
|
"year": "2023"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"title": "小蒙马研学课程体系",
|
||||||
|
"type": "教育课程著作权",
|
||||||
|
"year": "2024"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
1297
data/reviews.json
普通文件
1297
data/reviews.json
普通文件
文件差异内容过多而无法显示
加载差异
281
data/selector.json
普通文件
281
data/selector.json
普通文件
@ -0,0 +1,281 @@
|
|||||||
|
{
|
||||||
|
"questions": [
|
||||||
|
{
|
||||||
|
"id": "q1",
|
||||||
|
"hint": "根据你的假期长度,为你匹配最合适的行程版本",
|
||||||
|
"text": "你打算玩几天?",
|
||||||
|
"options": [
|
||||||
|
{
|
||||||
|
"desc": "草原+森林 或 草原+满洲里",
|
||||||
|
"label": "5天",
|
||||||
|
"value": "5天"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"desc": "越野穿越、两次骑马",
|
||||||
|
"label": "6天",
|
||||||
|
"value": "6天"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"desc": "深度探索不留遗憾",
|
||||||
|
"label": "7天",
|
||||||
|
"value": "7天"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "q2",
|
||||||
|
"hint": "不同人群有不同的节奏和侧重点",
|
||||||
|
"text": "这次出行是?",
|
||||||
|
"options": [
|
||||||
|
{
|
||||||
|
"desc": "爸妈带娃,家庭出游",
|
||||||
|
"label": "带孩子的家庭",
|
||||||
|
"value": "带孩子的家庭"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"desc": "两人世界,浪漫草原",
|
||||||
|
"label": "情侣",
|
||||||
|
"value": "情侣"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"desc": "几个好友一起出发",
|
||||||
|
"label": "朋友结伴",
|
||||||
|
"value": "朋友"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"desc": "一个人的草原之旅",
|
||||||
|
"label": "独自出行",
|
||||||
|
"value": "独行"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "q3",
|
||||||
|
"hint": "不同年龄的孩子,适合的活动和节奏差别很大",
|
||||||
|
"text": "孩子几岁了?",
|
||||||
|
"options": [
|
||||||
|
{
|
||||||
|
"desc": "小宝宝,需要舒适慢节奏",
|
||||||
|
"label": "3岁以下",
|
||||||
|
"value": "3岁以下"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"desc": "学前宝宝,活泼好动",
|
||||||
|
"label": "3—6岁",
|
||||||
|
"value": "3-6岁"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"desc": "小学阶段,探索欲强",
|
||||||
|
"label": "6—12岁",
|
||||||
|
"value": "6-12岁"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"desc": "大孩子,体能好敢于挑战",
|
||||||
|
"label": "12岁以上",
|
||||||
|
"value": "12岁以上"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"condition": {
|
||||||
|
"key": "q2",
|
||||||
|
"value": "带孩子的家庭"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "q4",
|
||||||
|
"hint": "我们有不同价位的版本,都是一家一单一车",
|
||||||
|
"text": "预算倾向是?",
|
||||||
|
"options": [
|
||||||
|
{
|
||||||
|
"desc": "控制预算,好玩就行",
|
||||||
|
"label": "经济实惠",
|
||||||
|
"value": "经济实惠"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"desc": "住得好,玩得舒心",
|
||||||
|
"label": "品质优先",
|
||||||
|
"value": "品质优先"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"desc": "最好的体验,价格不是问题",
|
||||||
|
"label": "不差钱",
|
||||||
|
"value": "不差钱"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "q5",
|
||||||
|
"hint": "呼伦贝尔有很多面,你更想要哪一面",
|
||||||
|
"text": "最期待哪种体验?",
|
||||||
|
"options": [
|
||||||
|
{
|
||||||
|
"desc": "骑马、非遗手作、蒙古文化、旅拍",
|
||||||
|
"label": "亲子互动",
|
||||||
|
"value": "亲子互动"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"desc": "草原、森林、湿地、界河",
|
||||||
|
"label": "自然风光",
|
||||||
|
"value": "自然风光"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"desc": "装甲车、漂流、帐篷营地、越野穿越",
|
||||||
|
"label": "极致冒险",
|
||||||
|
"value": "极致冒险"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"desc": "骑马穿越、大力山探索、秘境航拍",
|
||||||
|
"label": "深度探索",
|
||||||
|
"value": "深度探索"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"scoring": {
|
||||||
|
"q1": {
|
||||||
|
"5天": {
|
||||||
|
"v9-5d4n": 9,
|
||||||
|
"v9-6d5n-family": 2,
|
||||||
|
"v9-5d4n": 9
|
||||||
|
},
|
||||||
|
"6天": {
|
||||||
|
"v9-5d4n": 3,
|
||||||
|
"v9-6d5n-family": 10,
|
||||||
|
"v9-5d4n": 3,
|
||||||
|
"v9-6d5n-family": 9
|
||||||
|
},
|
||||||
|
"7天": {
|
||||||
|
"v9-7d6n-wild": 9,
|
||||||
|
"v9-6d5n-family": 3,
|
||||||
|
"v9-7d6n-family": 9
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"q2": {
|
||||||
|
"情侣": {
|
||||||
|
"v9-7d6n-wild": 4,
|
||||||
|
"v9-5d4n": 5,
|
||||||
|
"v9-6d5n-family": 6
|
||||||
|
},
|
||||||
|
"朋友": {
|
||||||
|
"v9-7d6n-wild": 6,
|
||||||
|
"v9-5d4n": 4,
|
||||||
|
"v9-6d5n-family": 5
|
||||||
|
},
|
||||||
|
"独行": {
|
||||||
|
"v9-5d4n": 4,
|
||||||
|
"v9-5d4n": 5,
|
||||||
|
"v9-6d5n-family": 6
|
||||||
|
},
|
||||||
|
"带孩子的家庭": {
|
||||||
|
"v9-5d4n": 4,
|
||||||
|
"v9-6d5n-family": 9,
|
||||||
|
"v9-7d6n-family": 8,
|
||||||
|
"v9-5d4n": 4
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"q3": {
|
||||||
|
"3-6岁": {
|
||||||
|
"v9-5d4n": 4,
|
||||||
|
"v9-6d5n-family": 10,
|
||||||
|
"v9-7d6n-family": 8
|
||||||
|
},
|
||||||
|
"6-12岁": {
|
||||||
|
"v9-6d5n-family": 9,
|
||||||
|
"v9-7d6n-family": 8,
|
||||||
|
"v9-6d5n-family": 5
|
||||||
|
},
|
||||||
|
"3岁以下": {
|
||||||
|
"v9-5d4n": 5,
|
||||||
|
"v9-6d5n-family": 8,
|
||||||
|
"v9-5d4n": 6
|
||||||
|
},
|
||||||
|
"12岁以上": {
|
||||||
|
"v9-7d6n-wild": 9,
|
||||||
|
"v9-7d6n-family": 4,
|
||||||
|
"v9-6d5n-family": 8
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"q4": {
|
||||||
|
"不差钱": {
|
||||||
|
"v9-7d6n-wild": 8,
|
||||||
|
"v9-7d6n-family": 6,
|
||||||
|
"v9-6d5n-family": 4
|
||||||
|
},
|
||||||
|
"品质优先": {
|
||||||
|
"v9-6d5n-family": 6,
|
||||||
|
"v9-7d6n-family": 6,
|
||||||
|
"v9-6d5n-family": 5
|
||||||
|
},
|
||||||
|
"经济实惠": {
|
||||||
|
"v9-5d4n": 7,
|
||||||
|
"v9-6d5n-family": 3,
|
||||||
|
"v9-5d4n": 7
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"q5": {
|
||||||
|
"亲子互动": {
|
||||||
|
"v9-5d4n": 3,
|
||||||
|
"v9-6d5n-family": 10,
|
||||||
|
"v9-7d6n-family": 8
|
||||||
|
},
|
||||||
|
"极致冒险": {
|
||||||
|
"v9-7d6n-wild": 10,
|
||||||
|
"v9-6d5n-family": 5
|
||||||
|
},
|
||||||
|
"深度探索": {
|
||||||
|
"v9-7d6n-wild": 6,
|
||||||
|
"v9-7d6n-family": 4,
|
||||||
|
"v9-6d5n-family": 9
|
||||||
|
},
|
||||||
|
"自然风光": {
|
||||||
|
"v9-5d4n": 8,
|
||||||
|
"v9-7d6n-family": 4,
|
||||||
|
"v9-5d4n": 6
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"matchReasons": {
|
||||||
|
"v9-7d6n-wild": {
|
||||||
|
"default": "旷野探索,装甲车穿越+湿地漂流+帐篷营地+专业航拍,解锁常规线路到不了的地方",
|
||||||
|
"q1:7天": "7天硬核户外——住帐篷营地和草原木屋,装甲车+漂流+航拍全部安排",
|
||||||
|
"q2:朋友": "和好友一起装甲车穿越、湿地漂流、秘境航拍,肾上腺素拉满",
|
||||||
|
"q4:不差钱": "全程特色住宿+装甲车+漂流+航拍+自有营地旅拍,体验价值最高",
|
||||||
|
"q3:12岁以上": "装甲车穿越+湿地漂流+全地形越野车+帐篷营地,最硬核的户外版本",
|
||||||
|
"q5:极致冒险": "装甲车穿越草地溪流+额尔古纳湿地漂流+寻龙诀秘境航拍,极致冒险之选"
|
||||||
|
},
|
||||||
|
"v9-5d4n": {
|
||||||
|
"default": "草原+大兴安岭森林双线深度,5天走遍两种风光",
|
||||||
|
"q1:5天": "5天假期想看草原又想进森林——森林版专为这种需求设计",
|
||||||
|
"q4:经济实惠": "5天4晚起步价最亲民,森林小火车+驯鹿+骑马一个不少",
|
||||||
|
"q5:自然风光": "草原+白桦林+大兴安岭+森林小火车+驯鹿园,自然风光层次最丰富"
|
||||||
|
},
|
||||||
|
"v9-6d5n-family": {
|
||||||
|
"default": "6天5晚亲子主推版,自有营地旅拍+非遗手作+骑马越野+蒙古文化,专为带孩子的家庭设计",
|
||||||
|
"q1:6天": "6天时间刚好——自有营地旅拍+非遗传承人授课+骑马越野+蒙古文化体验全覆盖",
|
||||||
|
"q3:3-6岁": "非遗传承人按年龄分层教学+搭蒙古包+熬奶茶+做羊毛毡,学前宝宝最爱的版本",
|
||||||
|
"q3:6-12岁": "骑马穿越+越野车+白桦林非遗手作+蒙古文化四合一,每天都有新体验",
|
||||||
|
"q3:3岁以下": "行程节奏最舒缓,单日最长不超300公里,小宝宝也能轻松跟上",
|
||||||
|
"q5:亲子互动": "非遗传承人授课+搭蒙古包+捡牛粪+熬奶茶+做羊毛毡+专属亲子手册,亲子互动最丰富",
|
||||||
|
"q2:带孩子的家庭": "主推亲子版——非遗按年龄分层、蒙古文化还原真实生活、专属亲子手册记录旅途发现"
|
||||||
|
},
|
||||||
|
"v9-7d6n-family": {
|
||||||
|
"default": "最完整亲子深度版,自有营地旅拍+非遗手作+森林小火车+蒙古文化体验",
|
||||||
|
"q1:7天": "7天假期值得最完整的行程——草原、森林、边境、满洲里全覆盖",
|
||||||
|
"q3:3-6岁": "非遗传承人按年龄分层教学+搭蒙古包+熬奶茶+做羊毛毡,内容最丰富",
|
||||||
|
"q3:6-12岁": "森林小火车+驯鹿+白桦林非遗手作+蒙古文化体验,每天都有新鲜感",
|
||||||
|
"q5:亲子互动": "非遗传承人授课+搭蒙古包+捡牛粪+熬奶茶+做羊毛毡,亲子互动最丰富",
|
||||||
|
"q2:带孩子的家庭": "专为带孩子的家庭设计,非遗按年龄分层,蒙古文化还原真实生活场景"
|
||||||
|
},
|
||||||
|
"v9-5d4n": {
|
||||||
|
"default": "不进森林,走草原+边境+满洲里环线,错峰安排",
|
||||||
|
"q1:5天": "5天假期不进森林——草原+寻龙诀秘境+套娃大马戏+马之舞,精彩不打折",
|
||||||
|
"q3:3岁以下": "不进深山森林,行程节奏更平缓,小宝宝也能轻松跟上"
|
||||||
|
},
|
||||||
|
"v9-6d5n-family": {
|
||||||
|
"default": "越野穿越、两次骑马、不走寻常路,更适合大孩子与成人的进阶体验",
|
||||||
|
"q1:6天": "6天时间够从容——自有营地旅拍+大力山穿越+两次骑马+秘境探索",
|
||||||
|
"q2:情侣": "大力山穿越+两次骑马+秘境航拍+风车公路,很适合追求深度的两人世界",
|
||||||
|
"q3:12岁以上": "两次骑马+全地形越野车+大力山穿越,大孩子最爱的进阶版本",
|
||||||
|
"q5:深度探索": "大力山穿越全程不走柏油路+两次骑马+寻龙诀秘境,探索感十足"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
60
data/seo.json
普通文件
60
data/seo.json
普通文件
@ -0,0 +1,60 @@
|
|||||||
|
{
|
||||||
|
"pages": {
|
||||||
|
"home": {
|
||||||
|
"title": "呼籁旅行 - 呼伦贝尔家庭定制游·一家一单一车",
|
||||||
|
"description": "呼籁旅行是呼伦贝尔家庭定制游品牌,深耕呼伦贝尔11年,已服务10000+组家庭。提供4-7天额吉的故乡V9系列亲子行程及小蒙马夏令营。",
|
||||||
|
"h1": "呼籁旅行 — 呼伦贝尔家庭定制游",
|
||||||
|
"ogImage": "/images/og-home.jpg",
|
||||||
|
"keywords": "呼伦贝尔亲子游,呼伦贝尔家庭定制游,呼籁旅行,一家一单一车,呼伦贝尔旅游,草原定制游,额吉的故乡"
|
||||||
|
},
|
||||||
|
"about": {
|
||||||
|
"title": "关于呼籁旅行 - 品牌故事·旗下9家企业·深耕呼伦贝尔11年",
|
||||||
|
"description": "呼籁旅行集团旗下9家企业,深耕呼伦贝尔11年,已服务10000+组家庭。了解呼籁的品牌故事、资质认证、服务保障和企业文化。",
|
||||||
|
"h1": "关于呼籁旅行",
|
||||||
|
"ogImage": "/images/og-about.jpg",
|
||||||
|
"keywords": "呼籁旅行,呼伦贝尔旅行社,自有营地,自有车队,呼籁文旅集团,深耕呼伦贝尔11年"
|
||||||
|
},
|
||||||
|
"products": {
|
||||||
|
"title": "额吉的故乡 - 呼伦贝尔夏季定制游 · V9系列4-7天 - 呼籁旅行",
|
||||||
|
"description": "呼籁旅行夏季定制游产品「额吉的故乡V9」,4天3晚至7天6晚多版本亲子行程,莫日格勒河、边境公路、呼伦湖、自有营地。一家一单一车,专属私家团。",
|
||||||
|
"h1": "额吉的故乡 · 呼伦贝尔夏季定制游",
|
||||||
|
"ogImage": "/images/og-products.jpg",
|
||||||
|
"keywords": "额吉的故乡,呼伦贝尔夏季定制游,呼伦贝尔亲子游,额吉的故乡V9,呼伦贝尔几天合适,4天3晚,5天4晚,6天5晚,7天6晚"
|
||||||
|
},
|
||||||
|
"faq": {
|
||||||
|
"title": "呼伦贝尔亲子游常见问题 - 价格·行程·安全·穿搭全解答 - 呼籁旅行",
|
||||||
|
"description": "呼伦贝尔定制游和亲子游常见问题解答:价格、行程天数、穿搭准备、安全保障、退改政策等高频问题,呼籁旅行为您详细解答。",
|
||||||
|
"h1": "呼伦贝尔定制游常见问答",
|
||||||
|
"ogImage": "/images/og-faq.jpg",
|
||||||
|
"keywords": "呼伦贝尔旅游攻略,呼伦贝尔亲子游攻略,呼伦贝尔多少钱,呼伦贝尔几月去好,呼伦贝尔穿什么"
|
||||||
|
},
|
||||||
|
"reviews": {
|
||||||
|
"title": "呼伦贝尔定制游客户评价 - 真实口碑·10000+家庭的选择 - 呼籁旅行",
|
||||||
|
"description": "查看呼籁旅行呼伦贝尔定制游客户真实评价,涵盖亲子游、家庭出行等场景。好评率98%,听听10000+家庭的呼伦贝尔旅行体验。",
|
||||||
|
"h1": "客户评价",
|
||||||
|
"ogImage": "/images/og-reviews.jpg",
|
||||||
|
"keywords": "呼伦贝尔旅游评价,呼籁旅行怎么样,呼伦贝尔亲子游评价,呼伦贝尔定制游口碑"
|
||||||
|
},
|
||||||
|
"guides": {
|
||||||
|
"title": "呼伦贝尔出行指南 - 穿搭·行李·活动安全·幼童专属攻略 - 呼籁旅行",
|
||||||
|
"description": "呼籁旅行出品的呼伦贝尔出行指南:各月穿搭建议(含气温数据)、行李清单、骑马/ATV/滑草安全须知、0-3岁幼童活动推荐、实用信息汇总。",
|
||||||
|
"h1": "呼伦贝尔出行指南",
|
||||||
|
"ogImage": "/images/og-guides.jpg",
|
||||||
|
"keywords": "呼伦贝尔穿搭指南,呼伦贝尔行李清单,呼伦贝尔几月份去最好,呼伦贝尔骑马安全,草原旅游注意事项"
|
||||||
|
},
|
||||||
|
"summer-camp": {
|
||||||
|
"title": "小蒙马夏令营 - 呼伦贝尔草原亲子夏令营·6天5晚 - 呼籁旅行",
|
||||||
|
"description": "小蒙马夏令营是呼籁旅行打造的呼伦贝尔草原亲子夏令营路线,6天5晚,每期仅限8组家庭,爸爸妈妈带着孩子一起出发。融入草原写生、非遗研学、民俗体验三大主题,骑马、做列巴、越野穿越、篝火晚会,孩子沉浸式成长,大人也能真正放松。",
|
||||||
|
"h1": "小蒙马夏令营",
|
||||||
|
"ogImage": "/images/og-summer-camp.jpg",
|
||||||
|
"keywords": "呼伦贝尔夏令营,草原亲子夏令营,小蒙马夏令营,呼伦贝尔亲子营,研学旅行"
|
||||||
|
},
|
||||||
|
"contact": {
|
||||||
|
"title": "联系呼籁旅行 - 微信客服·电话·小程序预订",
|
||||||
|
"description": "联系呼籁旅行:微信客服、电话咨询、小程序预订。所有行程签订正规电子合同,请认准官方渠道。",
|
||||||
|
"h1": "联系我们",
|
||||||
|
"ogImage": "/images/og-contact.jpg",
|
||||||
|
"keywords": "呼籁旅行联系方式,呼伦贝尔定制游咨询,呼籁旅行微信,呼伦贝尔旅游电话"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
409
data/stories.json
普通文件
409
data/stories.json
普通文件
文件差异因一行或多行过长而隐藏
257
data/versions.json
普通文件
257
data/versions.json
普通文件
@ -0,0 +1,257 @@
|
|||||||
|
{
|
||||||
|
"stats": {
|
||||||
|
"iterations": 9,
|
||||||
|
"years": 3,
|
||||||
|
"guests": "39000+"
|
||||||
|
},
|
||||||
|
"upgrades2026": [
|
||||||
|
{
|
||||||
|
"tag": "营地",
|
||||||
|
"name": "全新自营专属营地",
|
||||||
|
"description": "搬至敖包相会景区,「天下第一敖包」旁,俯瞰伊敏河湿地。呼籁自营场地,活动品质自己把控。",
|
||||||
|
"reason": "V8客户反馈雨季泥泞和电力不稳 → 全新自营专属营地"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"tag": "非遗",
|
||||||
|
"name": "非遗传承人手把手教学",
|
||||||
|
"description": "白桦林桦树皮画由非遗传承人亲自带课,按年龄分层体验,呼籁自营场地,体验更深度。",
|
||||||
|
"reason": "「讲故事听一听就走」不够深度 → 非遗传承人手把手教学"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"tag": "民俗",
|
||||||
|
"name": "呼籁牧场4大动手体验",
|
||||||
|
"description": "搭蒙古包框架、捡牛粪了解古老燃料、熬奶茶体验待客礼节、亲手制作羊毛毡。",
|
||||||
|
"reason": "客户说「希望感受真正的蒙古族文化」→ 从看变成做"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"highlights": [
|
||||||
|
{
|
||||||
|
"label": "自营",
|
||||||
|
"text": "全地形越野车呼籁自营场地,往返12km草原穿越"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"label": "升级",
|
||||||
|
"text": "乌兰山千米滑草,滑多少次呼籁买单(V8仅含一次)"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"label": "新增",
|
||||||
|
"text": "满洲里领队带队夜游,不用自己打车逛夜景"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"label": "新增",
|
||||||
|
"text": "D6呼和诺尔湖畔慢时光,给旅行最后一天留白"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"label": "自营",
|
||||||
|
"text": "自有旅拍团队,底片全送不套路"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"label": "服务",
|
||||||
|
"text": "行前语音通知 + 实时行程追踪,全程零购物"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"compareV8V9": {
|
||||||
|
"headers": [
|
||||||
|
"V8(2024–2025)",
|
||||||
|
"V9(2026)"
|
||||||
|
],
|
||||||
|
"rows": [
|
||||||
|
[
|
||||||
|
"草原腹地营地(雨季泥泞)",
|
||||||
|
"敖包相会景区 · 自营专属营地"
|
||||||
|
],
|
||||||
|
[
|
||||||
|
"访牧户(旺季人多体验差)",
|
||||||
|
"呼籁牧场4大动手体验"
|
||||||
|
],
|
||||||
|
[
|
||||||
|
"桦树皮画(专场,常规讲解)",
|
||||||
|
"非遗传承人手把手教学 · 自营场地"
|
||||||
|
],
|
||||||
|
[
|
||||||
|
"ATV穿越(公共场地)",
|
||||||
|
"全地形越野车 · 呼籁自营运营"
|
||||||
|
],
|
||||||
|
[
|
||||||
|
"乌兰山千米滑草(仅一次)",
|
||||||
|
"乌兰山千米滑草 · 滑多少次呼籁买单"
|
||||||
|
],
|
||||||
|
[
|
||||||
|
"满洲里自由活动",
|
||||||
|
"领队带队夜游 · 不用自己打车"
|
||||||
|
],
|
||||||
|
[
|
||||||
|
"D6看完马之舞直接送机",
|
||||||
|
"新增呼和诺尔湖畔慢时光"
|
||||||
|
]
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"timeline": [
|
||||||
|
{
|
||||||
|
"version": "V8",
|
||||||
|
"date": "2024.06.13",
|
||||||
|
"title": "从采购到自营,掌控每一环",
|
||||||
|
"changes": [
|
||||||
|
{
|
||||||
|
"type": "add",
|
||||||
|
"text": "独家私家牧场旅拍(从采购资源到自营)"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "add",
|
||||||
|
"text": "独家白桦林专场研学(10:00-11:00 黄金时段)"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"reason": "第二年旺季:路线打磨到第8版,我们意识到真正的品质不能依赖外部供应商。于是自建牧场、锁定白桦林专场时段——从采购到自营,品质自己把控。这一步,让呼籁的服务体系从概念变成了现实。"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"version": "V7",
|
||||||
|
"date": "2024.03.05",
|
||||||
|
"title": "第二年开季,路线再优化",
|
||||||
|
"changes": [
|
||||||
|
{
|
||||||
|
"type": "add",
|
||||||
|
"text": "牧云山顶下午茶(草原绝佳赏景点,俯瞰莫日格勒河)"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "update",
|
||||||
|
"text": "私家牧场地址优化(海拉尔东侧哈克镇,避开旺季堵车)"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "remove",
|
||||||
|
"text": "牧民家访(改为私家牧场喂小羊,体验更佳)"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"reason": "开季复盘:2023年整个旺季跑下来,我们积累了大量一线反馈。第二年一开季就着手优化:牧场迁址避开堵车路段,新增牧云山顶下午茶——「当别人还在堵车时,我们已经坐在山顶喝茶了」。"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"version": "V6",
|
||||||
|
"date": "2023.07.26",
|
||||||
|
"title": "用独家秘境替代常规体验",
|
||||||
|
"changes": [
|
||||||
|
{
|
||||||
|
"type": "add",
|
||||||
|
"text": "草原腹地寻龙诀拍摄地(独家观赏点,常规行程覆盖不到)"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "remove",
|
||||||
|
"text": "森林研学寻迹探秘(旺季客流量大,体验打折扣)"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"reason": "旺季实测:进入盛夏旺季后,森林寻迹探秘因为游客多、体验不够深度,和我们想要的「独家感」差距太大。正好我们找到了草原腹地的寻龙诀拍摄地——一个常规行程根本到不了的地方,果断替换。"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"version": "V5",
|
||||||
|
"date": "2023.07.19",
|
||||||
|
"title": "景区不好走?那就换个方式抵达",
|
||||||
|
"changes": [
|
||||||
|
{
|
||||||
|
"type": "add",
|
||||||
|
"text": "ATV全地形越野车穿越第一湿地(近距离到达「亚洲第一湿地」)"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "add",
|
||||||
|
"text": "生日蛋糕惊喜(旅途中会员生日赠送蛋糕)"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "remove",
|
||||||
|
"text": "额尔古纳第一湿地景区(木栈道太长对儿童老人不友好)"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"reason": "客户反馈驱动:连续几团客人反映湿地木栈道太长,老人走不动、孩子喊累。我们没有删掉这个点位,而是换了到达方式——ATV穿越,全家人用更有趣的方式亲近湿地。同一周,我们还加上了旅途生日蛋糕惊喜,因为细节里藏着温度。"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"version": "V4",
|
||||||
|
"date": "2023.07.11",
|
||||||
|
"title": "把服务从形式落到实处",
|
||||||
|
"changes": [
|
||||||
|
{
|
||||||
|
"type": "add",
|
||||||
|
"text": "备品箱(15件物品:哈达、雨衣鞋套、骑马手套、蚊不叮 等)"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "remove",
|
||||||
|
"text": "草原迎宾酒(旺季客流量大,体验感低)"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"reason": "首批客人出发后:旺季开始后,迎宾酒环节因为客流量大变得仓促。与其保留一个「看起来好但体验打折」的环节,不如换成15件实打实的备品箱——雨衣、骑马手套、蚊不叮……每一件都解决旅途中的真实需求。"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"version": "V3",
|
||||||
|
"date": "2023.06.25",
|
||||||
|
"title": "一条路线,两种住法",
|
||||||
|
"changes": [
|
||||||
|
{
|
||||||
|
"type": "add",
|
||||||
|
"text": "住宿分级机制(舒适 / 高档 两档可选)"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "add",
|
||||||
|
"text": "高档升级酒店列表首次确立"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"reason": "预售期洞察:预售咨询中发现,不同家庭对住宿预算差异很大。我们没有「一刀切」定高价,而是做了两档分级——同一条精心打磨的路线,可以匹配不同家庭的舒适度需求。"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"version": "V2",
|
||||||
|
"date": "2023.06.13",
|
||||||
|
"title": "第一次扩充体验内容",
|
||||||
|
"changes": [
|
||||||
|
{
|
||||||
|
"type": "add",
|
||||||
|
"text": "森林研学寻迹探秘"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "add",
|
||||||
|
"text": "草原迎宾酒"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"reason": "产品上线后:V1框架搭好后,我们开始往路线里注入更多「只有在草原才能体验到」的内容。森林研学、迎宾酒……虽然后来这些环节经过实测被替换了,但每一次尝试都是为了找到更好的答案。"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"version": "V1",
|
||||||
|
"date": "2023.03.18",
|
||||||
|
"title": "一切的起点",
|
||||||
|
"changes": [
|
||||||
|
{
|
||||||
|
"type": "add",
|
||||||
|
"text": "6大景点:私家牧场、额尔古纳湿地、白桦林、乌兰山等"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "add",
|
||||||
|
"text": "11项活动:骑马五项、桦树皮画DIY、千米滑草、篝火晚会 等"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "add",
|
||||||
|
"text": "5晚住宿:海拉尔→额尔古纳→恩和→黑山头→满洲里"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"reason": "起点:2023年3月,呼籁做了一个「反常识」的决定——只做一条路线。不铺量、不贪多,把所有精力集中在这6天5晚上,一个细节一个细节地磨。三年后回头看,正是这个决定,让「额吉的故乡」从V1走到了V9。"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"philosophy": [
|
||||||
|
{
|
||||||
|
"label": "去景区化",
|
||||||
|
"text": "用自营体验替代大众景区,让每一站都有呼籁的品质标准"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"label": "自营资源化",
|
||||||
|
"text": "从采购到自建,自有牧场、专场研学,品质自己把控"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"label": "体验安全化",
|
||||||
|
"text": "宁可砍项目也不降体验,孩子的安全永远是第一位"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"label": "服务标准化",
|
||||||
|
"text": "备品箱、住宿分级,把每一个服务细节做到位"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"label": "全链自营化",
|
||||||
|
"text": "车队、营地、旅拍、研学全部自营,不转包不外采"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"quote": {
|
||||||
|
"text": "每一次版本更新,都是因为我们觉得还可以让会员的体验再好一点点。不是做加法,而是做取舍。",
|
||||||
|
"author": "呼籁旅行 · 产品团队"
|
||||||
|
}
|
||||||
|
}
|
||||||
176
data/winter-camp.json
普通文件
176
data/winter-camp.json
普通文件
@ -0,0 +1,176 @@
|
|||||||
|
{
|
||||||
|
"name": "小蒙马冬季亲子营",
|
||||||
|
"positioning": "很多人只记住了呼伦贝尔的「冷」,却忽略了这片雪原独有的静谧、纯粹,以及站在大雪原前会突然安静下来的那种震撼。滑雪、雾凇、不冻河、泼水成冰、林海温泉……每一个瞬间都像是冬天送给大人与孩子的「治愈剂」。如果你想给家人一次真正的冬天,一次不用排队、不用拼、不焦虑的旅行——小蒙马冬季亲子营,值得期待。",
|
||||||
|
"days": 7,
|
||||||
|
"nights": 6,
|
||||||
|
"maxFamilies": 8,
|
||||||
|
"totalSessions": 3,
|
||||||
|
"ageRange": "5-12岁",
|
||||||
|
"deposit": 2000,
|
||||||
|
"season": "冬季(11月-次年3月)",
|
||||||
|
"route": "海拉尔 → 阿尔山 → 金江沟阿尔善 → 海拉尔",
|
||||||
|
"whyHulunbuir": "到北方看雪,很多人第一反应是哈尔滨。冰雕大、亮、好看,航班多,项目也密集。但热闹的反面是去哪都排队,假期被人流和「同款路线」填满。呼伦贝尔的冬天没有那么多「摆拍打卡点」,最打动人的就是那种一望无际的白:雪原铺到天际,风吹过来很干净,脚下踩雪的「咯吱」声,会让人一下子安静下来。不拥挤,不排队,也不赶时间。对带孩子的家庭来说,这种「纯粹的舒服」,反而比什么都值得。",
|
||||||
|
"closingNote": "我们不打算把自己说得多厉害,但有一点可以很坦诚地说:我们真的是用父母的视角,拿「自己带孩子的标准」在设计这条线。不是为了多一个产品,而是觉得——愿意选择小蒙马的家庭,值得在这个冬天,在一片干净的雪原里,拥有一次只属于他们自己的记忆。",
|
||||||
|
"photographer": {
|
||||||
|
"name": "小E",
|
||||||
|
"description": "夏季小蒙马11期的全能摄影师。不是那种拿着相机「拍你」的摄影师,更像一个能瞬间融入孩子世界的大哥哥。孩子们超级黏他,能捕捉到很多大人看不到的瞬间——自然、不刻意、带着真情绪的画面。",
|
||||||
|
"specialDay2": "行程第二天(大雪原日)额外增加一位摄影师协作,确保每个家庭在最好的光线、最舒服的状态下拍到属于自己的大片,并为每个家庭拍一支小Vlog。"
|
||||||
|
},
|
||||||
|
"winterClothing": {
|
||||||
|
"lower": "保暖秋裤/抓绒裤 + 防风外裤(羽绒裤/雪裤/软壳裤/厚棉裤)",
|
||||||
|
"shoes": "雪地靴为主,建议略大半码,加厚羊毛鞋垫+暖足贴",
|
||||||
|
"upper": "保暖内衣(排汗)+ 抓绒/毛衣/卫衣做中层 + 滑雪服或防风保暖棉服/羽绒服",
|
||||||
|
"accessories": "护耳帽子、防水滑雪手套、围巾/脖套、墨镜、护肤霜、防晒、润唇膏"
|
||||||
|
},
|
||||||
|
"campAdvantages": [
|
||||||
|
"孩子有年龄相仿的伙伴,有领队带着玩,不用一直黏着爸妈",
|
||||||
|
"每个环节都有安排、有照看,有专业研学领队看管孩子,孩子在玩的时候也在接触书本外的世界",
|
||||||
|
"家长无需不断做选择,不用跟着孩子满场跑;带娃不再是负担,而是一起参与,省心省力",
|
||||||
|
"随团配备专职摄影师,全程跟拍,家长也不用再纠结「谁来帮我们拍」"
|
||||||
|
],
|
||||||
|
"serviceConfig": [
|
||||||
|
"亲子领队 1 名",
|
||||||
|
"副领队 1 名",
|
||||||
|
"摄影师 1 名(D2配备2名)",
|
||||||
|
"专业马术教练(马术日)",
|
||||||
|
"专业滑雪教练(滑雪日)"
|
||||||
|
],
|
||||||
|
"campEssentials": [
|
||||||
|
"备用手套",
|
||||||
|
"保温水壶热水",
|
||||||
|
"孩子状态观察",
|
||||||
|
"简易补能零食"
|
||||||
|
],
|
||||||
|
"hotels": [
|
||||||
|
{
|
||||||
|
"name": "海拉尔嘉世豪大酒店",
|
||||||
|
"star": "携程5钻",
|
||||||
|
"nights": "D1-D2连住",
|
||||||
|
"description": "房间宽敞,两张1.35米大床,集中供暖,进屋就暖。周边吃饭购物方便,伊敏河公园很近。"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "阿尔山成悦大酒店",
|
||||||
|
"star": "携程4钻",
|
||||||
|
"nights": "D3+D6",
|
||||||
|
"description": "阿尔山市区最好的酒店之一,房间宽敞,早餐丰富。住得简单省心,回到房间就能放松。"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "金江沟阿尔善温泉酒店",
|
||||||
|
"star": "携程5钻",
|
||||||
|
"nights": "D4-D5连住",
|
||||||
|
"description": "行程中最特别的两晚。房间外就是独立泡池,不用预约不用排队。白天滑完雪,回房间就能泡温泉,外面是雪林,池子里是热气,反差感特别舒服。"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"itinerary": [
|
||||||
|
{
|
||||||
|
"day": 1,
|
||||||
|
"title": "海拉尔集合 · 把节奏放下来的一天",
|
||||||
|
"summary": "蒙古族礼仪接机 → 酒店入住 → 领取游学物资 → 开营破冰",
|
||||||
|
"highlights": [
|
||||||
|
"亲子领队提前机场等候,蒙古族礼仪迎接",
|
||||||
|
"领取专属游学物资,旅程正式开始",
|
||||||
|
"自由探索:自然博物馆、伊敏河公园冰雕、呼伦贝尔古城",
|
||||||
|
"开营破冰游戏,DIY专属羊毛毡游学背包"
|
||||||
|
],
|
||||||
|
"hotel": "海拉尔嘉世豪大酒店"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"day": 2,
|
||||||
|
"title": "莫日格勒大雪原 · 冬季那达慕 · 契努瓦狼园",
|
||||||
|
"summary": "雪原旅拍 → 那达慕体验 → 狼园探秘 → 雪地火锅 → 亲子雪地活动",
|
||||||
|
"highlights": [
|
||||||
|
"莫日格勒大雪原:一望无际的白,配备2名专业摄影师拍摄+家庭Vlog",
|
||||||
|
"冬季那达慕:博克、赛马近距离观看,穿民族服饰、参观蒙古包、喝奶茶",
|
||||||
|
"契努瓦狼园:中科院狼行为学科研基地,投喂狼群,近距离感受狼的力量与速度",
|
||||||
|
"雪地火锅午餐,四周干净雪色,锅里升腾热气",
|
||||||
|
"雪地足球、拔河、冰嘎、雪圈、泼水成冰、围炉煮茶"
|
||||||
|
],
|
||||||
|
"hotel": "海拉尔嘉世豪大酒店"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"day": 3,
|
||||||
|
"title": "雪地骑马 · 五里泉 · 童话阿尔山 · 梦幻雪村",
|
||||||
|
"summary": "马术课堂 → 五里泉自然课 → 阿尔山火车站 → 雪村夜景",
|
||||||
|
"highlights": [
|
||||||
|
"特伦马术营地:不是景区走一圈,而是专业亲子马术教学",
|
||||||
|
"五里泉:零下二三十度不结冰的泉眼,自然小课堂解读不冻密码",
|
||||||
|
"童话阿尔山:东方小巴黎,独特火车站,冬日童话画卷",
|
||||||
|
"梦幻雪村:木屋落雪,没有人挤人,灯光被雪反成暖色,邂逅纯白浪漫"
|
||||||
|
],
|
||||||
|
"hotel": "阿尔山成悦大酒店"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"day": 4,
|
||||||
|
"title": "阿尔山滑雪 · 蓝房子 · 泼水成冰 · 私汤温泉",
|
||||||
|
"summary": "滑雪教学 → 蓝房子拍照 → 泼水成冰 → 温泉酒店私汤",
|
||||||
|
"highlights": [
|
||||||
|
"阿尔山滑雪场:含教练+全套装备,多条不同难度雪道",
|
||||||
|
"蓝房子:纯净蓝色与白雪形成鲜明对比,每个家庭拍色彩对比照",
|
||||||
|
"泼水成冰体验:人手一个道具,领队教技巧,泼出完整冰花",
|
||||||
|
"阿尔善温泉酒店:房间自带私汤,天好时领队带孩子观星"
|
||||||
|
],
|
||||||
|
"hotel": "金江沟阿尔善温泉酒店"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"day": 5,
|
||||||
|
"title": "雾凇 · 不冻河漂流 · 孩子研学托管 · 篝火烟花",
|
||||||
|
"summary": "乌苏浪子湖雾凇 → 不冻河皮划艇 → 孩子托管/家长自由 → 篝火+烟花",
|
||||||
|
"highlights": [
|
||||||
|
"乌苏浪子湖雾凇:树木被白霜包住,整片林子像被点亮,可遇不可求的自然奇观",
|
||||||
|
"不冻河漂流:零下二三十度的皮划艇,有机会拍到雾凇+喝水的牛,孩子的生态课",
|
||||||
|
"孩子托管研学:制作冰灯、DIY太阳花,家长完全自由——泡温泉、补觉、散步",
|
||||||
|
"篝火+烟花之夜:脚下白雪,炽热火焰,绚烂烟花,满眼星辰"
|
||||||
|
],
|
||||||
|
"hotel": "金江沟阿尔善温泉酒店"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"day": 6,
|
||||||
|
"title": "驯鹿 · 越野车穿越林海雪原 · 冰糖葫芦 · 闭营",
|
||||||
|
"summary": "喂驯鹿 → 坦克300穿越林海 → DIY冰糖葫芦 → 包饺子 → 闭营仪式",
|
||||||
|
"highlights": [
|
||||||
|
"近距离接触驯鹿:喂食、摸鹿角、拍照,孩子最爱的软萌体验",
|
||||||
|
"坦克300越野穿越林海雪原:拐进林海深处,感受冬天的林海长什么样",
|
||||||
|
"DIY冰糖葫芦:从蘸糖到糖衣凝固全程动手",
|
||||||
|
"包饺子+闭营仪式:体验北方年味,颁发冬令营纪念徽章"
|
||||||
|
],
|
||||||
|
"hotel": "阿尔山成悦大酒店"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"day": 7,
|
||||||
|
"title": "返程 · 一个有温度有画面的冬天",
|
||||||
|
"summary": "早餐后送站,海拉尔/阿尔山/伊尔施均可安排",
|
||||||
|
"highlights": [
|
||||||
|
"根据航班/火车时间灵活安排送站",
|
||||||
|
"海拉尔、阿尔山、伊尔施三地均可送站",
|
||||||
|
"车上复盘旅程:冰雪、马、狼、森林、漂流、滑雪……有温度有画面的记忆"
|
||||||
|
],
|
||||||
|
"hotel": null
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"faq": [
|
||||||
|
{
|
||||||
|
"q": "呼伦贝尔冬天冷不冷?孩子受得了吗?",
|
||||||
|
"a": "冷是肯定的,海拉尔、阿尔山冬季-20℃~-35℃为常态。但冷不等于「难受」。户外活动时,只要节奏安排得好、活动够有趣,孩子很少喊冷。真正怕冷的是「站着等、排队、干耗着」,我们把干耗着的时间压到最低。按照穿衣指南准备装备,完全没问题。"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"q": "冬季营需要家长陪同吗?",
|
||||||
|
"a": "是的,小蒙马是亲子营,爸爸妈妈带着孩子一起出发。行程中D5特别设计了「孩子托管研学」时段——专业领队带孩子做冰灯、太阳花,家长可以完全自由:泡温泉、补觉、散步都行。"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"q": "为什么选呼伦贝尔而不是哈尔滨?",
|
||||||
|
"a": "哈尔滨冰雕大、亮、好看,第一次看雪没毛病。但如果心里更想看一场真正纯净的雪,不想被人群裹挟着走,呼伦贝尔会更适合。一望无际的白,随便站在哪儿都有一大片只属于自己的雪原。不拥挤,不排队,也不赶时间。"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"q": "行程会因天气调整吗?",
|
||||||
|
"a": "冬季受天气影响较大。如遇暴雪、大风(≥6级)、道路封控、极端低温(-30℃以下)等情况,我们会调整体验顺序或进行替代项目。安全第一,不会在不安全的条件下带孩子户外体验。"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"q": "定金和退改政策是什么?",
|
||||||
|
"a": "定金2000元/人,尾款出发前补齐。出发前≥15天可退全部定金并可调团期;10-14天扣50%定金;6-9天扣80%定金;0-5天不退。如因不可抗力导致无法出行,可提交证明协商处理。"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"q": "住宿条件怎么样?",
|
||||||
|
"a": "全程精选酒店:海拉尔嘉世豪(携程5钻)连住2晚、阿尔善温泉酒店(携程5钻)连住2晚带私汤、阿尔山成悦(携程4钻)2晚。连住设计不折腾行李,不折腾孩子。"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
325
data/winter-products.json
普通文件
325
data/winter-products.json
普通文件
@ -0,0 +1,325 @@
|
|||||||
|
{
|
||||||
|
"brand": "嗨冰雪",
|
||||||
|
"version": "V3",
|
||||||
|
"season": "冬季(11月-次年3月)",
|
||||||
|
"narrative": "呼伦贝尔和阿尔山的冬,安静的不像一个旅游地。你不需要到哪都排很长时间的队,却可以独享一整片无际的雪原和茫茫林海。这里也是呼籁旅行的家,所以这不单是一条旅行路线,也是一次跟我们回家的冬季体验之旅。",
|
||||||
|
"style": "独立成团不拼团 · 一单一车 · 随走随停 · 不错过每处风景",
|
||||||
|
"versions": [
|
||||||
|
{
|
||||||
|
"id": "winter-south-5d4n",
|
||||||
|
"name": "嗨冰雪V3·南线5天4晚",
|
||||||
|
"days": 5,
|
||||||
|
"nights": 4,
|
||||||
|
"tag": "精华版",
|
||||||
|
"line": "南线",
|
||||||
|
"route": "呼伦贝尔+阿尔山",
|
||||||
|
"audience": "假期有限、想体验冬季精华的家庭",
|
||||||
|
"description": "冬季南线精华浓缩版,5天时间串联呼伦贝尔雪原与阿尔山冰雪世界。冰雪那达慕、雪地狼群、摩托车穿越、骑马、不冻河、白狼峰日出,核心体验一个不少。行程紧凑但不赶路,适合假期有限但想深度体验冬季呼伦贝尔的旅行者。",
|
||||||
|
"highlights": [
|
||||||
|
"冰雪那达慕+雪地狼群+围炉煮茶,感受草原冬日的生命力",
|
||||||
|
"雪地骑马+摩托车穿越,速度与激情的冬日体验",
|
||||||
|
"白狼峰日出+不冻河奇观,阿尔山冬季精华"
|
||||||
|
],
|
||||||
|
"itinerary": [
|
||||||
|
"D1 各地→呼伦贝尔(接机/站+自由闲逛)",
|
||||||
|
"D2 冰雪那达慕-莫日格勒河+断崖-冰雪火锅-雪地狼群-围炉煮茶-日落-海拉尔",
|
||||||
|
"D3 雪地骑马+摩托车穿越-蓝房子-不冻河日落-泡温泉-阿尔山森林公园",
|
||||||
|
"D4 白狼峰日出-泼水成冰-百里雾凇画廊-森林越野-驯鹿拉车-海拉尔",
|
||||||
|
"D5 烟火早市-伊敏河嘉年华(超长冰滑梯)-返程"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "winter-south-6d5n",
|
||||||
|
"name": "嗨冰雪V3·南线6天5晚",
|
||||||
|
"days": 6,
|
||||||
|
"nights": 5,
|
||||||
|
"tag": "经典版",
|
||||||
|
"line": "南线",
|
||||||
|
"route": "呼伦贝尔+阿尔山",
|
||||||
|
"audience": "想深度体验阿尔山冬景的家庭",
|
||||||
|
"description": "冬季南线经典版本,6天5晚从容走遍呼伦贝尔雪原与阿尔山冰雪世界。在精华版基础上,增加了阿尔山森林公园深度游览、网红牛打卡、百里雾凇画廊等内容,在童话小城阿尔山住两晚,节奏更从容。平均每天车程不超180公里,走走停停、边走边玩。",
|
||||||
|
"highlights": [
|
||||||
|
"冰雪那达慕+雪地狼群+雪地火锅+围炉煮茶,冬日草原生命力",
|
||||||
|
"雪地骑马+摩托车穿越+不冻河日落+冬日烟花+泡温泉",
|
||||||
|
"网红牛-百里雾凇画廊-森林越野10公里-驯鹿拉车-白狼峰日出"
|
||||||
|
],
|
||||||
|
"itinerary": [
|
||||||
|
"D1 各地→呼伦贝尔(接机/站+自由闲逛)",
|
||||||
|
"D2 冰雪那达慕-莫日格勒河+断崖-冰雪火锅-雪地狼群-围炉煮茶-日落-海拉尔(140公里)",
|
||||||
|
"D3 雪地骑马+摩托车穿越-蓝房子-不冻河日落-冬日烟花-泡温泉-阿尔山森林公园(300公里)",
|
||||||
|
"D4 网红牛-百里雾凇画廊-森林越野10公里-赏梅花鹿-驯鹿拉车-雪村-阿尔山(100公里)",
|
||||||
|
"D5 阿尔山-白狼峰日出-泼水成冰-日式火车站-樟子松林-海拉尔(350公里)",
|
||||||
|
"D6 海拉尔-烟火早市-伊敏河嘉年华(超长冰滑梯)-历史或民俗博物馆-返程(20公里)"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "winter-north-7d6n",
|
||||||
|
"name": "嗨冰雪V3·北线7天6晚",
|
||||||
|
"days": 7,
|
||||||
|
"nights": 6,
|
||||||
|
"tag": "深度版",
|
||||||
|
"line": "北线",
|
||||||
|
"route": "呼伦贝尔+大兴安岭",
|
||||||
|
"audience": "假期充足、想深度探索冬季北线的家庭",
|
||||||
|
"description": "冬季北线深度版,7天6晚从容走遍呼伦贝尔与大兴安岭。从草原雪原到中俄蒙边境满洲里,从呼伦湖蓝冰到恩和雪地骑马,从敖鲁古雅驯鹿部落到根河铁锹烤肉。入住套娃酒店体验异域风情,望见林悦独栋别墅感受静谧山野。平均每天车程不超210公里,走走停停、边走边玩。",
|
||||||
|
"highlights": [
|
||||||
|
"冰雪那达慕+雪地狼群+围炉煮茶,冬日草原原始体验",
|
||||||
|
"满洲里套娃酒店+国门+呼伦湖穿越蓝冰,边境异域风情",
|
||||||
|
"恩和雪地骑马+敖鲁古雅驯鹿部落+铁锹烤肉,大兴安岭深度探索"
|
||||||
|
],
|
||||||
|
"itinerary": [
|
||||||
|
"D1 各地→呼伦贝尔(接机/站+自由闲逛)",
|
||||||
|
"D2 那达慕-莫日格勒河+断崖-冰雪火锅-雪地狼群-围炉煮茶-冬日烟花-海拉尔(140公里)",
|
||||||
|
"D3 烟火早市-伊敏河嘉年华+超长冰滑梯-扎赉诺尔博物馆-北欧夜景-套娃酒店(230公里)",
|
||||||
|
"D4 国门+北疆明珠观光塔-风车公路-呼伦湖穿越-边防公路-雪原日落-额尔古纳(280公里)",
|
||||||
|
"D5 雪圆圆-三河村景+小楼山打卡点-泼水成冰-恩和骑马-恩和日落+夜景-望见林悦(110公里)",
|
||||||
|
"D6 望见林悦-室韦+临江后山-敖鲁古雅乡-圣诞小屋+敖乡夜景-根河(230公里)",
|
||||||
|
"D7 根河-布冬霞驯鹿部落-铁锹烤肉-鄂温克民族服饰体验-海拉尔-返程(250公里)"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"highlights": [
|
||||||
|
{
|
||||||
|
"title": "呼伦贝尔大雪原",
|
||||||
|
"description": "一望无际的大雪原,不必担心过度的商业化,也不必担心看不到好看的雪景,这片大雪原足以满足你对冰雪的幻想,而且你完全可以独享一片梦幻的雪原。"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"title": "课本里的《大兴安岭》",
|
||||||
|
"description": "无边无际的森林海洋,蕴藏着数之不尽的宝藏!每年的11月至次年4月,这里就会变成一个冰雪的世界,无比震撼的美,让人流连忘返。"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"title": "小型冰雪那达慕",
|
||||||
|
"description": "体验冬日草原少数民族的「生命力」,天地之间千里冰封的莫日格勒河畔,一场小型那达慕正在举办,身着蒙古族传统盛装,载歌载舞,体验摔跤的力量较量以及射箭带来的乐趣。"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"title": "雪地狼群",
|
||||||
|
"description": "这里是中科院狼行为学的科研基地,狼群数量达到上百只,狼通常成群生活,狩猎时默契得像经过多年训练一样。在其他地方很少会见到如此多的狼群,近距离观赏狼、投喂狼,感受草原狼文化。"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"title": "雪地火锅+围炉煮茶",
|
||||||
|
"description": "在这片纯白里,围上一锅热气腾腾的火锅,汤底翻滚、香气四散,寒意一下就被驱散了。还有小炉慢慢地煨着茶,水声轻沸腾,茶香在冷空气中更显清甜。吃火锅、煮热茶,在雪地里形成一个温暖的小宇宙。"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"title": "雪地野骑",
|
||||||
|
"description": "冬季骑马更独具一番感受,在一望无际的雪原和白桦林之间,感受冬季的速度与激情,用骑行的角度丈量这片神奇的土地,深入茫茫无际的雪原,欣赏绝美的冬日风光。"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"southHighlights": [
|
||||||
|
{
|
||||||
|
"title": "摩托车穿越+雪地野骑",
|
||||||
|
"description": "骑马和摩托车穿越,感受冬季的速度与激情,用不一样的角度,深入茫茫无际的雪原,欣赏绝美的冬日风光,感受雪上运动带来的刺激和快乐。"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"title": "零下30℃也冻不上的一条河",
|
||||||
|
"description": "在阿尔山国家森林公园内,有一条常年流淌的河流,由于矿物质丰富、以及地热增温作用使得河水在严冬季节也不会结冰,河面上云蒸霞蔚,河两岸形成晶莹的雾凇景观,每天本地牧民会赶着牛群来饮水。"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"title": "冰雪森林轻徒步",
|
||||||
|
"description": "仿佛踏入了一个童话世界,这里是一片雪挂林,受天气、是否下雪等太多因素影响,并且类似于雾凇,阳光很足或者刮风的时候也很快会消散。"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"title": "白狼峰日出",
|
||||||
|
"description": "在白狼峰的山顶,向远方眺望,远处群山连绵间云雾缭绕,微晕、上升、光芒四射,整个过程让人期待而振奋。提前准备一壶热水,在山顶的小亭子前泼水成冰,非常出片!"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"title": "童话小城阿尔山",
|
||||||
|
"description": "阿尔山不是山,风景却美过任何一座山;这里是名副其实的大兴安岭的腹地,一个可以让时间慢下来的地方。有人说这里是「东方瑞士」,独具特色的欧式建筑,把这里装点成北欧小镇一般。"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"northHighlights": [
|
||||||
|
{
|
||||||
|
"title": "越野穿越+驯鹿拉车",
|
||||||
|
"description": "冬季茫茫的大兴安岭林海中非常漂亮,硬派越野车穿越林海10公里,让您尽情感受冬日魅力;另外还有圣诞老人的坐骑——神圣的驯鹿拉车体验,他们是冬日的精灵,感受北欧芬兰一样的冰雪风情。"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"title": "三河打卡点",
|
||||||
|
"description": "呼伦贝尔版的冰雪童话小镇,比横道河子还要小众;山脚下就是人间烟火,站在山顶处俯瞰整座小镇,非常壮观。"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"title": "雪原日落+蓝调时刻",
|
||||||
|
"description": "冬季北方日照时间短,每天下午16点-17点就可以看到日落;配合上一望无际的雪原和森林海洋,以及日落后的粉色天空或者蓝调的时刻,不论是拍照或欣赏,都会让您感到大自然的魅力。"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"title": "中俄蒙边境套娃酒店",
|
||||||
|
"description": "在中俄蒙三国边境的童话小城——满洲里,有一座富丽堂皇的「套娃酒店」;它不仅创造了世界吉尼斯记录,更是以套娃为主题打造的一座宫殿,感受不用走出国门、即可感受的异域风情。"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"title": "呼伦湖穿越+蓝冰",
|
||||||
|
"description": "呼伦湖是我国北方第一大湖,一旦进入冬季千里冰封、万里雪飘的时候,呼伦湖就会变成一整块巨冰;湖面穿越+寻找蓝冰的体验活动,乘车行驶在一望无际的冰面上,是一次特别且难忘的旅行体验。"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"timeline": [
|
||||||
|
{
|
||||||
|
"version": "V3",
|
||||||
|
"date": "2025.11",
|
||||||
|
"title": "南北双线全面升级,新增5天4晚精华版",
|
||||||
|
"changes": [
|
||||||
|
{
|
||||||
|
"text": "南线新增5天4晚精华版,假期有限也能体验冬季精华",
|
||||||
|
"type": "add"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"text": "北线重新加入满洲里行程,新增套娃酒店+呼伦湖穿越蓝冰",
|
||||||
|
"type": "add"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"text": "南线新增摩托车穿越、冰雪森林轻徒步体验",
|
||||||
|
"type": "add"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"text": "全线升级住宿标准,新增望见林悦独栋别墅等特色住宿",
|
||||||
|
"type": "update"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"reason": "V2取消满洲里后客户反馈北线内容偏少,同时很多客户假期有限但想体验冬季。V3重新优化满洲里行程(套娃酒店+呼伦湖蓝冰),同时新增南线5天4晚精华版满足短假期需求。"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"version": "V2(北线)",
|
||||||
|
"date": "2024.11",
|
||||||
|
"title": "深入大兴安岭腹地,探访原始鄂温克部落",
|
||||||
|
"changes": [
|
||||||
|
{
|
||||||
|
"text": "新增大兴安岭徒步,穿军大衣戴狗皮帽子踏入银装素裹的林海",
|
||||||
|
"type": "add"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"text": "新增铁锹烤肉,雪地里就地取材生火烤肉",
|
||||||
|
"type": "add"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"text": "新增原始鄂温克寻鹿点,走进真正的驯鹿部落",
|
||||||
|
"type": "add"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"text": "取消满洲里行程,把时间留给更值得的地方",
|
||||||
|
"type": "remove"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"text": "增加冬季随车备品,让寒冷的冬天充满温度",
|
||||||
|
"type": "update"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"reason": "前往满洲里路途景色单一,俄罗斯大马戏、马术表演停止演出,呼伦湖湖面被雪覆盖难看到大面积蓝冰。取消满洲里后把时间给了大兴安岭深度体验——徒步、铁锹烤肉、原始鄂温克部落。"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"version": "V2(南线)",
|
||||||
|
"date": "2024.11",
|
||||||
|
"title": "新增森林牧场UTV穿越体验",
|
||||||
|
"changes": [
|
||||||
|
{
|
||||||
|
"text": "新增森林牧场UTV卡丁车穿越,在林海雪原中自由驰骋",
|
||||||
|
"type": "add"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"text": "取消满洲里行程,优化时间分配",
|
||||||
|
"type": "remove"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"reason": "距离阿尔山仅3公里的森林牧场,被冰雪覆盖宛如童话中的银色世界。驾驶雪地全地形越野车穿梭于林海雪原之间,取代满洲里的单调路程。"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"version": "V1(北线)",
|
||||||
|
"date": "2023.11",
|
||||||
|
"title": "嗨冰雪首发·北线呼伦贝尔+满洲里+大兴安岭",
|
||||||
|
"changes": [
|
||||||
|
{
|
||||||
|
"text": "冰雪那达慕·莫日格勒河畔蒙古族传统活动",
|
||||||
|
"type": "add"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"text": "雪原骑马/骑骆驼,驰骋在被雪覆盖的原野上",
|
||||||
|
"type": "add"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"text": "驯鹿拉爬犁,属于鄂温克人的浪漫",
|
||||||
|
"type": "add"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"text": "冷极村森林民俗体验馆+冰雪乐园",
|
||||||
|
"type": "add"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"text": "敖鲁古雅驯鹿苑+博物馆,国内独一的驯鹿主题博物馆",
|
||||||
|
"type": "add"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"text": "呼伦湖成吉思汗拴马桩,中国最大一块冰",
|
||||||
|
"type": "add"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"reason": "呼籁深耕呼伦贝尔多年后首次推出冬季产品线。北线串联草原雪原、满洲里边境、大兴安岭森林三大核心场景,让冬天的呼伦贝尔不再只是一个冷的概念。"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"version": "V1(南线)",
|
||||||
|
"date": "2023.11",
|
||||||
|
"title": "嗨冰雪首发·南线呼伦贝尔+阿尔山",
|
||||||
|
"changes": [
|
||||||
|
{
|
||||||
|
"text": "冰雪那达慕·莫日格勒河畔体验冬日草原活力",
|
||||||
|
"type": "add"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"text": "雪原骑马/骑骆驼,在大雪原中策马奔腾",
|
||||||
|
"type": "add"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"text": "森林牧场UTV全地形越野车穿越林海雪原",
|
||||||
|
"type": "add"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"text": "阿尔山雪村,逃离喧嚣的冬日胜地",
|
||||||
|
"type": "add"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"text": "不冻河漂流,零下30℃的河面云蒸霞蔚",
|
||||||
|
"type": "add"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"text": "白狼峰日出+泼水成冰,山顶看群山云雾",
|
||||||
|
"type": "add"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"text": "百里雾凇画廊,仿佛踏入童话世界的雪挂林",
|
||||||
|
"type": "add"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"reason": "南线以阿尔山为核心,串联草原雪原与大兴安岭腹地的童话小城。阿尔山不是山,风景却美过任何一座山,被称为「东方瑞士」,冬季更是一个让时间慢下来的地方。"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"selectionGuide": {
|
||||||
|
"byPreference": [
|
||||||
|
{
|
||||||
|
"reason": "白狼峰日出+不冻河+童话小城",
|
||||||
|
"condition": "想看阿尔山",
|
||||||
|
"recommendation": "winter-south-6d5n"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"reason": "满洲里+呼伦湖蓝冰+驯鹿部落",
|
||||||
|
"condition": "想去边境",
|
||||||
|
"recommendation": "winter-north-7d6n"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"reason": "5天精华浓缩,核心不缺",
|
||||||
|
"condition": "假期有限",
|
||||||
|
"recommendation": "winter-south-5d4n"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"byVacationLength": [
|
||||||
|
{
|
||||||
|
"reason": "精华浓缩,核心体验一个不少",
|
||||||
|
"condition": "5天假期",
|
||||||
|
"recommendation": "winter-south-5d4n"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"reason": "阿尔山住两晚,节奏更从容",
|
||||||
|
"condition": "6天假期",
|
||||||
|
"recommendation": "winter-south-6d5n"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"reason": "深度探索,大兴安岭+边境全覆盖",
|
||||||
|
"condition": "7天以上",
|
||||||
|
"recommendation": "winter-north-7d6n"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
73
error.vue
普通文件
73
error.vue
普通文件
@ -0,0 +1,73 @@
|
|||||||
|
<template>
|
||||||
|
<div class="error-page">
|
||||||
|
<div class="container">
|
||||||
|
<h1 class="error-code">{{ error.statusCode }}</h1>
|
||||||
|
<p class="error-message">
|
||||||
|
{{ error.statusCode === 404 ? '页面不存在' : '出了点问题' }}
|
||||||
|
</p>
|
||||||
|
<p class="error-desc">
|
||||||
|
您访问的页面可能已移动或不存在,请返回首页继续浏览。
|
||||||
|
</p>
|
||||||
|
<NuxtLink to="/" class="error-back">返回首页</NuxtLink>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup>
|
||||||
|
defineProps({
|
||||||
|
error: { type: Object, required: true },
|
||||||
|
})
|
||||||
|
|
||||||
|
useHead({
|
||||||
|
title: '页面未找到 - 呼籁旅行',
|
||||||
|
meta: [
|
||||||
|
{ name: 'description', content: '您访问的页面不存在,请返回呼籁旅行首页继续浏览呼伦贝尔家庭定制游产品和服务。' },
|
||||||
|
{ name: 'robots', content: 'noindex' },
|
||||||
|
],
|
||||||
|
})
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="less" scoped>
|
||||||
|
.error-page {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
min-height: 80vh;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.error-code {
|
||||||
|
font-size: 80px;
|
||||||
|
font-weight: @font-weight-bold;
|
||||||
|
color: @color-primary-lighter;
|
||||||
|
line-height: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
.error-message {
|
||||||
|
margin-top: @space-md;
|
||||||
|
font-size: @font-size-xl;
|
||||||
|
color: @color-text-primary;
|
||||||
|
}
|
||||||
|
|
||||||
|
.error-desc {
|
||||||
|
margin-top: @space-sm;
|
||||||
|
color: @color-text-muted;
|
||||||
|
}
|
||||||
|
|
||||||
|
.error-back {
|
||||||
|
display: inline-block;
|
||||||
|
margin-top: @space-xl;
|
||||||
|
padding: @space-md @space-xl;
|
||||||
|
background: @color-primary;
|
||||||
|
color: #fff;
|
||||||
|
border-radius: @border-radius-md;
|
||||||
|
text-decoration: none;
|
||||||
|
font-weight: @font-weight-medium;
|
||||||
|
transition: background @transition-fast;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
background: @color-primary-light;
|
||||||
|
color: #fff;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
41
layouts/default.vue
普通文件
41
layouts/default.vue
普通文件
@ -0,0 +1,41 @@
|
|||||||
|
<template>
|
||||||
|
<div class="app-layout">
|
||||||
|
<a href="#main-content" class="sr-only skip-link">跳转到主要内容</a>
|
||||||
|
<LayoutAppHeader />
|
||||||
|
<main id="main-content" class="app-main">
|
||||||
|
<slot />
|
||||||
|
</main>
|
||||||
|
<LayoutAppFooter />
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<style lang="less" scoped>
|
||||||
|
.app-layout {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
min-height: 100vh;
|
||||||
|
}
|
||||||
|
|
||||||
|
.app-main {
|
||||||
|
flex: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
.skip-link {
|
||||||
|
&:focus {
|
||||||
|
position: fixed;
|
||||||
|
top: @space-sm;
|
||||||
|
left: @space-sm;
|
||||||
|
z-index: 200;
|
||||||
|
width: auto;
|
||||||
|
height: auto;
|
||||||
|
padding: @space-sm @space-md;
|
||||||
|
background: @color-primary;
|
||||||
|
color: #fff;
|
||||||
|
font-size: @font-size-sm;
|
||||||
|
border-radius: @border-radius-md;
|
||||||
|
clip: auto;
|
||||||
|
white-space: normal;
|
||||||
|
overflow: visible;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
74
nuxt.config.js
普通文件
74
nuxt.config.js
普通文件
@ -0,0 +1,74 @@
|
|||||||
|
// https://nuxt.com/docs/api/configuration/nuxt-config
|
||||||
|
export default defineNuxtConfig({
|
||||||
|
ssr: true,
|
||||||
|
|
||||||
|
nitro: {
|
||||||
|
// preset: 'static' 已移除——静态模式下 server/api/ 不可用。
|
||||||
|
// 部署时使用 `nuxt build` + Node.js 服务器(如 PM2)。
|
||||||
|
// 若必须静态部署,需将表单改为第三方服务(飞书/EmailJS 等)。
|
||||||
|
prerender: {
|
||||||
|
crawlLinks: true,
|
||||||
|
routes: [
|
||||||
|
'/', '/about', '/products', '/summer-camp', '/winter-camp', '/courses', '/guides', '/guide-custom', '/faq', '/reviews', '/contact', '/customize', '/pricing', '/selector', '/sitemap.xml',
|
||||||
|
'/products/v9-4d3n', '/products/v9-5d4n', '/products/v9-6d5n-family',
|
||||||
|
'/products/v9-6d5n-comfort', '/products/v9-7d6n-family', '/products/v9-7d6n-wild',
|
||||||
|
'/products/autumn', '/products/winter',
|
||||||
|
'/destinations',
|
||||||
|
'/destinations/moriguole', '/destinations/eergunashire', '/destinations/baihualin',
|
||||||
|
'/destinations/enhe-shiwei', '/destinations/heishantou', '/destinations/manzhouli',
|
||||||
|
'/destinations/hulunhu', '/destinations/aershan', '/destinations/shiwei',
|
||||||
|
'/destinations/daxinganling', '/destinations/aoluguya', '/destinations/genhe',
|
||||||
|
'/gallery',
|
||||||
|
'/news', '/calendar',
|
||||||
|
'/stories',
|
||||||
|
'/blog',
|
||||||
|
'/blog/hulunbuir-travel-guide-2026',
|
||||||
|
'/blog/hulunbuir-family-travel-guide',
|
||||||
|
'/blog/hulunbuir-best-month-to-visit',
|
||||||
|
'/blog/hulunbuir-self-drive-vs-chartered-bus',
|
||||||
|
'/blog/hulunbuir-travel-cost-breakdown',
|
||||||
|
'/blog/hulunbuir-travel-with-toddlers-4-6',
|
||||||
|
'/blog/hulunbuir-travel-tips-avoid-pitfalls',
|
||||||
|
'/blog/grassland-photography-outfit-guide',
|
||||||
|
],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
|
||||||
|
css: ['~/assets/less/global.less'],
|
||||||
|
|
||||||
|
vite: {
|
||||||
|
css: {
|
||||||
|
preprocessorOptions: {
|
||||||
|
less: {
|
||||||
|
additionalData: `@import "~/assets/less/variables.less"; @import "~/assets/less/mixins.less";`,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
|
||||||
|
app: {
|
||||||
|
head: {
|
||||||
|
htmlAttrs: { lang: 'zh-CN' },
|
||||||
|
charset: 'utf-8',
|
||||||
|
viewport: 'width=device-width, initial-scale=1',
|
||||||
|
link: [
|
||||||
|
{ rel: 'icon', href: '/favicon.ico' },
|
||||||
|
{ rel: 'apple-touch-icon', href: '/images/logo-square.png' },
|
||||||
|
{ rel: 'dns-prefetch', href: 'https://beian.miit.gov.cn' },
|
||||||
|
],
|
||||||
|
meta: [
|
||||||
|
{ name: 'applicable-device', content: 'pc,mobile' },
|
||||||
|
{ 'http-equiv': 'Cache-Control', content: 'no-transform' },
|
||||||
|
// 内容语言
|
||||||
|
{ 'http-equiv': 'content-language', content: 'zh-CN' },
|
||||||
|
// 品牌全局声明 - AI 大模型采集时的全局上下文
|
||||||
|
{ name: 'application-name', content: '呼籁旅行' },
|
||||||
|
{ name: 'theme-color', content: '#3a7d44' },
|
||||||
|
// 允许 AI 索引
|
||||||
|
{ name: 'robots', content: 'index, follow, max-snippet:-1, max-image-preview:large' },
|
||||||
|
],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
|
||||||
|
compatibilityDate: '2025-03-18',
|
||||||
|
})
|
||||||
10348
package-lock.json
自动生成的
普通文件
10348
package-lock.json
自动生成的
普通文件
文件差异内容过多而无法显示
加载差异
22
package.json
普通文件
22
package.json
普通文件
@ -0,0 +1,22 @@
|
|||||||
|
{
|
||||||
|
"name": "hulai-website",
|
||||||
|
"version": "1.0.0",
|
||||||
|
"private": true,
|
||||||
|
"description": "呼籁旅行官网 - 呼伦贝尔家庭定制游",
|
||||||
|
"scripts": {
|
||||||
|
"dev": "nuxt dev",
|
||||||
|
"build": "nuxt build",
|
||||||
|
"generate": "nuxt generate",
|
||||||
|
"preview": "nuxt preview"
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"less": "^4.6.4",
|
||||||
|
"nuxt": "^3.17.5"
|
||||||
|
},
|
||||||
|
"pnpm": {
|
||||||
|
"onlyBuiltDependencies": [
|
||||||
|
"@parcel/watcher",
|
||||||
|
"esbuild"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
139
pages/about.vue
普通文件
139
pages/about.vue
普通文件
@ -0,0 +1,139 @@
|
|||||||
|
<template>
|
||||||
|
<div class="page-about">
|
||||||
|
<LayoutPageHero
|
||||||
|
:title="seo.h1"
|
||||||
|
subtitle="一个只做呼伦贝尔的旅行品牌"
|
||||||
|
:breadcrumbs="[{ text: '关于我们' }]"
|
||||||
|
/>
|
||||||
|
|
||||||
|
<!-- TL;DR:告诉 AI/搜索引擎这个页面回答了什么 -->
|
||||||
|
<section class="page-tldr" aria-label="关于我们摘要">
|
||||||
|
<div class="container">
|
||||||
|
<div class="page-tldr-inner">
|
||||||
|
<p>呼籁旅行创立于2015年,是内蒙古呼伦贝尔本地旅行品牌,11年专注呼伦贝尔一个目的地。旗下持有三重旅行社经营许可证,购买1000万旅游责任险,已服务超10000个家庭。集团旗下涵盖旅行社、牧场商贸、研学教育等多家主体。</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
<!-- 品牌故事 -->
|
||||||
|
<AboutBrandStory :story="about.story" class="reveal" />
|
||||||
|
|
||||||
|
<!-- 集团实力 -->
|
||||||
|
<AboutSubsidiaryGrid :subsidiaries="about.subsidiaries" class="reveal" />
|
||||||
|
|
||||||
|
<!-- 资质认证 & 服务保障 -->
|
||||||
|
<AboutQualificationList :certifications="about.certifications" :guarantees="about.guarantees" class="reveal" />
|
||||||
|
|
||||||
|
<!-- 小红书 -->
|
||||||
|
<AboutXiaohongshuShowcase :xhs="about.xiaohongshu" class="reveal" />
|
||||||
|
|
||||||
|
<!-- 知识产权 -->
|
||||||
|
<AboutCopyrightList :copyrights="about.copyrights" :trademark="about.trademark" class="reveal" />
|
||||||
|
|
||||||
|
<!-- 品牌IP -->
|
||||||
|
<AboutMascotShowcase class="reveal" />
|
||||||
|
|
||||||
|
<!-- 团队介绍 -->
|
||||||
|
<AboutTeamIntro :team="about.team" class="reveal" />
|
||||||
|
|
||||||
|
<!-- 8个温度时刻 -->
|
||||||
|
<section class="section section--gray reveal" aria-label="服务旅程">
|
||||||
|
<div class="container">
|
||||||
|
<CommonSectionTitle :title="about.serviceJourney.title" :subtitle="about.serviceJourney.subtitle" />
|
||||||
|
<ol class="journey-list">
|
||||||
|
<li v-for="m in about.serviceJourney.moments" :key="m.step" class="journey-item">
|
||||||
|
<span class="journey-step">{{ m.step }}</span>
|
||||||
|
<div class="journey-body">
|
||||||
|
<strong class="journey-name">{{ m.name }}</strong>
|
||||||
|
<p class="journey-detail">{{ m.detail }}</p>
|
||||||
|
</div>
|
||||||
|
</li>
|
||||||
|
</ol>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
<!-- 企业文化 -->
|
||||||
|
<AboutCultureValues :culture="about.culture" class="reveal" />
|
||||||
|
|
||||||
|
<!-- 内链 -->
|
||||||
|
<CommonSectionCTA
|
||||||
|
title="想了解我们的产品?"
|
||||||
|
description="查看额吉的故乡V9系列和小蒙马夏令营"
|
||||||
|
:links="[{ to: '/products', text: '查看呼伦贝尔定制游产品' }]"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup>
|
||||||
|
import about from '~/data/about.json'
|
||||||
|
import brand from '~/data/brand.json'
|
||||||
|
import contact from '~/data/contact.json'
|
||||||
|
import { useOrganizationSchema, useBreadcrumbSchema, usePersonSchema } from '~/composables/useJsonLd'
|
||||||
|
|
||||||
|
const seo = useSEO('about')
|
||||||
|
useScrollReveal()
|
||||||
|
useOrganizationSchema(brand, contact)
|
||||||
|
usePersonSchema(about.founder)
|
||||||
|
useBreadcrumbSchema([
|
||||||
|
{ text: '首页', to: '/' },
|
||||||
|
{ text: '关于我们' },
|
||||||
|
])
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="less" scoped>
|
||||||
|
.journey-list {
|
||||||
|
list-style: none;
|
||||||
|
padding: 0;
|
||||||
|
margin: @space-xl 0 0;
|
||||||
|
display: grid;
|
||||||
|
grid-template-columns: 1fr;
|
||||||
|
gap: @space-lg;
|
||||||
|
|
||||||
|
.respond-md({
|
||||||
|
grid-template-columns: repeat(2, 1fr);
|
||||||
|
});
|
||||||
|
|
||||||
|
.respond-lg({
|
||||||
|
grid-template-columns: repeat(4, 1fr);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
.journey-item {
|
||||||
|
display: flex;
|
||||||
|
gap: @space-md;
|
||||||
|
align-items: flex-start;
|
||||||
|
}
|
||||||
|
|
||||||
|
.journey-step {
|
||||||
|
flex-shrink: 0;
|
||||||
|
width: 32px;
|
||||||
|
height: 32px;
|
||||||
|
background: @color-primary;
|
||||||
|
color: #fff;
|
||||||
|
border-radius: 50%;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
font-size: @font-size-sm;
|
||||||
|
font-weight: @font-weight-bold;
|
||||||
|
}
|
||||||
|
|
||||||
|
.journey-body {
|
||||||
|
flex: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
.journey-name {
|
||||||
|
display: block;
|
||||||
|
font-size: @font-size-base;
|
||||||
|
font-weight: @font-weight-bold;
|
||||||
|
color: @color-text-primary;
|
||||||
|
margin-bottom: @space-xs;
|
||||||
|
}
|
||||||
|
|
||||||
|
.journey-detail {
|
||||||
|
font-size: @font-size-sm;
|
||||||
|
color: @color-text-secondary;
|
||||||
|
line-height: @line-height-base;
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
某些文件未显示,因为此 diff 中更改的文件太多 显示更多
正在加载...
x
在新工单中引用
屏蔽一个用户