chore: initialize WanderQ MiniAPP 2.0 repository

This commit is contained in:
inman
2026-07-23 15:48:34 +08:00
commit b4c0a1c516
93 changed files with 53525 additions and 0 deletions

4052
src/App.tsx Normal file

File diff suppressed because it is too large Load Diff

217
src/api.ts Normal file
View File

@@ -0,0 +1,217 @@
const API_BASE = import.meta.env.VITE_API_BASE_URL ?? "";
export type PublicHeroSlide = {
id: string;
title: string;
kicker?: string | null;
image: string;
targetType?: string | null;
targetValue?: string | null;
isActive?: boolean;
};
export type PublicDestination = {
id: string;
name: string;
image?: string | null;
isHot?: boolean;
isActive?: boolean;
aliases?: { id: string; alias: string }[];
};
export type PublicTheme = {
id: string;
label: string;
image: string;
targetType?: string | null;
targetValue?: string | null;
isActive?: boolean;
};
export type PublicCta = {
id: string;
alt: string;
image: string;
targetType?: string | null;
targetValue?: string | null;
isActive?: boolean;
};
export type PublicSearchPageKeyword = {
id: string;
label: string;
image?: string | null;
isActive?: boolean;
sortOrder: number;
};
export type PublicSearchPageGroup = {
id: string;
label: string;
items: PublicSearchPageKeyword[];
isActive?: boolean;
sortOrder: number;
};
export type PublicSearchPageModuleCopy = {
title: string;
subtitle: string;
};
export type PublicSearchPageConfig = {
placeholder: string;
modules: {
seasonalInspiration: PublicSearchPageModuleCopy;
preferenceDiscovery: PublicSearchPageModuleCopy;
};
popularKeywords: PublicSearchPageKeyword[];
groups: PublicSearchPageGroup[];
/** Transitional fields accepted while an older API response is still cached. */
title?: string;
subtitle?: string;
};
export type PublicHomeModule = {
id: string;
label: string;
sortOrder: number;
isActive?: boolean;
templateType?: "explore" | "themes" | "deals" | "hotels" | "vehicles";
content?: {
items: Array<{
id: string;
title: string;
subtitle?: string;
description?: string;
image?: string | null;
targetType?: string | null;
targetValue?: string | null;
productIds?: string[];
chips?: string[];
isActive: boolean;
sortOrder: number;
}>;
};
};
export type ProductPricingTier = {
groupSize: number;
adultPrice: number;
child6PlusPrice: number;
childUnder6Price: number;
};
export type PublicProduct = {
id: string;
sourceId?: number | null;
title: string;
subtitle?: string | null;
destination?: { id: string; name: string } | null;
priceAmount?: number | null;
priceUnit?: string | null;
pricingTiers?: ProductPricingTier[] | null;
tags?: string[];
coverImage?: string | null;
summary?: string | null;
durationDays?: number | null;
durationNights?: number | null;
departureDates?: string[];
remainingSpots?: number | null;
recommendation?: string | null;
images?: Array<{ id?: string; url: string; alt?: string | null; sortOrder: number }>;
keyFacts?: ProductKeyFact[] | null;
contentBlocks?: ProductContentBlock[] | null;
detailSections?: ProductDetailSection[] | null;
status?: string;
sortWeight?: number;
};
export type ProductKeyFact = { label: string; value: string };
export type ProductContentBlock =
| { type: "title"; text: string }
| { type: "image"; url: string; alt?: string | null };
export type ProductDetailBlock =
| { type: "text"; text: string }
| { type: "image"; url: string; alt?: string | null };
export type ProductDetailSection = {
key: string;
label: string;
title?: string | null;
blocks: ProductDetailBlock[];
};
export type PublicSiteConfig = {
homeModules?: PublicHomeModule[];
heroSlides?: PublicHeroSlide[];
destinations?: PublicDestination[];
themes?: PublicTheme[];
ctaBanners?: PublicCta[];
destinationRecommendations?: { productIds: string[] };
searchPage?: PublicSearchPageConfig;
};
export type PublicLeadPayload = {
destination?: string;
phone: string;
contactName?: string;
wechat?: string;
travelDate?: string;
peopleCount?: number;
adultCount?: number;
childCount?: number;
roomType?: string;
plan?: string;
addOns?: string[];
budgetMin?: number;
budgetMax?: number;
note?: string;
sourcePage?: string;
sourceTheme?: string;
sourceProductId?: string;
};
async function request<T>(path: string, init?: RequestInit) {
const response = await fetch(`${API_BASE}${path}`, {
headers: {
"content-type": "application/json",
...init?.headers,
},
...init,
});
if (!response.ok) {
const message = await response.text();
throw new Error(message || `Request failed: ${response.status}`);
}
return response.json() as Promise<T>;
}
export async function fetchPublicContent() {
const [siteConfig, products] = await Promise.all([
request<PublicSiteConfig>("/api/public/site-config"),
request<{ items: PublicProduct[] }>("/api/public/products"),
]);
return {
siteConfig,
products: products.items,
};
}
export async function createPublicLead(payload: PublicLeadPayload) {
return request<{ id: string; status: string }>("/api/public/leads", {
method: "POST",
body: JSON.stringify(payload),
});
}
export async function createPublicBooking(payload: PublicLeadPayload) {
return request<{ id: string; status: string; requestType: "booking" }>("/api/public/bookings", {
method: "POST",
body: JSON.stringify(payload),
});
}

228
src/content.ts Normal file
View File

