Skip to content

About

婚礼拼车规划:用高德真实行车时间算高铁站接驳和顺风车方案,带方案页和在线版

Resources

Security policy

Stars

0 stars

Watchers

0 watching

Forks

Latest commit

 

History

127 Commits

Folders and files

Repository files navigation

拼车出行规划(wedding-carpool)

一群人从不同城市去同一个地方(婚礼、聚会、团建……):有人开车,有人坐高铁。这个工具用高德的真实行车时间先给出一个大方向,让大家心里有个底;具体在哪接、几点到,还是同行的人之间再商量。它回答:

  • 不开车的人坐到哪个高铁站最合适(不一定是离目的地最近的那个);
  • 哪位车主顺路接谁、在哪接、几点出发,绕路不超过各自的上限;
  • 搭不上车的人在哪个站汇合打车,到站时间相近的拼一辆,尽量省钱;
  • 可选:散场后怎么回去(返程:车主顺路送人去车站或回家),每个人可以有自己的离场时间。去程和返程是两个独立的开关,可以只规划返程。

结果包括:

  • 推荐方案和备选方案;
  • 每辆车的路线地图:灰色虚线是不接人时的直达路线,和实际路线对比,就能看出绕了哪段;
  • 一页可以直接发给大家的方案页:每人一张时间线卡片,带高德导航链接;开了返程的话,另有返程一节。

线上版:https://carpool.eigentime.org ,首页有效果图、示例方案页(/demo)、适合哪些场合和常见问题,不用注册。也可以在本机运行,或者自己部署一份。

使用流程

  1. 目的地:搜索并选中,坐标最准。

  2. 成员:谁开车、空几个座、最多愿意绕多久;每个人的出发地。几个人一起走(比如带家属)的,填「同行人数」,这组人会一起上同一辆车,或者一起打车,不会被拆开。选好或算过的地点会马上显示在地图上,坐标存进配置,下次不再查。

  3. 候选车站:点「推荐车站」,抽屉顶部是「找站设置」,默认在三个范围里找火车站,都可以改,改完先显示要搜索多少次:

    • 目的地周边(默认 90 公里);
    • 各车主出发地附近(默认 30 公里);
    • 各车主的路上:默认沿路线每隔 30 公里取一个点,也可以改成「绕路上限内全覆盖」,更全但搜索次数更多;
    • 还可以加上乘客出发地附近,给坐高铁的人找离家近的站。

    不在 12306 站名表里的站(多半是货运站)、建设中或暂停营业的站、已在候选里的站会被去掉,但会列在「没列出的站」里写明原因,可以手动加入。结果默认按「车主最少绕路」排序,每位车主各绕多少、超过绕路上限的都标出来,地图上画出搜索过程,勾选加入即可。设置存在行程的 [options.suggest] 里,各项含义和默认值见「推荐车站怎么找」。

  4. 车次:不开车的人在每个站后面点「查」,打开已填好出发城市、到达站和日期的 12306 页面,查到后填入车次和时刻(如 G1234 08:00→11:30)。程序会自动算用时,并倒推车主几点出发。

  5. 规划哪几段、返程(可选):表单顶部的「规划哪几段」有去程、返程两个开关,至少选一段,可以只规划返程(要填返程日期,用不到去程的车次和出发时间)。开了返程,填散场时间;不开车的人填回程车次(同样有 12306 查询链接),程序按「发车前多久到站」(默认 40 分钟)倒推;车主可以选返程是否顺路送人、最多绕多久。每个人可以填自己的离场时间(不填就是散场时间):车主几点走,车就几点走,乘客准备好后最多等车主 30 分钟(默认,可以改)。

  6. 计算方案:先让尽量多的人搭上顺风车,每位车主的绕路不超过上限;再比总分钟数(车主绕路 + 乘客坐车 + 打车组车程)。没搭上车的人另外打车:到站(返程是离场)时间相近的拼一辆,默认尽量拼车省钱,「选项」里可以改成各人走自己最快的站。去程和返程分别出方案,可以分别选,方案页按你选的组合生成。规则、默认值和版本号见「方案是怎么算出来的」,每个方案下面也列出了总分钟的构成。

  7. 发布方案页:每个行程一个方案页链接,重新发布会更新同一个链接。

