顶栏天气组件策略与实现说明
这篇文档记录顶栏天气组件的产品策略、实现思路和排障方式。
当前组件不是服务端天气组件,也不是显示服务器所在地天气。它在浏览器端运行,通过高德 JSAPI 尝试识别访问者所在城市,再查询该城市天气。
目标策略
天气组件采用三层策略:
- 页面加 载后,优先通过高德 IP 定位识别访问者城市。
- 如果 IP 定位失败,或者 IP 定位得到的数据无法继续查询天气,则显示默认城市成都。
- 如果当前展示的是默认城市,用户点击天气组件时再请求浏览器地理位置权限;授权成功后切换到浏览器精确位置对应的天气。
如果一开始 IP 定位已经成功,用户点击组件只展开天气详情,不再请求浏览器地理位置。
这样做的原因是:
- IP 定位不需要用户授权,适合静默初始化。
- IP 定位可能失败,不能让组件因此消失。
- 浏览器地理位置权限比较敏感,只有用户主动点击组件后才请求。
- 默认城市能保证组件在公网、代理、海外网络、机房出口等场景下仍然可见。
默认城市配置为:
城市:成都市
adcode:510100
初始化流程
组件初始化时执行下面的流程:
加载高德 JSAPI
-> 加载 AMap.CitySearch 和 AMap.Weather 插件
-> 调用 CitySearch.getLocalCity()
-> 如果获得 city 或 province,使用 adcode/city 查询天气
-> 如果失败,使用成都市 510100 查询天气
-> 成功后渲染顶栏按钮并写入 sessionStorage 缓存
IP 定位成功时,天气数据会标记为:
source: ip
默认城市兜底成功时,天气数据会标记为:
source: default
这个 source 字段是后续点击策略的关键。组件通过它判断用户点击时是否需要请求浏览器地理位置。
点击流程
用户点击天气组件时,组件始终会先切换详情面板的展开状态。
随后根据当前天气来源决定是否请求浏览器定位:
source: ip:说明已经通过 IP 识别到用户城市,只展开详情,不请求权限。source: browser:说明已经通过浏览器定位更新过,只展开详情,不重复请求权限。source: default:说明当前只是成都兜底天气,首次点击时请求浏览器定位。
浏览器定位流程:
navigator.geolocation.getCurrentPosition()
-> 获取 WGS84/GPS 经纬度
-> 调用 AMap.convertFrom(..., 'gps') 转换为高德可用坐标
-> 加载 AMap.Geocoder
-> 调用 geocoder.getAddress() 反查城市和 adcode
-> 使用 adcode 查询实时天气和天气预报
-> 更新组件并刷新 sessionStorage 缓存
浏览器定位成功后,天气数据会标记为:
source: browser
如果用户拒绝权限、浏览器不支持定位、定位超时、逆地理编码失败,组件不会报错给用户,也不会隐藏。它会继续展示成都兜底天气。
为什么不能只依赖 IP 定位
IP 定位只能识别公网出口 IP,不等于用户真实 GPS 位置。
下面这些网络环境经常导致 IP 定位失败或不准:
- 校园网、公司网、酒店网络等统一出口
- 手机流量运营商 NAT 出口
- VPN、代理、加速器
- 海外网络或跨境出口
- 云服务器、机房、CDN 或远程浏览器环境
- 高德 IP 库暂未收录的地址段
线上排查时曾看到高德 IP 接口返回:
{
"status": "1",
"info": "OK",
"infocode": "10000",
"province": [],
"city": [],
"adcode": [],
"rectangle": []
}
这类响应代表请求本身成功,但没有可用城市数据。旧逻辑会因为拿不到城市而隐藏组件;新逻辑会回退到成都天气。
缓存策略
组件使用 sessionStorage 缓存天气数据:
key: navbar-weather-v2
ttl: 30 分钟
缓存目标是减少同一次浏览会话内重复请求高德接口。
缓存内容包括:
- 城市名
- adcode
- 省份
- 实时天气
- 温度
- 湿度
- 风向风力
- 预报列表
- 数据来源
source - 报告时间
缓存过期或解析失败时会被忽略,不影响组件重新请求。
高德 JSAPI 依赖
组件依赖的高德插件包括:
AMap.CitySearch:用于 IP 定位。AMap.Weather:用于实时天气和天气预报。AMap.Geocoder:用于浏览器定位后的逆地理编码。
高德鉴权配置来自 Docusaurus customFields.amap:
customFields: {
amap: {
key,
serviceHost,
securityJsCode,
},
}
组件只有在存在 key,且存在 serviceHost 或 securityJsCode 时才会尝试加载高德 JSAPI。
组件隐藏条件
当前组件仍然会在这些情况下隐藏:
- 移动端 navbar item 渲染路径传入
mobile。 - 缺少高德 JSAPI key 或安全配置。
- 高德 JSAPI 无法加载,且没有可用缓存。
- 成都兜底天气也查询失败,且没有可用缓存。
- CSS 媒体查询命中
max-width: 996px。
除此之外,单纯 IP 定位失败不再导致组件隐藏。