@@ -0,0 +1,228 @@
import { staticMedia } from "./media";
const guizhouAsset = (name: string) => staticMedia(`guizhou/${name}.webp`);
const volumeAsset = (name: string) => staticMedia(`guizhou/volumes/${name}.webp`);
export type VolumeKey = "shan" | "shui" | "ren" | "yun" | "ling" | "xing";
export type VolumeCatalogItem = {
key: VolumeKey;
label: string;
shortLabel: string;
story: string;
subtitle: string;
image: string;
overviewImage: string;
destinations: string[];
productIds: string[];
};
export const volumeCatalog: VolumeCatalogItem[] = [
{
key: "shan",
label: "山之卷",
shortLabel: "山",
story: "苗岭仙山 · 喀斯特秘境",
subtitle: "施秉、杉木河与云台山,把清凉写进苗岭山水。",
image: volumeAsset("volume-shan-cover"),
overviewImage: volumeAsset("volume-shan-overview"),
destinations: ["施秉", "杉木河", "云台山"],
productIds: ["1"],
},
{
key: "yun",
label: "云之卷",
shortLabel: "云",
story: "乌蒙高原 · 云端草山",
subtitle: "中国凉都的高原风、草原湿地与云端慢生活。",
image: volumeAsset("volume-yun-cover"),
overviewImage: volumeAsset("volume-yun-overview"),
destinations: ["六盘水", "野玉海", "乌蒙大草原", "威宁草海"],
productIds: ["5"],
},
{
key: "shui",
label: "水之卷",
shortLabel: "水",
story: "峡谷漂流 · 河湖泛舟",
subtitle: "两条水线,一条奔向野洞河,一条进入荔波绿宝石。",
image: volumeAsset("volume-shui-gorge-cover"),
overviewImage: volumeAsset("volume-shui-gorge-overview"),
destinations: ["飞云崖", "旧州", "野洞河", "荔波小七孔", "茂兰"],
productIds: ["2", "3"],
},
{
key: "ren",
label: "人之卷",
shortLabel: "人",
story: "屯堡古韵 · 瀑洞双绝",
subtitle: "黄果树的水声、屯堡的石巷与织金洞的地心光影。",
image: volumeAsset("volume-ren-cover"),
overviewImage: volumeAsset("volume-ren-overview"),
destinations: ["云峰屯堡", "黄果树", "织金洞", "织金大峡谷"],
productIds: ["4"],
},
{
key: "xing",
label: "星之卷",
shortLabel: "星",
story: "仰望星河 · 天眼探索",
subtitle: "从平塘天眼到掌布,把贵州的夜空和地质奇观连成一线。",
image: volumeAsset("volume-xing-cover"),
overviewImage: volumeAsset("volume-xing-overview"),
destinations: ["平塘天眼", "天文体验馆", "掌布", "独山"],
productIds: ["7"],
},
{
key: "ling",
label: "灵之卷",
shortLabel: "灵",
story: "武陵秘境 · 山水人文",
subtitle: "梵净山的云上灵气,连着铜仁峡谷与亚木沟的水声。",
image: volumeAsset("volume-ling-cover"),
overviewImage: volumeAsset("volume-ling-overview"),
destinations: ["铜仁", "梵净山", "亚木沟", "中南门古城"],
productIds: ["6"],
},
];
export const heroVolumeOrder: VolumeKey[] = ["shan", "yun", "shui", "ren", "xing", "ling"];
export const heroSlides = heroVolumeOrder
.map((key) => volumeCatalog.find((volume) => volume.key === key))
.filter((volume): volume is VolumeCatalogItem => Boolean(volume))
.map((volume) => ({
id: `hero-${volume.key}`,
image: volume.image,
kicker: `${volume.label} · 多彩贵州号`,
title: volume.story,
action: "查看这一卷",
targetType: "volume",
targetValue: volume.key,
}));
export type HomeModuleId = "explore" | "themes" | "deals" | "hotels" | "vehicles";
export type HomeModuleTemplateType = HomeModuleId;
export type HomeModuleContentItem = {
id: string;
title: string;
subtitle?: string;
description?: string;
image?: string | null;
targetType?: string | null;
targetValue?: string | null;
productIds?: string[];
chips?: string[];
isActive: boolean;
sortOrder: number;
};
export type HomeModuleContent = {
items: HomeModuleContentItem[];
};
export type HomeModuleConfig = {
id: string;
label: string;
sortOrder: number;
isActive: boolean;
templateType: HomeModuleTemplateType;
content?: HomeModuleContent;
};
const volumeHomeItems: HomeModuleContentItem[] = volumeCatalog.map((volume, index) => ({
id: `volume-${volume.key}`,
title: volume.label,
subtitle: volume.story,
description: volume.subtitle,
image: volume.image,
targetType: "volume",
targetValue: volume.key,
productIds: volume.productIds,
chips: volume.destinations,
isActive: true,
sortOrder: index,
}));
export const homeModules: HomeModuleConfig[] = [
{ id: "explore", label: "目的地灵感", sortOrder: 0, isActive: true, templateType: "explore" },
{ id: "themes", label: "六卷读懂贵州", sortOrder: 1, isActive: true, templateType: "themes", content: { items: volumeHomeItems } },
{ id: "deals", label: "首期发车活动", sortOrder: 2, isActive: true, templateType: "deals" },
{ id: "hotels", label: "行程服务", sortOrder: 3, isActive: true, templateType: "hotels" },
{ id: "vehicles", label: "交通保障", sortOrder: 4, isActive: true, templateType: "vehicles" },
];
export const destinations = [
{ label: "施秉", image: guizhouAsset("fanjing-mountain") },
{ label: "荔波小七孔", image: guizhouAsset("libo-xiaoqikong") },
{ label: "黄果树", image: guizhouAsset("huangguoshu-waterfall") },
{ label: "六盘水", image: guizhouAsset("wumeng-grassland") },
{ label: "梵净山", image: guizhouAsset("fanjing-mountain") },
{ label: "平塘天眼", image: guizhouAsset("tiankeng-pool") },
{ label: "贵阳", image: guizhouAsset("jiaxiu-tower") },
{ label: "织金洞", image: guizhouAsset("zhijin-cave") },
{ label: "铜仁", image: guizhouAsset("fanjing-mountain") },
{ label: "威宁草海", image: guizhouAsset("wumeng-grassland") },
{ label: "独山", image: guizhouAsset("tiankeng-pool") },
{ label: "亚木沟", image: guizhouAsset("gorge-paddle") },
];
export const themeCards = volumeCatalog.map((volume) => ({
id: `theme-${volume.key}`,
label: volume.label,
image: volume.image,
targetType: "volume",
targetValue: volume.key,
}));
export const dealCards = [
{
label: "六卷定制服务",
demandPrefill: "综合混搭特惠",
image: volumeAsset("volume-ling-overview"),
description: "可跨卷组合目的地,也可按人数、预算与体力重新编排。",
},
] as const;
export const hotelGroups = [
{
title: "列车行程服务",
image: volumeAsset("volume-shui-libo-overview"),
description: "出发日期、住宿房型、团队节奏和每日接驳,提交需求后由服务管家确认。",
hotels: ["出发日期确认", "住宿房型选择", "接送站安排", "行程通知单"],
},
{
title: "可选增值体验",
image: volumeAsset("volume-xing-overview"),
description: "座席、房型、特色餐、在地体验与小团服务可在咨询时一起备注。",
hotels: ["座席/房型", "特色餐饮", "在地向导", "延伸定制"],
},
];
export const vehicleOptions = [
{
title: "5座舒适出行",
image: "https://one-feel-bucket.oss-cn-guangzhou.aliyuncs.com/wanqu/miniapp/static/vehicles/5-seat.webp",
description: "适合 24 人家庭或好友小团,城市接送与景区穿梭更灵活。",
},
{
title: "7座商务出行",
image: "https://one-feel-bucket.oss-cn-guangzhou.aliyuncs.com/wanqu/miniapp/static/vehicles/7-seat-3.webp",
description: "适合 46 人同行,兼顾行李空间、乘坐舒适度与山路机动性。",
},
{
title: "9座精品商务车",
image: "https://one-feel-bucket.oss-cn-guangzhou.aliyuncs.com/wanqu/miniapp/static/vehicles/9-seat.webp",
description: "适合 58 人同行,留足行李与休息空间,适合跨城及多日行程。",
},
];
export const bottomCtas = [
{ image: volumeAsset("volume-shan-overview"), alt: "查看山之卷贵州行程", targetType: "volume", targetValue: "shan" },
{ image: volumeAsset("volume-ling-overview"), alt: "咨询贵州服务管家", targetType: "support", targetValue: null },
{ image: volumeAsset("volume-xing-overview"), alt: "查看星之卷贵州行程", targetType: "volume", targetValue: "xing" },
{ image: volumeAsset("volume-ren-overview"), alt: "提交贵州出行需求", targetType: "demand", targetValue: null },
];
export const footerImages = [volumeAsset("volume-shan-overview"), volumeAsset("volume-ling-overview")];

440
src/generated-products.json Normal file
View File

