- 新增 Client/src/lib/amap.ts:高德 JS 定位封装 - weather.ts / useWeather.ts:带经纬度/城市请求,定位失败不兜底 - Server weather.rs:相应调整 - 文档同步;.gitignore 忽略本地 .codegraph 索引 Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
44 lines
1.3 KiB
TypeScript
44 lines
1.3 KiB
TypeScript
import { useEffect, useState } from 'react'
|
||
import { fetchWeather, type WeatherResult } from '../api/weather'
|
||
import { locate } from '../lib/amap'
|
||
|
||
export interface WeatherState {
|
||
loading: boolean
|
||
/** 后端返回的结果(含限流/未配置等业务态);网络错误时为 null */
|
||
data: WeatherResult | null
|
||
/** 网络层错误(后端不可达) */
|
||
error: boolean
|
||
}
|
||
|
||
/**
|
||
* 拉取天气。默认每 30 分钟刷新一次(后端有 10 分钟缓存与每日限流,
|
||
* 所以前端即便频繁挂载也不会浪费上游额度)。
|
||
*/
|
||
export function useWeather(intervalMs = 30 * 60 * 1000): WeatherState {
|
||
const [state, setState] = useState<WeatherState>({ loading: true, data: null, error: false })
|
||
|
||
useEffect(() => {
|
||
let cancelled = false
|
||
|
||
const load = async () => {
|
||
try {
|
||
// 先前端定位(未配 JS Key 或失败 → null,后端用 IP 兜底)。locate 不抛错。
|
||
const geo = await locate()
|
||
const data = await fetchWeather(geo ?? undefined)
|
||
if (!cancelled) setState({ loading: false, data, error: false })
|
||
} catch {
|
||
if (!cancelled) setState({ loading: false, data: null, error: true })
|
||
}
|
||
}
|
||
|
||
load()
|
||
const id = setInterval(load, intervalMs)
|
||
return () => {
|
||
cancelled = true
|
||
clearInterval(id)
|
||
}
|
||
}, [intervalMs])
|
||
|
||
return state
|
||
}
|