feat: implement scan terminal service with AI-powered city analysis and caching support
This commit is contained in:
@@ -155,7 +155,7 @@ function AiPinnedCityCard({
|
||||
const { aiForecast, refreshAiForecast } = useAiCityForecast({
|
||||
detail,
|
||||
detailCityName,
|
||||
enabled: Boolean(detail && !collapsed),
|
||||
enabled: Boolean(detail),
|
||||
isEn,
|
||||
locale,
|
||||
report,
|
||||
@@ -163,7 +163,7 @@ function AiPinnedCityCard({
|
||||
const { marketScan, marketStatus } = useCityMarketScan({
|
||||
detail,
|
||||
detailCityName,
|
||||
enabled: Boolean(detail && !collapsed),
|
||||
enabled: Boolean(detail),
|
||||
});
|
||||
|
||||
const aiCityForecast = aiForecast.payload?.city_forecast || null;
|
||||
@@ -572,7 +572,6 @@ export function AiPinnedForecastView({
|
||||
items.forEach((item) => {
|
||||
const stableKey = normalizeCityKey(item.cityName) || item.cityName;
|
||||
if (!knownCityKeysRef.current.has(stableKey)) {
|
||||
next.add(stableKey);
|
||||
changed = true;
|
||||
}
|
||||
});
|
||||
|
||||
@@ -82,6 +82,16 @@ function writeCachedPayload<T>(key: string, payload: T) {
|
||||
}
|
||||
}
|
||||
|
||||
function removeCachedPayload(key: string) {
|
||||
const storage = getStorage();
|
||||
if (!storage) return;
|
||||
try {
|
||||
storage.removeItem(key);
|
||||
} catch {
|
||||
// Ignore privacy-mode failures; the next network request can still proceed.
|
||||
}
|
||||
}
|
||||
|
||||
function parseAiCityStreamBlock(block: string): AiCityStreamEvent | null {
|
||||
const eventLines = block
|
||||
.split(/\r?\n/)
|
||||
@@ -369,10 +379,17 @@ export function useAiCityForecast({
|
||||
)
|
||||
: null;
|
||||
if (cachedPayload) {
|
||||
setAiForecast({ payload: cachedPayload, status: "ready" });
|
||||
return () => {
|
||||
cancelled = true;
|
||||
};
|
||||
if (
|
||||
cachedPayload.status === "ready" &&
|
||||
!cachedPayload.degraded &&
|
||||
cachedPayload.city_forecast
|
||||
) {
|
||||
setAiForecast({ payload: cachedPayload, status: "ready" });
|
||||
return () => {
|
||||
cancelled = true;
|
||||
};
|
||||
}
|
||||
removeCachedPayload(cacheKey);
|
||||
}
|
||||
const initialFallback = buildAiCityFallbackPayload({ detail, isEn, report });
|
||||
setAiForecast({
|
||||
|
||||
Reference in New Issue
Block a user