@@ -0,0 +1,440 @@
[
{
"id": 1,
"title": "第一卷|山之卷·苗岭仙山·喀斯特秘境 2天1晚",
"price": "1799",
"priceUnit": "成人起/人",
"pricingTiers": [
{ "groupSize": 2, "adultPrice": 2399, "child6PlusPrice": 1859, "childUnder6Price": 1599 },
{ "groupSize": 4, "adultPrice": 2099, "child6PlusPrice": 1499, "childUnder6Price": 1299 },
{ "groupSize": 6, "adultPrice": 1999, "child6PlusPrice": 1399, "childUnder6Price": 1199 },
{ "groupSize": 8, "adultPrice": 1799, "child6PlusPrice": 1299, "childUnder6Price": 999 }
],
"tags": ["山之卷", "7月30日", "2天1晚", "2-8人贵宾小包团"],
"image": "https://one-feel-bucket.oss-cn-guangzhou.aliyuncs.com/wanqu/miniapp/static/guizhou/train/products/volume-shan-vip.webp",
"images": [
{ "url": "https://one-feel-bucket.oss-cn-guangzhou.aliyuncs.com/wanqu/miniapp/static/guizhou/train/products/volume-shan-vip.webp", "alt": "山之卷贵宾小包团价格海报" },
{ "url": "https://one-feel-bucket.oss-cn-guangzhou.aliyuncs.com/wanqu/miniapp/static/guizhou/train/cover-family.webp", "alt": "乘坐多彩贵州号,读懂贵州六卷书" }
],
"summary": "贵阳出发乘坐多彩贵州号前往施秉串联杉木河与云台山2-8人贵宾小包团专属小车接驳。",
"destinationName": "施秉",
"durationDays": 2,
"durationNights": 1,
"departureDates": ["7月30日"],
"remainingSpots": null,
"recommendation": "适合想把漂流、山林与喀斯特景观压缩进周末的人群。",
"contentBlocks": [
{ "type": "title", "text": "行程单详情" },
{ "type": "image", "url": "https://one-feel-bucket.oss-cn-guangzhou.aliyuncs.com/wanqu/miniapp/static/guizhou/routes/shan/shan-page-03.webp", "alt": "山之卷两天一晚线路概览" },
{ "type": "image", "url": "https://one-feel-bucket.oss-cn-guangzhou.aliyuncs.com/wanqu/miniapp/static/guizhou/routes/shan/shan-page-04.webp", "alt": "山之卷特色体验" },
{ "type": "image", "url": "https://one-feel-bucket.oss-cn-guangzhou.aliyuncs.com/wanqu/miniapp/static/guizhou/routes/shan/shan-page-05.webp", "alt": "山之卷列车餐饮与住宿" },
{ "type": "image", "url": "https://one-feel-bucket.oss-cn-guangzhou.aliyuncs.com/wanqu/miniapp/static/guizhou/routes/shan/shan-page-06.webp", "alt": "山之卷产品概览" },
{ "type": "image", "url": "https://one-feel-bucket.oss-cn-guangzhou.aliyuncs.com/wanqu/miniapp/static/guizhou/routes/shan/shan-page-07.webp", "alt": "山之卷第一天行程" },
{ "type": "image", "url": "https://one-feel-bucket.oss-cn-guangzhou.aliyuncs.com/wanqu/miniapp/static/guizhou/routes/shan/shan-page-08.webp", "alt": "山之卷第一天行程续页" },
{ "type": "image", "url": "https://one-feel-bucket.oss-cn-guangzhou.aliyuncs.com/wanqu/miniapp/static/guizhou/routes/shan/shan-page-09.webp", "alt": "山之卷第二天行程" },
{ "type": "image", "url": "https://one-feel-bucket.oss-cn-guangzhou.aliyuncs.com/wanqu/miniapp/static/guizhou/routes/shan/shan-page-10.webp", "alt": "山之卷返程安排" },
{ "type": "image", "url": "https://one-feel-bucket.oss-cn-guangzhou.aliyuncs.com/wanqu/miniapp/static/guizhou/routes/shan/shan-page-11.webp", "alt": "山之卷费用包含与不含" },
{ "type": "image", "url": "https://one-feel-bucket.oss-cn-guangzhou.aliyuncs.com/wanqu/miniapp/static/guizhou/routes/shan/shan-page-12.webp", "alt": "山之卷参团须知" },
{ "type": "image", "url": "https://one-feel-bucket.oss-cn-guangzhou.aliyuncs.com/wanqu/miniapp/static/guizhou/routes/shan/shan-page-13.webp", "alt": "山之卷特别提示与报名确认" },
{ "type": "image", "url": "https://one-feel-bucket.oss-cn-guangzhou.aliyuncs.com/wanqu/miniapp/static/guizhou/routes/shan/shan-page-14.webp", "alt": "山之卷退改规则" }
],
"keyFacts": [
{ "label": "行程时长", "value": "2天1晚" },
{ "label": "主题目的地", "value": "施秉 · 杉木河 · 云台山" },
{ "label": "出发城市", "value": "贵阳" },
{ "label": "成团方式", "value": "2-8人贵宾小包团" }
],
"detailSections": [
{ "key": "overview", "label": "行程概述", "title": "苗岭仙山,清凉入夏", "blocks": [
{ "type": "image", "url": "https://one-feel-bucket.oss-cn-guangzhou.aliyuncs.com/wanqu/miniapp/static/guizhou/volumes/volume-shan-overview.webp", "alt": "山之卷行程介绍" },
{ "type": "text", "text": "以施秉山水为核心,串联杉木河清凉水线与云台山喀斯特峰林,适合首次乘坐多彩贵州号、希望轻松看山水的旅客。" }
] },
{ "key": "itinerary", "label": "每日行程", "title": "两天一晚线路", "blocks": [
{ "type": "text", "text": "D1 贵阳出发,前往施秉,游览杉木河及周边山水,入住当地酒店。" },
{ "type": "text", "text": "D2 早餐后游览云台山,按通知时间返程贵阳。具体停留顺序、集合时间以出团通知为准。" }
] },
{ "key": "service", "label": "包含/不含服务", "title": "费用边界清晰", "blocks": [
{ "type": "text", "text": "费用通常包含行程内交通、住宿、列明景区门票及旅行社责任险;具体以报名确认单为准。" },
{ "type": "text", "text": "不含个人消费、未列明餐食、单房差及其他自选项目,儿童标准与房型差价请咨询服务管家。" }
] },
{ "key": "notice", "label": "出行须知", "title": "山地旅行提示", "blocks": [
{ "type": "text", "text": "贵州山地天气变化快,建议准备防滑鞋、雨具和薄外套;漂流、徒步等活动会根据天气与安全条件调整。最终以出团通知和报名确认单为准。" }
] }
]
},
{
"id": 2,
"title": "第三卷·水之卷|峡谷漂流·河湖泛舟 2天1晚",
"price": "1599",
"priceUnit": "成人起/人",
"pricingTiers": [
{ "groupSize": 2, "adultPrice": 2299, "child6PlusPrice": 1749, "childUnder6Price": 1599 },
{ "groupSize": 4, "adultPrice": 1899, "child6PlusPrice": 1499, "childUnder6Price": 1199 },
{ "groupSize": 6, "adultPrice": 1759, "child6PlusPrice": 1359, "childUnder6Price": 1059 },
{ "groupSize": 8, "adultPrice": 1599, "child6PlusPrice": 1199, "childUnder6Price": 959 }
],
"tags": ["水之卷", "8月8日", "2天1晚", "2-8人贵宾小包团"],
"image": "https://one-feel-bucket.oss-cn-guangzhou.aliyuncs.com/wanqu/miniapp/static/guizhou/train/products/volume-shui-vip.webp",
"images": [
{ "url": "https://one-feel-bucket.oss-cn-guangzhou.aliyuncs.com/wanqu/miniapp/static/guizhou/train/products/volume-shui-vip.webp", "alt": "水之卷贵宾小包团价格海报8月8日峡谷线" }
],
"summary": "8月8日出发贵阳—飞云崖—旧州古镇—野洞河体验黄平古韵与河谷清凉2-8人贵宾小包团专属小车接驳。",
"destinationName": "施秉",
"durationDays": 2,
"durationNights": 1,
"departureDates": ["8月8日"],
"remainingSpots": null,
"recommendation": "适合喜欢水上体验、古镇慢游和短途清凉线路的旅客。",
"contentBlocks": [
{ "type": "title", "text": "行程单详情" },
{ "type": "image", "url": "https://one-feel-bucket.oss-cn-guangzhou.aliyuncs.com/wanqu/miniapp/static/guizhou/routes/water-gorge/water-gorge-page-03.webp", "alt": "峡谷漂流线路两天一晚概览" },
{ "type": "image", "url": "https://one-feel-bucket.oss-cn-guangzhou.aliyuncs.com/wanqu/miniapp/static/guizhou/routes/water-gorge/water-gorge-page-04.webp", "alt": "峡谷漂流线路特色体验" },
{ "type": "image", "url": "https://one-feel-bucket.oss-cn-guangzhou.aliyuncs.com/wanqu/miniapp/static/guizhou/routes/water-gorge/water-gorge-page-05.webp", "alt": "峡谷漂流线路注意事项" },
{ "type": "image", "url": "https://one-feel-bucket.oss-cn-guangzhou.aliyuncs.com/wanqu/miniapp/static/guizhou/routes/water-gorge/water-gorge-page-06.webp", "alt": "峡谷漂流线路产品概览" },
{ "type": "image", "url": "https://one-feel-bucket.oss-cn-guangzhou.aliyuncs.com/wanqu/miniapp/static/guizhou/routes/water-gorge/water-gorge-page-07.webp", "alt": "峡谷漂流线路第一天行程" },
{ "type": "image", "url": "https://one-feel-bucket.oss-cn-guangzhou.aliyuncs.com/wanqu/miniapp/static/guizhou/routes/water-gorge/water-gorge-page-08.webp", "alt": "峡谷漂流线路第一天行程续页" },
{ "type": "image", "url": "https://one-feel-bucket.oss-cn-guangzhou.aliyuncs.com/wanqu/miniapp/static/guizhou/routes/water-gorge/water-gorge-page-09.webp", "alt": "峡谷漂流线路第二天行程" },
{ "type": "image", "url": "https://one-feel-bucket.oss-cn-guangzhou.aliyuncs.com/wanqu/miniapp/static/guizhou/routes/water-gorge/water-gorge-page-10.webp", "alt": "峡谷漂流线路返程安排" },
{ "type": "image", "url": "https://one-feel-bucket.oss-cn-guangzhou.aliyuncs.com/wanqu/miniapp/static/guizhou/routes/water-gorge/water-gorge-page-11.webp", "alt": "峡谷漂流线路费用包含与不含" },
{ "type": "image", "url": "https://one-feel-bucket.oss-cn-guangzhou.aliyuncs.com/wanqu/miniapp/static/guizhou/routes/water-gorge/water-gorge-page-12.webp", "alt": "峡谷漂流线路补充说明" },
{ "type": "image", "url": "https://one-feel-bucket.oss-cn-guangzhou.aliyuncs.com/wanqu/miniapp/static/guizhou/routes/water-gorge/water-gorge-page-13.webp", "alt": "峡谷漂流线路参团须知" },
{ "type": "image", "url": "https://one-feel-bucket.oss-cn-guangzhou.aliyuncs.com/wanqu/miniapp/static/guizhou/routes/water-gorge/water-gorge-page-14.webp", "alt": "峡谷漂流线路特别提示与报名确认" },
{ "type": "image", "url": "https://one-feel-bucket.oss-cn-guangzhou.aliyuncs.com/wanqu/miniapp/static/guizhou/routes/water-gorge/water-gorge-page-15.webp", "alt": "峡谷漂流线路退改规则" }
],
"keyFacts": [
{ "label": "行程时长", "value": "2天1晚" },
{ "label": "主题目的地", "value": "飞云崖 · 旧州 · 野洞河" },
{ "label": "出发城市", "value": "贵阳" },
{ "label": "线路气质", "value": "峡谷漂流 · 河湖泛舟" },
{ "label": "成团方式", "value": "2-8人贵宾小包团" }
],
"detailSections": [
{ "key": "overview", "label": "行程概述", "title": "古韵与清凉同程", "blocks": [
{ "type": "image", "url": "https://one-feel-bucket.oss-cn-guangzhou.aliyuncs.com/wanqu/miniapp/static/guizhou/volumes/volume-shui-gorge-overview.webp", "alt": "水之卷峡谷线路介绍" },
{ "type": "text", "text": "从飞云崖的人文古迹、旧州古镇的街巷,到野洞河的峡谷水线,把黄平一带的历史与清凉串成两天一晚。" }
] },
{ "key": "itinerary", "label": "每日行程", "title": "峡谷与古镇两日", "blocks": [
{ "type": "text", "text": "D1 贵阳出发,游览飞云崖,前往旧州古镇,夜宿周边。" },
{ "type": "text", "text": "D2 前往野洞河体验河谷水线,按通知时间返程贵阳。具体活动与开放情况以现场安全安排为准。" }
] },
{ "key": "service", "label": "包含/不含服务", "title": "先确认,再出发", "blocks": [
{ "type": "text", "text": "费用包含行程内交通、住宿、列明门票/体验及基础保险;餐食、儿童标准、房型和自选项目以确认单为准。" }
] },
{ "key": "notice", "label": "出行须知", "title": "水上体验提示", "blocks": [
{ "type": "text", "text": "水上体验需结合天气、水位和景区开放状态;请穿着便于活动的衣物,听从现场工作人员安排。" }
] }
]
},
{
"id": 3,
"title": "第三卷·水之卷|水润黔中·地球绿宝石 2天1晚",
"price": "2459",
"priceUnit": "成人起/人",
"pricingTiers": [
{ "groupSize": 2, "adultPrice": 2999, "child6PlusPrice": 2099, "childUnder6Price": 1899 },
{ "groupSize": 4, "adultPrice": 2799, "child6PlusPrice": 1899, "childUnder6Price": 1699 },
{ "groupSize": 6, "adultPrice": 2599, "child6PlusPrice": 1699, "childUnder6Price": 1399 },
{ "groupSize": 8, "adultPrice": 2459, "child6PlusPrice": 1559, "childUnder6Price": 1259 }
],
"tags": ["水之卷", "8月6日", "2天1晚", "2-8人贵宾小包团"],
"image": "https://one-feel-bucket.oss-cn-guangzhou.aliyuncs.com/wanqu/miniapp/static/guizhou/train/products/volume-shui-vip.webp",
"images": [
{ "url": "https://one-feel-bucket.oss-cn-guangzhou.aliyuncs.com/wanqu/miniapp/static/guizhou/train/products/volume-shui-vip.webp", "alt": "水之卷贵宾小包团价格海报8月6日荔波线" }
],
"summary": "8月6日出发贵阳—荔波小七孔—瑶山古寨—茂兰走入水润黔中的绿宝石秘境2-8人贵宾小包团专属小车接驳。",
"destinationName": "荔波小七孔",
"durationDays": 2,
"durationNights": 1,
"departureDates": ["8月6日"],
"remainingSpots": null,
"recommendation": "适合首次贵州出行、想看清凉水景和喀斯特森林的旅客。",
"contentBlocks": [
{ "type": "title", "text": "行程单详情" },
{ "type": "image", "url": "https://one-feel-bucket.oss-cn-guangzhou.aliyuncs.com/wanqu/miniapp/static/guizhou/routes/water-libo/water-libo-page-03.webp", "alt": "荔波水之卷两天一晚线路概览" },
{ "type": "image", "url": "https://one-feel-bucket.oss-cn-guangzhou.aliyuncs.com/wanqu/miniapp/static/guizhou/routes/water-libo/water-libo-page-04.webp", "alt": "荔波水之卷特色体验" },
{ "type": "image", "url": "https://one-feel-bucket.oss-cn-guangzhou.aliyuncs.com/wanqu/miniapp/static/guizhou/routes/water-libo/water-libo-page-05.webp", "alt": "荔波水之卷注意事项" },
{ "type": "image", "url": "https://one-feel-bucket.oss-cn-guangzhou.aliyuncs.com/wanqu/miniapp/static/guizhou/routes/water-libo/water-libo-page-06.webp", "alt": "荔波水之卷产品概览" },
{ "type": "image", "url": "https://one-feel-bucket.oss-cn-guangzhou.aliyuncs.com/wanqu/miniapp/static/guizhou/routes/water-libo/water-libo-page-07.webp", "alt": "荔波水之卷第一天行程" },
{ "type": "image", "url": "https://one-feel-bucket.oss-cn-guangzhou.aliyuncs.com/wanqu/miniapp/static/guizhou/routes/water-libo/water-libo-page-08.webp", "alt": "荔波水之卷第一天行程续页" },
{ "type": "image", "url": "https://one-feel-bucket.oss-cn-guangzhou.aliyuncs.com/wanqu/miniapp/static/guizhou/routes/water-libo/water-libo-page-09.webp", "alt": "荔波水之卷第二天行程" },
{ "type": "image", "url": "https://one-feel-bucket.oss-cn-guangzhou.aliyuncs.com/wanqu/miniapp/static/guizhou/routes/water-libo/water-libo-page-10.webp", "alt": "荔波水之卷返程安排" },
{ "type": "image", "url": "https://one-feel-bucket.oss-cn-guangzhou.aliyuncs.com/wanqu/miniapp/static/guizhou/routes/water-libo/water-libo-page-11.webp", "alt": "荔波水之卷费用包含与不含" },
{ "type": "image", "url": "https://one-feel-bucket.oss-cn-guangzhou.aliyuncs.com/wanqu/miniapp/static/guizhou/routes/water-libo/water-libo-page-12.webp", "alt": "荔波水之卷费用说明续页" },
{ "type": "image", "url": "https://one-feel-bucket.oss-cn-guangzhou.aliyuncs.com/wanqu/miniapp/static/guizhou/routes/water-libo/water-libo-page-13.webp", "alt": "荔波水之卷参团须知" },
{ "type": "image", "url": "https://one-feel-bucket.oss-cn-guangzhou.aliyuncs.com/wanqu/miniapp/static/guizhou/routes/water-libo/water-libo-page-14.webp", "alt": "荔波水之卷特别提示与报名确认" },
{ "type": "image", "url": "https://one-feel-bucket.oss-cn-guangzhou.aliyuncs.com/wanqu/miniapp/static/guizhou/routes/water-libo/water-libo-page-15.webp", "alt": "荔波水之卷退改规则" }
],
"keyFacts": [
{ "label": "行程时长", "value": "2天1晚" },
{ "label": "主题目的地", "value": "小七孔 · 瑶山古寨 · 茂兰" },
{ "label": "出发城市", "value": "贵阳" },
{ "label": "线路气质", "value": "绿宝石水线" },
{ "label": "成团方式", "value": "2-8人贵宾小包团" }
],
"detailSections": [
{ "key": "overview", "label": "行程概述", "title": "把水色读成一卷", "blocks": [
{ "type": "image", "url": "https://one-feel-bucket.oss-cn-guangzhou.aliyuncs.com/wanqu/miniapp/static/guizhou/volumes/volume-shui-libo-overview.webp", "alt": "荔波水之卷行程介绍" },
{ "type": "text", "text": "以小七孔的碧水、瑶山古寨的人文和茂兰喀斯特森林为主线,浓缩成一段适合短假出发的黔南清凉旅程。" }
] },
{ "key": "itinerary", "label": "每日行程", "title": "小七孔与茂兰两日", "blocks": [
{ "type": "text", "text": "D1 贵阳出发,游览荔波小七孔,体验水上森林与瀑布群,入住荔波。" },
{ "type": "text", "text": "D2 游览瑶山古寨或茂兰景区,按通知时间返程贵阳。景区游览顺序会根据客流与天气调整。" }
] },
{ "key": "service", "label": "包含/不含服务", "title": "行程说明", "blocks": [
{ "type": "text", "text": "费用包含行程内交通、住宿、列明门票及基础保险;不含个人消费、未列明餐食、自选体验和单房差。" }
] },
{ "key": "notice", "label": "出行须知", "title": "景区提示", "blocks": [
{ "type": "text", "text": "小七孔步行路段较多,请穿防滑鞋;旺季客流、天气和景区开放状态可能影响游览顺序。" }
] }
]
},
{
"id": 4,
"title": "第四卷·人之卷|黄果树织金洞·瀑洞双绝 2天1晚",
"price": "2259",
"priceUnit": "成人起/人",
"pricingTiers": [
{ "groupSize": 2, "adultPrice": 2899, "child6PlusPrice": 2099, "childUnder6Price": 1799 },
{ "groupSize": 4, "adultPrice": 2599, "child6PlusPrice": 1699, "childUnder6Price": 1459 },
{ "groupSize": 6, "adultPrice": 2399, "child6PlusPrice": 1559, "childUnder6Price": 1299 },
{ "groupSize": 8, "adultPrice": 2259, "child6PlusPrice": 1399, "childUnder6Price": 1159 }
],
"tags": ["人之卷", "8月12日", "2天1晚", "2-8人贵宾小包团"],
"image": "https://one-feel-bucket.oss-cn-guangzhou.aliyuncs.com/wanqu/miniapp/static/guizhou/train/products/volume-ren-vip.webp",
"images": [
{ "url": "https://one-feel-bucket.oss-cn-guangzhou.aliyuncs.com/wanqu/miniapp/static/guizhou/train/products/volume-ren-vip.webp", "alt": "人之卷贵宾小包团价格海报" }
],
"summary": "8月12日出发贵阳—云峰屯堡—黄果树—织金洞—织金大峡谷瀑布与溶洞一次读懂2-8人贵宾小包团专属小车接驳。",
"destinationName": "黄果树",
"durationDays": 2,
"durationNights": 1,
"departureDates": ["8月12日"],
"remainingSpots": null,
"recommendation": "适合第一次来贵州、希望在短时间内完成经典自然与人文打卡的人群。",
"contentBlocks": [
{ "type": "title", "text": "行程单详情" },
{ "type": "image", "url": "https://one-feel-bucket.oss-cn-guangzhou.aliyuncs.com/wanqu/miniapp/static/guizhou/routes/ren/ren-page-03.webp", "alt": "人之卷两天一晚线路概览" },
{ "type": "image", "url": "https://one-feel-bucket.oss-cn-guangzhou.aliyuncs.com/wanqu/miniapp/static/guizhou/routes/ren/ren-page-04.webp", "alt": "人之卷特色体验" },
{ "type": "image", "url": "https://one-feel-bucket.oss-cn-guangzhou.aliyuncs.com/wanqu/miniapp/static/guizhou/routes/ren/ren-page-05.webp", "alt": "人之卷注意事项与住宿" },
{ "type": "image", "url": "https://one-feel-bucket.oss-cn-guangzhou.aliyuncs.com/wanqu/miniapp/static/guizhou/routes/ren/ren-page-06.webp", "alt": "人之卷产品概览" },
{ "type": "image", "url": "https://one-feel-bucket.oss-cn-guangzhou.aliyuncs.com/wanqu/miniapp/static/guizhou/routes/ren/ren-page-07.webp", "alt": "人之卷第一天行程" },
{ "type": "image", "url": "https://one-feel-bucket.oss-cn-guangzhou.aliyuncs.com/wanqu/miniapp/static/guizhou/routes/ren/ren-page-08.webp", "alt": "人之卷第一天行程续页" },
{ "type": "image", "url": "https://one-feel-bucket.oss-cn-guangzhou.aliyuncs.com/wanqu/miniapp/static/guizhou/routes/ren/ren-page-09.webp", "alt": "人之卷第二天行程" },
{ "type": "image", "url": "https://one-feel-bucket.oss-cn-guangzhou.aliyuncs.com/wanqu/miniapp/static/guizhou/routes/ren/ren-page-10.webp", "alt": "人之卷返程安排" },
{ "type": "image", "url": "https://one-feel-bucket.oss-cn-guangzhou.aliyuncs.com/wanqu/miniapp/static/guizhou/routes/ren/ren-page-11.webp", "alt": "人之卷费用包含与不含" },
{ "type": "image", "url": "https://one-feel-bucket.oss-cn-guangzhou.aliyuncs.com/wanqu/miniapp/static/guizhou/routes/ren/ren-page-12.webp", "alt": "人之卷参团须知" },
{ "type": "image", "url": "https://one-feel-bucket.oss-cn-guangzhou.aliyuncs.com/wanqu/miniapp/static/guizhou/routes/ren/ren-page-13.webp", "alt": "人之卷特别提示与报名确认" },
{ "type": "image", "url": "https://one-feel-bucket.oss-cn-guangzhou.aliyuncs.com/wanqu/miniapp/static/guizhou/routes/ren/ren-page-14.webp", "alt": "人之卷退改规则" }
],
"keyFacts": [
{ "label": "行程时长", "value": "2天1晚" },
{ "label": "主题目的地", "value": "屯堡 · 黄果树 · 织金洞" },
{ "label": "出发城市", "value": "贵阳" },
{ "label": "线路气质", "value": "瀑洞双绝" },
{ "label": "成团方式", "value": "2-8人贵宾小包团" }
],
"detailSections": [
{ "key": "overview", "label": "行程概述", "title": "看水,也看人如何生活", "blocks": [
{ "type": "image", "url": "https://one-feel-bucket.oss-cn-guangzhou.aliyuncs.com/wanqu/miniapp/static/guizhou/volumes/volume-ren-overview.webp", "alt": "人之卷行程介绍" },
{ "type": "text", "text": "从屯堡古村落的石头巷道,到黄果树瀑布的水声,再进入织金洞与织金大峡谷的地心景观,适合用两天完成贵州经典的一次浓缩阅读。" }
] },
{ "key": "itinerary", "label": "每日行程", "title": "瀑布、屯堡与洞天", "blocks": [
{ "type": "text", "text": "D1 贵阳出发,游览云峰屯堡,前往黄果树景区,入住安顺或景区周边。" },
{ "type": "text", "text": "D2 游览织金洞、织金大峡谷,按通知时间返程贵阳。具体景点顺序以出团通知为准。" }
] },
{ "key": "service", "label": "包含/不含服务", "title": "费用说明", "blocks": [
{ "type": "text", "text": "费用通常包含行程内交通、住宿、列明景区门票和保险;不含大交通、个人消费、未列明餐食、单房差和自选项目。" }
] },
{ "key": "notice", "label": "出行须知", "title": "景区体力提示", "blocks": [
{ "type": "text", "text": "瀑布与溶洞景区均有步行路段,建议穿舒适防滑鞋;儿童、老人和特殊人群请提前与服务管家确认。" }
] }
]
},
{
"id": 5,
"title": "第二卷·云之卷|乌蒙高原·云端草山 3天2晚",
"price": "2699",
"priceUnit": "成人起/人",
"pricingTiers": [
{ "groupSize": 2, "adultPrice": 3599, "child6PlusPrice": 2659, "childUnder6Price": 2259 },
{ "groupSize": 4, "adultPrice": 3259, "child6PlusPrice": 2259, "childUnder6Price": 1859 },
{ "groupSize": 6, "adultPrice": 2899, "child6PlusPrice": 1959, "childUnder6Price": 1559 },
{ "groupSize": 8, "adultPrice": 2699, "child6PlusPrice": 1699, "childUnder6Price": 1299 }
],
"tags": ["云之卷", "8月3日", "3天2晚", "2-8人贵宾小包团"],
"image": "https://one-feel-bucket.oss-cn-guangzhou.aliyuncs.com/wanqu/miniapp/static/guizhou/train/products/volume-yun-vip.webp",
"images": [
{ "url": "https://one-feel-bucket.oss-cn-guangzhou.aliyuncs.com/wanqu/miniapp/static/guizhou/train/products/volume-yun-vip.webp", "alt": "云之卷贵宾小包团价格海报" }
],
"summary": "8月3日出发贵阳—野玉海—乌蒙大草原—威宁草海在中国凉都看云端草山2-8人贵宾小包团专属小车接驳。",
"destinationName": "六盘水",
"durationDays": 3,
"durationNights": 2,
"departureDates": ["8月3日"],
"remainingSpots": null,
"recommendation": "适合夏季避暑、喜欢高原草原、湿地和松弛节奏的旅客。",
"contentBlocks": [
{ "type": "title", "text": "行程单详情" },
{ "type": "image", "url": "https://one-feel-bucket.oss-cn-guangzhou.aliyuncs.com/wanqu/miniapp/static/guizhou/routes/yun/yun-page-03.webp", "alt": "云之卷三天两晚线路概览" },
{ "type": "image", "url": "https://one-feel-bucket.oss-cn-guangzhou.aliyuncs.com/wanqu/miniapp/static/guizhou/routes/yun/yun-page-04.webp", "alt": "云之卷特色体验" },
{ "type": "image", "url": "https://one-feel-bucket.oss-cn-guangzhou.aliyuncs.com/wanqu/miniapp/static/guizhou/routes/yun/yun-page-05.webp", "alt": "云之卷餐饮住宿与注意事项" },
{ "type": "image", "url": "https://one-feel-bucket.oss-cn-guangzhou.aliyuncs.com/wanqu/miniapp/static/guizhou/routes/yun/yun-page-06.webp", "alt": "云之卷产品概览" },
{ "type": "image", "url": "https://one-feel-bucket.oss-cn-guangzhou.aliyuncs.com/wanqu/miniapp/static/guizhou/routes/yun/yun-page-07.webp", "alt": "云之卷第一天行程" },
{ "type": "image", "url": "https://one-feel-bucket.oss-cn-guangzhou.aliyuncs.com/wanqu/miniapp/static/guizhou/routes/yun/yun-page-08.webp", "alt": "云之卷第一天行程续页" },
{ "type": "image", "url": "https://one-feel-bucket.oss-cn-guangzhou.aliyuncs.com/wanqu/miniapp/static/guizhou/routes/yun/yun-page-09.webp", "alt": "云之卷第二天行程" },
{ "type": "image", "url": "https://one-feel-bucket.oss-cn-guangzhou.aliyuncs.com/wanqu/miniapp/static/guizhou/routes/yun/yun-page-10.webp", "alt": "云之卷第二天行程续页" },
{ "type": "image", "url": "https://one-feel-bucket.oss-cn-guangzhou.aliyuncs.com/wanqu/miniapp/static/guizhou/routes/yun/yun-page-11.webp", "alt": "云之卷费用包含与不含" },
{ "type": "image", "url": "https://one-feel-bucket.oss-cn-guangzhou.aliyuncs.com/wanqu/miniapp/static/guizhou/routes/yun/yun-page-12.webp", "alt": "云之卷参团须知" },
{ "type": "image", "url": "https://one-feel-bucket.oss-cn-guangzhou.aliyuncs.com/wanqu/miniapp/static/guizhou/routes/yun/yun-page-13.webp", "alt": "云之卷参团须知续页" },
{ "type": "image", "url": "https://one-feel-bucket.oss-cn-guangzhou.aliyuncs.com/wanqu/miniapp/static/guizhou/routes/yun/yun-page-14.webp", "alt": "云之卷特别提示与报名确认" },
{ "type": "image", "url": "https://one-feel-bucket.oss-cn-guangzhou.aliyuncs.com/wanqu/miniapp/static/guizhou/routes/yun/yun-page-15.webp", "alt": "云之卷退改规则" }
],
"keyFacts": [
{ "label": "行程时长", "value": "3天2晚" },
{ "label": "主题目的地", "value": "六盘水 · 野玉海 · 乌蒙草原 · 草海" },
{ "label": "出发城市", "value": "贵阳" },
{ "label": "线路气质", "value": "中国凉都避暑" },
{ "label": "成团方式", "value": "2-8人贵宾小包团" }
],
"detailSections": [
{ "key": "overview", "label": "行程概述", "title": "把夏天交给云和草", "blocks": [
{ "type": "image", "url": "https://one-feel-bucket.oss-cn-guangzhou.aliyuncs.com/wanqu/miniapp/static/guizhou/volumes/volume-yun-overview.webp", "alt": "云之卷行程介绍" },
{ "type": "text", "text": "沿六盘水、野玉海、乌蒙大草原与威宁草海展开,适合在高原风、草山和湿地之间慢下来。" }
] },
{ "key": "itinerary", "label": "每日行程", "title": "三天两晚高原线", "blocks": [
{ "type": "text", "text": "D1 贵阳出发抵达六盘水,游览城市或野玉海片区,入住当地。" },
{ "type": "text", "text": "D2 前往乌蒙大草原,体验高原草山与湿地景观,入住周边。" },
{ "type": "text", "text": "D3 游览威宁草海或按当日开放情况调整,返程贵阳。" }
] },
{ "key": "service", "label": "包含/不含服务", "title": "高原行程说明", "blocks": [
{ "type": "text", "text": "费用包含行程内交通、住宿、列明景区门票及保险;具体餐食、房型差价、个人消费和自选项目以报名确认单为准。" }
] },
{ "key": "notice", "label": "出行须知", "title": "高原天气提示", "blocks": [
{ "type": "text", "text": "高原地区昼夜温差较大,建议携带防晒用品、薄外套和雨具;如有高原适应或健康顾虑,请提前告知服务管家。" }
] }
]
},
{
"id": 6,
"title": "第六卷·灵之卷|武陵秘境·梵净山水人文 3天2晚",
"price": "2659",
"priceUnit": "成人起/人",
"pricingTiers": [
{ "groupSize": 2, "adultPrice": 3988.75, "child6PlusPrice": 3059, "childUnder6Price": 2659 },
{ "groupSize": 4, "adultPrice": 3099, "child6PlusPrice": 2159, "childUnder6Price": 1759 },
{ "groupSize": 6, "adultPrice": 2799, "child6PlusPrice": 1799, "childUnder6Price": 1399 },
{ "groupSize": 8, "adultPrice": 2659, "child6PlusPrice": 1659, "childUnder6Price": 1299 }
],
"tags": ["灵之卷", "8月19日", "3天2晚", "2-8人贵宾小包团"],
"image": "https://one-feel-bucket.oss-cn-guangzhou.aliyuncs.com/wanqu/miniapp/static/guizhou/train/products/volume-ling-vip.webp",
"images": [
{ "url": "https://one-feel-bucket.oss-cn-guangzhou.aliyuncs.com/wanqu/miniapp/static/guizhou/train/products/volume-ling-vip.webp", "alt": "灵之卷贵宾小包团价格海报" }
],
"summary": "8月19日出发贵阳—铜仁大峡谷—中南门古城—梵净山—亚木沟走入武陵秘境2-8人贵宾小包团专属小车接驳。",
"destinationName": "梵净山",
"durationDays": 3,
"durationNights": 2,
"departureDates": ["8月19日"],
"remainingSpots": null,
"recommendation": "适合想看梵净山云海、古城夜色与峡谷山水,并愿意留出三天慢游的人群。",
"contentBlocks": [
{ "type": "title", "text": "行程单详情" },
{ "type": "image", "url": "https://one-feel-bucket.oss-cn-guangzhou.aliyuncs.com/wanqu/miniapp/static/guizhou/routes/ling/ling-page-03.webp", "alt": "灵之卷三天两晚线路概览" },
{ "type": "image", "url": "https://one-feel-bucket.oss-cn-guangzhou.aliyuncs.com/wanqu/miniapp/static/guizhou/routes/ling/ling-page-04.webp", "alt": "灵之卷特色体验" },
{ "type": "image", "url": "https://one-feel-bucket.oss-cn-guangzhou.aliyuncs.com/wanqu/miniapp/static/guizhou/routes/ling/ling-page-05.webp", "alt": "灵之卷注意事项与住宿" },
{ "type": "image", "url": "https://one-feel-bucket.oss-cn-guangzhou.aliyuncs.com/wanqu/miniapp/static/guizhou/routes/ling/ling-page-06.webp", "alt": "灵之卷产品概览" },
{ "type": "image", "url": "https://one-feel-bucket.oss-cn-guangzhou.aliyuncs.com/wanqu/miniapp/static/guizhou/routes/ling/ling-page-07.webp", "alt": "灵之卷第一天行程" },
{ "type": "image", "url": "https://one-feel-bucket.oss-cn-guangzhou.aliyuncs.com/wanqu/miniapp/static/guizhou/routes/ling/ling-page-08.webp", "alt": "灵之卷第一天行程续页" },
{ "type": "image", "url": "https://one-feel-bucket.oss-cn-guangzhou.aliyuncs.com/wanqu/miniapp/static/guizhou/routes/ling/ling-page-09.webp", "alt": "灵之卷第二天行程" },
{ "type": "image", "url": "https://one-feel-bucket.oss-cn-guangzhou.aliyuncs.com/wanqu/miniapp/static/guizhou/routes/ling/ling-page-10.webp", "alt": "灵之卷第三天行程与费用说明" },
{ "type": "image", "url": "https://one-feel-bucket.oss-cn-guangzhou.aliyuncs.com/wanqu/miniapp/static/guizhou/routes/ling/ling-page-11.webp", "alt": "灵之卷费用不含与参团须知" },
{ "type": "image", "url": "https://one-feel-bucket.oss-cn-guangzhou.aliyuncs.com/wanqu/miniapp/static/guizhou/routes/ling/ling-page-12.webp", "alt": "灵之卷特别提示与报名确认" },
{ "type": "image", "url": "https://one-feel-bucket.oss-cn-guangzhou.aliyuncs.com/wanqu/miniapp/static/guizhou/routes/ling/ling-page-13.webp", "alt": "灵之卷退改规则" }
],
"keyFacts": [
{ "label": "行程时长", "value": "3天2晚" },
{ "label": "主题目的地", "value": "铜仁大峡谷 · 梵净山 · 亚木沟" },
{ "label": "出发城市", "value": "贵阳" },
{ "label": "线路气质", "value": "山水人文秘境" },
{ "label": "成团方式", "value": "2-8人贵宾小包团" }
],
"detailSections": [
{ "key": "overview", "label": "行程概述", "title": "梵净山下,山水有灵", "blocks": [
{ "type": "image", "url": "https://one-feel-bucket.oss-cn-guangzhou.aliyuncs.com/wanqu/miniapp/static/guizhou/volumes/volume-ling-overview.webp", "alt": "灵之卷行程介绍" },
{ "type": "text", "text": "把铜仁大峡谷、中南门古城、梵净山与亚木沟连成一条武陵山水线,给登山与人文体验都留出余地。" }
] },
{ "key": "itinerary", "label": "每日行程", "title": "三天两晚武陵线", "blocks": [
{ "type": "text", "text": "D1 贵阳出发,经玉屏抵达铜仁,游览铜仁大峡谷或中南门古城。" },
{ "type": "text", "text": "D2 前往梵净山,按预约及天气安排登山游览,入住周边。" },
{ "type": "text", "text": "D3 游览亚木沟或周边山水,按通知时间返程贵阳。" }
] },
{ "key": "service", "label": "包含/不含服务", "title": "登山线路说明", "blocks": [
{ "type": "text", "text": "费用包含行程内交通、住宿、列明景区门票及保险;梵净山预约、索道、餐食、房型及其他差价以最终方案为准。" }
] },
{ "key": "notice", "label": "出行须知", "title": "登山提示", "blocks": [
{ "type": "text", "text": "梵净山游览受预约、天气和体力影响较大,出行前请确认健康状况,具体登山安排以服务管家和景区通知为准。" }
] }
]
},
{
"id": 7,
"title": "第五卷·星之卷|仰望星河·中国天眼探索 2天1晚",
"price": "1899",
"priceUnit": "成人起/人",
"pricingTiers": [
{ "groupSize": 2, "adultPrice": 2599, "child6PlusPrice": 1899, "childUnder6Price": 1599 },
{ "groupSize": 4, "adultPrice": 2199, "child6PlusPrice": 1499, "childUnder6Price": 1259 },
{ "groupSize": 6, "adultPrice": 1999, "child6PlusPrice": 1359, "childUnder6Price": 1099 },
{ "groupSize": 8, "adultPrice": 1899, "child6PlusPrice": 1199, "childUnder6Price": 959 }
],
"tags": ["星之卷", "8月19日", "2天1晚", "2-8人贵宾小包团"],
"image": "https://one-feel-bucket.oss-cn-guangzhou.aliyuncs.com/wanqu/miniapp/static/guizhou/train/products/volume-xing-vip.webp",
"images": [
{ "url": "https://one-feel-bucket.oss-cn-guangzhou.aliyuncs.com/wanqu/miniapp/static/guizhou/train/products/volume-xing-vip.webp", "alt": "星之卷贵宾小包团价格海报" }
],
"summary": "8月19日出发贵阳—中国天眼—天文体验馆—掌布在平塘仰望星河2-8人贵宾小包团专属小车接驳。",
"destinationName": "平塘天眼",
"durationDays": 2,
"durationNights": 1,
"departureDates": ["8月19日"],
"remainingSpots": null,
"recommendation": "适合亲子、摄影和对天文地质感兴趣的旅客,把夜空与地貌一起看。",
"contentBlocks": [
{ "type": "title", "text": "行程单详情" },
{ "type": "image", "url": "https://one-feel-bucket.oss-cn-guangzhou.aliyuncs.com/wanqu/miniapp/static/guizhou/routes/xing/xing-page-03.webp", "alt": "星之卷两天一晚线路概览" },
{ "type": "image", "url": "https://one-feel-bucket.oss-cn-guangzhou.aliyuncs.com/wanqu/miniapp/static/guizhou/routes/xing/xing-page-04.webp", "alt": "星之卷特色体验" },
{ "type": "image", "url": "https://one-feel-bucket.oss-cn-guangzhou.aliyuncs.com/wanqu/miniapp/static/guizhou/routes/xing/xing-page-05.webp", "alt": "星之卷餐饮住宿与注意事项" },
{ "type": "image", "url": "https://one-feel-bucket.oss-cn-guangzhou.aliyuncs.com/wanqu/miniapp/static/guizhou/routes/xing/xing-page-06.webp", "alt": "星之卷产品概览" },
{ "type": "image", "url": "https://one-feel-bucket.oss-cn-guangzhou.aliyuncs.com/wanqu/miniapp/static/guizhou/routes/xing/xing-page-07.webp", "alt": "星之卷第一天行程" },
{ "type": "image", "url": "https://one-feel-bucket.oss-cn-guangzhou.aliyuncs.com/wanqu/miniapp/static/guizhou/routes/xing/xing-page-08.webp", "alt": "星之卷第一天行程续页" },
{ "type": "image", "url": "https://one-feel-bucket.oss-cn-guangzhou.aliyuncs.com/wanqu/miniapp/static/guizhou/routes/xing/xing-page-09.webp", "alt": "星之卷第二天行程" },
{ "type": "image", "url": "https://one-feel-bucket.oss-cn-guangzhou.aliyuncs.com/wanqu/miniapp/static/guizhou/routes/xing/xing-page-10.webp", "alt": "星之卷费用包含与不含" },
{ "type": "image", "url": "https://one-feel-bucket.oss-cn-guangzhou.aliyuncs.com/wanqu/miniapp/static/guizhou/routes/xing/xing-page-11.webp", "alt": "星之卷参团须知" },
{ "type": "image", "url": "https://one-feel-bucket.oss-cn-guangzhou.aliyuncs.com/wanqu/miniapp/static/guizhou/routes/xing/xing-page-12.webp", "alt": "星之卷特别提示与报名确认" },
{ "type": "image", "url": "https://one-feel-bucket.oss-cn-guangzhou.aliyuncs.com/wanqu/miniapp/static/guizhou/routes/xing/xing-page-13.webp", "alt": "星之卷退改规则" }
],
"keyFacts": [
{ "label": "行程时长", "value": "2天1晚" },
{ "label": "主题目的地", "value": "中国天眼 · 天文体验馆 · 掌布" },
{ "label": "出发城市", "value": "贵阳" },
{ "label": "线路气质", "value": "仰望星河" },
{ "label": "成团方式", "value": "2-8人贵宾小包团" }
],
"detailSections": [
{ "key": "overview", "label": "行程概述", "title": "从地上仰望星河", "blocks": [
{ "type": "image", "url": "https://one-feel-bucket.oss-cn-guangzhou.aliyuncs.com/wanqu/miniapp/static/guizhou/volumes/volume-xing-overview.webp", "alt": "星之卷行程介绍" },
{ "type": "text", "text": "以中国天眼和天文体验馆为核心,加入掌布地质奇观与独山在地停靠,适合一段有知识、有夜空也有风景的短途旅行。" }
] },
{ "key": "itinerary", "label": "每日行程", "title": "两天一晚探索线", "blocks": [
{ "type": "text", "text": "D1 贵阳出发,经独山前往平塘,参观中国天眼及天文体验馆,入住周边。" },
{ "type": "text", "text": "D2 游览掌布或周边地质景观,按通知时间返程贵阳。天文项目以预约和景区开放为准。" }
] },
{ "key": "service", "label": "包含/不含服务", "title": "预约说明", "blocks": [
{ "type": "text", "text": "费用包含行程内交通、住宿、列明门票及保险;中国天眼预约、讲解、餐食、房型和自选项目以最终确认单为准。" }
] },
{ "key": "notice", "label": "出行须知", "title": "观测项目提示", "blocks": [
{ "type": "text", "text": "中国天眼相关参观项目存在预约和设备管理要求,请遵守景区规定;具体开放时间、参观顺序和天气影响以出团通知为准。" }
] }
]
}
]