在线版

  • 试玩:没有邀请码、也没有高德 Key 的人可以打开 /try。里面是虚构的行程(宏村示例酒店,老王、老张开车,小李、小陈坐高铁,开返程),数据在 web/try-trip.json;能改谁开车、空座、最多绕路、同行人数、车次和分钟数,能删成员和候选站,能开关去程和返程(可以只规划返程)、改乘客的离场时间、切换打车方式,「恢复示例」回到初始。不能搜索和改地点、加成员和车站、保存、发布方案页。行车时间在浏览器里按直线距离估算(直线公里数 × 1.3 ÷ 75 km/h,再加 10 分钟),路线画成直线,报告里写明是示意;全程不调用高德 Web 服务,也没有 /api/t/ 请求(地图底图仍是高德瓦片)。构建时把编辑页复制成 dist/try.html,页面按路径 /try 切到试玩模式。
  • 新建行程:首页填行程名称,然后二选一:
    • 有邀请码(站长发的,也可以直接打开邀请链接 /?invite=<邀请码>),用站点的公共高德额度;
    • 填自己的高德 Web 服务 Key。Key 只保存在服务端,不会回传到网页,调用次数算在你自己的额度里。
  • 编辑链接即权限:形如 /t/<行程>#k=<密钥>,发给一起规划的人就能多人同时编辑。链接外传了,可以在「更多」里重置,旧链接和已经打开的页面立即失效。
  • 编辑口令(可选,默认关):在「更多」里设置。设了以后,新设备打开编辑链接要先输入口令,已经在线的其他人会被请出、要重新输入;每个行程每小时最多试 10 次。清除后只凭编辑链接就能打开。
  • 方案页:链接形如 /p/<方案页 id>,和行程 id 无关,只能看不能改。v3 之前发布过的行程沿用原来的 /p/<行程 id>,重新发布还是更新这个链接;想分开可以在「更多」里换链接。
    • 车主的路线从出发地约 2 公里外开始画,「到家附近接」的地点不标位置,导航链接不带出发地。
    • 可以设访问口令(每个方案页每小时最多试 20 次)、换一个链接(旧链接失效)或停止分享。
    • 页面上有「打印 / 存为 PDF」按钮,打印时隐藏按钮、地图固定高度、卡片不跨页,黑白打印也能看清。
  • 多人实时编辑:
    • 改动停顿约 0.8 秒后自动保存;
    • 顶部显示谁在线,正在被别人编辑的格子会标出名字;
    • 两人改了不同的地方会自动合并;改了同一格时,保留后保存的一方,并给他弹出提示「对方改成了什么」,可以一键改用对方的;
    • 断线期间的改动,恢复后补存。
  • 历史版本:同一个人 2 分钟内的连续修改合并成一条,每个行程保留最近 100 条。可以查看和现在的差别、一键恢复;恢复本身也会生成新版本,还能再撤回。
  • 调用上限:
    • 用公共额度的行程:每个行程每天最多 1500 次(邀请码可以单独设),全站每天最多 4000 次高德调用。全站用过八成后,当天还没用过公共额度的行程暂停分配,留给已经在算的行程。
    • 自带 Key 的行程每天最多 3000 次,只防程序出错时无限调用。
    • 站点公共额度按高德的两个类别(路线测距类、搜索类)分别记今天和本月的用量,到月预算就停下提示。月预算默认路线测距类 140000 次、搜索类 4500 次,比高德的免费额度留了余量,可以用可选变量 OWNER_MONTHLY_LBS_BUDGET、OWNER_MONTHLY_SEARCH_BUDGET 调整。高德没有查询剩余额度的接口,只能自己计数;条款或额度变了,改配置即可。
    • 高德返回配额用完时,按 Key 和接口类别(搜索类、路线测距类)分开记住,北京时间次日零点前这一类不再调用。高德个人开发者的搜索配额比路线类少得多,搜索用完了不影响算行车时间。
    • 到上限都是停下提示,不会继续调用;提示里可以直接改用自己的 Key。
  • 数据保留期:出行日期过后 60 天、连续 180 天没人编辑,两者取较晚的,到期自动删除行程和方案页;删除前 7 天编辑页会提示。「更多」里可以随时手动删除。
  • 其他:
    • 配置可以导出、导入(JSON);
    • 公开额度状态:GET /api/status 只返回粗粒度信息(ok、tight、out、paused 四档、已用百分比、能否新建),节点缓存 60 秒;首页据此显示「今天站点公共额度:已用 23%」,紧张时提示可以改用自己的 Key,接口不可用时整块隐藏;
    • 同一 IP 每天最多新建 10 个行程,全站每天最多 200 个;
    • 存了什么、给了哪些第三方、哪里可能花钱,见站内的费用与隐私页。

