323 lines
13 KiB
JavaScript
Raw Permalink 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.

/**
* 基础参数说明:
* @plugin 全局插件行动 - 策略模式
* @plugin .default 行动默认数据
* @plugin _willAppear 在 willAppear 方法之后立即执行
* @plugin _willDisappear 在 willDisappear 方法之前立即执行
* @common sendToPlugin keyUp propertyInspectorDidAppear
* =========================================================================>
*/
window.QWEATHER_API_KEY = 'bdd98ec1d87747f3a2e8b1741a5af796';
window.WEATHERAPI_COM_API_KEY = 'c4aeca457d9e4a36a9982404252804';
const $local = false,
$plugin = {
name: "weather",
action1: new Action({
default: {
inputCity: "", // 输入框
tempList: "0", //
cityId: "",
city: "",
title: "",
radio: "0",
radio2: "0",
radioUseApi: window.WeatherApiEnum.qweather,
searchList: [],
theme: "Modern",
wdata: { tmp: "20", code: "101" , name: '', img: '', cityName: ''},
titleParameters: {
titleColor: "#ffffff",
},
count: 0,
Localization: {}
},
/**
* 1. 和风开发者KEY: 641403ded7f348bf88681308e648bdde
* 2. 和风官方地理位置KEY: bdd98ec1d87747f3a2e8b1741a5af796
* 3. 和风官方网页查询数据: https://www.qweather.com/v2/current/condition/s/x-cityId.html
*/
async queryLocation(context, device) {
console.log("queryLocation");
const data = this.data[context];
const langMap = {
'zh_CN': 'zh', 'en': 'en', 'ja': 'ja', 'fr': 'fr',
'it': 'it', 'ru': 'ru', 'es': 'es', 'pt': 'pt', 'de': 'de'
};
const lang = langMap[$lang] || 'en';
const weatherService = window.WeatherServiceFactory.createWeatherService(data.radioUseApi); // 获取天气服务实例
try {
if (data.inputCity) {
// console.log("inputCity");
$websocket.setTitle(context, "Loading");
const [error, locationList] = await weatherService.queryLocation(data.inputCity, lang);
if (error) {
console.error("queryLocation failed:", error);
data.searchList = [];
this.canvasFunc(context, device, "error");
$websocket.setSettings(context, data);
} else if (locationList && locationList.length > 0) {
// **需要根据不同服务商的返回数据结构进行适配**
// 和风天气返回的是一个包含城市信息的数组 (res.data.location)
// WeatherAPI.com 返回的也是一个数组 (res.data)
data.searchList = locationList;
this.queryWeather(context, device);
data.count = 0;
} else {
data.searchList = [];
this.canvasFunc(context, device, "404");
$websocket.setSettings(context, data);
}
}
} catch (e) {
console.error("queryLocation general error:", e);
if (++data.count <= 3) {
this.queryLocation(context, device);
$websocket.setTitle(context, "Try again");
return;
}
this.canvasFunc(context, device, "error");
}
},
async queryWeather(context, device) {
const data = this.data[context];
const weatherService = window.WeatherServiceFactory.createWeatherService(data.radioUseApi); // 获取天气服务实例
const langMap = {
'zh_CN': 'zh', 'en': 'en', 'ja': 'ja', 'fr': 'fr',
'it': 'it', 'ru': 'ru', 'es': 'es', 'pt': 'pt', 'de': 'de'
};
const lang = langMap[$lang] || 'en';
try {
clearTimeout(data.timer);
console.log(data,data.cityId, data.searchList)
// 过滤出用户选择的城市
data.cityId = (
data.searchList.filter((item) => item.id === data.cityId)[0] ||
data.searchList[0]
)?.id;
data.city = data.searchList.filter(
(item) => item.id === data.cityId
)[0]?.name;
if (data.cityId) {
$websocket.setTitle(context, "Loading");
const [error, weatherData] = await weatherService.queryWeather(data.cityId, lang);
if (error) {
console.error("queryWeather failed:", error);
this.canvasFunc(context, device, "error");
} else if (weatherData) {
// **需要根据不同服务商的返回数据结构进行适配**
let tmp, code, img, name, cityName;
if (weatherService instanceof window.QWeatherService) {
tmp = weatherData.tmp;
code = weatherData.code; // 需要查阅和风天气的 icon 对应关系
} else if (weatherService instanceof window.WeatherApiComService) {
tmp = weatherData.current.temp_c; // 或 temp_f根据需求
code = weatherData.current.condition.code; // 需要查阅 WeatherAPI.com 的 code 对应关系
img = 'https:' + weatherData.current.condition.icon;
name = weatherData.current.condition.text;
cityName = weatherData.location.name;
}
data.wdata = { tmp, code, img, name, cityName};
data.count = 0;
data.timer = setTimeout(
() => this.queryWeather(context, device),
1000 * 60 * 60 * 1
);
$websocket.setSettings(context, data);
this.canvasFunc(context, device);
} else {
this.canvasFunc(context, device, "error");
}
}
} catch (e) {
console.error("queryWeather general error:", e);
if (++data.count <= 3) {
this.queryWeather(context, device);
$websocket.setTitle(context, "Try again");
return;
}
this.canvasFunc(context, device, "error");
}
},
// 绘制
async canvasFunc(context, device, status = "success") {
if (status === "error") {
$websocket.setImage(
context,
this.data[context].isBackgroundHidden
? "../static/img/tm.png"
: "../static/img/default.jpg"
);
$websocket.setTitle(context, "Timeout");
return;
} else if (status === "404") {
$websocket.setImage(
context,
this.data[context].isBackgroundHidden
? "../static/img/tm.png"
: "../static/img/default.jpg"
);
$websocket.setTitle(context, "Not found");
return;
}
if (!this.data[context].cityId) return;
// 主题配置
const data = this.data[context];
const { tmp, code, img, name, cityName } = data.wdata;
// 摄氏度/华氏度
const unit = data.tempList === "0" ? "℃" : "℉";
const tmps = data.tempList === "0" ? tmp : tmp * 1.8 + 32;
// 设置gif背景
// if (data.theme == "dynamic") {
// $websocket.setImage(context,`${dynamicEnum[101]}`, true);
// $websocket.setTitle(
// context,
// data.radio == "0" ? `${Number(tmps).toFixed(1)}${unit}\n${data.city}` : `${Number(tmps).toFixed(1)}${unit}\n${data.title}`
// );
// return
// }
// console.log(this.data[context].radioUseApi, window.WeatherApiEnum, data.wdata);
const image = new Image();
switch(this.data[context].radioUseApi) {
case window.WeatherApiEnum.qweather:
if (data.theme == "Modern")
image.src = `../static/img/Modern/${code}-fill.svg`;
if (data.theme == "Luxury")
image.src = `../static/img/Luxury/${LuxuryEnum[code]}.png`;
break;
case window.WeatherApiEnum.weatherapi:
image.src = img
break;
default:
}
/* 加载完毕后开始 */
image.onload = async function () {
let canvas = document.createElement("canvas");
canvas.width = canvas.height = 512;
let ctx = canvas.getContext("2d");
// 是否隐藏背景 适配 296
// if (!data.isBackgroundHidden) {
ctx.fillStyle = "rgba(0,0,0,0)";
ctx.fillRect(0, 0, 512, 512);
ctx.save();
// }
if (data.theme == "Modern") ctx.drawImage(this, (512 - 260) / 2, 20, 260, 260);
if (data.theme == "Luxury") ctx.drawImage(this, -2, -2, 516, 516);
// ctx.fillStyle = data.titleParameters.titleColor;
// ctx.font = `${data.titleParameters.fontStyle == "Regular" ? "" : data.titleParameters.fontStyle} ${data.titleParameters.fontSize + 10}px '${data.titleParameters.fontFamily}'`;
// ctx.shadowColor = "white";
// ctx.shadowBlur = 1;
// ctx.shadowOffsetX = 1;
// ctx.shadowOffsetY = 1;
// ctx.fillText(`${Number(tmps).toFixed(1)}${unit}`, 14, 29);
// if (data.titleParameters.fontUnderline) {
// let textMetrics = ctx.measureText(`${Number(tmps).toFixed(1)}${unit}`);
// let underlineHeight = 1;
// ctx.fillRect(14, 29 + 2, textMetrics.width, underlineHeight);
// }
let weatherName;
switch(data.radioUseApi) {
case window.WeatherApiEnum.qweather:
weatherName = data.radio2 == "0" ? data.Localization[code == 154 ? 153 : code] + "\n" : '';
data.Localization[code == 154 ? 153 : code] + "\n"
$websocket.setTitle(
context,
weatherName + (data.radio == "0" ? `${Number(tmps).toFixed(1)}${unit}\n${data.city}` : `${Number(tmps).toFixed(1)}${unit}\n${data.title}`)
);
break;
case window.WeatherApiEnum.weatherapi:
weatherName = data.radio2 == "0" ? name + "\n" : '';
$websocket.setTitle(
context,
weatherName + (data.radio == "0" ? `${Number(tmps).toFixed(1)}${unit}\n${cityName}` : `${Number(tmps).toFixed(1)}${unit}\n${data.title}`),
);
break;
default:
}
// 国际化json文件里面没有154154与153是一样的夜间多云
$websocket.setImage(context, canvas.toDataURL("image/png"));
};
},
titleParametersDidChange({ context, payload, device }) {
this.data[context].titleParameters = payload.titleParameters;
this.canvasFunc(context, device);
},
didReceiveSettings({ context, payload, device }) {
this.data[context].isBackgroundHidden = payload.settings.isBackgroundHidden;
this.canvasFunc(context, device);
},
async _willAppear({ context, device, payload }) {
console.log("willAppear", payload);
this.data[context].Localization = await new Promise(resolve => {
const req = new XMLHttpRequest();
req.open('GET', `../${$lang}.json`);
req.send();
req.onreadystatechange = () => {
if (req.readyState === 4) {
resolve(JSON.parse(req.responseText).Localization)
}
};
})
const { radioUseApi } = payload.settings;
this.data[context].radioUseApi = radioUseApi !== undefined? window.WeatherApiEnum[radioUseApi]: window.WeatherApiEnum.qweather;
this.queryLocation(context, device);
},
_willDisappear({ context}) {
clearTimeout(this.data[context].timer);
},
sendToPlugin({ context, payload, device }) {
const data = this.data[context];
const { inputCity, cityId, title, theme, radio, radio2, tempList, radioUseApi } = payload;
// 切换提供商
if (radioUseApi !== undefined) {
data.radioUseApi = radioUseApi;
this.data[context].radioUseApi = window.WeatherApiEnum[radioUseApi];
this.data[context].count = 0;
return this.queryLocation(context, device);
}
// 输入城市
if (inputCity !== undefined) {
data.inputCity = inputCity;
this.data[context].count = 0;
return this.queryLocation(context, device);
}
// 更新天气
if (cityId !== undefined) {
data.cityId = cityId;
this.data[context].count = 0;
return this.queryWeather(context, device);
}
// 更新选项
if (title !== undefined) data.title = title;
if (theme !== undefined) data.theme = theme;
if (radio !== undefined) data.radio = radio;
if (radio2 !== undefined) data.radio2 = radio2;
if (tempList !== undefined) data.tempList = tempList;
this.canvasFunc(context, device);
},
keyUp({ context, device }) {
this.data[context].count = 0;
this.queryWeather(context, device);
},
}),
};