Files
blog/js/weather.js
T
biss d0ea62809e 优化移动端侧边栏
··[CST 2026-04-25 Saturday 13:47:24]
2026-04-25 13:47:24 +08:00

205 lines
6.2 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
// weather.js
(function () {
const WEATHER_ID = "aside-weather";
const LOCATION_WAIT_MS = 3000;
const LOCATION_POLL_INTERVAL_MS = 100;
const WEATHER_KEY = "70201debab4245379e376d116b05f8a2";
const WEATHER_HOST = "https://ny5vxmbbkd.re.qweatherapi.com";
const WEATHER_LANG = "zh";
function debugLog(label, payload) {
console.log(`[weather.js] ${label}`, payload);
}
function maskSecret(secret) {
if (!secret || secret.length < 10) return secret;
return `${secret.slice(0, 4)}***${secret.slice(-4)}`;
}
function readExistingLocation() {
return window.ipLocation?.result?.location || null;
}
function waitForExistingLocation(timeout = LOCATION_WAIT_MS) {
return new Promise((resolve, reject) => {
const existingLocation = readExistingLocation();
if (existingLocation) {
resolve(existingLocation);
return;
}
const startTime = Date.now();
const timer = window.setInterval(() => {
const location = readExistingLocation();
if (location) {
window.clearInterval(timer);
resolve(location);
return;
}
if (Date.now() - startTime >= timeout) {
window.clearInterval(timer);
reject(new Error("等待 ipLocation 超时"));
}
}, LOCATION_POLL_INTERVAL_MS);
});
}
function requestLocationFallback() {
return new Promise((resolve, reject) => {
if (!window.$?.ajax) {
reject(new Error("jQuery 未加载,无法执行定位兜底请求"));
return;
}
$.ajax({
type: 'get',
url: 'https://apis.map.qq.com/ws/location/v1/ip',
data: {
key: '你的key',
output: 'jsonp',
callback: '?',
},
dataType: 'jsonp',
success: function (res) {
debugLog("定位兜底返回", res);
if (res && res.status === 0 && res.result?.location) {
window.ipLocation = res;
resolve(res.result.location);
} else {
reject(new Error("定位失败"));
}
},
error: function () {
reject(new Error("定位请求失败"));
}
});
});
}
function getLocation() {
return waitForExistingLocation()
.then(location => {
debugLog("使用 txmap.js 定位", location);
return location;
})
.catch(error => {
debugLog("等待 txmap.js 定位失败,转兜底请求", error);
return requestLocationFallback();
});
}
function getWeather(lng, lat) {
const location = `${lng.toFixed(2)},${lat.toFixed(2)}`;
const params = new URLSearchParams({
location,
lang: WEATHER_LANG,
key: WEATHER_KEY
});
const requestUrl = `${WEATHER_HOST}/v7/weather/now?${params.toString()}`;
debugLog("天气请求参数", {
host: WEATHER_HOST,
location,
lang: WEATHER_LANG,
key: maskSecret(WEATHER_KEY)
});
return fetch(requestUrl, {
headers: {
Accept: "application/json"
}
}).then(async res => {
const responseText = await res.text();
let data;
try {
data = JSON.parse(responseText);
} catch (parseError) {
debugLog("天气接口返回非 JSON", {
status: res.status,
statusText: res.statusText,
body: responseText
});
throw new Error(`天气接口返回非 JSONHTTP ${res.status}`);
}
debugLog("天气接口响应", {
status: res.status,
statusText: res.statusText,
body: data
});
if (!res.ok) {
const detail = data?.error?.detail || data?.msg || `HTTP ${res.status}`;
throw new Error(`天气接口请求失败:${detail}`);
}
return data;
});
}
function renderWeather(data) {
const el = document.getElementById(WEATHER_ID);
if (!el) return;
if (data.code !== "200") {
debugLog("天气接口业务错误", data);
el.innerHTML = `天气获取失败:${data.code || "未知错误"}`;
return;
}
const now = data.now;
const emojiMap = {
"晴": "☀️",
"多云": "⛅",
"阴": "☁️",
"雨": "🌧️",
"雪": "❄️",
"雷": "⛈️"
};
const emoji = emojiMap[now.text] || "🌡️";
const weatherSentence = `当前天气${now.text},气温${now.temp}℃,体感${now.feelsLike}℃,${now.windDir}${now.windScale}级,湿度${now.humidity}%,能见度${now.vis}km。`;
el.innerHTML = `
<div class="aside-weather-card">
<div class="weather-top">
</div>
<div class="weather-info">
${weatherSentence}
</div>
</div>
`;
}
function initWeather() {
const el = document.getElementById(WEATHER_ID);
if (!el) return;
el.innerHTML = "🌥️ 获取天气中...";
getLocation()
.then(loc => getWeather(loc.lng, loc.lat))
.then(renderWeather)
.catch(err => {
console.error("[weather.js] 天气加载失败", err);
el.innerHTML = `🌧️ 天气加载失败:${err.message || "未知错误"}`;
});
}
// 🚀 初次加载
window.addEventListener("load", initWeather);
// 🔄 pjax
document.addEventListener("pjax:complete", initWeather);
})();