管理页

站长在 /admin 用站长口令登录。站长口令只用于管理页,不能在首页当邀请码用;登录后发的是随机会话令牌(24 小时过期),不是口令本身。可以:

  • 看今天和本月的公共额度用量(按两个类别分开)、近 30 天每天的用量、今天新建的行程数;
  • 用公共额度新建行程:直接给出编辑链接,不需要邀请码;
  • 发邀请码:备注、最多建几个行程、有效期、每个行程每天的高德上限;
  • 看每个邀请码建了几个行程、今天用了多少;停用或重新启用。邀请码停用后,用它建的行程不能再用公共额度,要改用自己的 Key,已有数据不受影响;
  • 应急开关(置顶,操作要二次确认,最近 50 条操作有记录):暂停公共额度(用公共额度的行程立刻停止计算并提示改用自己的 Key,自带 Key 的不受影响)、暂停新建行程、一键停用所有邀请码、退出所有管理会话、对单个行程停用公共额度。「最近用公共额度的行程」只显示行程 id、新建时间、所用邀请码和今天用量,不显示行程内容。

应急处理

站长口令可能泄露了,按顺序处理(管理页里也有同样的手册):

  1. 在管理页点「退出所有管理会话」,再暂停新建行程,需要的话也暂停公共额度;
  2. 在本机运行 npx wrangler secret put ACCESS_CODE 换口令,旧口令立刻失效;
  3. 检查邀请码和最近用过公共额度的行程,可疑的邀请码停用、可疑的行程停用公共额度,也看一下「最近操作」里有没有不是你做的;
  4. 确认没问题后,把暂停的开关恢复。

登录失败有次数限制(同一网络 15 分钟 5 次、全站每小时 30 次)。

登不进管理页时(比如有人故意试错,把全站登录锁了一小时),可以用环境变量直接暂停,不需要登录:

npx wrangler secret put FORCE_PUBLIC_PAUSED     # 值填 1:暂停公共额度
npx wrangler secret put FORCE_CREATION_PAUSED   # 值填 1:暂停新建行程
npx wrangler secret delete FORCE_PUBLIC_PAUSED  # 恢复(另一个同理)

管理页会标出哪些开关是被环境变量强制打开的。

本地版

需要 Python 3.11+,只用标准库。高德 Key 放在环境变量 AMAP_KEY 里,或者存进同目录的 .amap_key(已加入 .gitignore)。

python3 ui.py            # 编辑 trip.toml,打开 http://127.0.0.1:8765
python3 carpool.py trip.toml   # 只用命令行:报告打印到终端,并写到 trip-report.md

返程在 TOML 里加一节 [return](enabled、depart_time、security_min、max_wait_min、date),成员的回程车次写在 return_trains,离场时间写 leave_time,同行人数写 party;只规划返程时在 [options] 里写 outbound = false,并填 [return] 的 date。打车怎么安排是 [options] 里的 taxi_mode、taxi_pool_extra_min、taxi_wait_min。都见 trip.example.toml。

本地版是单人使用:没有多人同步和历史版本,需要手动保存。保存时会把配置写回 TOML,手写注释不会保留;第一次保存前,原文件会备份为 trip.toml.bak。字段说明见 trip.example.toml。

自己部署(Cloudflare Workers)

浏览器:界面 + Pyodide(浏览器里运行的 Python,跑 carpool.py 等,计算都在这里;Pyodide、地图组件随站点自己托管在 /vendor/)
   │  编辑链接换来的 Cookie(只对该行程的路径有效);WebSocket 实时同步
   ▼
