fare-alert
by ashleymao523
README.md
# FareAlert · 低价出行提醒组件
监控未来 N 天 **机票最低价(含机建燃油,即最终支付口径)**,低于你的心理价位就推送到 iPhone;同时对比 12306 列车全席位票价(二等座/卧铺/普速,含学生票估算),帮你选出**出行最优方案**。自带 Web 仪表盘,单文件依赖极简,适合部署在私人设备上长期运行。
> 个人比价参考工具:数据来自公开接口的低频查询,不破解任何签名/验证码,购票始终跳转官方/平台页面人工完成。
> 📖 **新手建议先看 [使用指南.md](使用指南.md)** —— 组件介绍 / 从零搭建 / 推送配置 / 日常使用,一条龙图文教程。
## 功能特性
- ✈️ **机票低价监控**:去哪儿价格日历(免登录公开接口),一次拉取未来数月每日最低价+航班号,总价=裸价+机建+燃油(可配置)
- 🔔 **低于心理价位即推送**:Bark(iPhone 通知)+ ServerChan(微信)双通道,带去重/冷却/降价再提醒,不轰炸
- 🚄 **列车对比(全席位)**:12306 票价接口(免登录),接口查到什么席位就展示什么(二等座/一等座/商务座/硬卧/软卧/动卧/硬座…),含学生票估算,识别夕发朝至车次
- 🧳 **托运行李标注**:按航司标注是否含免费托运,廉航/特价舱自动加 ⚠️ 提示
- 🧠 **联想输入**:城市/车站全部从数据源字典联想选择(中文/全拼/首字母,如 hzd→杭州东),不依赖手输精确文字,不会因偏差走模糊搜索
- 📊 **Web 仪表盘**:60 天价格热力日历、价格趋势图、"出行最优"卡片对比(机票/动车/学生动车/卧铺)、配置全可视化编辑
- ⚙️ **一切皆可配**:出发/到达城市、窗口天数、心理价位、税费、数据源开关、查询频率——页面上直接改
- 📦 **多线路**:支持同时监控任意多条线路(如 杭州→重庆、成都→杭州 …)
- 🔁 **往返模式**:按"去程+返程合计总价"判定阈值,主趋势图显示往返合计、另附返程独立趋势,日历热力按合计着色
- 🌍 **国际航线**:免 Key 即可用——自动接入去哪儿国际特价日历(稀疏但真实的含税促销价);配置免费 Amadeus Key 后升级为全日期覆盖 + 真实起降时刻(数据源页内置 3 步配置向导 + 一键测试连接)
- 🕐 **航班时刻与时长(v0.19 跨日班期补全)**:详情卡起飞→落地时间轴;杭州出发/到达线路自动经机场官网公开班期板沉淀「航班号+星期几」计划时刻库(零密钥、6h 缓存),目标星期未沉淀时自动借用同号航班其他班期时刻(「跨日班期·参考」徽标),仅有起飞时落地按大圆估算(~ 前缀);配置 Amadeus 后优先实时刻
- 📱 **PWA(v0.20)**:PNG 图标 + Service Worker 离线壳(静态资源缓存优先、接口网络优先+离线兜底),iPhone Safari「添加到主屏幕」后获得独立图标与最近一屏数据的离线阅读;数据源页新增「时刻库沉淀进度」七天可视化,时刻缺口原因一目了然
- 🩹 **缺价日自动补全**:去哪儿日历缓存没价的日期(返回空价)自动用 Amadeus 含税最低价补洞,日历/趋势/最优卡打「Amadeus补」徽标,补全结果缓存 24 小时保护免费额度;未配密钥时优雅跳过
- 📐 **无价日插值估算(v0.11)**:两侧 14 天内都有真实价的空洞日按距离线性插值(琥珀色斜纹+≈前缀,取整到 10 元);插值/参考价一律不触发提醒、不参与最低价/均价/TOP5 统计,趋势图估算点为琥珀空心圆
- 🕸 **爬虫监控**: 每次抓取逐步实时可视化——数据源/动作/耗时/条数/缓存命中/错误,保留最近 20 次运行历史; 手动查询时自动 2 秒轮询刷新
- 🫀 **数据源健康自愈(v0.12)**: 每轮抓取自动聚合各源健康分(滑动窗口),单轮≥2步失败或连续3轮失败即降级并展开诊断(候选原因+修复动作),恢复后自动解除;爬虫监控页顶部常驻绿/琥珀/红徽标,MCP snapshot_get 同步透出降级源供 Agent 自助排障
- 🧭 **预算找目的地(v0.13)**: "¥X 以内从 A 出发能去哪"——逐候选查价格日历,按含税总价升序返回可去列表(日期/航司/直达购票链接/实时·缓存新鲜度徽标);实发请求有硬预算(默认8,上限15,缓存命中不耗预算),结果缓存 6 小时;Web UI 新增「预算找目的地」页,MCP 新增 reverse_search 工具
- 📈 **洞察周报(v0.14)**: 每轮查询自动归档每日线路指标(最低含税价/均价/低价天数,保留180天),周报汇总本周最低·均价·环比上周·最佳出发日,每个数字可从历史重算;Web UI 新增「洞察周报」页(周度走势图+摘要卡),推送默认关闭(push.weekly_enabled 开启后每 7 天自动推一次)
- 🔗 **一键直达购票**: KPI 卡、对比卡、车次表全部可点——机票直达去哪儿下单页, 车次直达 12306 预填查询页(自动带入日期/车站)
- 🔒 **本地优先**:数据只落在本机 data/ 目录,推送 key 只存在本机 config.json(不入库)
## 界面预览
Web 仪表盘(v0.8 设计系统:Skyscanner 式浅色+城市图鉴+低价柱状图,移动端自适应并带浮动低价提醒横幅,iPhone 可"添加到主屏幕"当 App 用):
v0.29 起新增 **/v2 前后端分离版**(web/ 下的 Vite+Preact 工程,构建产物由后端同源托管,使用者无需 Node;开发者改界面见使用指南第十一节)。
| 仪表盘 | 配置编辑 |
| --- | --- |
| KPI 卡片 / 价格热力日历 / 趋势图 / 出行最优判定 | 线路 CRUD / 数据源开关 / 推送设置 |
## 快速开始
### Windows
1. 安装 Python 3.10+(勾选 Add to PATH)
2. 安装依赖:
```powershell
pip install -r requirements.txt
```
3. 双击 `start_windows.bat`,浏览器自动打开 http://127.0.0.1:8765
4. 在"提醒推送"页填入 Bark Key(iPhone App Store 下载 Bark,复制 Key),点"发送测试推送"验证
5. 想要后台自动监控:以管理员运行 `deploy/register_task.ps1`(计划任务每 45 分钟静默查询一次,满足条件即推送)
6. 想要开机自启(面板+抓取循环):运行 `tools/install_autostart.ps1`(写 HKCU Run 键,免管理员,默认装 webui+worker 双条目;`-Components webui` 仅面板;`-Uninstall` 卸载;已在运行时自动跳过)。worker 循环持续采集班期板,星期覆盖 7 天长满后起飞时刻缺口自动收敛
### macOS / Linux
```bash
pip3 install -r requirements.txt
bash start_mac.sh
# 或后台常驻: python3 main.py --loop
```
### iPhone 上怎么用?
iPhone 不跑 Python 后端,它的角色是**接收推送 + 查看面板**:
- **推送**:装 Bark → 复制 Key 填入配置,低于价位秒收通知,通知可直接跳购票页
- **面板**:把 Windows/Mac 上 config.json 的 `webui.host` 改为 `0.0.0.0`(并在防火墙放行 Python),手机 Safari 访问 `http://电脑局域网IP:8765`,分享→添加到主屏幕,即得到一个全功能 App 图标
## 配置说明
首次运行自动生成 `config.json`(个人配置,已 gitignore);模板见 `config.example.json`,所有项均可在 Web UI 修改:
| 配置 | 说明 | 默认 |
| --- | --- | --- |
| routes[].from_city / to_city | 出发/到达城市(必须中文城市名) | 杭州 / 重庆 |
| routes[].trip_type | 行程类型:oneway 单程 / roundtrip 往返(按合计价判定) | oneway |
| routes[].intl + from_iata / to_iata | 国际航线开关 + IATA 三字码(intl 时必填,如 HGH/NRT) | false / 空 |
| routes[].window_days | 查询窗口天数 | 60 |
| routes[].threshold_total | 心理价位(总价口径,含机建燃油) | 500 |
| routes[].train_compare.station_pairs | 动车对比车站对,如 杭州东|重庆北 | 杭州东/杭州西→重庆北/重庆西 |
| tax.airport_fee + fuel_surcharge | 机建+燃油(当前合计 120) | 50+70 |
| push.bark_key / serverchan_sendkey | 推送通道(留空禁用) | 空 |
| schedule.interval_minutes | 轮询间隔(分钟) | 45 |
| sources.enabled | 数据源开关(可用/规划中) | 全开 |
| sources.amadeus | 国际数据源(env=test/prod + client_id + client_secret,在 Web UI 数据源页填写) | test / 空 |
## 数据源与合规
| 源 | 状态 | 说明 |
| --- | --- | --- |
| 去哪儿·价格日历 | ✅ 可用 | 免登录免签名的公开接口,一次返回 365 天每日最低价(挂牌价,不含 OTA 券后;与券后实付通常只差小几十,可接受) |
| 12306·票价查询 | ✅ 可用 | 免登录低频查询,结果缓存 24h;全席位(含卧铺/普速 K/T/Z);学生票按 动车二等75折/硬座5折/硬卧=卧铺-硬座半价 估算(以下单页为准) |
| 去哪儿·国际特价日历 | ✅ 可用(免 Key) | 国际线路的兜底数据源:返回稀疏但真实的含税促销价(每月约 3-5 个日期),配 Amadeus Key 后自动合并、同日取更低 |
| Amadeus·低价日历(国际+补全) | ✅ 可用(需免费 Key) | developers.amadeus.com(注意复数)注册 Self-Service,用 /v1/shopping/flight-dates/cheapest 查含税最低价;国际线路全量使用,国内线路缺价日自动补洞(缓存24h) |
| Amadeus·航班时刻表 | ✅ 可用(需免费 Key) | /v1/schedules 按月查询真实起降时刻,匹配航班号自动填充详情卡;24h 缓存 |
| 机场班期·参考时刻 | ✅ 可用(免 Key) | 杭州机场官网公开班期板(与浏览器同源只读接口),按 航班号+星期 沉淀计划起降时刻库;目标星期未沉淀时跨日借用同号航班班期(v0.19),详情卡打「计划时刻·机场班期/跨日班期·参考」徽标,Amadeus 配置后自动让位实时刻 |
| Wikipedia·城市图片 | ⚠️ 视网络而定 | /api/city-photo 经 REST summary 取城市实拍图(缓存24h,失败负缓存);大陆网络下 Wikimedia 域名常不可达,自动回退到内置旅行海报剪影(离线可用) |
| 临近日参考价(内置) | ✅ 可用(免 Key) | 源日历"查价"空洞日自动镜像最近有价日的价格作展示参考(7 天内紧参考/45 天内远参考,标注距离天数);仅用于补全日历显示,**不触发提醒、不参与最优价判定**,点击直达当日实查 |
| 插值估算价(内置) | ✅ 可用(免 Key) | v0.11:空洞日两侧 14 天内均有真实价时按距离线性插值;**仅展示用,不触发提醒、不参与统计**,详情卡标注参考航班号 |
| 携程 H5 / 航司官网 | 🚧 规划中 | 备选交叉验证源 |
原则:**不破解签名、不绕过验证码、低频查询(分钟级)、只读公开数据、购票永远人工**。请将本工具用于个人比价,勿改造为商业爬虫。
## 项目结构
```
fare-alert/
├── main.py # 后端核心:查询→判定→推送 流水线
├── webui.py # Web 仪表盘(Flask)
├── core/
│ ├── config.py # 配置加载/合并
│ ├── flights.py # 去哪儿价格日历
│ ├── trains.py # 12306 票价+车站字典
│ ├── alerts.py # 阈值判定/去重/消息组装
│ ├── notify.py # Bark/ServerChan 推送+历史
│ ├── crawl.py # 抓取遥测(爬虫监控数据)
│ └── report.py # 静态 HTML 报告(旧版)
├── webui/ # 前端(原生 JS,无构建步骤)
├── deploy/ # Windows 计划任务注册/卸载
├── tools/ # 接口侦查脚本(开发用)
└── data/ # 快照/状态/日志/提醒历史(运行时生成)
```
## 开发路线图
- [x] **v0.1 实现**:双源查询、含税总价、阈值推送、托运标注、计划任务
- [x] **v0.2 可视化**:Web 仪表盘、热力日历、趋势图、出行最优判定、可视化配置
- [x] **v0.3 全席位+联想输入**:12306 全席位(卧铺/普速)、城市/车站拼音联想选择、快捷线路模板、多线路编辑器、学生卧铺估算
- [x] **v0.4 爬虫监控+直达购票**: 抓取步骤实时可视化(耗时/条数/缓存/错误)、KPI/对比卡/车次表一键直达购票页、车次时刻+历时展示、航班时刻字段预留
- [x] **v0.5 高级趋势图**: 平滑曲线、渐变面积/描边、悬浮十字线提示、周末底纹、阈值线与低价点高亮
- [x] **v0.6 浅色重设计+往返+国际**: shadcn 风格浅色主题、趋势图浅色化并新增返程趋势、往返合计判定、Amadeus 国际线接入
- [x] **v0.6.1 缺价补全**: 去哪儿日历空洞自动用 Amadeus 含税价回填、来源徽标、24h 缓存、内置城市→IATA 映射
- [x] **v0.7 国际免Key+航班时刻+UI精修**: 去哪儿国际特价日历免 Key 兜底、Amadeus 时刻表增强(真实起降+时长)、时长大圆估算、详情卡起降时间轴、Amadeus 配置向导+测试连接、v0.7 设计系统(渐变强调色/热度日历/时刻卡片)
- [x] **v0.8 缺价补全+Skyscanner式UI+移动提醒**: 临近日参考价补全(7天紧/45天远二级半径+距离标注+≈标记,日历 60/60 无空洞)、v0.8 设计系统(Skyscanner 配色/城市图鉴 Hero/低价柱状图视图/日历柱状一键切换)、移动端浮动低价提醒横幅+震动+系统通知授权按钮、城市旅行海报剪影(6 种 SVG 场景离线渲染,Wikipedia 实拍图网络可达时自动叠加)、Amadeus 官方域名修正(developer→developers)、中转行程按航段匹配真实时刻、无时刻状态"时刻待接入"徽标
- [x] **v0.9 扁平趋势图+API指引**: Google Flights 式扁平趋势(去渐变/辉光/动画,均价点线,最低价标注)、Amadeus 注册直达与推送指引
- [x] **v0.10 TOP5+目的地情报**: 低价日 TOP5 表、目的地天气(Open-Meteo)/汇率情报卡、Amadeus 隐私说明
- [x] **v0.11 插值补全**: 无价日期两侧真实价线性插值(琥珀标识,不参与统计)、趋势图估算空心点
- [x] **eng 工程化**: AGENTS.md 人机守则、G0-G6 验收门禁(tools/acceptance.py)、核心单测、CI
- [x] **M1 Agent接入**: 自研零依赖 MCP Server(stdio)五工具 fare_search/train_search/watch_add/watch_del/snapshot_get、"一句话建监控"意图解析(12组单测+8项协议自测+独立E2E验收)
- [x] **M2 源健康自愈**: 健康分/双阈值降级/诊断报告/UI徽标/MCP透出(单测 7/7)
- [x] **M3 反向搜索(首版)**: 预算过滤含税口径/请求硬预算+限速/6h结果缓存/UI页签+直达链接/MCP工具(单测 5/5,多城市并行与节假日联动留 M3.1)
- [x] **v0.18 零密钥航班时刻**: 萧山机场公开班期板→周班期时刻库(核心/sched_board),Amadeus 未配置时兜底填充起降时刻并打徽标,含共享航班号索引/到达板双时刻优先/15项单测;周报自动推送增加无渠道守卫(不再空耗 7 天计时器)。复核修复:时刻库合并改「双时刻整替/残缺行只填不删」防丢时刻、每板每日抓取硬上限落地(≤2次/日)、库文件原子写+坏库先备份、推送渠道非 200 显式标 ERR、周报全失败 6h 退避防 45 分钟风暴、非杭州线路跳过班期抓取
- [x] **v0.19 跨日班期时刻补全**: 班期板无日期参数(官网页面无日期选择,?date= 与路径段探测均无效,按日期回填否决)→改跨日借用:日历价已证明航班号当日执飞,board_lookup_x 先精确星期再跨星期借用同号时刻(优先双时刻条目),「跨日班期·参考」徽标;仅有起飞时新增落地估算 arr_est(大圆+滑行,~ 前缀+虚线样式,不写入 arr_time 防混源);时刻仍纯展示不影响提醒。新增 9 项单测(42+8 全绿),dump_dom 改同步等待版防半写
- [x] **v0.20 真 PWA + 时刻库透明度**: 新增 tools/gen_icons.py(PIL 渐变底+纸飞机,可复现)产出 512/192/180/32 与 maskable 图标,manifest 补 PNG(iOS apple-touch-icon 不支持 SVG 的空白主屏图标修复);sw.js 离线壳(/static 缓存优先、?v= 版本 busted;/api GET 网络优先+缓存兜底);/api/sched-stats + 数据源页七天沉淀进度 widget(回答「为什么这天没时刻」);周报推送无渠道时自动跳转推送页并高亮输入框。新增 2 项单测(44+8 全绿)
- [ ] **M4-M5**: 洞察周报/插件生态(见 docs/迭代路线图.md)
- [x] **v0.21 时刻覆盖仪表 + 自启 + selftest 隔离**: snapshot 每线路写入 time_coverage(起飞/落地时刻 精确/借用/估算/缺失 四档统计,剔除邻近日参考价),数据源页新增「本轮时刻覆盖体检」分组条形图,时刻质量从黑盒变仪表;mcp_server 支持 FAREALERT_HOME 环境变量,selftest 改临时目录副本运行(修复并发验收假 FAIL,真实 config.json 零触碰+校验);tools/install_autostart.ps1 一条命令装开机自启(HKCU Run 键,免管理员,8765 已监听自动跳过,-Uninstall 卸载,-Mode task 备选计划任务);周报页无推送渠道时「立即推送」按钮直接禁用并提示,不再点了才报错。新增 5 项单测(49+8 全绿)
- [x] **v0.22 经停友好时刻借用 + 按字段来源 + 推送修复**: board_lookup_x 城市匹配改四层分级(双城>仅出发侧=经停>仅到达侧>拒绝),经停航班(杭州→克拉玛依经停郑州类)不再被整体误杀,跨 dow 借用只认双城/经停两档;FlightDeal 拆出 dep_src/arr_src 独立字段,「起飞精确+落地借用」混合态可表达,前端徽章按段显示;测试推送重复告警去重+test-push 标记;autostart wrapper 读 config webui.port 不再写死 8765。新增 4 项单测(53+8 全绿)
- [x] **v0.23 趋势图重画 + 全站去装饰渐变**: 趋势主线从 AI 感靛紫统一为品牌蓝并加 7% 面积填充,新增顶部图例行(低于价位/高于价位/含税总价/30日均价/插值估算),最低价标签改绿色胶囊,点位色收敛为绿/灰两档,悬停点统一品牌蓝;全站清理 20 处装饰性渐变(品牌名渐变字/按钮/日历格/角标/城市海报底色改纯色),仅保留功能性纹理与遮罩。视觉对齐 Skyscanner 式克制风格。
- [x] **v0.24 沉淀进度 ETA + 周报推送三步引导**: 时刻库沉淀进度 widget 增加「预计全覆盖日期」推算(按当前星期推算剩余 dow 的入库日期,覆盖 N/7 天·预计 M/D 全覆盖,每个 dow 悬停可见预计入库日);周报页推送引导从单条警示升级为按缺口动态生成的分步清单(无渠道/未启用两维检测,/api/weekly-report 新增 channel_ready 字段,一键跳转提醒推送页),修复用户 config 缺 weekly_enabled 键时周报静默不推且无引导的问题;CSS 引入 4 级间距变量(--sp-1~4),容器 1100→1160px、卡片/网格间距统一收口,版面呼吸感更接近开源旅行产品。
- [x] **v0.24.1 API v1 版本化别名**: 全部 /api/* 路由自动镜像为 /api/v1/*(同 endpoint 同方法,旧路径一等公民不受影响),为未来独立前端/原生 App 提供可钉住的稳定契约——前后端物理分离的「留缝」落地;新增 tests/test_api_v1.py 4 项契约测试(路由镜像完备性/v0-v1 响应等价/POST 方法保持/新字段),并修复测试文件直跑时项目根不在 sys.path 的问题。tools/probe_ota_times.py 留档本日时刻源勘探结论(去哪儿日历接口无起降时刻字段,思路关闭)。
- [x] **v0.25 同航线真实时长先验**: 落地时刻估算从「大圆圈几何模型」升级为「数据驱动」——萧山到达板每天 1600+ 行双时刻(前站起飞 preschtime + 落地 jhsj)沉淀出 83 城真实飞行时长中位数,直飞航线的 arr_est 与时长文本改用同航线实测值(重庆 140min/成都 155min/郑州 100min/曼谷 240min,几何模型普遍高估 10-30 分钟);国际前站城市名归一化(「曼谷素万那普机场」→「曼谷」)+ 前缀合并查询取最繁忙机场;经停航线保持几何+中转模型(先验只覆盖单段,不能映射多段)。tools/probe_dest_boards2.py 留档目的地机场勘探负结论(郑州 DNS 失败/重庆官网域名停放/成都 403,大陆目的地机场板数据源关闭),返程方向(落地杭州)时刻可由萧山到达板精确命中,开启往返线路即自然生效。
- [x] **v0.26 无号日历价参考班次 + Docker 部署修复**: Amadeus 日历价无航班号的日期(曼谷 48/50)按城市+星期从萧山板库补「当日参考班次」chips(exact/cross-dow 标记, 只展示不触发提醒); Docker start.sh 补 --loop 修复调度假死, 端口统一 8765; 顶栏新增「提醒未配置」健康徽标直达推送页。全套 43+9 单测全绿。
- [x] **v0.26.1 参考班次补挂修复**: nearby-ref 日期在 enrich 之后才补齐导致挂载点失效, 新增幂等 _attach_alt_times 在 fill 后补挂(只挂去程), 曼谷 48/50 日期获得起飞时刻参考; 同轮修复测试归位/徽标实时刷新/start.sh 优雅关停。全套 43+11 单测全绿。
- [x] **v0.27 覆盖率合并口径 + 部署可观测**: KPI 覆盖大数字改精确+参考合并口径(副文案拆分); /api/health 一站式健康端点(快照新鲜度/板库沉淀/推送就绪, 供外部 uptime 监控轮询); 顶栏更新时间带绿/黄/红新鲜度状态色。
- [x] **v0.32 落地时刻精确化 + v2 默认入口**: 出发板 nextschtime 提取为精确落地时刻(经停存 via 元数据)+ 离线回填 backfill_from_cache + 快照再富化工具 reenrich_times.py, 双时刻条目 3253→6075(重庆真实落地 22/39, 此前全 0); / 根路径 302 至 /v2/, 经典版转 /classic 维护模式; Docker HEALTHCHECK。85 单测全绿。(v0.28–v0.31 设计令牌/web 前端工程/三波 tab 迁移详见 docs/迭代路线图.md)
- [x] **v0.33 中转/经停透明化 + CI 前端门禁**: 联程票首段到达+中转城市、经停票经停站+到达时刻从板库透传至日详情时间线(「中转 武汉 · 08:55 到」), 四线 81 天获得说明, 估算落地不再是无解释的孤数; ci.yml 新增 frontend job(npm ci+build+git diff --exit-code, dist 与提交强制同步)。87 单测全绿。
- [x] **v0.34 部署工业化: worker 自启 + 心跳可观测**: 「时刻显示不全」的机制根因=抓取循环无人拉起、班期 dow 覆盖停在手动运行那两天。autostart_worker.ps1 单实例守卫 + install_autostart.ps1 升级双组件(-Components webui,worker); main.py 每轮写心跳、/api/health 暴露 worker 存活年龄; 无时刻文案按换季/联程段细化原因。92 单测全绿。
- [x] **v0.35 调度心跳面板化 + 板库 API 勘探归档**: v2 数据源页新增「调度心跳」卡——/api/health 的 worker 状态(运行中脉冲/心跳过期/未启动三态 + 最近轮次成败与分钟年龄)从命令行知识变成面板可视化, 未启动时直接给出 autostart_worker.ps1 启动指引; tools/probe_hbh_date.py 归档板库 API 勘探负结论(无 date 参数, keywords 仅航班号, 只服务当天 → dow 覆盖唯一路径=worker 每日积累, v0.34 自启方向实证正确)。92 单测 + ui_check(新增 v0.35 断言) 全绿。
- [x] **v0.36 UI 质感专项: 排版放大 + 趋势图重做**: 「不够高级」的根因之一=字号系统偏小(正文 13px/KPI 数字 22px)。v2 专属排版令牌层(--fs-body2/title2/hero2/kpi2, 正文 14/标题 16/Hero 28/KPI 30) + 趋势图重做(Catmull-Rom 平滑曲线、去掉 60 个噪声点只留信息点、最低价绿色胶囊标签、周末淡色底带、心理价位文案标签、悬浮卡片阴影升级) + tab 导航改分段控制器 + Hero 去 emoji(无照片显示城市首字、纸飞机换 SVG)。92 单测 + ui_check(新增 v0.36 断言) 全绿。
- [x] **v0.37 agent 自主验收闭环: verify_release MCP 工具**: 多 agent 协作的最后一块拼图——子 agent 改完代码可自助跑验收链, 不再依赖主 agent 手工转述。新增 MCP 工具 verify_release(steps=unittest/ui_check/build/health, 默认 unittest+ui_check+health), 返回结构化 {all_ok, steps:[{step,ok,seconds,tail}]}; health 步骤读 config 探活 /api/health 并给 worker 三态语义(alive/stale/none)。mcp_selftest 扩到 10 项(含真实 tools/call verify_release), 新增 5 个全 mock 单测, 全套 97 全绿。
- [x] **v0.38 部署硬化: worker 每日自愈机制**: 「起飞时间显示不全」的机制根因=自启只在登录时触发, 桌面数周不重登则 worker 死后无人拉活, dow 覆盖冻结(实测 2/7)。双层自愈: ① webui 进程内守护线程(每日 07:00 窗口探测 main.py --loop, 缺失则拉起; 纯 Python 跨平台, 不依赖任务计划权限——本机 Register-ScheduledTask 实测拒绝非提权会话); ② install_autostart.ps1 尽力注册每日计划任务(允许的宿主生效, 拒绝则告警不失败)。/api/health 暴露 revive 双层状态(supervisor+task), v2 数据源页心跳卡新增自愈状态行。106 单测 + ui_check(v0.38 断言) 全绿。
## 常见问题
- **机票起降时刻从哪来?** 去哪儿低价日历只返回每日最低价+航班号(列表页需签名,按合规原则不破解)。v0.18 起杭州相关线路自动用机场官网公开班期板按「航班号+星期几」沉淀计划时刻(零密钥);v0.19 起目标星期未沉淀时自动借用同号航班其他班期时刻(跨日班期·参考),仅有起飞时落地按大圆估算(~ 前缀);配置 Amadeus 后优先实时刻。车次时刻/历时来自 12306, 原生即有。
- **为什么按"总价"而不是裸价判定?** 你下单付的就是裸价+机建+燃油,以最终支付口径对比心理价位才有意义。
- **和 OTA 券后价有偏差?** 日历接口是挂牌价,不含平台券;偏差通常几十元内,收到提醒后点进下单页看券后实付即可。
- **学生票准吗?** 12306 查询接口不区分学生价,这里按 动车二等座75折/硬座5折/硬卧=卧铺-硬座半价 估算(略偏低),优惠区间/资格以下单页为准。
- **推送没收到?** 先在 Web UI 点"发送测试推送";Bark 确认 Key 正确、通知权限开启;Windows 计划任务看"日志"页排查。
## 开发与验收
每轮改动(无论人还是 AI)都必须走同一条验收流水线,全绿才算完成:
```powershell
python tools/acceptance.py
```
- 门禁覆盖 G0 静态检查 / G1 单测 / G2 API 契约 / G3 DOM 断言 / G4-G6 红线(提醒、隐私、估算价)。
- 人机协作守则见 [AGENTS.md](AGENTS.md),逐条门禁定义见 [docs/验收规范.md](docs/验收规范.md),里程碑与 DoD 见 [docs/迭代路线图.md](docs/迭代路线图.md),API 契约见 [docs/API.md](docs/API.md)。
本仓库已接入 CI(push/PR 自动跑验收),本地全绿 + CI 全绿才可合入。
## 免责声明
本项目仅聚合公开接口数据做个人出行比价提醒,不保证价格实时准确,不构成购票建议;购票请以航司/12306/平台下单页为准。请遵守各数据源服务条款,合理控制查询频率。
## License
[MIT](LICENSE) © FareAlert contributors
This server cannot be deployed
Maintenance
ActivityMaintained
ResponsivenessNo issues