优化移动端侧边栏

··[CST 2026-04-25 Saturday 13:47:24]
This commit is contained in:
biss
2026-04-25 13:47:24 +08:00
commit d0ea62809e
134 changed files with 71002 additions and 0 deletions
+204
View File
@@ -0,0 +1,204 @@
// 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);
})();