Worker(web/worker.js,用 placement.region 固定在香港附近运行,离高德近)
   ├─ 新建行程:校验邀请码或自带 Key,限制新建频率
   ├─ ConfigRoom(Durable Object,每个行程一个):配置、版本号、历史、当天用量、在线名单、
   │                                         方案页设置、到期删除的定时任务
   ├─ Usage(Durable Object):全站新建次数、站长 Key 当天用量、邀请码、按天汇总的访问统计
   ├─ 高德代理:只放行用到的接口;先查 Cloudflare 节点缓存,再按每秒 3 个批量请求
   ├─ 管理页接口:/api/admin/*,站长口令登录,之后凭会话令牌
   └─ KV:方案页(带访问口令和过期时间)、按 Key 和接口类别记的配额标记

计算内核按职责分成几个模块,都在仓库根目录:

模块 内容
base.py 常量、配置项定义(FIELDS、DEFAULTS)、规则版本号、进度回调
geo.py 地点、高德客户端 Amap、高德接口 AmapLike、找站时的 POI 过滤
model.py 行程模型和读配置、行车时间矩阵
routes.py、taxi.py、solver.py 车主路线和乘客分配、打车安排、求解
timetable.py 行程表
reporting.py 报告
tomlio.py TOML 写出

carpool.py 是门面兼命令行:原来的 carpool.X 都还能用,给 carpool.progress 这类变量赋值,会转到真正定义它的模块。网页版加载哪些 Python 文件只写在 web/py-manifest.json 一处。

高德接口:计算只通过 geo.AmapLike 规定的那几个方法调用高德,文档字符串里列了每个方法对应的高德 Web 服务接口和额度类别。现在有四个实现:

  • geo.Amap:本地,直连高德;
  • browser.BrowserAmap:网页版,经 Worker 代理;
  • browser.TryAmap:试玩,不联网;
  • 测试里的 FakeAmap。

要改成浏览器直接调用、改用 JS API,或者换数据源(天地图、腾讯),只需新写一个满足 AmapLike 的实现,求解、行程表、报告、方案页都不用动。测试会检查各个实现都满足接口,也会检查计算里用到的方法都在接口里。

计算内核以「一段行程」(leg)为单位求解:去程是车主从家出发接人去目的地,返程是从目的地出发送人。两段互不影响,可以只算其中一段。座位按同行人数算,一组人不拆开。没搭上车的人怎么打车由 TaxiPool 安排,结果按「哪些人没搭上车」缓存。方案页由 share.py 生成。编辑器是 ui.html(本地版、在线版、试玩共用),页面只有结构和样式,脚本是 web/editor/ 下的 ES 模块:入口 main.js 判断是哪种模式;backend.js 是三种模式的后端实现,接口相同,并按模式生成一张能力表(caps:能不能保存、能不能实际搜索、有没有历史、能不能实时同步……)。其他模块只看能力表,不判断模式,测试会检查这一点。模块之间单向依赖,没有环,也由测试守着。求解之后,每个方案里「谁几点出发、几点到哪、等多久、打车几点汇合」只在行程表(carpool.timelines)里算一次,报告、方案页和界面数据都只读它,不再各自推算。tests/golden/ 里的金标准测试逐字节固定这三样输出:有意改了输出,用 GOLDEN_UPDATE=1 python3 -m unittest test_carpool.GoldenTest 重新生成,再看一遍 git diff。

需要 Node.js、Cloudflare 账号,以及一个高德 Web 服务 Key。免费套餐就够用,超出免费额度只会报错,不会扣费。

npm install
npx wrangler login
npx wrangler kv namespace create DATA      # 把输出的 id 填进 wrangler.jsonc
npx wrangler secret put AMAP_KEY           # 站长的高德 Web 服务 Key
npx wrangler secret put ACCESS_CODE        # 站长口令:只用来登录管理页 /admin
npm run deploy                             # 构建 dist/ 并部署

构建时(web/vendor.mjs)会下载编辑页用的 Pyodide、Leaflet、marked(约 13 MB),逐个校验 sha256,缓存在 .cache/vendor/,拷到 dist/vendor/;第一次构建要能访问 jsDelivr 和 cdnjs,下载失败或校验不对会让构建报错,不会回退到 CDN。网络要走代理的话,设好 HTTPS_PROXY(下载用 curl)。许可证文件随依赖一起放在 dist/vendor/ 下。

可选设置:

  • 在 wrangler.jsonc 的 vars 里设 TRIP_DAILY_LIMIT、OWN_TRIP_DAILY_LIMIT、OWNER_DAILY_LIMIT,调整每日上限;设 OWNER_MONTHLY_LBS_BUDGET、OWNER_MONTHLY_SEARCH_BUDGET,调整站点公共额度的月预算(默认 140000 和 4500);
  • 在 routes 里绑定自己的域名。workers.dev 域名在国内不翻墙常常打不开。
  • wrangler.jsonc 的 assets.run_worker_first 里的页面路径(/、/demo、/try、/guide、/for/* 等)让 Worker 先处理再转给静态文件,用来统计页面访问;not_found_handling: "404-page" 让不存在的地址返回 404.html。这两处和 web/worker.js 配套,不要删。
  • 站点地址和搜索引擎收录(构建时读环境变量,在 npm run build / npm run deploy 前设好):
    • SITE_ORIGIN:站点的完整地址,如 https://carpool.example.com(不带路径)。用在页面的 canonical、Open Graph、结构化数据、sitemap.xml、robots.txt 和 llms*.txt 里。不设就是官方站 https://carpool.eigentime.org。
    • SITE_INDEXABLE:设成 1 才允许搜索引擎收录。换了域名又没设它的话,默认不收录:所有页面加 <meta name="robots" content="noindex">,robots.txt 只有 Disallow: /,不生成 sitemap.xml、llms.txt、llms-full.txt。这样自部署的副本不会和官方站抢搜索结果;想让自己的站被收录再设 SITE_INDEXABLE=1。
    • 例:SITE_ORIGIN=https://carpool.example.com SITE_INDEXABLE=1 npm run deploy。
    • 自部署的站点请用你自己的名字、域名和标识,不要冒充官方服务:「拼车出行规划」、Eigentime 的名称和标识不授权给分叉使用,见 LICENSING.md 第 5 节。别忘了改 wrangler.jsonc 里 routes 的域名。
  • 不设 AMAP_KEY 和 ACCESS_CODE 的话,就只能自带 Key 新建行程。
  • 高德 Key 的使用条款和配额以高德开放平台为准。按 2025 年 5 月起的定价,个人认证开发者「非商业目的」的免费月配额是:路线、测距、地理编码等基础服务 15 万次,关键字、周边等搜索服务 5000 次,只有认证后的第一年;用于商业目的要另外购买许可。部署前请自己确认你的用途符合条款。

本地调试:在 .dev.vars 里写上 AMAP_KEY=... 和 ACCESS_CODE=...,然后运行 npm run dev。12306 站名表 web/stations12306.json 由 web/gen_stations12306.py 生成,需要时重新生成。

自部署升级

版本发布在 GitHub Releases,更新内容看仓库的 CHANGELOG.md;从 v3.2.0 开始按版本号发布。

  1. 关注新版本:在 GitHub 仓库页点 Watch → Custom → 勾上 Releases,有新版本会通知你。
  2. 拉取上游的更新:
    • 你是 fork 的:在你的 fork 页面点 Sync fork,再 git pull 到本机;
    • 你是直接克隆的:git pull(想固定在某个版本,用 git checkout v3.2.0 这样的标签)。
  3. 看 CHANGELOG.md 里标了「不兼容」的条目:它们说明了配置、环境变量或接口有哪些必须同步改动的地方(比如 wrangler.jsonc 里的 assets 设置)。你自己改过 wrangler.jsonc(KV id、域名、vars)的话,合并时保留你的值,只补上新增的条目。
  4. 部署:npm install && npm run deploy。Durable Object 的迁移由 wrangler 按 wrangler.jsonc 里的 migrations 自动执行,不用手动处理;已有的行程和方案页不受影响。
  5. 出问题要回滚:npx wrangler rollback,回到上一个已部署的版本(要指定版本时先 npx wrangler deployments list 看版本号)。回滚只换代码,不会改动已存的数据;如果新版本新增了 Durable Object 迁移,回滚后那一步迁移不会撤销。

搜索引擎与 AI 问答

首页带 Open Graph、Twitter 卡片和 JSON-LD(WebApplication 与 FAQPage)。robots.txt 允许首页、/demo、/privacy,禁止 /t/、/p/、/api/、/admin;另有 sitemap.xml 和 llms.txt(给 AI 问答读的简短说明)。/demo 是静态的示例方案页,行程是虚构的。编辑页和管理页带 noindex。这几个文件都在 web/ 下,换了域名要一起改。

安全措施

  • 构建时(web/build.mjs)给每个页面生成内容安全策略(CSP):内嵌脚本按哈希放行,不允许 unsafe-inline 和 unsafe-eval;编辑页的 Pyodide、Leaflet、marked 都是自己托管的同源文件,不放行任何 CDN;示例页和方案页仍用 cdnjs,带 SRI 完整性校验。
  • 所有响应都带安全头(nosniff、X-Frame-Options、Referrer-Policy、HSTS、Permissions-Policy):静态文件在 web/_headers,Worker 生成的响应在 web/worker.js,两处要保持一致。
  • 方案页的 HTML 由编辑者的浏览器上传,所以放进 CSP 沙箱(独立的匿名来源):读不到本站的存储和 Cookie,也不能发请求。
  • 改动状态的请求(/api/* 的 POST 和 DELETE、方案页口令表单)校验 Origin,跨站来源会被拒;WebSocket 也校验 Origin;500 错误不返回内部错误原文。
  • 流量统计在服务端做,只记按天汇总的次数(页面访问、爬虫、外站来源的域名和 ?from= 参数、新建行程、发布和打开方案页的次数),不记 IP 和完整地址,不用 Cookie,保留 35 天;管理接口 /api/admin/stats 返回近 30 天。
  • 行程实例(Durable Object)的内部接口只接受 Worker 自己发起的请求;客户端请求只有白名单里的路径(配置、同步、历史、恢复、改名)会转给行程实例。不是自带 Key 的行程一律经过公共额度的全部护栏。
  • 限次:管理登录(检查和记录是一次原子操作)、编辑口令(最近一小时)、方案页口令(按来源和按页各有上限)、新建行程(按来源和全站);来源 IP 只存加盐、按天轮换的哈希。每个行程的保存、发布和实时连接也有频率或数量上限。
  • 免费套餐的额度(Workers 请求、Durable Object、KV 写入)在代码里没法完全防住恶意刷量;用完时当天报错、不扣费(前提是 Workers Free 套餐)。需要的话在 Cloudflare 后台给站点加一条速率限制规则。
  • Cloudflare 的 Web Analytics 开了自动注入时,会往页面里加统计脚本标签。CSP 不放行它,浏览器会直接拦下,不下载、不运行(构建时 web/build.mjs 检查每个页面的 script-src 只放行本站、cdnjs 和内嵌脚本的哈希)。官方站因为同一域名下的博客在用,保持开启,隐私页写明了这一点。自己部署时不需要的话,在 Cloudflare 后台关掉即可。
  • 发现安全问题请按 SECURITY.md 私下报告,不要公开提 issue。

已知限制

  • 行车时间来自高德驾车测距,接近查询时的路况,每次查会浮动几分钟,当天也可能有出入。
  • 不调用 12306 的非公开接口,车次需要手填。不填车次时,会用高德公共交通估算,但高德跨城只给直达火车、不含换乘,也查不到刚开通的线路,可能很不准。
  • 推荐车站分不出高铁站和普速站,选的时候留意一下。高德没收录、或站名和 12306 站名表(2026-10-07 生成)对不上的站找不到,会列在「没列出的站」里;「沿路线取点」只保证路线两侧一定宽度内没有遗漏,要更全就切到「绕路上限内全覆盖」。
  • 同一格两人同时改时,保留后保存的一方;先保存的一方的改动,可以在提示里一键改回,或者去「历史」里找回。
  • 方案页存在 KV 里,重新发布后,其他地区可能要等约一分钟才看到新内容。
  • 方案页模糊了车主出发地,但路线和车站仍然能看出大致区域,只发给相关的人;需要的话加访问口令。
  • 返程只考虑车主从目的地送人去车站或顺路的家,不考虑在车站之间换乘;打车费用是按里程的粗估。

测试

npm test     # Worker、页面合并逻辑、编辑页静态检查、站点构建(node --test)和 Python(unittest),都离线运行

编辑页的交互用端到端测试验证:

npm run e2e  # 试玩、本地、在线三种模式的 18 个场景,约 2 分钟
  • 什么时候跑:改了编辑页(ui.html、web/editor/)、ui.py 或 Worker 接口以后,以及每次发布前。它要起本地服务和浏览器,所以不在 npm test 里。
  • 前提:本机要有 Playwright 1.62.1 对应的 Chromium。没有的话先运行 npx playwright install chromium。
  • 会不会碰到真的 Key:不会。测试自己起 wrangler dev 和 ui.py:用临时生成的假 Key 和测试口令,不读 .dev.vars;本地存储放在临时目录,跑完按进程号停掉、删掉。浏览器里发往高德代理和站外的请求一律拦下,出现一次就算失败。
  • 截图对比:node web/e2e/shots.mjs <目录> 生成 32 张固定状态的截图,用于重构前后逐像素比对。偶尔会有地图矢量图形边缘的抗锯齿差异,比如试玩、桌面、深色那几张,重跑一次即可。

管理页的交互仍在浏览器里手动验证:npm run build 后 npx wrangler dev。编辑页里所有确认、提示、输入都是页内弹窗(<dialog>)和轻提示,没有原生 alert / confirm / prompt;自动化脚本用稳定的选择器:确认 [data-dialog-ok]、取消 [data-dialog-cancel]、输入框 [data-dialog-input]、错误提示 [data-dialog-error]。

计算规则的版本

carpool.RULES_VERSION 是计算规则的版本号。所有配置项(默认值、范围、中文名)只在 config-fields.json 里定义一处,carpool.DEFAULTS 由它生成。只有排序规则或成本口径变了才加一,改界面、改文字不加。test_carpool.py 里的规则快照测试固定了几个场景的方案顺序和各项数字:快照失败说明排序或成本变了,如果是有意修改,更新期望值、把 RULES_VERSION 加一,并同步 web/pages/guide-method.html(默认值表会和 DEFAULTS 自动核对)和 CHANGELOG.md。

地图审图号

地图角标写着高德的审图号 GS(2025)5996号,在三处各写了一份:web/editor/map.js、share.py、web/demo.html 的 attribution(web/ui.test.mjs 会检查三处一样)。高德更新审图号时,三处都要改。

重新生成示例页 /demo

示例页是用虚构数据算一次方案、发布,再把生成的方案页改成站点页面:在编辑页导入虚构配置(宏村示例酒店,老王从杭州开车、老张从南京开车,小李同行 2 人从上海、小陈从武汉坐高铁,开返程)、计算方案、发布方案页,把得到的 HTML 存下来,运行 python3 web/make_demo.py 存下的文件.html 生成 web/demo.html。计算一次会消耗一次高德额度,方案页模板(share.py)改了才需要重新生成。

v2(多行程、并发、通用化)的计划和验收标准见 docs/v2-plan.md,v3(开源授权、隐私、邀请码、返程和同行人数)见 docs/v3-plan.md。

许可证

AGPL-3.0-or-later。授权说明、第三方组件与数据来源、贡献须知见 LICENSING.md。

支持作者

这个项目是作者业余时间做的。觉得有用的话,可以在爱发电支持作者的开源工作,也可以看看作者的赞助页。支持完全自愿,不对应任何功能或权益;线上站点继续免费、没有付费功能,赞不赞助都不影响使用。

致谢

我的 AI 启蒙和学习,来自 LINUX DO 社区。

About

婚礼拼车规划:用高德真实行车时间算高铁站接驳和顺风车方案,带方案页和在线版

Resources

Security policy

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages