系统设置
天气数据源、固定地点订阅策略、系统字典与维护操作
运行参数
只读展示;如需修改请编辑 .env 后重启| 参数 | 当前值 |
|---|---|
| 默认时区 | Asia/Shanghai |
| 默认数据源 | open-meteo |
| 预报抓取天数 | 7 天 |
| 预报自动获取时刻 | 04:00 |
| 实际天气回补时刻 | 00:30(抓取前一天) |
| 数据库 | sqlite:///C:/Jacklee/PAIOS/db/climate/climate.db |
| 天气 API 密钥 | 未配置(当前数据源免密钥) |
| 降级数据源 | 已启用(外部 API 失败时自动切换,保证网站可用) |
安全约定:密钥只从环境变量读取,绝不写入源码、模板、JavaScript 或数据库。 数据库中只保存环境变量名(如 WEATHER_API_KEY)。
维护操作
手动触发抓取、回补与统计重算初始化操作全部是幂等的:执行一次和执行十次不会产生重复数据。 生产环境的结构变更请使用 flask db migrate / flask db upgrade,绝不通过删除数据库重建来解决。
天气数据源(Provider Adapter)
业务代码只调用统一接口,更换服务商无需重写系统| 数据源 | 显示名 | 优先级 | 预报 | 实际天气 | 降级源 | 密钥环境变量 | 启用 | 配置 |
|---|---|---|---|---|---|---|---|---|
| open-meteo | Open-Meteo(免密钥,推荐) | 1 | ✔ | ✔ | — | — | 已启用 | |
| 免费且无需注册密钥,提供 16 天预报与历史实际天气。 | ||||||||
| simulated | 离线模拟数据源 | 9 | ✔ | ✔ | ✔ | — | 已启用 | |
| 无网络环境下的降级数据源,同时供自动化测试使用,保证网站永不因外部 API 失败而不可用。 | ||||||||
固定地点自动获取配置
默认每天 04:00 自动抓取;失败重试间隔 0 / 10 / 30 / 60 分钟固定地点信息
| 地点 | 类型 | 经纬度 | 时区 | 启用 / 名称 / 保存 |
|---|---|---|---|---|
| 山东省枣庄市山亭区 | fixed | 35.1003000, 117.4559000 | Asia/Shanghai | |
| 浙江省杭州市西湖区 | fixed | 30.2596000, 120.1300000 | Asia/Shanghai | |
| 北京市海淀区 | fixed | 39.9593000, 116.2981000 | Asia/Shanghai |
系统字典
衣物类别、天气类型、活动类型等全部数据驱动,模板中不硬编码
activity_type · 8clothing_category · 9clothing_status · 4clothing_subcategory · 34feel · 5indoor_outdoor · 3purchase_reason · 8trip_status · 4trip_type · 3weather_type · 14
| 字典类型 | 编码 | 显示名 | 父级 | 排序 | 启用 | 系统内置 |
|---|---|---|---|---|---|---|
| activity_type | study | 学习 | — | 10 | ✔ | ✔ |
| activity_type | work | 工作 | — | 20 | ✔ | ✔ |
| activity_type | walk | 步行/散步 | — | 30 | ✔ | ✔ |
| activity_type | sport | 运动 | — | 40 | ✔ | ✔ |
| activity_type | commute | 通勤 | — | 50 | ✔ | ✔ |
| activity_type | travel | 旅行 | — | 60 | ✔ | ✔ |
| activity_type | indoor | 居家 | — | 70 | ✔ | ✔ |
| activity_type | other | 其他 | — | 80 | ✔ | ✔ |
| clothing_category | 上身 | 上身 | — | 10 | ✔ | ✔ |
| clothing_category | 下身 | 下身 | — | 20 | ✔ | ✔ |
| clothing_category | 鞋 | 鞋 | — | 30 | ✔ | ✔ |
| clothing_category | 脚部 | 脚部 | — | 35 | ✔ | ✔ |
| clothing_category | 头部 | 头部 | — | 40 | ✔ | ✔ |
| clothing_category | 颈部 | 颈部 | — | 50 | ✔ | ✔ |
| clothing_category | 手部 | 手部 | — | 60 | ✔ | ✔ |
| clothing_category | 眼部 | 眼部 | — | 70 | ✔ | ✔ |
| clothing_category | 其他 | 其他 | — | 80 | ✔ | ✔ |
| clothing_status | active | 在用 | — | 10 | ✔ | ✔ |
| clothing_status | idle | 闲置 | — | 20 | ✔ | ✔ |
| clothing_status | damaged | 损坏 | — | 30 | ✔ | ✔ |
| clothing_status | archived | 淘汰 | — | 40 | ✔ | ✔ |
| clothing_subcategory | T恤 | T恤 | 上身 | 10 | ✔ | ✔ |
| clothing_subcategory | 牛仔裤 | 牛仔裤 | 下身 | 10 | ✔ | ✔ |
| clothing_subcategory | 运动鞋 | 运动鞋 | 鞋 | 10 | ✔ | ✔ |
| clothing_subcategory | 帽子 | 帽子 | 头部 | 10 | ✔ | ✔ |
| clothing_subcategory | 围巾 | 围巾 | 颈部 | 10 | ✔ | ✔ |
| clothing_subcategory | 手套 | 手套 | 手部 | 10 | ✔ | ✔ |
| clothing_subcategory | 太阳镜 | 太阳镜 | 眼部 | 10 | ✔ | ✔ |
| clothing_subcategory | 雨伞 | 雨伞 | 其他 | 10 | ✔ | ✔ |
| clothing_subcategory | 袜子 | 袜子 | 脚部 | 10 | ✔ | ✔ |
| clothing_subcategory | 长袖 | 长袖 | 上身 | 20 | ✔ | ✔ |
| clothing_subcategory | 休闲裤 | 休闲裤 | 下身 | 20 | ✔ | ✔ |
| clothing_subcategory | 皮鞋 | 皮鞋 | 鞋 | 20 | ✔ | ✔ |
| clothing_subcategory | 衬衫 | 衬衫 | 上身 | 30 | ✔ | ✔ |
| clothing_subcategory | 运动裤 | 运动裤 | 下身 | 30 | ✔ | ✔ |
| clothing_subcategory | 靴子 | 靴子 | 鞋 | 30 | ✔ | ✔ |
| clothing_subcategory | 卫衣 | 卫衣 | 上身 | 40 | ✔ | ✔ |
| clothing_subcategory | 短裤 | 短裤 | 下身 | 40 | ✔ | ✔ |
| clothing_subcategory | 凉鞋 | 凉鞋 | 鞋 | 40 | ✔ | ✔ |
| clothing_subcategory | 毛衣 | 毛衣 | 上身 | 50 | ✔ | ✔ |
| clothing_subcategory | 保暖裤 | 保暖裤 | 下身 | 50 | ✔ | ✔ |
| clothing_subcategory | 拖鞋 | 拖鞋 | 鞋 | 50 | ✔ | ✔ |
| clothing_subcategory | 薄外套 | 薄外套 | 上身 | 60 | ✔ | ✔ |
| clothing_subcategory | 裙子 | 裙子 | 下身 | 60 | ✖ | ✔ |
| clothing_subcategory | 棉拖鞋 | 棉拖鞋 | 鞋 | 60 | ✔ | ✔ |
| clothing_subcategory | 厚外套 | 厚外套 | 上身 | 70 | ✔ | ✔ |
| clothing_subcategory | 西裤 | 西裤 | 下身 | 70 | ✔ | ✔ |
| clothing_subcategory | 羽绒服 | 羽绒服 | 上身 | 80 | ✔ | ✔ |
| clothing_subcategory | 秋裤 | 秋裤 | 下身 | 80 | ✔ | ✔ |
| clothing_subcategory | 棉服 | 棉服 | 上身 | 90 | ✔ | ✔ |
| clothing_subcategory | 风衣 | 风衣 | 上身 | 100 | ✔ | ✔ |
| clothing_subcategory | 背心 | 背心 | 上身 | 110 | ✔ | ✔ |
| clothing_subcategory | 马褂 | 马褂 | 上身 | 120 | ✔ | ✔ |
| clothing_subcategory | 西服 | 西服 | 上身 | 130 | ✔ | ✔ |
| clothing_subcategory | 秋衣 | 秋衣 | 上身 | 140 | ✔ | ✔ |
| feel | 很冷 | 很冷 | — | 10 | ✔ | ✔ |
| feel | 偏冷 | 偏冷 | — | 20 | ✔ | ✔ |
| feel | 合适 | 合适 | — | 30 | ✔ | ✔ |
| feel | 偏热 | 偏热 | — | 40 | ✔ | ✔ |
| feel | 很热 | 很热 | — | 50 | ✔ | ✔ |
| indoor_outdoor | indoor | 室内 | — | 10 | ✔ | ✔ |
| indoor_outdoor | outdoor | 室外 | — | 20 | ✔ | ✔ |
| indoor_outdoor | mixed | 室内外混合 | — | 30 | ✔ | ✔ |
| purchase_reason | 衣柜缺口 | 衣柜缺口 | — | 10 | ✔ | ✔ |
| purchase_reason | 数量不足 | 数量不足 | — | 20 | ✔ | ✔ |
| purchase_reason | 使用频率过高 | 使用频率过高 | — | 30 | ✔ | ✔ |
| purchase_reason | 磨损替换 | 磨损替换 | — | 40 | ✔ | ✔ |
| purchase_reason | 季节需求 | 季节需求 | — | 50 | ✔ | ✔ |
| purchase_reason | 旅行需求 | 旅行需求 | — | 60 | ✔ | ✔ |
| purchase_reason | 主动添置 | 主动添置 | — | 70 | ✔ | ✔ |
| purchase_reason | 其他 | 其他 | — | 80 | ✔ | ✔ |
| trip_status | planned | 计划中 | — | 10 | ✔ | ✔ |
| trip_status | ongoing | 进行中 | — | 20 | ✔ | ✔ |
| trip_status | completed | 已结束 | — | 30 | ✔ | ✔ |
| trip_status | cancelled | 已取消 | — | 40 | ✔ | ✔ |
| trip_type | travel | 旅游 | — | 10 | ✔ | ✔ |
| trip_type | business | 出差 | — | 20 | ✔ | ✔ |
| trip_type | other | 其他 | — | 30 | ✔ | ✔ |
| weather_type | 晴 | 晴 | — | 10 | ✔ | ✔ |
| weather_type | 多云 | 多云 | — | 20 | ✔ | ✔ |
| weather_type | 阴 | 阴 | — | 30 | ✔ | ✔ |
| weather_type | 小雨 | 小雨 | — | 40 | ✔ | ✔ |
| weather_type | 中雨 | 中雨 | — | 50 | ✔ | ✔ |
| weather_type | 大雨 | 大雨 | — | 60 | ✔ | ✔ |
| weather_type | 暴雨 | 暴雨 | — | 70 | ✔ | ✔ |
| weather_type | 雷阵雨 | 雷阵雨 | — | 80 | ✔ | ✔ |
| weather_type | 小雪 | 小雪 | — | 90 | ✔ | ✔ |
| weather_type | 中雪 | 中雪 | — | 100 | ✔ | ✔ |
| weather_type | 大雪 | 大雪 | — | 110 | ✔ | ✔ |
| weather_type | 雨夹雪 | 雨夹雪 | — | 120 | ✔ | ✔ |
| weather_type | 雾 | 雾 | — | 130 | ✔ | ✔ |
| weather_type | 霾 | 霾 | — | 140 | ✔ | ✔ |
定时任务部署说明
Windows 环境推荐使用任务计划程序- 推荐方式:Windows 任务计划程序每天 04:00 执行 python -m app.tasks.weather_tasks,工作目录设为项目根目录。
- 实际天气回补:每天 00:30 执行 python -m app.tasks.weather_tasks --actual。
- 行李计划:每天 06:00 执行 python -m app.tasks.weather_tasks --packing。
- 手动测试:python -m app.tasks.weather_tasks --now。
- 查看订阅状态:python -m app.tasks.weather_tasks --check。
- 也可在 .env 中设置 SCHEDULER_ENABLED=true 使用进程内 APScheduler (已处理 Flask debug reloader 重复执行问题)。
- 单个城市失败不会影响其它城市;全部失败才返回非零退出码,便于任务计划程序告警。