10
src/main.tsx Normal file
View File

@@ -0,0 +1,10 @@
import React from "react";
import { createRoot } from "react-dom/client";
import App from "./App";
import "./styles.css";
createRoot(document.getElementById("root")!).render(
<React.StrictMode>
<App />
</React.StrictMode>,
);

15
src/media.ts Normal file
View File

@@ -0,0 +1,15 @@
const DEFAULT_MEDIA_PUBLIC_BASE_URL = "https://one-feel-bucket.oss-cn-guangzhou.aliyuncs.com";
const runtimeImportMeta = import.meta as ImportMeta & { env?: Record<string, string | undefined> };
const configuredMediaPublicBaseUrl = String(runtimeImportMeta.env?.VITE_MEDIA_PUBLIC_BASE_URL ?? "").replace(/\/$/, "");
export const MEDIA_PUBLIC_BASE_URL = configuredMediaPublicBaseUrl || DEFAULT_MEDIA_PUBLIC_BASE_URL;
export const STATIC_MEDIA_BASE_URL = `${MEDIA_PUBLIC_BASE_URL}/wanqu/miniapp/static`;
export function staticMedia(relativePath: string) {
const normalized = relativePath
.replace(/\\/g, "/")
.replace(/^\/+/, "")
.replace(/\.(?:jpe?g|png|gif|svg|avif|webp)$/i, ".webp");
return `${STATIC_MEDIA_BASE_URL}/${normalized}`;
}
export const WANDERQ_LOGO_URL = staticMedia("brand/wanderq-logo.webp");

View File

@@ -0,0 +1,77 @@
import type { PublicSearchPageConfig, PublicSearchPageGroup, PublicSearchPageKeyword } from "./api";
import { staticMedia } from "./media";
const image = (name: string) => staticMedia(`guizhou/${name}.webp`);
function keyword(id: string, label: string, imageName: string | null, sortOrder: number): PublicSearchPageKeyword {
return { id, label, image: imageName ? image(imageName) : null, isActive: true, sortOrder };
}
function group(id: string, label: string, items: PublicSearchPageKeyword[], sortOrder: number): PublicSearchPageGroup {
return { id, label, items, isActive: true, sortOrder };
}
export const fallbackSearchPageConfig: PublicSearchPageConfig = {
placeholder: "搜索目的地、玩法或线路",
modules: {
seasonalInspiration: {
title: "从贵州出发,去看不一样的山水",
subtitle: "热门目的地、村寨与山野体验,先从一处心动开始。",
},
preferenceDiscovery: {
title: "换一种方式找灵感",
subtitle: "按区域、主题和体验偏好,找到下一处想去的地方。",
},
},
popularKeywords: [
keyword("popular-huangguoshu", "黄果树", "huangguoshu-waterfall", 0),
keyword("popular-libo", "荔波小七孔", "libo-xiaoqikong", 1),
keyword("popular-xijiang", "西江苗寨", "xijiang-miao-village", 2),
keyword("popular-fanjing", "梵净山", "fanjing-mountain", 3),
keyword("popular-wanfenglin", "万峰林", "wanfenglin", 4),
],
groups: [
group("region", "贵州区域", [
keyword("region-guiyang-anshun", "贵阳安顺", "huangguoshu-waterfall", 0),
keyword("region-qiandongnan", "黔东南", "xijiang-miao-village", 1),
keyword("region-qiannan-libo", "黔南荔波", "libo-xiaoqikong", 2),
keyword("region-tongren-fanjing", "铜仁梵净山", "fanjing-mountain", 3),
keyword("region-qianxinan-wanfenglin", "黔西南万峰林", "wanfenglin", 4),
keyword("region-zunyi-chishui", "遵义赤水", "chishui-danxia", 5),
keyword("region-bijie-liupanshui", "毕节六盘水", "zhijin-cave", 6),
], 0),
group("classic", "经典打卡", [
keyword("classic-huangguoshu", "黄果树", "huangguoshu-waterfall", 0),
keyword("classic-libo", "荔波小七孔", "libo-xiaoqikong", 1),
keyword("classic-xijiang", "西江苗寨", "xijiang-miao-village", 2),
keyword("classic-fanjing", "梵净山", "fanjing-mountain", 3),
keyword("classic-zhenyuan", "镇远古城", "zhenyuan-ancient-town", 4),
keyword("classic-wanfenglin", "万峰林", "wanfenglin", 5),
keyword("classic-zhaoxing", "肇兴侗寨", "dong-village", 6),
], 1),
group("outdoor", "山野户外", [
keyword("outdoor-shierbeihou", "十二背后", "zhijin-cave", 0),
keyword("outdoor-zhijin", "织金洞", "zhijin-cave", 1),
keyword("outdoor-wanfenglin", "万峰林", "wanfenglin", 2),
keyword("outdoor-libo", "荔波小七孔", "libo-xiaoqikong", 3),
keyword("outdoor-chishui", "赤水丹霞", "chishui-danxia", 4),
keyword("outdoor-wumeng", "乌蒙草原", "wumeng-grassland", 5),
], 2),
group("culture", "人文体验", [
keyword("culture-loushanguan", "娄山关", "chishui-danxia", 0),
keyword("culture-xijiang", "西江苗寨", "xijiang-miao-village", 1),
keyword("culture-zhaoxing", "肇兴侗寨", "dong-village", 2),
keyword("culture-zhenyuan", "镇远古城", "zhenyuan-ancient-town", 3),
keyword("culture-jiabang", "加榜梯田", "jiabang-terrace", 4),
keyword("culture-qiandongnan", "黔东南", "xijiang-miao-village", 5),
], 3),
group("stay-transport", "酒店用车", [
keyword("stay-classic", "经典酒店", "bailian-hot-spring", 0),
keyword("stay-wild-luxury", "野奢酒店", "mountain-resort", 1),
keyword("transport", "万趣用车", "gorge-paddle", 2),
keyword("stay-huangguoshu", "黄果树", "huangguoshu-waterfall", 3),
keyword("stay-xijiang", "西江苗寨", "xijiang-miao-village", 4),
keyword("stay-wanfenglin", "万峰林", "wanfenglin", 5),
], 4),
],
};

6631
src/styles.css Normal file

File diff suppressed because it is too large Load Diff

84
src/train-activity.ts Normal file
View File

@@ -0,0 +1,84 @@
const trainIntroPageTitles = [
"贵州旅游列车汇报方案封面",
"项目背景",
"贵州旅游资源分析",
"苗岭号车身设计方案一",
"苗岭号车身设计理念",
"苗岭号车身设计方案二",
"苗岭号车身设计方案三",
"苗岭号车身设计方案四",
"列车编组方案",
"软卧平面图",
"软卧效果图一",
"软卧效果图二",
"软卧效果图三",
"软卧卫生间效果图一",
"软卧卫生间效果图二",
"多功能车娱乐车平面图",
"多功能车娱乐车效果图一",
"多功能车娱乐车效果图二",
"餐车平面图",
"餐车效果图",
"多功能观光车平面图",
"多功能观光车效果图一",
"多功能观光车效果图二",
"宿营车平面图",
"宿营车效果图",
] as const;
export const trainIntroPdfPages = trainIntroPageTitles.map((title, index) => ({
src: staticMedia(`guizhou/train-intro/page-${String(index + 1).padStart(2, "0")}.webp`),
title,
alt: `多彩贵州号介绍:${title}`,
}));
export const trainIntroSections = [
{
id: "train-intro-design",
label: "01 / 车身设计",
title: "把贵州的民族纹样绣进列车",
description: "紫色车身、民族纹样与贵州山水线路,组成多彩贵州号的第一眼。",
start: 4,
end: 8,
},
{
id: "train-intro-formation",
label: "02 / 列车编组",
title: "17 辆编组468 人总可住旅客人数",
description: "发电车、宿营车、软卧、多功能娱乐车、餐车与多功能观光车协同组成。",
start: 9,
end: 9,
},
{
id: "train-intro-carriages",
label: "03 / 车厢方案",
title: "住、娱、餐、观光,每一节都是贵州体验",
description: "从软卧包间到娱乐、餐饮、观景与宿营方案,完整查看苗岭号的车厢设计。",
start: 10,
end: 25,
},
] as const;
export const trainActivityContent = {
hero: {
image: staticMedia("guizhou/train/hero-front.webp"),
eyebrow: "首期发车 · 多彩贵州号",
title: "坐着多彩贵州号",
accent: "六卷读懂贵州",
description: "一列主题列车,六种贵州读法。把山水、人文、云端、灵境与星空,连成一场可以出发的阅读。",
},
priceOverview: {
image: staticMedia("guizhou/train/price-overview.webp"),
alt: "多彩贵州号六卷团期与价格总览",
},
trainIntro: {
eyebrow: "多彩贵州号 · 列车介绍",
title: "认识苗岭号",
},
productIntro: {
eyebrow: "六卷 · 七条产品线",
title: "六卷导览",
description: "每一卷把贵州拆成一条可出发的路线,点击产品查看完整行程与报名信息。",
},
} as const;
import { staticMedia } from "./media";

1
src/vite-env.d.ts vendored Normal file
View File

@@ -0,0 +1 @@
/// <reference types="vite/client" />