Travel Planner — 旅行行程页面生成器
将旅行计划转化为一个精美的、可分享的单文件 HTML 页面:图文并茂、交互丰富、移动端友好。
触发条件
- 用户要求做旅行规划/行程页面
- 用户说
/travel-planner或 "做一个旅行页面" - 用户提供了旅行日期、目的地、住宿信息
核心原则
- Zero Dependencies — 单 HTML 文件,内联 CSS/JS,无需构建工具
- Distance-Verified — 所有步行/驾车时间必须通过路线 API 验证,不要凭感觉估算
- Real Images — 使用 Wikipedia API 获取真实景点照片,不用占位图
- Local Names First — 景点名用当地语言(方便导航认路),括号内加中文:
La Pedrera (米拉之家) - Mobile-First — 手机端是主要阅读场景,所有交互都要在触屏上流畅
Phase 1: 收集信息
用 AskUserQuestion 一次性问清关键信息:
Question 1 — 行程概览 (header: "行程"): 请提供你的旅行日期和目的地城市
Question 2 — 住宿信息 (header: "住宿"): 有住宿地址吗?(精确地址能优化每日动线)Options: 有地址 / 只有城市 / 还没订
Question 3 — 已确定行程 (header: "已定行程"): 有没有已经确定的景点/时间?(如预约了某个博物馆的时段)Options: 有 / 没有
Question 4 — 偏好 (header: "偏好"): 旅行风格?Options: 文化深度游 / 美食为主 / 休闲放松 / 暴走打卡
关键:从住宿地址反推动线
住宿地址是优化行程的锚点:
- 用住宿坐标计算到各景点的步行距离
- 按"从住处出发 → 沿一个方向推进 → 回住处"的逻辑设计每日动线
- 避免"上午去城东,中午回城西吃饭,下午又去城东"的折返
Phase 2: 行程规划 + 距离验证
Step 2.1: 规划日程
按天组织行程,每天包含:
- 上午/下午/晚间的时间轴
- 景点描述(历史背景、亮点、实用信息)
- 餐厅推荐(结合当天动线终点,不要在城东逛完推荐城西的餐厅)
- 交通方式和预估时间
- 需要提前预约的标注
Step 2.2: 距离验证(CRITICAL)
必须使用路线 API 验证所有步行/驾车段落。不要凭直觉估算距离。
优先使用 OpenRouteService MCP(如果已安装)。如果 MCP 未加载,直接 curl 调用 ORS API:
# Geocoding(注意:不带 /v2 前缀)
GET https://api.openrouteservice.org/geocode/search?api_key={KEY}&text={address}&size=1
# 步行路线
GET https://api.openrouteservice.org/v2/directions/foot-walking?api_key={KEY}&start={lon},{lat}&end={lon},{lat}
# 驾车路线
GET https://api.openrouteservice.org/v2/directions/driving-car?api_key={KEY}&start={lon},{lat}&end={lon},{lat}
标记所有超过 2.5km 的步行段落,建议替代交通方式(地铁/公交/打车)。
Step 2.3: 预约检查
整理所有景点的预约要求:
- 🔴 必须提前预约(限时入场)
- 🟡 强烈建议预约(热门日期会售罄)
- 🟢 可以现场买票
- ⚪ 免费/无需门票
Phase 3: 图片获取
使用 Wikipedia API 批量获取景点照片:
url = f"https://{lang}.wikipedia.org/w/api.php?action=query&titles={title}&prop=pageimages&format=json&pithumbsize=1200"
# headers: User-Agent required
策略:
- 先用英文 Wikipedia 搜索
- 找不到则用当地语言版本(it/es/de...)
- 所有图片容器必须设置
aspect-ratio+background占位色,防止加载时布局偏移 - 加
loading="lazy"延迟加载 - 加
onerror处理函数优雅降级
图片准确性: 只用确认对应的 Wikipedia 词条图片。不要猜测 URL,不要用 Unsplash source(已废弃,返回 503)。
Phase 4: HTML 生成
生成前必读: design-system.md 和 pitfalls-and-fixes.md
分段写入策略
HTML 文件通常 1000+ 行,单次生成容易超时。必须分段写入:
- Part 1:
<head>+ CSS + Hero + Day 1-2(用cat >创建文件) - Part 2-N: 剩余天数(用
cat >>追加) - Final: JavaScript(用
cat >>追加)
页面结构
├── Hero(全屏封面 + 倒计时 + 城市概览)
├── Day Navigation(sticky 顶部导航)
├── Day 1-N Sections(每天一个 section)
│ ├── Day Header(日期 + 天气 + 标签)
│ ├── Hero Image(当天目的地大图)
│ ├── Timeline(时间轴组件,每个活动一个节点)
│ ├── Image Grid(景点照片 2-3 列)
│ ├── Restaurant Cards(可折叠的餐厅推荐)
│ ├── Insider Tips(实用贴士框)
│ └── Local Info(当地特色,可折叠)
├── Practical Info(签证/货币/插头/安全等)
├── Travel Phrases(当地语言常用语 + 发音)
└── Footer
倒计时逻辑
const target = new Date('YYYY-MM-DDT00:00:00+TZ');
// 如果已过出发日期 → 隐藏倒计时
if (diff <= 0) { wrap.classList.add('hidden'); return; }
日期导航 Tab
设计要点(来自实际踩坑):
- 视觉要克制:无边框、透明背景、小字号。Active 状态用浅灰底 + 加粗,不要用填充色
- 点击区域要足够大:
padding: 8px 14px最低限度 - 加
-webkit-tap-highlight-color: transparent和touch-action: manipulation(消除移动端 300ms 延迟) - 用
scroll-margin-top控制滚动对齐,不要手算 offset
Insider Tips 格式
每个景点提供"不一定要 XX,但一定要 YY"式的实用建议:
- "不一定要进博物馆,但一定要爬上台阶看全景 — 免费"
- "不一定要买票上岛,从沙洲上看和踩水就已经很棒了"
- "不一定要进内部,但屋顶天台是精华中的精华"
天气信息
不要断言实际天气("晴"、"多云"),只写"往年均温 XX-XX°C"。加上日出日落时间。
Phase 5: 移动端适配
移动端是主要阅读场景。 必须检查:
@media (max-width: 768px) {
/* 图片网格 3列→2列 */
/* 餐厅卡片纵向堆叠 */
/* 天气栏纵向堆叠 */
/* section padding 收紧 */
}
@media (max-width: 640px) {
/* 图片网格→1列 */
/* 表格→卡片布局(尤其是常用语表格!) */
/* hero 图比例 21:9 → 4:3 */
/* timeline 左间距缩小 */
/* info-grid → 1列 */
}
表格在手机上的处理: 4列表格(如常用语)在手机上必须重排为卡片布局:
.phrase-table thead { display: none }
.phrase-table tr { display: grid; grid-template-columns: auto 1fr; }
Phase 6: 部署
GitHub Pages(推荐,公开分享)
cd <project-dir>
git init && git checkout -b main
# 创建 GitHub Actions workflow
mkdir -p .github/workflows
cat > .github/workflows/pages.yml << 'EOF'
name: Deploy to GitHub Pages
on:
push:
branches: ["main"]
permissions:
contents: read
pages: write
id-token: write
jobs:
deploy:
environment:
name: github-pages
url: ${{ steps.deployment.outputs.page_url }}
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/configure-pages@v5
- uses: actions/upload-pages-artifact@v3
with:
path: '.'
- id: deployment
uses: actions/deploy-pages@v4
EOF
# 用 gh CLI 创建仓库并部署
gh repo create <name> --public --source . --remote origin --push
gh api repos/<user>/<name>/pages --method POST \
--field "build_type=workflow" --field "source[branch]=main" --field "source[path]=/"
缓存提示: GitHub Pages cache-control: max-age=600(10分钟)。更新后给朋友发 ?t=xxx 参数链接绕过缓存。
Phase 7: 交付
告诉用户:
- 文件位置(完整绝对路径)
- 在线链接
- 需要提前预约的景点清单 + 预约链接
- 如何更新:改
index.html→git commit→git push自动重新部署
Supporting Files
| File | Purpose | When to Read |
|---|---|---|
| design-system.md | CSS 变量、组件样式、颜色方案 | Phase 4 生成 HTML 前 |
| pitfalls-and-fixes.md | 实际踩过的坑和修复方案 | Phase 4-5 生成和测试时 |