mirror of
https://github.com/imsyy/home.git
synced 2025-05-19 20:50:14 +09:00
天气模块修改
>> ·[FIX]以韩小韩API替代失效的教书先生API >> ·[ADD]添加腾讯位置服务支持,以解决高德接口次数不足以及不支持 IPV6 的问题 >> ·[ADD]修改天气模块策略,在一个接口失效时切换另一个接口 >> ·[FIX]修复天气模块中的错误,处理气温平均数时自动删除多余符号单位,处理分量时先判断是否携带级字再考虑添加
This commit is contained in:
parent
74c7558d91
commit
5ae2d86855
21
.env.example
21
.env.example
@ -22,12 +22,13 @@ VITE_DESC_TEXT_OTHER = "哎呀,这都被你发现了( 再点击一次可关
|
||||
## 网站链接的图标名称可前往 https://www.xicons.org 自行挑选并在 src/components/Links/index.vue 中引入
|
||||
|
||||
# 天气 Key
|
||||
## 请前往 高德开放平台注册 Web服务 Key
|
||||
## 请注意不是 Web端 (JS API),免费申请,每日上限 5000 次
|
||||
## 此处提供的服务可能会超量从而无法访问,请自行申请!请自行申请!请自行申请!
|
||||
## 若此处设为空则调用 教书先生 API https://api.oioweb.cn/doc/weather/GetWeather (已失效)
|
||||
## 备注:如需使用天气,请自行获取 token 。几乎所有的天气api都需要token,并且限制频率或收费。
|
||||
VITE_WEATHER_KEY = ""
|
||||
## 请前往 腾讯位置服务 [https://lbs.qq.com/] 或 高德开放平台 [https://lbs.amap.com/] 注册并获得 Web 服务端(WebServiceAPI) Key
|
||||
## 请注意不是 Web端 (JS API),免费申请。腾讯每日上限 10000 次,高德每日上限 5000 次。
|
||||
## 目前首推腾讯位置服务,因为高德的 API 不支持 IPV6,需要付费找客服额外开通高级版本,在有 IPV6 的网络环境会出现 IP 定位异常。
|
||||
## 可以同时填写两个服务的 Key,若一个服务无法访问则会自动切换到另一个服务。
|
||||
## 若此处设为空则调用 韩小韩 API 与 教书先生 API,此处提供的服务可能会超量从而无法访问,请自行申请!请自行申请!请自行申请!
|
||||
VITE_TX_WEATHER_KEY = "" # 腾讯位置服务 Key
|
||||
VITE_GD_WEATHER_KEY = "" # 高德开放平台 Key
|
||||
|
||||
# 建站日期
|
||||
## 若不需要,请设为空即可
|
||||
@ -58,3 +59,11 @@ VITE_SONG_ID = "9379831714"
|
||||
VITE_TTS_API = ""
|
||||
VITE_TTS_Voice = "zh-CN-YunxiaNeural"
|
||||
VITE_TTS_Style = "cheerful"
|
||||
|
||||
# 鉴权参数
|
||||
## 这是一些用于鉴权用的 Key,正常只有 VITE_TX_WEATHER_SKEY 有效。其它高级功能如需使用请自行配置功能!
|
||||
## 腾讯位置服务鉴权 SKEY 是签名校验 KEY,不强制要求。如需使用,可在控制台生成密钥并填写在这里,填写将启用鉴权模式。
|
||||
VITE_TX_WEATHER_SKEY = "" # 腾讯位置服务鉴权SKEY
|
||||
VITE_TTS_SKEY = "" # 文字转语音鉴权 SKEY (自行配置)
|
||||
VITE_METING_SKEY = "" # METING API 鉴权 SKEY (自行配置)
|
||||
VITE_SFILE_SKEY = "" # 特殊文件 API 鉴权 SKEY (自行配置)
|
||||
|
25
package.json
25
package.json
@ -7,7 +7,7 @@
|
||||
"home": "https://imsyy.top",
|
||||
"efuh": "https://nanorocky.top",
|
||||
"private": true,
|
||||
"version": "4.2.1 [EFU]",
|
||||
"version": "4.2.2 [EFU]",
|
||||
"type": "module",
|
||||
"scripts": {
|
||||
"dev": "vite --host",
|
||||
@ -24,12 +24,13 @@
|
||||
"element-plus": "^2.9.7",
|
||||
"fetch-jsonp": "^1.3.0",
|
||||
"jparticles": "^3.5.0",
|
||||
"js-md5": "^0.8.3",
|
||||
"lodash-es": "^4.17.21",
|
||||
"pinia": "^3.0.1",
|
||||
"pinia-plugin-persistedstate": "^4.2.0",
|
||||
"pinia-plugin-persistedstate-2": "^2.0.29",
|
||||
"pinia-plugin-persistedstate-2": "^2.0.30",
|
||||
"swiper": "^11.2.6",
|
||||
"three": "^0.174.0",
|
||||
"three": "^0.175.0",
|
||||
"vue": "^3.5.13",
|
||||
"vuex": "^4.1.0"
|
||||
},
|
||||
@ -42,16 +43,17 @@
|
||||
"@vicons/tabler": "^0.13.0",
|
||||
"@vicons/utils": "^0.1.4",
|
||||
"@vitejs/plugin-vue": "^5.2.3",
|
||||
"eslint": "^9.22.0",
|
||||
"eslint-plugin-vue": "^9.33.0",
|
||||
"eslint": "^9.23.0",
|
||||
"eslint-plugin-vue": "^10.0.0",
|
||||
"vue-eslint-parser": "^10.1.1",
|
||||
"prettier": "^3.5.3",
|
||||
"sass": "^1.86.0",
|
||||
"sass": "^1.86.2",
|
||||
"terser": "^5.39.0",
|
||||
"unplugin-auto-import": "^19.1.1",
|
||||
"unplugin-auto-import": "^19.1.2",
|
||||
"unplugin-vue-components": "^28.4.1",
|
||||
"vite": "^6.2.2",
|
||||
"vite": "^6.2.5",
|
||||
"vite-plugin-compression2": "^1.3.3",
|
||||
"vite-plugin-pwa": "^0.21.1"
|
||||
"vite-plugin-pwa": "^1.0.0"
|
||||
},
|
||||
"pnpm": {
|
||||
"overrides": {
|
||||
@ -59,6 +61,9 @@
|
||||
"@jridgewell/sourcemap-codec": "^1.5.0",
|
||||
"magic-string": "^0.30.17",
|
||||
"workbox-build": "^7.3.0"
|
||||
}
|
||||
},
|
||||
"ignoredBuiltDependencies": [
|
||||
"esbuild"
|
||||
]
|
||||
}
|
||||
}
|
905
pnpm-lock.yaml
generated
905
pnpm-lock.yaml
generated
File diff suppressed because it is too large
Load Diff
117
src/api/index.js
117
src/api/index.js
@ -1,5 +1,28 @@
|
||||
// import axios from "axios";
|
||||
import fetchJsonp from "fetch-jsonp";
|
||||
import { gwg } from "@/utils/authServer";
|
||||
|
||||
/**
|
||||
* JSONP 请求模块
|
||||
*/
|
||||
// JSONP 请求函数,并返回 JSON 【关于为什么要有这个呢...请腾讯自觉扫一下(x)】
|
||||
const loadJSONP = (url, callbackName) => {
|
||||
return new Promise((resolve, reject) => {
|
||||
// 定义 JSONP 回调函数
|
||||
window[callbackName] = (data) => {
|
||||
resolve(data); // 解析 JSON 数据
|
||||
delete window[callbackName]; // 清理全局变量,防止污染
|
||||
};
|
||||
// 创建 script 标签
|
||||
const script = document.createElement('script');
|
||||
script.src = url;
|
||||
script.onerror = () => {
|
||||
reject(new Error('JSONP 请求失败'));
|
||||
delete window[callbackName]; // 出错时也要清理
|
||||
};
|
||||
document.body.appendChild(script);
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* 音乐播放器
|
||||
@ -52,18 +75,72 @@ export const getHitokoto = async () => {
|
||||
/**
|
||||
* 天气
|
||||
*/
|
||||
// 获取腾讯地理位置信息(JSONP 方式)
|
||||
export const getTXAdcode = async (key) => {
|
||||
const callback = `jsonpCallback_${Date.now()}_${Math.floor(Math.random() * 100000)}`;
|
||||
const url = `https://apis.map.qq.com/ws/location/v1/ip?key=${key}&output=jsonp&callback=${callback}`;
|
||||
return await loadJSONP(url, callback);
|
||||
};
|
||||
|
||||
// 获取腾讯地理天气信息(JSONP 方式)
|
||||
export const getTXWeather = async (key, adcode) => {
|
||||
const callback = `jsonpCallback_${Date.now()}_${Math.floor(Math.random() * 100000)}`;
|
||||
const url = `https://apis.map.qq.com/ws/weather/v1/?key=${key}&adcode=${adcode}&type=now&output=jsonp&callback=${callback}`;
|
||||
return await loadJSONP(url, callback);
|
||||
};
|
||||
|
||||
// 获取腾讯地理位置信息(鉴权模式 JSONP 方式)
|
||||
export const getTXAdcodeS = async (key, skey) => {
|
||||
const callback = `jsonpCallback_${Date.now()}_${Math.floor(Math.random() * 100000)}`;
|
||||
const url = `https://apis.map.qq.com/ws/location/v1/ip?key=${key}&output=jsonp&callback=${callback}`;
|
||||
const urls = await gwg(url, skey);
|
||||
return await loadJSONP(urls, callback);
|
||||
};
|
||||
|
||||
// 获取腾讯地理天气信息(鉴权模式 JSONP 方式)
|
||||
export const getTXWeatherS = async (key, adcode, skey) => {
|
||||
const callback = `jsonpCallback_${Date.now()}_${Math.floor(Math.random() * 100000)}`;
|
||||
const url = `https://apis.map.qq.com/ws/weather/v1/?key=${key}&adcode=${adcode}&type=now&output=jsonp&callback=${callback}`;
|
||||
const urls = await gwg(url, skey);
|
||||
return await loadJSONP(urls, callback);
|
||||
};
|
||||
|
||||
|
||||
// 获取高德地理位置信息
|
||||
export const getAdcode = async (key) => {
|
||||
export const getGDAdcode = async (key) => {
|
||||
const res = await fetch(`https://restapi.amap.com/v3/ip?key=${key}`);
|
||||
return await res.json();
|
||||
};
|
||||
|
||||
// 获取高德地理位置信息(带IP)
|
||||
export const getGDAdcodeI = async (ipv4, key) => {
|
||||
const res = await fetch(`https://restapi.amap.com/v3/ip?ip=${ipv4}&key=${key}`);
|
||||
return await res.json();
|
||||
};
|
||||
|
||||
// 获取高德地理天气信息
|
||||
export const getWeather = async (key, city) => {
|
||||
const res = await fetch(
|
||||
`https://restapi.amap.com/v3/weather/weatherInfo?key=${key}&city=${city}`,
|
||||
);
|
||||
export const getGDWeather = async (key, city) => {
|
||||
const res = await fetch(`https://restapi.amap.com/v3/weather/weatherInfo?key=${key}&city=${city}`);
|
||||
return await res.json();
|
||||
};
|
||||
|
||||
// 补充的获取 IPV4 地址的 API
|
||||
export const getIPV4Addr = async () => {
|
||||
const res = await fetch(`https://api4.ipify.org?format=json`);
|
||||
return await res.json();
|
||||
};
|
||||
|
||||
// 补充的获取 IPV6 地址的 API
|
||||
export const getIPV6Addr = async () => {
|
||||
const res = await fetch(`https://api6.ipify.org?format=json`);
|
||||
return await res.json();
|
||||
};
|
||||
|
||||
// 免 KEY 区域
|
||||
// 强烈建议自己注册腾讯或高德的 API
|
||||
// 获取韩小韩天气 API
|
||||
export const getHXHWeather = async () => {
|
||||
const res = await fetch("https://api.vvhan.com/api/weather");
|
||||
return await res.json();
|
||||
};
|
||||
|
||||
@ -74,27 +151,9 @@ export const getOtherWeather = async () => {
|
||||
return await res.json();
|
||||
};
|
||||
|
||||
|
||||
// 这是一个待完善的新免 token 天气模块
|
||||
|
||||
// // 获取位置信息
|
||||
// export const getLocation = async () => {
|
||||
// const res = await fetch("http://inip.in/ip.json");
|
||||
// return await res.json();
|
||||
// };
|
||||
|
||||
// // 转换城市 ID
|
||||
// export const getCityId = async (city) => {
|
||||
// const res = await fetch(
|
||||
// `https://api.songzixian.com/api/china-city?dataSource=LOCAL_CHINA_CITY&district=${city}`,
|
||||
// );
|
||||
// return await res.json();
|
||||
// };
|
||||
|
||||
// // 获取小米天气 API
|
||||
// export const getOtherWeather = async () => {
|
||||
// const res = await fetch(
|
||||
// `https://weatherapi.market.xiaomi.com/wtr-v3/weather/all?latitude=0&longitude=0&isLocated=true&locationKey=weathercn%3A${city}&days=2&appKey=weather20151024&sign=zUFJoAR2ZVrDy1vF3D07&locale=zh_cn&alpha=false&isGlobal=false`,
|
||||
// );
|
||||
// return await res.json();
|
||||
// };
|
||||
// 获取小米天气 API
|
||||
// 这个接口或许会比上面两个稳的多,但是它需要自己定位并转换 Adcode ...
|
||||
export const getXMWeather = async () => {
|
||||
const res = await fetch(`https://weatherapi.market.xiaomi.com/wtr-v3/weather/all?latitude=0&longitude=0&isLocated=true&locationKey=weathercn%3A${city}&days=2&appKey=weather20151024&sign=zUFJoAR2ZVrDy1vF3D07&locale=zh_cn&alpha=false&isGlobal=false`);
|
||||
return await res.json();
|
||||
};
|
||||
|
@ -10,7 +10,9 @@
|
||||
: weatherData.weather.winddirection + "风"
|
||||
}}
|
||||
</span>
|
||||
<span class="sm-hidden">{{ weatherData.weather.windpower }} 级</span>
|
||||
<span class="sm-hidden">{{ weatherData.weather.windpower?.endsWith("级")
|
||||
? weatherData.weather.windpower
|
||||
: weatherData.weather.windpower + "级" }} </span>
|
||||
</div>
|
||||
<div class="weather" v-else>
|
||||
<span>天气数据获取失败</span>
|
||||
@ -18,14 +20,16 @@
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { getAdcode, getWeather, getOtherWeather } from "@/api";
|
||||
import { getTXAdcode, getTXWeather, getTXAdcodeS, getTXWeatherS, getGDAdcode, getGDAdcodeI, getGDWeather, getIPV4Addr, getIPV6Addr, getOtherWeather, getHXHWeather, getXMWeather } from "@/api";
|
||||
import { Error } from "@icon-park/vue-next";
|
||||
import { mainStore } from "@/store";
|
||||
import { Speech, stopSpeech, SpeechLocal } from "@/utils/speech";
|
||||
const store = mainStore();
|
||||
|
||||
// 高德开发者 Key
|
||||
const mainKey = import.meta.env.VITE_WEATHER_KEY;
|
||||
// 加载密钥
|
||||
const txkey = import.meta.env.VITE_TX_WEATHER_KEY; // 腾讯天气密钥
|
||||
const txskey = import.meta.env.VITE_TX_WEATHER_SKEY; // 选择性对腾讯天气接口加密
|
||||
const gdkey = import.meta.env.VITE_GD_WEATHER_KEY; // 高德天气密钥
|
||||
|
||||
// 天气数据
|
||||
const weatherData = reactive({
|
||||
@ -44,8 +48,12 @@ const weatherData = reactive({
|
||||
// 取出天气平均值
|
||||
const getTemperature = (min, max) => {
|
||||
try {
|
||||
// 计算平均值并四舍五入
|
||||
const average = (Number(min) + Number(max)) / 2;
|
||||
const cleanMin = parseFloat(min.toString().replace(/[^\d.-]/g, ""));
|
||||
const cleanMax = parseFloat(max.toString().replace(/[^\d.-]/g, ""));
|
||||
if (isNaN(cleanMin) || isNaN(cleanMax)) {
|
||||
throw new Error("无法解析温度数据");
|
||||
};
|
||||
const average = (cleanMin + cleanMax) / 2;
|
||||
return Math.round(average);
|
||||
} catch (error) {
|
||||
console.error("计算温度出现错误:", error);
|
||||
@ -59,30 +67,12 @@ const getTemperature = (min, max) => {
|
||||
}
|
||||
};
|
||||
|
||||
// 获取天气数据
|
||||
const getWeatherData = async () => {
|
||||
try {
|
||||
// 获取地理位置信息
|
||||
if (!mainKey) {
|
||||
console.log("未配置,使用备用天气接口");
|
||||
const result = await getOtherWeather();
|
||||
console.log(result);
|
||||
const data = result.result;
|
||||
weatherData.adCode = {
|
||||
city: data.city.City || "未知地区",
|
||||
// adcode: data.city.cityId,
|
||||
};
|
||||
weatherData.weather = {
|
||||
weather: data.condition.day_weather,
|
||||
temperature: getTemperature(data.condition.min_degree, data.condition.max_degree),
|
||||
winddirection: data.condition.day_wind_direction,
|
||||
windpower: data.condition.day_wind_power,
|
||||
};
|
||||
} else {
|
||||
const getTXW = async () => {
|
||||
if (!txskey) {
|
||||
console.log("正在使用腾讯天气接口");
|
||||
// 获取 Adcode
|
||||
const adCode = await getAdcode(mainKey);
|
||||
console.log(adCode);
|
||||
if (adCode.infocode !== "10000") {
|
||||
const adCode = await getTXAdcode(txkey);
|
||||
if (String(adCode.status) !== "0") {
|
||||
if (store.webSpeech) {
|
||||
stopSpeech();
|
||||
const voice = import.meta.env.VITE_TTS_Voice;
|
||||
@ -90,20 +80,215 @@ const getWeatherData = async () => {
|
||||
SpeechLocal("位置信息获取失败.mp3");
|
||||
};
|
||||
throw "地区查询失败";
|
||||
}
|
||||
};
|
||||
weatherData.adCode = {
|
||||
city: adCode.city,
|
||||
adcode: adCode.adcode,
|
||||
city: adCode.result.ad_info.district || adCode.result.ad_info.city || adCode.result.ad_info.province || "未知地区",
|
||||
adcode: adCode.result.ad_info.adcode,
|
||||
};
|
||||
// 获取天气信息
|
||||
const result = await getWeather(mainKey, weatherData.adCode.adcode);
|
||||
const txWeather = await getTXWeather(txkey, weatherData.adCode.adcode);
|
||||
if (String(txWeather.status) !== "0") {
|
||||
if (store.webSpeech) {
|
||||
stopSpeech();
|
||||
const voice = import.meta.env.VITE_TTS_Voice;
|
||||
const vstyle = import.meta.env.VITE_TTS_Style;
|
||||
SpeechLocal("天气加载失败.mp3");
|
||||
};
|
||||
throw "天气信息获取失败";
|
||||
};
|
||||
const realtimeData = txWeather.result.realtime?.[0];
|
||||
if (!realtimeData?.infos) {
|
||||
if (store.webSpeech) {
|
||||
stopSpeech();
|
||||
const voice = import.meta.env.VITE_TTS_Voice;
|
||||
const vstyle = import.meta.env.VITE_TTS_Style;
|
||||
SpeechLocal("天气加载失败.mp3");
|
||||
};
|
||||
throw "天气信息获取失败";
|
||||
};
|
||||
weatherData.weather = {
|
||||
weather: realtimeData.infos.weather,
|
||||
temperature: realtimeData.infos.temperature,
|
||||
winddirection: realtimeData.infos.wind_direction,
|
||||
windpower: realtimeData.infos.wind_power,
|
||||
};
|
||||
} else {
|
||||
console.log("正在使用腾讯天气接口,鉴权模式已启用");
|
||||
// 获取 Adcode
|
||||
const adCode = await getTXAdcodeS(txkey, txskey);
|
||||
if (String(adCode?.status) !== "0") {
|
||||
if (store.webSpeech) {
|
||||
stopSpeech();
|
||||
const voice = import.meta.env.VITE_TTS_Voice;
|
||||
const vstyle = import.meta.env.VITE_TTS_Style;
|
||||
SpeechLocal("位置信息获取失败.mp3");
|
||||
};
|
||||
throw "地区查询失败";
|
||||
};
|
||||
weatherData.adCode = {
|
||||
city: adCode.result.ad_info.district || adCode.result.ad_info.city || adCode.result.ad_info.province || "未知地区",
|
||||
adcode: adCode.result.ad_info.adcode,
|
||||
};
|
||||
// 获取天气信息
|
||||
const txWeather = await getTXWeatherS(txkey, weatherData.adCode.adcode, txskey);
|
||||
if (String(txWeather.status) !== "0") {
|
||||
if (store.webSpeech) {
|
||||
stopSpeech();
|
||||
const voice = import.meta.env.VITE_TTS_Voice;
|
||||
const vstyle = import.meta.env.VITE_TTS_Style;
|
||||
SpeechLocal("天气加载失败.mp3");
|
||||
};
|
||||
throw "天气信息获取失败";
|
||||
};
|
||||
const realtimeData = txWeather.result.realtime?.[0];
|
||||
if (!realtimeData?.infos) {
|
||||
if (store.webSpeech) {
|
||||
stopSpeech();
|
||||
const voice = import.meta.env.VITE_TTS_Voice;
|
||||
const vstyle = import.meta.env.VITE_TTS_Style;
|
||||
SpeechLocal("天气加载失败.mp3");
|
||||
};
|
||||
throw "天气信息获取失败";
|
||||
};
|
||||
weatherData.weather = {
|
||||
weather: realtimeData.infos.weather,
|
||||
temperature: realtimeData.infos.temperature,
|
||||
winddirection: realtimeData.infos.wind_direction,
|
||||
windpower: realtimeData.infos.wind_power,
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
const getGDW = async () => {
|
||||
// 获取 Adcode
|
||||
const adCode = await getGDAdcode(gdkey);
|
||||
let adCodei = null;
|
||||
if (String(adCode?.infocode) !== "10000" || String(adCode?.status) !== "1") {
|
||||
console.log("检测到高德接口 IP 获取失败,调用额外接口获取 IPV4 地址...");
|
||||
const ipV4addr = await getIPV4Addr();
|
||||
adCodei = await getGDAdcodeI(ipV4addr.ip, gdkey);
|
||||
if (String(adCodei?.infocode) !== "10000" || String(adCodei?.status) !== "1") {
|
||||
if (store.webSpeech) {
|
||||
stopSpeech();
|
||||
const voice = import.meta.env.VITE_TTS_Voice;
|
||||
const vstyle = import.meta.env.VITE_TTS_Style;
|
||||
SpeechLocal("位置信息获取失败.mp3");
|
||||
};
|
||||
throw "地区查询失败";
|
||||
};
|
||||
};
|
||||
if (!adCodei) {
|
||||
weatherData.adCode = {
|
||||
city: adCode.city || adCode.province || "未知地区",
|
||||
adcode: adCode.adcode,
|
||||
};
|
||||
} else {
|
||||
weatherData.adCode = {
|
||||
city: adCodei.city || adCodei.province || "未知地区",
|
||||
adcode: adCodei.adcode,
|
||||
};
|
||||
};
|
||||
// 获取天气信息
|
||||
const result = await getGDWeather(gdkey, weatherData.adCode.adcode);
|
||||
if (String(result?.status) !== "1" || String(result?.infocode) !== "10000") {
|
||||
if (store.webSpeech) {
|
||||
stopSpeech();
|
||||
const voice = import.meta.env.VITE_TTS_Voice;
|
||||
const vstyle = import.meta.env.VITE_TTS_Style;
|
||||
SpeechLocal("天气加载失败.mp3");
|
||||
};
|
||||
throw "天气信息获取失败";
|
||||
};
|
||||
weatherData.weather = {
|
||||
weather: result.lives[0].weather,
|
||||
temperature: result.lives[0].temperature,
|
||||
winddirection: result.lives[0].winddirection,
|
||||
windpower: result.lives[0].windpower,
|
||||
};
|
||||
}
|
||||
};
|
||||
|
||||
const getOW = async () => {
|
||||
const result = await getOtherWeather();
|
||||
const data = result.result;
|
||||
weatherData.adCode = {
|
||||
city: data.city.City || "未知地区",
|
||||
};
|
||||
weatherData.weather = {
|
||||
weather: data.condition.day_weather,
|
||||
temperature: getTemperature(data.condition.min_degree, data.condition.max_degree),
|
||||
winddirection: data.condition.day_wind_direction,
|
||||
windpower: data.condition.day_wind_power,
|
||||
};
|
||||
};
|
||||
|
||||
const getHXHW = async () => {
|
||||
const result = await getHXHWeather();
|
||||
if (String(result?.success) !== "true") {
|
||||
if (store.webSpeech) {
|
||||
stopSpeech();
|
||||
const voice = import.meta.env.VITE_TTS_Voice;
|
||||
const vstyle = import.meta.env.VITE_TTS_Style;
|
||||
SpeechLocal("天气加载失败.mp3");
|
||||
};
|
||||
throw "天气信息获取失败";
|
||||
};
|
||||
weatherData.adCode = {
|
||||
city: result.city || "未知地区",
|
||||
};
|
||||
weatherData.weather = {
|
||||
weather: result.data.type || result.data.night.type,
|
||||
temperature: getTemperature(result.data.low || result.data.night.low, result.data.high || result.data.night.high),
|
||||
winddirection: result.data.fengxiang || result.data.night.fengxiang,
|
||||
windpower: result.data.fengli || result.data.night.fengli,
|
||||
};
|
||||
};
|
||||
|
||||
const getXMW = async () => {
|
||||
// 待补()
|
||||
};
|
||||
|
||||
// 获取天气数据
|
||||
const getWeatherData = async () => {
|
||||
try {
|
||||
// 获取地理位置信息
|
||||
if (!gdkey && !txkey) {
|
||||
console.log("未配置天气接口密钥,使用备用天气接口");
|
||||
try {
|
||||
await getHXHW();
|
||||
} catch (error) {
|
||||
await getOW();
|
||||
};
|
||||
} else if (!txkey) {
|
||||
// 调用高德天气 API
|
||||
console.log("正在使用高德天气接口");
|
||||
try {
|
||||
await getGDW();
|
||||
} catch (error) {
|
||||
console.error("高德天气接口获取失败,尝试调用备用接口");
|
||||
try {
|
||||
await getHXHW();
|
||||
} catch (error) {
|
||||
await getOW();
|
||||
};
|
||||
};
|
||||
} else {
|
||||
// 调用腾讯天气 API
|
||||
try {
|
||||
await getTXW();
|
||||
} catch (error) {
|
||||
console.error("腾讯天气接口获取失败,尝试使用高德天气接口");
|
||||
try {
|
||||
await getGDW();
|
||||
} catch (error) {
|
||||
console.error("高德天气接口获取失败,尝试调用备用接口");
|
||||
try {
|
||||
await getHXHW();
|
||||
} catch (error) {
|
||||
await getOW();
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
} catch (error) {
|
||||
console.error("天气信息获取失败:" + error);
|
||||
onError("天气信息获取失败");
|
||||
@ -113,7 +298,7 @@ const getWeatherData = async () => {
|
||||
const vstyle = import.meta.env.VITE_TTS_Style;
|
||||
SpeechLocal("天气加载失败.mp3");
|
||||
};
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
// 报错信息
|
||||
|
71
src/utils/authServer.js
Normal file
71
src/utils/authServer.js
Normal file
@ -0,0 +1,71 @@
|
||||
/**
|
||||
* authServer
|
||||
* Made by NanoRocky
|
||||
* 这个模块除了腾讯地图的签名认证外,其余函数并不对其他人有任何鸟用(大概叭)
|
||||
* 涉及到接口加密的东西怎么能不整点代码混淆,对叭对叭~(x)
|
||||
* 该说不说写点答辩还挺有意思嘟(bushi)
|
||||
*/
|
||||
|
||||
|
||||
import { md5 as d } from "js-md5";
|
||||
|
||||
let x = null, y = null;
|
||||
const f = () => Math.floor(Date.now() / 1000);
|
||||
const o = (v) => v.toString(16);
|
||||
|
||||
async function gst() {
|
||||
if (!x) {
|
||||
try {
|
||||
const { timestamp: t } = await (await fetch("https://nanorocky.top/time/")).json();
|
||||
x = t;
|
||||
y = f();
|
||||
} catch (error) {
|
||||
x = y = f();
|
||||
};
|
||||
};
|
||||
return x + (f() - y);
|
||||
};
|
||||
|
||||
export async function gwp(u, s, b) {
|
||||
// 备注:POST 方法需要传入 body !
|
||||
const { origin: ul, pathname: p } = new URL(u);
|
||||
return `${ul}${p}?sig=${d(`${p}?${Object.keys(b).sort().map(key => `${key}=${JSON.stringify(b[key])}`).join("&")}${s}`).toLowerCase()}`;
|
||||
};
|
||||
|
||||
|
||||
export async function gwg(u, s) {
|
||||
const { origin: ul, pathname: p } = new URL(u), q = new URLSearchParams(new URL(u).search);
|
||||
q.set("sig", d(`${p}?${[...q.entries()].sort(([a], [b]) => a.localeCompare(b)).map(([key, value]) => `${key}=${value}`).join("&")}${s}`).toLowerCase());
|
||||
return `${ul}${p}?${q.toString()}`;
|
||||
};
|
||||
|
||||
export async function gasA(p, s) {
|
||||
const t = await gst(), r = Math.random().toString(36).substring(2, 12);
|
||||
return [t, r, "0", d(`${p}-${t}-${r}-0-${s}`)].join("-");
|
||||
};
|
||||
|
||||
export async function gasB(u, s) {
|
||||
const { origin: ul, pathname: p } = new URL(u);
|
||||
const t = new Date((await gst()) * 1000 + 8 * 3600 * 1000).toISOString().replace(/[-T:]|(\..*)/g, "").substring(0, 12);
|
||||
return `${ul}/${t}/${d(`${s}${t}/${p}`)}/${p}`;
|
||||
};
|
||||
|
||||
export async function gasC(u, s) {
|
||||
const { origin: ul, pathname: p } = new URL(u);
|
||||
const t = o((await gst()));
|
||||
return `${ul}/${d(`${s}/${p}${t}`)}/${t}/${p}`;
|
||||
};
|
||||
|
||||
export async function gasDH(u, s) {
|
||||
const ul = new URL(u), p = ul.pathname, t = await gst();
|
||||
ul.searchParams.set("sign", d(`${s}/${p}${t}`));
|
||||
ul.searchParams.set("t", t);
|
||||
return ul.toString();
|
||||
};
|
||||
|
||||
export async function gasDI(u, s) {
|
||||
const ul = new URL(u), p = ul.pathname, t = o(await gst());
|
||||
ul.searchParams.set("sign", d(`${s}/${p}${t}`));
|
||||
ul.searchParams.set("t", t);
|
||||
return ul.toString();
|
||||
};
|
Loading…
Reference in New Issue
Block a user