mirror of
https://github.com/Buriburizaem0n/nezha-dash-v1.git
synced 2026-05-06 13:58:43 +00:00
perf: use biome
This commit is contained in:
+16
-6
@@ -1,11 +1,21 @@
|
||||
export function formatBytes(bytes: number, decimals: number = 2) {
|
||||
if (!+bytes) return "0 Bytes"
|
||||
if (!+bytes) return "0 Bytes";
|
||||
|
||||
const k = 1024
|
||||
const dm = decimals < 0 ? 0 : decimals
|
||||
const sizes = ["Bytes", "KiB", "MiB", "GiB", "TiB", "PiB", "EiB", "ZiB", "YiB"]
|
||||
const k = 1024;
|
||||
const dm = decimals < 0 ? 0 : decimals;
|
||||
const sizes = [
|
||||
"Bytes",
|
||||
"KiB",
|
||||
"MiB",
|
||||
"GiB",
|
||||
"TiB",
|
||||
"PiB",
|
||||
"EiB",
|
||||
"ZiB",
|
||||
"YiB",
|
||||
];
|
||||
|
||||
const i = Math.floor(Math.log(bytes) / Math.log(k))
|
||||
const i = Math.floor(Math.log(bytes) / Math.log(k));
|
||||
|
||||
return `${parseFloat((bytes / Math.pow(k, i)).toFixed(dm))} ${sizes[i]}`
|
||||
return `${parseFloat((bytes / k ** i).toFixed(dm))} ${sizes[i]}`;
|
||||
}
|
||||
|
||||
File diff suppressed because one or more lines are too long
+207
-204
@@ -1,209 +1,212 @@
|
||||
export const countryCoordinates: Record<string, { lat: number; lng: number; name: string }> = {
|
||||
// 亚洲
|
||||
AF: { lat: 33.0, lng: 65.0, name: "Afghanistan" }, // 阿富汗
|
||||
AM: { lat: 40.0, lng: 45.0, name: "Armenia" }, // 亚美尼亚
|
||||
AZ: { lat: 40.5, lng: 47.5, name: "Azerbaijan" }, // 阿塞拜疆
|
||||
BD: { lat: 24.0, lng: 90.0, name: "Bangladesh" }, // 孟加拉国
|
||||
BH: { lat: 26.0, lng: 50.55, name: "Bahrain" }, // 巴林
|
||||
BT: { lat: 27.5, lng: 90.5, name: "Bhutan" }, // 不丹
|
||||
BN: { lat: 4.5, lng: 114.6667, name: "Brunei" }, // 文莱
|
||||
KH: { lat: 13.0, lng: 105.0, name: "Cambodia" }, // 柬埔寨
|
||||
CN: { lat: 35.0, lng: 105.0, name: "China" }, // 中国
|
||||
HK: { lat: 22.0, lng: 114.0, name: "Hong Kong" }, // 香港
|
||||
MO: { lat: 22.1667, lng: 113.55, name: "Macau" }, // 澳门
|
||||
CY: { lat: 35.0, lng: 33.0, name: "Cyprus" }, // 塞浦路斯
|
||||
GE: { lat: 42.0, lng: 43.5, name: "Georgia" }, // 格鲁吉亚
|
||||
IN: { lat: 20.0, lng: 77.0, name: "India" }, // 印度
|
||||
ID: { lat: -5.0, lng: 120.0, name: "Indonesia" }, // 印度尼西亚
|
||||
IR: { lat: 32.0, lng: 53.0, name: "Iran" }, // 伊朗
|
||||
IQ: { lat: 33.0, lng: 44.0, name: "Iraq" }, // 伊拉克
|
||||
IL: { lat: 31.5, lng: 34.75, name: "Israel" }, // 以色列
|
||||
JP: { lat: 36.0, lng: 138.0, name: "Japan" }, // 日本
|
||||
JO: { lat: 31.0, lng: 36.0, name: "Jordan" }, // 约旦
|
||||
KZ: { lat: 48.0, lng: 68.0, name: "Kazakhstan" }, // 哈萨克斯坦
|
||||
KW: { lat: 29.3375, lng: 47.6581, name: "Kuwait" }, // 科威特
|
||||
KG: { lat: 41.0, lng: 75.0, name: "Kyrgyzstan" }, // 吉尔吉斯斯坦
|
||||
LA: { lat: 18.0, lng: 105.0, name: "Laos" }, // 老挝
|
||||
LB: { lat: 33.8333, lng: 35.8333, name: "Lebanon" }, // 黎巴嫩
|
||||
MY: { lat: 2.5, lng: 112.5, name: "Malaysia" }, // 马来西亚
|
||||
MV: { lat: 3.25, lng: 73.0, name: "Maldives" }, // 马尔代夫
|
||||
MN: { lat: 46.0, lng: 105.0, name: "Mongolia" }, // 蒙古
|
||||
MM: { lat: 22.0, lng: 98.0, name: "Myanmar" }, // 缅甸
|
||||
NP: { lat: 28.0, lng: 84.0, name: "Nepal" }, // 尼泊尔
|
||||
OM: { lat: 21.0, lng: 57.0, name: "Oman" }, // 阿曼
|
||||
PK: { lat: 30.0, lng: 70.0, name: "Pakistan" }, // 巴基斯坦
|
||||
PH: { lat: 13.0, lng: 122.0, name: "Philippines" }, // 菲律宾
|
||||
QA: { lat: 25.5, lng: 51.25, name: "Qatar" }, // 卡塔尔
|
||||
SA: { lat: 25.0, lng: 45.0, name: "Saudi Arabia" }, // 沙特阿拉伯
|
||||
SG: { lat: 1.3667, lng: 103.8, name: "Singapore" }, // 新加坡
|
||||
KR: { lat: 37.0, lng: 127.5, name: "South Korea" }, // 韩国
|
||||
LK: { lat: 7.0, lng: 81.0, name: "Sri Lanka" }, // 斯里兰卡
|
||||
SY: { lat: 35.0, lng: 38.0, name: "Syria" }, // 叙利亚
|
||||
TW: { lat: 23.5, lng: 121.0, name: "Taiwan" }, // 台湾
|
||||
TJ: { lat: 39.0, lng: 71.0, name: "Tajikistan" }, // 塔吉克斯坦
|
||||
TH: { lat: 15.0, lng: 100.0, name: "Thailand" }, // 泰国
|
||||
TR: { lat: 39.0, lng: 35.0, name: "Turkey" }, // 土耳其
|
||||
TM: { lat: 40.0, lng: 60.0, name: "Turkmenistan" }, // 土库曼斯坦
|
||||
AE: { lat: 24.0, lng: 54.0, name: "United Arab Emirates" }, // 阿联酋
|
||||
UZ: { lat: 41.0, lng: 64.0, name: "Uzbekistan" }, // 乌兹别克斯坦
|
||||
VN: { lat: 16.0, lng: 106.0, name: "Vietnam" }, // 越南
|
||||
YE: { lat: 15.0, lng: 48.0, name: "Yemen" }, // 也门
|
||||
PS: { lat: 32.0, lng: 35.25, name: "Palestine" }, // 巴勒斯坦
|
||||
export const countryCoordinates: Record<
|
||||
string,
|
||||
{ lat: number; lng: number; name: string }
|
||||
> = {
|
||||
// 亚洲
|
||||
AF: { lat: 33.0, lng: 65.0, name: "Afghanistan" }, // 阿富汗
|
||||
AM: { lat: 40.0, lng: 45.0, name: "Armenia" }, // 亚美尼亚
|
||||
AZ: { lat: 40.5, lng: 47.5, name: "Azerbaijan" }, // 阿塞拜疆
|
||||
BD: { lat: 24.0, lng: 90.0, name: "Bangladesh" }, // 孟加拉国
|
||||
BH: { lat: 26.0, lng: 50.55, name: "Bahrain" }, // 巴林
|
||||
BT: { lat: 27.5, lng: 90.5, name: "Bhutan" }, // 不丹
|
||||
BN: { lat: 4.5, lng: 114.6667, name: "Brunei" }, // 文莱
|
||||
KH: { lat: 13.0, lng: 105.0, name: "Cambodia" }, // 柬埔寨
|
||||
CN: { lat: 35.0, lng: 105.0, name: "China" }, // 中国
|
||||
HK: { lat: 22.0, lng: 114.0, name: "Hong Kong" }, // 香港
|
||||
MO: { lat: 22.1667, lng: 113.55, name: "Macau" }, // 澳门
|
||||
CY: { lat: 35.0, lng: 33.0, name: "Cyprus" }, // 塞浦路斯
|
||||
GE: { lat: 42.0, lng: 43.5, name: "Georgia" }, // 格鲁吉亚
|
||||
IN: { lat: 20.0, lng: 77.0, name: "India" }, // 印度
|
||||
ID: { lat: -5.0, lng: 120.0, name: "Indonesia" }, // 印度尼西亚
|
||||
IR: { lat: 32.0, lng: 53.0, name: "Iran" }, // 伊朗
|
||||
IQ: { lat: 33.0, lng: 44.0, name: "Iraq" }, // 伊拉克
|
||||
IL: { lat: 31.5, lng: 34.75, name: "Israel" }, // 以色列
|
||||
JP: { lat: 36.0, lng: 138.0, name: "Japan" }, // 日本
|
||||
JO: { lat: 31.0, lng: 36.0, name: "Jordan" }, // 约旦
|
||||
KZ: { lat: 48.0, lng: 68.0, name: "Kazakhstan" }, // 哈萨克斯坦
|
||||
KW: { lat: 29.3375, lng: 47.6581, name: "Kuwait" }, // 科威特
|
||||
KG: { lat: 41.0, lng: 75.0, name: "Kyrgyzstan" }, // 吉尔吉斯斯坦
|
||||
LA: { lat: 18.0, lng: 105.0, name: "Laos" }, // 老挝
|
||||
LB: { lat: 33.8333, lng: 35.8333, name: "Lebanon" }, // 黎巴嫩
|
||||
MY: { lat: 2.5, lng: 112.5, name: "Malaysia" }, // 马来西亚
|
||||
MV: { lat: 3.25, lng: 73.0, name: "Maldives" }, // 马尔代夫
|
||||
MN: { lat: 46.0, lng: 105.0, name: "Mongolia" }, // 蒙古
|
||||
MM: { lat: 22.0, lng: 98.0, name: "Myanmar" }, // 缅甸
|
||||
NP: { lat: 28.0, lng: 84.0, name: "Nepal" }, // 尼泊尔
|
||||
OM: { lat: 21.0, lng: 57.0, name: "Oman" }, // 阿曼
|
||||
PK: { lat: 30.0, lng: 70.0, name: "Pakistan" }, // 巴基斯坦
|
||||
PH: { lat: 13.0, lng: 122.0, name: "Philippines" }, // 菲律宾
|
||||
QA: { lat: 25.5, lng: 51.25, name: "Qatar" }, // 卡塔尔
|
||||
SA: { lat: 25.0, lng: 45.0, name: "Saudi Arabia" }, // 沙特阿拉伯
|
||||
SG: { lat: 1.3667, lng: 103.8, name: "Singapore" }, // 新加坡
|
||||
KR: { lat: 37.0, lng: 127.5, name: "South Korea" }, // 韩国
|
||||
LK: { lat: 7.0, lng: 81.0, name: "Sri Lanka" }, // 斯里兰卡
|
||||
SY: { lat: 35.0, lng: 38.0, name: "Syria" }, // 叙利亚
|
||||
TW: { lat: 23.5, lng: 121.0, name: "Taiwan" }, // 台湾
|
||||
TJ: { lat: 39.0, lng: 71.0, name: "Tajikistan" }, // 塔吉克斯坦
|
||||
TH: { lat: 15.0, lng: 100.0, name: "Thailand" }, // 泰国
|
||||
TR: { lat: 39.0, lng: 35.0, name: "Turkey" }, // 土耳其
|
||||
TM: { lat: 40.0, lng: 60.0, name: "Turkmenistan" }, // 土库曼斯坦
|
||||
AE: { lat: 24.0, lng: 54.0, name: "United Arab Emirates" }, // 阿联酋
|
||||
UZ: { lat: 41.0, lng: 64.0, name: "Uzbekistan" }, // 乌兹别克斯坦
|
||||
VN: { lat: 16.0, lng: 106.0, name: "Vietnam" }, // 越南
|
||||
YE: { lat: 15.0, lng: 48.0, name: "Yemen" }, // 也门
|
||||
PS: { lat: 32.0, lng: 35.25, name: "Palestine" }, // 巴勒斯坦
|
||||
|
||||
// 欧洲
|
||||
AL: { lat: 41.0, lng: 20.0, name: "Albania" }, // 阿尔巴尼亚
|
||||
AD: { lat: 42.5, lng: 1.6, name: "Andorra" }, // 安道尔
|
||||
AT: { lat: 47.3333, lng: 13.3333, name: "Austria" }, // 奥地利
|
||||
BY: { lat: 53.0, lng: 28.0, name: "Belarus" }, // 白俄罗斯
|
||||
BE: { lat: 50.8333, lng: 4.0, name: "Belgium" }, // 比利时
|
||||
BA: { lat: 44.0, lng: 18.0, name: "Bosnia and Herzegovina" }, // 波黑
|
||||
BG: { lat: 43.0, lng: 25.0, name: "Bulgaria" }, // 保加利亚
|
||||
HR: { lat: 45.1667, lng: 15.5, name: "Croatia" }, // 克罗地亚
|
||||
CZ: { lat: 49.75, lng: 15.5, name: "Czech Republic" }, // 捷克
|
||||
DK: { lat: 56.0, lng: 10.0, name: "Denmark" }, // 丹麦
|
||||
EE: { lat: 59.0, lng: 26.0, name: "Estonia" }, // 爱沙尼亚
|
||||
FI: { lat: 64.0, lng: 26.0, name: "Finland" }, // 芬兰
|
||||
FR: { lat: 46.0, lng: 2.0, name: "France" }, // 法国
|
||||
DE: { lat: 51.0, lng: 9.0, name: "Germany" }, // 德国
|
||||
GR: { lat: 39.0, lng: 22.0, name: "Greece" }, // 希腊
|
||||
HU: { lat: 47.0, lng: 20.0, name: "Hungary" }, // 匈牙利
|
||||
IS: { lat: 65.0, lng: -18.0, name: "Iceland" }, // 冰岛
|
||||
IE: { lat: 53.0, lng: -8.0, name: "Ireland" }, // 爱尔兰
|
||||
IT: { lat: 42.8333, lng: 12.8333, name: "Italy" }, // 意大利
|
||||
LV: { lat: 57.0, lng: 25.0, name: "Latvia" }, // 拉脱维亚
|
||||
LI: { lat: 47.1667, lng: 9.5333, name: "Liechtenstein" }, // 列支敦士登
|
||||
LT: { lat: 56.0, lng: 24.0, name: "Lithuania" }, // 立陶宛
|
||||
LU: { lat: 49.75, lng: 6.1667, name: "Luxembourg" }, // 卢森堡
|
||||
MT: { lat: 35.8333, lng: 14.5833, name: "Malta" }, // 马耳他
|
||||
MD: { lat: 47.0, lng: 29.0, name: "Moldova" }, // 摩尔多瓦
|
||||
MC: { lat: 43.7333, lng: 7.4, name: "Monaco" }, // 摩纳哥
|
||||
ME: { lat: 42.0, lng: 19.0, name: "Montenegro" }, // 黑山
|
||||
NL: { lat: 52.5, lng: 5.75, name: "Netherlands" }, // 荷兰
|
||||
NO: { lat: 62.0, lng: 10.0, name: "Norway" }, // 挪威
|
||||
PL: { lat: 52.0, lng: 20.0, name: "Poland" }, // 波兰
|
||||
PT: { lat: 39.5, lng: -8.0, name: "Portugal" }, // 葡萄牙
|
||||
RO: { lat: 46.0, lng: 25.0, name: "Romania" }, // 罗马尼亚
|
||||
RU: { lat: 60.0, lng: 100.0, name: "Russia" }, // 俄罗斯
|
||||
SM: { lat: 43.7667, lng: 12.4167, name: "San Marino" }, // 圣马力诺
|
||||
RS: { lat: 44.0, lng: 21.0, name: "Serbia" }, // 塞尔维亚
|
||||
SK: { lat: 48.6667, lng: 19.5, name: "Slovakia" }, // 斯洛伐克
|
||||
SI: { lat: 46.0, lng: 15.0, name: "Slovenia" }, // 斯洛文尼亚
|
||||
ES: { lat: 40.0, lng: -4.0, name: "Spain" }, // 西班牙
|
||||
SE: { lat: 62.0, lng: 15.0, name: "Sweden" }, // 瑞典
|
||||
CH: { lat: 47.0, lng: 8.0, name: "Switzerland" }, // 瑞士
|
||||
UA: { lat: 49.0, lng: 32.0, name: "Ukraine" }, // 乌克兰
|
||||
GB: { lat: 54.0, lng: -2.0, name: "United Kingdom" }, // 英国
|
||||
VA: { lat: 41.9, lng: 12.45, name: "Vatican City" }, // 梵蒂冈
|
||||
// 欧洲
|
||||
AL: { lat: 41.0, lng: 20.0, name: "Albania" }, // 阿尔巴尼亚
|
||||
AD: { lat: 42.5, lng: 1.6, name: "Andorra" }, // 安道尔
|
||||
AT: { lat: 47.3333, lng: 13.3333, name: "Austria" }, // 奥地利
|
||||
BY: { lat: 53.0, lng: 28.0, name: "Belarus" }, // 白俄罗斯
|
||||
BE: { lat: 50.8333, lng: 4.0, name: "Belgium" }, // 比利时
|
||||
BA: { lat: 44.0, lng: 18.0, name: "Bosnia and Herzegovina" }, // 波黑
|
||||
BG: { lat: 43.0, lng: 25.0, name: "Bulgaria" }, // 保加利亚
|
||||
HR: { lat: 45.1667, lng: 15.5, name: "Croatia" }, // 克罗地亚
|
||||
CZ: { lat: 49.75, lng: 15.5, name: "Czech Republic" }, // 捷克
|
||||
DK: { lat: 56.0, lng: 10.0, name: "Denmark" }, // 丹麦
|
||||
EE: { lat: 59.0, lng: 26.0, name: "Estonia" }, // 爱沙尼亚
|
||||
FI: { lat: 64.0, lng: 26.0, name: "Finland" }, // 芬兰
|
||||
FR: { lat: 46.0, lng: 2.0, name: "France" }, // 法国
|
||||
DE: { lat: 51.0, lng: 9.0, name: "Germany" }, // 德国
|
||||
GR: { lat: 39.0, lng: 22.0, name: "Greece" }, // 希腊
|
||||
HU: { lat: 47.0, lng: 20.0, name: "Hungary" }, // 匈牙利
|
||||
IS: { lat: 65.0, lng: -18.0, name: "Iceland" }, // 冰岛
|
||||
IE: { lat: 53.0, lng: -8.0, name: "Ireland" }, // 爱尔兰
|
||||
IT: { lat: 42.8333, lng: 12.8333, name: "Italy" }, // 意大利
|
||||
LV: { lat: 57.0, lng: 25.0, name: "Latvia" }, // 拉脱维亚
|
||||
LI: { lat: 47.1667, lng: 9.5333, name: "Liechtenstein" }, // 列支敦士登
|
||||
LT: { lat: 56.0, lng: 24.0, name: "Lithuania" }, // 立陶宛
|
||||
LU: { lat: 49.75, lng: 6.1667, name: "Luxembourg" }, // 卢森堡
|
||||
MT: { lat: 35.8333, lng: 14.5833, name: "Malta" }, // 马耳他
|
||||
MD: { lat: 47.0, lng: 29.0, name: "Moldova" }, // 摩尔多瓦
|
||||
MC: { lat: 43.7333, lng: 7.4, name: "Monaco" }, // 摩纳哥
|
||||
ME: { lat: 42.0, lng: 19.0, name: "Montenegro" }, // 黑山
|
||||
NL: { lat: 52.5, lng: 5.75, name: "Netherlands" }, // 荷兰
|
||||
NO: { lat: 62.0, lng: 10.0, name: "Norway" }, // 挪威
|
||||
PL: { lat: 52.0, lng: 20.0, name: "Poland" }, // 波兰
|
||||
PT: { lat: 39.5, lng: -8.0, name: "Portugal" }, // 葡萄牙
|
||||
RO: { lat: 46.0, lng: 25.0, name: "Romania" }, // 罗马尼亚
|
||||
RU: { lat: 60.0, lng: 100.0, name: "Russia" }, // 俄罗斯
|
||||
SM: { lat: 43.7667, lng: 12.4167, name: "San Marino" }, // 圣马力诺
|
||||
RS: { lat: 44.0, lng: 21.0, name: "Serbia" }, // 塞尔维亚
|
||||
SK: { lat: 48.6667, lng: 19.5, name: "Slovakia" }, // 斯洛伐克
|
||||
SI: { lat: 46.0, lng: 15.0, name: "Slovenia" }, // 斯洛文尼亚
|
||||
ES: { lat: 40.0, lng: -4.0, name: "Spain" }, // 西班牙
|
||||
SE: { lat: 62.0, lng: 15.0, name: "Sweden" }, // 瑞典
|
||||
CH: { lat: 47.0, lng: 8.0, name: "Switzerland" }, // 瑞士
|
||||
UA: { lat: 49.0, lng: 32.0, name: "Ukraine" }, // 乌克兰
|
||||
GB: { lat: 54.0, lng: -2.0, name: "United Kingdom" }, // 英国
|
||||
VA: { lat: 41.9, lng: 12.45, name: "Vatican City" }, // 梵蒂冈
|
||||
|
||||
// 北美洲
|
||||
AG: { lat: 17.05, lng: -61.8, name: "Antigua and Barbuda" }, // 安提瓜和巴布达
|
||||
BS: { lat: 24.25, lng: -76.0, name: "Bahamas" }, // 巴哈马
|
||||
BB: { lat: 13.1667, lng: -59.5333, name: "Barbados" }, // 巴巴多斯
|
||||
BZ: { lat: 17.25, lng: -88.75, name: "Belize" }, // 伯利兹
|
||||
CA: { lat: 60.0, lng: -95.0, name: "Canada" }, // 加拿大
|
||||
CR: { lat: 10.0, lng: -84.0, name: "Costa Rica" }, // 哥斯达黎加
|
||||
CU: { lat: 21.5, lng: -80.0, name: "Cuba" }, // 古巴
|
||||
DM: { lat: 15.4167, lng: -61.3333, name: "Dominica" }, // 多米尼克
|
||||
DO: { lat: 19.0, lng: -70.6667, name: "Dominican Republic" }, // 多米尼加共和国
|
||||
SV: { lat: 13.8333, lng: -88.9167, name: "El Salvador" }, // 萨尔瓦多
|
||||
GD: { lat: 12.1167, lng: -61.6667, name: "Grenada" }, // 格林纳达
|
||||
GT: { lat: 15.5, lng: -90.25, name: "Guatemala" }, // 危地马拉
|
||||
HT: { lat: 19.0, lng: -72.4167, name: "Haiti" }, // 海地
|
||||
HN: { lat: 15.0, lng: -86.5, name: "Honduras" }, // 洪都拉斯
|
||||
JM: { lat: 18.25, lng: -77.5, name: "Jamaica" }, // 牙买加
|
||||
MX: { lat: 23.0, lng: -102.0, name: "Mexico" }, // 墨西哥
|
||||
NI: { lat: 13.0, lng: -85.0, name: "Nicaragua" }, // 尼加拉瓜
|
||||
PA: { lat: 9.0, lng: -80.0, name: "Panama" }, // 巴拿马
|
||||
KN: { lat: 17.3333, lng: -62.75, name: "Saint Kitts and Nevis" }, // 圣基茨和尼维斯
|
||||
LC: { lat: 13.8833, lng: -61.1333, name: "Saint Lucia" }, // 圣卢西亚
|
||||
VC: { lat: 13.25, lng: -61.2, name: "Saint Vincent and the Grenadines" }, // 圣文森特和格林纳丁斯
|
||||
TT: { lat: 11.0, lng: -61.0, name: "Trinidad and Tobago" }, // 特立尼达和多巴哥
|
||||
US: { lat: 38.0, lng: -97.0, name: "United States" }, // 美国
|
||||
// 北美洲
|
||||
AG: { lat: 17.05, lng: -61.8, name: "Antigua and Barbuda" }, // 安提瓜和巴布达
|
||||
BS: { lat: 24.25, lng: -76.0, name: "Bahamas" }, // 巴哈马
|
||||
BB: { lat: 13.1667, lng: -59.5333, name: "Barbados" }, // 巴巴多斯
|
||||
BZ: { lat: 17.25, lng: -88.75, name: "Belize" }, // 伯利兹
|
||||
CA: { lat: 60.0, lng: -95.0, name: "Canada" }, // 加拿大
|
||||
CR: { lat: 10.0, lng: -84.0, name: "Costa Rica" }, // 哥斯达黎加
|
||||
CU: { lat: 21.5, lng: -80.0, name: "Cuba" }, // 古巴
|
||||
DM: { lat: 15.4167, lng: -61.3333, name: "Dominica" }, // 多米尼克
|
||||
DO: { lat: 19.0, lng: -70.6667, name: "Dominican Republic" }, // 多米尼加共和国
|
||||
SV: { lat: 13.8333, lng: -88.9167, name: "El Salvador" }, // 萨尔瓦多
|
||||
GD: { lat: 12.1167, lng: -61.6667, name: "Grenada" }, // 格林纳达
|
||||
GT: { lat: 15.5, lng: -90.25, name: "Guatemala" }, // 危地马拉
|
||||
HT: { lat: 19.0, lng: -72.4167, name: "Haiti" }, // 海地
|
||||
HN: { lat: 15.0, lng: -86.5, name: "Honduras" }, // 洪都拉斯
|
||||
JM: { lat: 18.25, lng: -77.5, name: "Jamaica" }, // 牙买加
|
||||
MX: { lat: 23.0, lng: -102.0, name: "Mexico" }, // 墨西哥
|
||||
NI: { lat: 13.0, lng: -85.0, name: "Nicaragua" }, // 尼加拉瓜
|
||||
PA: { lat: 9.0, lng: -80.0, name: "Panama" }, // 巴拿马
|
||||
KN: { lat: 17.3333, lng: -62.75, name: "Saint Kitts and Nevis" }, // 圣基茨和尼维斯
|
||||
LC: { lat: 13.8833, lng: -61.1333, name: "Saint Lucia" }, // 圣卢西亚
|
||||
VC: { lat: 13.25, lng: -61.2, name: "Saint Vincent and the Grenadines" }, // 圣文森特和格林纳丁斯
|
||||
TT: { lat: 11.0, lng: -61.0, name: "Trinidad and Tobago" }, // 特立尼达和多巴哥
|
||||
US: { lat: 38.0, lng: -97.0, name: "United States" }, // 美国
|
||||
|
||||
// 南美洲
|
||||
AR: { lat: -34.0, lng: -64.0, name: "Argentina" }, // 阿根廷
|
||||
BO: { lat: -17.0, lng: -65.0, name: "Bolivia" }, // 玻利维亚
|
||||
BR: { lat: -10.0, lng: -55.0, name: "Brazil" }, // 巴西
|
||||
CL: { lat: -30.0, lng: -71.0, name: "Chile" }, // 智利
|
||||
CO: { lat: 4.0, lng: -72.0, name: "Colombia" }, // 哥伦比亚
|
||||
EC: { lat: -2.0, lng: -77.5, name: "Ecuador" }, // 厄瓜多尔
|
||||
GY: { lat: 5.0, lng: -59.0, name: "Guyana" }, // 圭亚那
|
||||
PY: { lat: -23.0, lng: -58.0, name: "Paraguay" }, // 巴拉圭
|
||||
PE: { lat: -10.0, lng: -76.0, name: "Peru" }, // 秘鲁
|
||||
SR: { lat: 4.0, lng: -56.0, name: "Suriname" }, // 苏里南
|
||||
UY: { lat: -33.0, lng: -56.0, name: "Uruguay" }, // 乌拉圭
|
||||
VE: { lat: 8.0, lng: -66.0, name: "Venezuela" }, // 委内瑞拉
|
||||
// 南美洲
|
||||
AR: { lat: -34.0, lng: -64.0, name: "Argentina" }, // 阿根廷
|
||||
BO: { lat: -17.0, lng: -65.0, name: "Bolivia" }, // 玻利维亚
|
||||
BR: { lat: -10.0, lng: -55.0, name: "Brazil" }, // 巴西
|
||||
CL: { lat: -30.0, lng: -71.0, name: "Chile" }, // 智利
|
||||
CO: { lat: 4.0, lng: -72.0, name: "Colombia" }, // 哥伦比亚
|
||||
EC: { lat: -2.0, lng: -77.5, name: "Ecuador" }, // 厄瓜多尔
|
||||
GY: { lat: 5.0, lng: -59.0, name: "Guyana" }, // 圭亚那
|
||||
PY: { lat: -23.0, lng: -58.0, name: "Paraguay" }, // 巴拉圭
|
||||
PE: { lat: -10.0, lng: -76.0, name: "Peru" }, // 秘鲁
|
||||
SR: { lat: 4.0, lng: -56.0, name: "Suriname" }, // 苏里南
|
||||
UY: { lat: -33.0, lng: -56.0, name: "Uruguay" }, // 乌拉圭
|
||||
VE: { lat: 8.0, lng: -66.0, name: "Venezuela" }, // 委内瑞拉
|
||||
|
||||
// 大洋洲
|
||||
AU: { lat: -27.0, lng: 133.0, name: "Australia" }, // 澳大利亚
|
||||
FJ: { lat: -18.0, lng: 175.0, name: "Fiji" }, // 斐济
|
||||
KI: { lat: 1.4167, lng: 173.0, name: "Kiribati" }, // 基里巴斯
|
||||
MH: { lat: 9.0, lng: 168.0, name: "Marshall Islands" }, // 马绍尔群岛
|
||||
FM: { lat: 6.9167, lng: 158.25, name: "Micronesia" }, // 密克罗尼西亚
|
||||
NR: { lat: -0.5333, lng: 166.9167, name: "Nauru" }, // 瑙鲁
|
||||
NZ: { lat: -41.0, lng: 174.0, name: "New Zealand" }, // 新西兰
|
||||
PW: { lat: 7.5, lng: 134.5, name: "Palau" }, // 帕劳
|
||||
PG: { lat: -6.0, lng: 147.0, name: "Papua New Guinea" }, // 巴布亚新几内亚
|
||||
WS: { lat: -13.5833, lng: -172.3333, name: "Samoa" }, // 萨摩亚
|
||||
SB: { lat: -8.0, lng: 159.0, name: "Solomon Islands" }, // 所罗门群岛
|
||||
TO: { lat: -20.0, lng: -175.0, name: "Tonga" }, // 汤加
|
||||
TV: { lat: -8.0, lng: 178.0, name: "Tuvalu" }, // 图瓦卢
|
||||
VU: { lat: -16.0, lng: 167.0, name: "Vanuatu" }, // 瓦努阿图
|
||||
// 大洋洲
|
||||
AU: { lat: -27.0, lng: 133.0, name: "Australia" }, // 澳大利亚
|
||||
FJ: { lat: -18.0, lng: 175.0, name: "Fiji" }, // 斐济
|
||||
KI: { lat: 1.4167, lng: 173.0, name: "Kiribati" }, // 基里巴斯
|
||||
MH: { lat: 9.0, lng: 168.0, name: "Marshall Islands" }, // 马绍尔群岛
|
||||
FM: { lat: 6.9167, lng: 158.25, name: "Micronesia" }, // 密克罗尼西亚
|
||||
NR: { lat: -0.5333, lng: 166.9167, name: "Nauru" }, // 瑙鲁
|
||||
NZ: { lat: -41.0, lng: 174.0, name: "New Zealand" }, // 新西兰
|
||||
PW: { lat: 7.5, lng: 134.5, name: "Palau" }, // 帕劳
|
||||
PG: { lat: -6.0, lng: 147.0, name: "Papua New Guinea" }, // 巴布亚新几内亚
|
||||
WS: { lat: -13.5833, lng: -172.3333, name: "Samoa" }, // 萨摩亚
|
||||
SB: { lat: -8.0, lng: 159.0, name: "Solomon Islands" }, // 所罗门群岛
|
||||
TO: { lat: -20.0, lng: -175.0, name: "Tonga" }, // 汤加
|
||||
TV: { lat: -8.0, lng: 178.0, name: "Tuvalu" }, // 图瓦卢
|
||||
VU: { lat: -16.0, lng: 167.0, name: "Vanuatu" }, // 瓦努阿图
|
||||
|
||||
// 非洲
|
||||
DZ: { lat: 28.0, lng: 3.0, name: "Algeria" }, // 阿尔及利亚
|
||||
AO: { lat: -12.5, lng: 18.5, name: "Angola" }, // 安哥拉
|
||||
BJ: { lat: 9.5, lng: 2.25, name: "Benin" }, // 贝宁
|
||||
BW: { lat: -22.0, lng: 24.0, name: "Botswana" }, // 博茨瓦纳
|
||||
BF: { lat: 13.0, lng: -2.0, name: "Burkina Faso" }, // 布基纳法索
|
||||
BI: { lat: -3.5, lng: 30.0, name: "Burundi" }, // 布隆迪
|
||||
CM: { lat: 6.0, lng: 12.0, name: "Cameroon" }, // 喀麦隆
|
||||
CV: { lat: 16.0, lng: -24.0, name: "Cape Verde" }, // 佛得角
|
||||
CF: { lat: 7.0, lng: 21.0, name: "Central African Republic" }, // 中非共和国
|
||||
TD: { lat: 15.0, lng: 19.0, name: "Chad" }, // 乍得
|
||||
KM: { lat: -12.1667, lng: 44.25, name: "Comoros" }, // 科摩罗
|
||||
CG: { lat: -1.0, lng: 15.0, name: "Congo" }, // 刚果
|
||||
CD: { lat: 0.0, lng: 25.0, name: "Democratic Republic of the Congo" }, // 刚果民主共和国
|
||||
CI: { lat: 8.0, lng: -5.0, name: "Côte d'Ivoire" }, // 科特迪瓦
|
||||
DJ: { lat: 11.5, lng: 43.0, name: "Djibouti" }, // 吉布提
|
||||
EG: { lat: 27.0, lng: 30.0, name: "Egypt" }, // 埃及
|
||||
GQ: { lat: 2.0, lng: 10.0, name: "Equatorial Guinea" }, // 赤道几内亚
|
||||
ER: { lat: 15.0, lng: 39.0, name: "Eritrea" }, // 厄立特里亚
|
||||
ET: { lat: 8.0, lng: 38.0, name: "Ethiopia" }, // 埃塞俄比亚
|
||||
GA: { lat: -1.0, lng: 11.75, name: "Gabon" }, // 加蓬
|
||||
GM: { lat: 13.4667, lng: -16.5667, name: "Gambia" }, // 冈比亚
|
||||
GH: { lat: 8.0, lng: -2.0, name: "Ghana" }, // 加纳
|
||||
GN: { lat: 11.0, lng: -10.0, name: "Guinea" }, // 几内亚
|
||||
GW: { lat: 12.0, lng: -15.0, name: "Guinea-Bissau" }, // 几内亚比绍
|
||||
KE: { lat: 1.0, lng: 38.0, name: "Kenya" }, // 肯尼亚
|
||||
LS: { lat: -29.5, lng: 28.5, name: "Lesotho" }, // 莱索托
|
||||
LR: { lat: 6.5, lng: -9.5, name: "Liberia" }, // 利比里亚
|
||||
LY: { lat: 25.0, lng: 17.0, name: "Libya" }, // 利比亚
|
||||
MG: { lat: -20.0, lng: 47.0, name: "Madagascar" }, // 马达加斯加
|
||||
MW: { lat: -13.5, lng: 34.0, name: "Malawi" }, // 马拉维
|
||||
ML: { lat: 17.0, lng: -4.0, name: "Mali" }, // 马里
|
||||
MR: { lat: 20.0, lng: -12.0, name: "Mauritania" }, // 毛里塔尼亚
|
||||
MU: { lat: -20.2833, lng: 57.55, name: "Mauritius" }, // 毛里求斯
|
||||
YT: { lat: -12.8333, lng: 45.1667, name: "Mayotte" }, // 马约特
|
||||
MA: { lat: 32.0, lng: -5.0, name: "Morocco" }, // 摩洛哥
|
||||
MZ: { lat: -18.25, lng: 35.0, name: "Mozambique" }, // 莫桑比克
|
||||
NA: { lat: -22.0, lng: 17.0, name: "Namibia" }, // 纳米比亚
|
||||
NE: { lat: 16.0, lng: 8.0, name: "Niger" }, // 尼日尔
|
||||
NG: { lat: 10.0, lng: 8.0, name: "Nigeria" }, // 尼日利亚
|
||||
RW: { lat: -2.0, lng: 30.0, name: "Rwanda" }, // 卢旺达
|
||||
ST: { lat: 1.0, lng: 7.0, name: "São Tomé and Principe" }, // 圣多美和普林西比
|
||||
SN: { lat: 14.0, lng: -14.0, name: "Senegal" }, // 塞内加尔
|
||||
SC: { lat: -4.5833, lng: 55.6667, name: "Seychelles" }, // 塞舌尔
|
||||
SL: { lat: 8.5, lng: -11.5, name: "Sierra Leone" }, // 塞拉利昂
|
||||
SO: { lat: 10.0, lng: 49.0, name: "Somalia" }, // 索马里
|
||||
ZA: { lat: -29.0, lng: 24.0, name: "South Africa" }, // 南非
|
||||
SD: { lat: 15.0, lng: 30.0, name: "Sudan" }, // 苏丹
|
||||
SZ: { lat: -26.5, lng: 31.5, name: "Swaziland" }, // 斯威士兰
|
||||
TZ: { lat: -6.0, lng: 35.0, name: "Tanzania" }, // 坦桑尼亚
|
||||
TG: { lat: 8.0, lng: 1.1667, name: "Togo" }, // 多哥
|
||||
TN: { lat: 34.0, lng: 9.0, name: "Tunisia" }, // 突尼斯
|
||||
UG: { lat: 1.0, lng: 32.0, name: "Uganda" }, // 乌干达
|
||||
EH: { lat: 24.5, lng: -13.0, name: "Western Sahara" }, // 西撒哈拉
|
||||
ZM: { lat: -15.0, lng: 30.0, name: "Zambia" }, // 赞比亚
|
||||
ZW: { lat: -20.0, lng: 30.0, name: "Zimbabwe" }, // 津巴布韦
|
||||
}
|
||||
// 非洲
|
||||
DZ: { lat: 28.0, lng: 3.0, name: "Algeria" }, // 阿尔及利亚
|
||||
AO: { lat: -12.5, lng: 18.5, name: "Angola" }, // 安哥拉
|
||||
BJ: { lat: 9.5, lng: 2.25, name: "Benin" }, // 贝宁
|
||||
BW: { lat: -22.0, lng: 24.0, name: "Botswana" }, // 博茨瓦纳
|
||||
BF: { lat: 13.0, lng: -2.0, name: "Burkina Faso" }, // 布基纳法索
|
||||
BI: { lat: -3.5, lng: 30.0, name: "Burundi" }, // 布隆迪
|
||||
CM: { lat: 6.0, lng: 12.0, name: "Cameroon" }, // 喀麦隆
|
||||
CV: { lat: 16.0, lng: -24.0, name: "Cape Verde" }, // 佛得角
|
||||
CF: { lat: 7.0, lng: 21.0, name: "Central African Republic" }, // 中非共和国
|
||||
TD: { lat: 15.0, lng: 19.0, name: "Chad" }, // 乍得
|
||||
KM: { lat: -12.1667, lng: 44.25, name: "Comoros" }, // 科摩罗
|
||||
CG: { lat: -1.0, lng: 15.0, name: "Congo" }, // 刚果
|
||||
CD: { lat: 0.0, lng: 25.0, name: "Democratic Republic of the Congo" }, // 刚果民主共和国
|
||||
CI: { lat: 8.0, lng: -5.0, name: "Côte d'Ivoire" }, // 科特迪瓦
|
||||
DJ: { lat: 11.5, lng: 43.0, name: "Djibouti" }, // 吉布提
|
||||
EG: { lat: 27.0, lng: 30.0, name: "Egypt" }, // 埃及
|
||||
GQ: { lat: 2.0, lng: 10.0, name: "Equatorial Guinea" }, // 赤道几内亚
|
||||
ER: { lat: 15.0, lng: 39.0, name: "Eritrea" }, // 厄立特里亚
|
||||
ET: { lat: 8.0, lng: 38.0, name: "Ethiopia" }, // 埃塞俄比亚
|
||||
GA: { lat: -1.0, lng: 11.75, name: "Gabon" }, // 加蓬
|
||||
GM: { lat: 13.4667, lng: -16.5667, name: "Gambia" }, // 冈比亚
|
||||
GH: { lat: 8.0, lng: -2.0, name: "Ghana" }, // 加纳
|
||||
GN: { lat: 11.0, lng: -10.0, name: "Guinea" }, // 几内亚
|
||||
GW: { lat: 12.0, lng: -15.0, name: "Guinea-Bissau" }, // 几内亚比绍
|
||||
KE: { lat: 1.0, lng: 38.0, name: "Kenya" }, // 肯尼亚
|
||||
LS: { lat: -29.5, lng: 28.5, name: "Lesotho" }, // 莱索托
|
||||
LR: { lat: 6.5, lng: -9.5, name: "Liberia" }, // 利比里亚
|
||||
LY: { lat: 25.0, lng: 17.0, name: "Libya" }, // 利比亚
|
||||
MG: { lat: -20.0, lng: 47.0, name: "Madagascar" }, // 马达加斯加
|
||||
MW: { lat: -13.5, lng: 34.0, name: "Malawi" }, // 马拉维
|
||||
ML: { lat: 17.0, lng: -4.0, name: "Mali" }, // 马里
|
||||
MR: { lat: 20.0, lng: -12.0, name: "Mauritania" }, // 毛里塔尼亚
|
||||
MU: { lat: -20.2833, lng: 57.55, name: "Mauritius" }, // 毛里求斯
|
||||
YT: { lat: -12.8333, lng: 45.1667, name: "Mayotte" }, // 马约特
|
||||
MA: { lat: 32.0, lng: -5.0, name: "Morocco" }, // 摩洛哥
|
||||
MZ: { lat: -18.25, lng: 35.0, name: "Mozambique" }, // 莫桑比克
|
||||
NA: { lat: -22.0, lng: 17.0, name: "Namibia" }, // 纳米比亚
|
||||
NE: { lat: 16.0, lng: 8.0, name: "Niger" }, // 尼日尔
|
||||
NG: { lat: 10.0, lng: 8.0, name: "Nigeria" }, // 尼日利亚
|
||||
RW: { lat: -2.0, lng: 30.0, name: "Rwanda" }, // 卢旺达
|
||||
ST: { lat: 1.0, lng: 7.0, name: "São Tomé and Principe" }, // 圣多美和普林西比
|
||||
SN: { lat: 14.0, lng: -14.0, name: "Senegal" }, // 塞内加尔
|
||||
SC: { lat: -4.5833, lng: 55.6667, name: "Seychelles" }, // 塞舌尔
|
||||
SL: { lat: 8.5, lng: -11.5, name: "Sierra Leone" }, // 塞拉利昂
|
||||
SO: { lat: 10.0, lng: 49.0, name: "Somalia" }, // 索马里
|
||||
ZA: { lat: -29.0, lng: 24.0, name: "South Africa" }, // 南非
|
||||
SD: { lat: 15.0, lng: 30.0, name: "Sudan" }, // 苏丹
|
||||
SZ: { lat: -26.5, lng: 31.5, name: "Swaziland" }, // 斯威士兰
|
||||
TZ: { lat: -6.0, lng: 35.0, name: "Tanzania" }, // 坦桑尼亚
|
||||
TG: { lat: 8.0, lng: 1.1667, name: "Togo" }, // 多哥
|
||||
TN: { lat: 34.0, lng: 9.0, name: "Tunisia" }, // 突尼斯
|
||||
UG: { lat: 1.0, lng: 32.0, name: "Uganda" }, // 乌干达
|
||||
EH: { lat: 24.5, lng: -13.0, name: "Western Sahara" }, // 西撒哈拉
|
||||
ZM: { lat: -15.0, lng: 30.0, name: "Zambia" }, // 赞比亚
|
||||
ZW: { lat: -20.0, lng: 30.0, name: "Zimbabwe" }, // 津巴布韦
|
||||
};
|
||||
|
||||
+97
-89
@@ -1,99 +1,107 @@
|
||||
export const InjectContext = (content: string) => {
|
||||
const tempDiv = document.createElement("div")
|
||||
tempDiv.innerHTML = content
|
||||
const tempDiv = document.createElement("div");
|
||||
tempDiv.innerHTML = content;
|
||||
|
||||
const INJECTION_MARK = "data-injected" // 自定义属性标识
|
||||
const INJECTION_MARK = "data-injected"; // 自定义属性标识
|
||||
|
||||
// 清理已有的注入资源
|
||||
const cleanInjectedResources = () => {
|
||||
document.querySelectorAll(`[${INJECTION_MARK}]`).forEach((node) => node.remove())
|
||||
}
|
||||
// 清理已有的注入资源
|
||||
const cleanInjectedResources = () => {
|
||||
document.querySelectorAll(`[${INJECTION_MARK}]`).forEach((node) => {
|
||||
node.remove();
|
||||
});
|
||||
};
|
||||
|
||||
const loadExternalScript = (scriptElement: HTMLScriptElement): Promise<void> => {
|
||||
return new Promise((resolve, reject) => {
|
||||
const script = document.createElement("script")
|
||||
script.src = scriptElement.src
|
||||
script.async = false // 保持顺序执行
|
||||
script.setAttribute(INJECTION_MARK, "true") // 添加标识
|
||||
script.onload = () => resolve()
|
||||
script.onerror = () => reject(new Error(`Failed to load script: ${scriptElement.src}`))
|
||||
document.head.appendChild(script)
|
||||
})
|
||||
}
|
||||
const loadExternalScript = (
|
||||
scriptElement: HTMLScriptElement,
|
||||
): Promise<void> => {
|
||||
return new Promise((resolve, reject) => {
|
||||
const script = document.createElement("script");
|
||||
script.src = scriptElement.src;
|
||||
script.async = false; // 保持顺序执行
|
||||
script.setAttribute(INJECTION_MARK, "true"); // 添加标识
|
||||
script.onload = () => resolve();
|
||||
script.onerror = () =>
|
||||
reject(new Error(`Failed to load script: ${scriptElement.src}`));
|
||||
document.head.appendChild(script);
|
||||
});
|
||||
};
|
||||
|
||||
const executeInlineScript = (scriptContent: string): Promise<void> => {
|
||||
return new Promise((resolve) => {
|
||||
const script = document.createElement("script")
|
||||
script.textContent = scriptContent
|
||||
script.setAttribute(INJECTION_MARK, "true") // 添加标识
|
||||
document.body.appendChild(script)
|
||||
resolve()
|
||||
})
|
||||
}
|
||||
const executeInlineScript = (scriptContent: string): Promise<void> => {
|
||||
return new Promise((resolve) => {
|
||||
const script = document.createElement("script");
|
||||
script.textContent = scriptContent;
|
||||
script.setAttribute(INJECTION_MARK, "true"); // 添加标识
|
||||
document.body.appendChild(script);
|
||||
resolve();
|
||||
});
|
||||
};
|
||||
|
||||
const loadStyle = (styleElement: HTMLStyleElement): Promise<void> => {
|
||||
return new Promise((resolve, reject) => {
|
||||
if ((styleElement as any).href) {
|
||||
// 处理 <link>
|
||||
const link = document.createElement("link")
|
||||
link.rel = "stylesheet"
|
||||
link.href = (styleElement as any).href
|
||||
link.setAttribute(INJECTION_MARK, "true") // 添加标识
|
||||
link.onload = () => resolve()
|
||||
link.onerror = () => reject(new Error(`Failed to load stylesheet: ${link.href}`))
|
||||
document.head.appendChild(link)
|
||||
} else {
|
||||
const style = document.createElement("style")
|
||||
style.textContent = styleElement.textContent
|
||||
style.setAttribute(INJECTION_MARK, "true") // 添加标识
|
||||
document.head.appendChild(style)
|
||||
resolve()
|
||||
}
|
||||
})
|
||||
}
|
||||
const loadStyle = (styleElement: HTMLStyleElement): Promise<void> => {
|
||||
return new Promise((resolve, reject) => {
|
||||
if ((styleElement as any).href) {
|
||||
// 处理 <link>
|
||||
const link = document.createElement("link");
|
||||
link.rel = "stylesheet";
|
||||
link.href = (styleElement as any).href;
|
||||
link.setAttribute(INJECTION_MARK, "true"); // 添加标识
|
||||
link.onload = () => resolve();
|
||||
link.onerror = () =>
|
||||
reject(new Error(`Failed to load stylesheet: ${link.href}`));
|
||||
document.head.appendChild(link);
|
||||
} else {
|
||||
const style = document.createElement("style");
|
||||
style.textContent = styleElement.textContent;
|
||||
style.setAttribute(INJECTION_MARK, "true"); // 添加标识
|
||||
document.head.appendChild(style);
|
||||
resolve();
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
const handlers: { [key: string]: (element: HTMLElement) => Promise<void> } = {
|
||||
SCRIPT: (element) => {
|
||||
const scriptElement = element as HTMLScriptElement
|
||||
if (scriptElement.src) {
|
||||
// 加载外部脚本
|
||||
return loadExternalScript(scriptElement)
|
||||
} else {
|
||||
// 执行内联脚本
|
||||
return executeInlineScript(scriptElement.textContent || "")
|
||||
}
|
||||
},
|
||||
STYLE: (element) => loadStyle(element as HTMLStyleElement),
|
||||
META: (element) => {
|
||||
const meta = element.cloneNode(true) as HTMLElement
|
||||
meta.setAttribute(INJECTION_MARK, "true") // 添加标识
|
||||
document.head.appendChild(meta) // 将 meta 标签插入到 <head>
|
||||
return Promise.resolve()
|
||||
},
|
||||
DEFAULT: (element) => {
|
||||
element.setAttribute(INJECTION_MARK, "true") // 添加标识
|
||||
document.body.appendChild(element)
|
||||
return Promise.resolve()
|
||||
},
|
||||
}
|
||||
const handlers: { [key: string]: (element: HTMLElement) => Promise<void> } = {
|
||||
SCRIPT: (element) => {
|
||||
const scriptElement = element as HTMLScriptElement;
|
||||
if (scriptElement.src) {
|
||||
// 加载外部脚本
|
||||
return loadExternalScript(scriptElement);
|
||||
} else {
|
||||
// 执行内联脚本
|
||||
return executeInlineScript(scriptElement.textContent || "");
|
||||
}
|
||||
},
|
||||
STYLE: (element) => loadStyle(element as HTMLStyleElement),
|
||||
META: (element) => {
|
||||
const meta = element.cloneNode(true) as HTMLElement;
|
||||
meta.setAttribute(INJECTION_MARK, "true"); // 添加标识
|
||||
document.head.appendChild(meta); // 将 meta 标签插入到 <head>
|
||||
return Promise.resolve();
|
||||
},
|
||||
DEFAULT: (element) => {
|
||||
element.setAttribute(INJECTION_MARK, "true"); // 添加标识
|
||||
document.body.appendChild(element);
|
||||
return Promise.resolve();
|
||||
},
|
||||
};
|
||||
|
||||
// 开始注入前清理已有资源
|
||||
cleanInjectedResources()
|
||||
// 开始注入前清理已有资源
|
||||
cleanInjectedResources();
|
||||
|
||||
const executeSequentially = async () => {
|
||||
for (const node of Array.from(tempDiv.childNodes)) {
|
||||
if (node.nodeType === Node.ELEMENT_NODE) {
|
||||
const element = node as HTMLElement
|
||||
const handler = handlers[element.tagName] || handlers.DEFAULT
|
||||
await handler(element) // 按顺序等待当前脚本或资源完成处理
|
||||
} else if (node.nodeType === Node.TEXT_NODE) {
|
||||
document.body.appendChild(document.createTextNode(node.textContent || ""))
|
||||
}
|
||||
}
|
||||
console.log("All resources have been injected and executed in sequence.")
|
||||
}
|
||||
const executeSequentially = async () => {
|
||||
for (const node of Array.from(tempDiv.childNodes)) {
|
||||
if (node.nodeType === Node.ELEMENT_NODE) {
|
||||
const element = node as HTMLElement;
|
||||
const handler = handlers[element.tagName] || handlers.DEFAULT;
|
||||
await handler(element); // 按顺序等待当前脚本或资源完成处理
|
||||
} else if (node.nodeType === Node.TEXT_NODE) {
|
||||
document.body.appendChild(
|
||||
document.createTextNode(node.textContent || ""),
|
||||
);
|
||||
}
|
||||
}
|
||||
console.log("All resources have been injected and executed in sequence.");
|
||||
};
|
||||
|
||||
return executeSequentially().catch((error) => {
|
||||
console.error("Error during resource injection:", error)
|
||||
})
|
||||
}
|
||||
return executeSequentially().catch((error) => {
|
||||
console.error("Error during resource injection:", error);
|
||||
});
|
||||
};
|
||||
|
||||
+139
-133
@@ -1,142 +1,148 @@
|
||||
import type { SVGProps } from "react"
|
||||
import type { SVGProps } from "react";
|
||||
|
||||
export function GetFontLogoClass(platform: string): string {
|
||||
if (
|
||||
[
|
||||
"almalinux",
|
||||
"alpine",
|
||||
"aosc",
|
||||
"apple",
|
||||
"archlinux",
|
||||
"archlabs",
|
||||
"artix",
|
||||
"budgie",
|
||||
"centos",
|
||||
"coreos",
|
||||
"debian",
|
||||
"deepin",
|
||||
"devuan",
|
||||
"docker",
|
||||
"elementary",
|
||||
"fedora",
|
||||
"ferris",
|
||||
"flathub",
|
||||
"freebsd",
|
||||
"gentoo",
|
||||
"gnu-guix",
|
||||
"illumos",
|
||||
"kali-linux",
|
||||
"linuxmint",
|
||||
"mageia",
|
||||
"mandriva",
|
||||
"manjaro",
|
||||
"nixos",
|
||||
"openbsd",
|
||||
"opensuse",
|
||||
"pop-os",
|
||||
"raspberry-pi",
|
||||
"redhat",
|
||||
"rocky-linux",
|
||||
"sabayon",
|
||||
"slackware",
|
||||
"snappy",
|
||||
"solus",
|
||||
"tux",
|
||||
"ubuntu",
|
||||
"void",
|
||||
"zorin",
|
||||
].indexOf(platform) > -1
|
||||
) {
|
||||
return platform
|
||||
}
|
||||
if (platform == "darwin") {
|
||||
return "apple"
|
||||
}
|
||||
if (["openwrt", "linux", "immortalwrt"].indexOf(platform) > -1) {
|
||||
return "tux"
|
||||
}
|
||||
if (platform == "amazon") {
|
||||
return "redhat"
|
||||
}
|
||||
if (platform == "arch") {
|
||||
return "archlinux"
|
||||
}
|
||||
if (platform.toLowerCase().includes("opensuse")) {
|
||||
return "opensuse"
|
||||
}
|
||||
return "tux"
|
||||
if (
|
||||
[
|
||||
"almalinux",
|
||||
"alpine",
|
||||
"aosc",
|
||||
"apple",
|
||||
"archlinux",
|
||||
"archlabs",
|
||||
"artix",
|
||||
"budgie",
|
||||
"centos",
|
||||
"coreos",
|
||||
"debian",
|
||||
"deepin",
|
||||
"devuan",
|
||||
"docker",
|
||||
"elementary",
|
||||
"fedora",
|
||||
"ferris",
|
||||
"flathub",
|
||||
"freebsd",
|
||||
"gentoo",
|
||||
"gnu-guix",
|
||||
"illumos",
|
||||
"kali-linux",
|
||||
"linuxmint",
|
||||
"mageia",
|
||||
"mandriva",
|
||||
"manjaro",
|
||||
"nixos",
|
||||
"openbsd",
|
||||
"opensuse",
|
||||
"pop-os",
|
||||
"raspberry-pi",
|
||||
"redhat",
|
||||
"rocky-linux",
|
||||
"sabayon",
|
||||
"slackware",
|
||||
"snappy",
|
||||
"solus",
|
||||
"tux",
|
||||
"ubuntu",
|
||||
"void",
|
||||
"zorin",
|
||||
].indexOf(platform) > -1
|
||||
) {
|
||||
return platform;
|
||||
}
|
||||
if (platform === "darwin") {
|
||||
return "apple";
|
||||
}
|
||||
if (["openwrt", "linux", "immortalwrt"].indexOf(platform) > -1) {
|
||||
return "tux";
|
||||
}
|
||||
if (platform === "amazon") {
|
||||
return "redhat";
|
||||
}
|
||||
if (platform === "arch") {
|
||||
return "archlinux";
|
||||
}
|
||||
if (platform.toLowerCase().includes("opensuse")) {
|
||||
return "opensuse";
|
||||
}
|
||||
return "tux";
|
||||
}
|
||||
|
||||
export function GetOsName(platform: string): string {
|
||||
if (
|
||||
[
|
||||
"almalinux",
|
||||
"alpine",
|
||||
"aosc",
|
||||
"apple",
|
||||
"archlinux",
|
||||
"archlabs",
|
||||
"artix",
|
||||
"budgie",
|
||||
"centos",
|
||||
"coreos",
|
||||
"debian",
|
||||
"deepin",
|
||||
"devuan",
|
||||
"docker",
|
||||
"fedora",
|
||||
"ferris",
|
||||
"flathub",
|
||||
"freebsd",
|
||||
"gentoo",
|
||||
"gnu-guix",
|
||||
"illumos",
|
||||
"linuxmint",
|
||||
"mageia",
|
||||
"mandriva",
|
||||
"manjaro",
|
||||
"nixos",
|
||||
"openbsd",
|
||||
"opensuse",
|
||||
"pop-os",
|
||||
"redhat",
|
||||
"sabayon",
|
||||
"slackware",
|
||||
"snappy",
|
||||
"solus",
|
||||
"tux",
|
||||
"ubuntu",
|
||||
"void",
|
||||
"zorin",
|
||||
].indexOf(platform) > -1
|
||||
) {
|
||||
return platform.charAt(0).toUpperCase() + platform.slice(1)
|
||||
}
|
||||
if (platform == "darwin") {
|
||||
return "macOS"
|
||||
}
|
||||
if (["openwrt", "linux", "immortalwrt"].indexOf(platform) > -1) {
|
||||
return "Linux"
|
||||
}
|
||||
if (platform == "amazon") {
|
||||
return "Redhat"
|
||||
}
|
||||
if (platform == "arch") {
|
||||
return "Archlinux"
|
||||
}
|
||||
if (platform.toLowerCase().includes("opensuse")) {
|
||||
return "Opensuse"
|
||||
}
|
||||
return "Linux"
|
||||
if (
|
||||
[
|
||||
"almalinux",
|
||||
"alpine",
|
||||
"aosc",
|
||||
"apple",
|
||||
"archlinux",
|
||||
"archlabs",
|
||||
"artix",
|
||||
"budgie",
|
||||
"centos",
|
||||
"coreos",
|
||||
"debian",
|
||||
"deepin",
|
||||
"devuan",
|
||||
"docker",
|
||||
"fedora",
|
||||
"ferris",
|
||||
"flathub",
|
||||
"freebsd",
|
||||
"gentoo",
|
||||
"gnu-guix",
|
||||
"illumos",
|
||||
"linuxmint",
|
||||
"mageia",
|
||||
"mandriva",
|
||||
"manjaro",
|
||||
"nixos",
|
||||
"openbsd",
|
||||
"opensuse",
|
||||
"pop-os",
|
||||
"redhat",
|
||||
"sabayon",
|
||||
"slackware",
|
||||
"snappy",
|
||||
"solus",
|
||||
"tux",
|
||||
"ubuntu",
|
||||
"void",
|
||||
"zorin",
|
||||
].indexOf(platform) > -1
|
||||
) {
|
||||
return platform.charAt(0).toUpperCase() + platform.slice(1);
|
||||
}
|
||||
if (platform === "darwin") {
|
||||
return "macOS";
|
||||
}
|
||||
if (["openwrt", "linux", "immortalwrt"].indexOf(platform) > -1) {
|
||||
return "Linux";
|
||||
}
|
||||
if (platform === "amazon") {
|
||||
return "Redhat";
|
||||
}
|
||||
if (platform === "arch") {
|
||||
return "Archlinux";
|
||||
}
|
||||
if (platform.toLowerCase().includes("opensuse")) {
|
||||
return "Opensuse";
|
||||
}
|
||||
return "Linux";
|
||||
}
|
||||
|
||||
export function MageMicrosoftWindows(props: SVGProps<SVGSVGElement>) {
|
||||
return (
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="1em" height="1em" viewBox="0 0 24 24" {...props}>
|
||||
<path
|
||||
fill="currentColor"
|
||||
d="M2.75 7.189V2.865c0-.102 0-.115.115-.115h8.622c.128 0 .14 0 .14.128V11.5c0 .128 0 .128-.14.128H2.865c-.102 0-.115 0-.115-.116zM7.189 21.25H2.865c-.102 0-.115 0-.115-.116V12.59c0-.128 0-.128.128-.128h8.635c.102 0 .115 0 .115.115v8.57c0 .09 0 .103-.116.103zM21.25 7.189v4.31c0 .116 0 .116-.116.116h-8.557c-.102 0-.128 0-.128-.115V2.865c0-.09 0-.102.115-.102h8.48c.206 0 .206 0 .206.205zm-8.763 9.661v-4.273c0-.09 0-.115.103-.09h8.621c.026 0 0 .09 0 .142v8.518a.06.06 0 0 1-.017.06a.06.06 0 0 1-.06.017H12.54s-.09 0-.077-.09V16.85z"
|
||||
></path>
|
||||
</svg>
|
||||
)
|
||||
return (
|
||||
<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
width="1em"
|
||||
height="1em"
|
||||
viewBox="0 0 24 24"
|
||||
{...props}
|
||||
>
|
||||
<path
|
||||
fill="currentColor"
|
||||
d="M2.75 7.189V2.865c0-.102 0-.115.115-.115h8.622c.128 0 .14 0 .14.128V11.5c0 .128 0 .128-.14.128H2.865c-.102 0-.115 0-.115-.116zM7.189 21.25H2.865c-.102 0-.115 0-.115-.116V12.59c0-.128 0-.128.128-.128h8.635c.102 0 .115 0 .115.115v8.57c0 .09 0 .103-.116.103zM21.25 7.189v4.31c0 .116 0 .116-.116.116h-8.557c-.102 0-.128 0-.128-.115V2.865c0-.09 0-.102.115-.102h8.48c.206 0 .206 0 .206.205zm-8.763 9.661v-4.273c0-.09 0-.115.103-.09h8.621c.026 0 0 .09 0 .142v8.518a.06.06 0 0 1-.017.06a.06.06 0 0 1-.06.017H12.54s-.09 0-.077-.09V16.85z"
|
||||
></path>
|
||||
</svg>
|
||||
);
|
||||
}
|
||||
|
||||
+55
-43
@@ -1,55 +1,67 @@
|
||||
import { LoginUserResponse, MonitorResponse, ServerGroupResponse, ServiceResponse, SettingResponse } from "@/types/nezha-api"
|
||||
import type {
|
||||
LoginUserResponse,
|
||||
MonitorResponse,
|
||||
ServerGroupResponse,
|
||||
ServiceResponse,
|
||||
SettingResponse,
|
||||
} from "@/types/nezha-api";
|
||||
|
||||
let lastestRefreshTokenAt = 0
|
||||
let lastestRefreshTokenAt = 0;
|
||||
|
||||
export const fetchServerGroup = async (): Promise<ServerGroupResponse> => {
|
||||
const response = await fetch("/api/v1/server-group")
|
||||
const data = await response.json()
|
||||
if (data.error) {
|
||||
throw new Error(data.error)
|
||||
}
|
||||
return data
|
||||
}
|
||||
const response = await fetch("/api/v1/server-group");
|
||||
const data = await response.json();
|
||||
if (data.error) {
|
||||
throw new Error(data.error);
|
||||
}
|
||||
return data;
|
||||
};
|
||||
|
||||
export const fetchLoginUser = async (): Promise<LoginUserResponse> => {
|
||||
const response = await fetch("/api/v1/profile")
|
||||
const data = await response.json()
|
||||
if (data.error) {
|
||||
throw new Error(data.error)
|
||||
}
|
||||
const response = await fetch("/api/v1/profile");
|
||||
const data = await response.json();
|
||||
if (data.error) {
|
||||
throw new Error(data.error);
|
||||
}
|
||||
|
||||
// auto refresh token
|
||||
if (document.cookie && (!lastestRefreshTokenAt || Date.now() - lastestRefreshTokenAt > 1000 * 60 * 60)) {
|
||||
lastestRefreshTokenAt = Date.now()
|
||||
fetch("/api/v1/refresh-token")
|
||||
}
|
||||
// auto refresh token
|
||||
if (
|
||||
document.cookie &&
|
||||
(!lastestRefreshTokenAt ||
|
||||
Date.now() - lastestRefreshTokenAt > 1000 * 60 * 60)
|
||||
) {
|
||||
lastestRefreshTokenAt = Date.now();
|
||||
fetch("/api/v1/refresh-token");
|
||||
}
|
||||
|
||||
return data
|
||||
}
|
||||
return data;
|
||||
};
|
||||
|
||||
export const fetchMonitor = async (server_id: number): Promise<MonitorResponse> => {
|
||||
const response = await fetch(`/api/v1/service/${server_id}`)
|
||||
const data = await response.json()
|
||||
if (data.error) {
|
||||
throw new Error(data.error)
|
||||
}
|
||||
return data
|
||||
}
|
||||
export const fetchMonitor = async (
|
||||
server_id: number,
|
||||
): Promise<MonitorResponse> => {
|
||||
const response = await fetch(`/api/v1/service/${server_id}`);
|
||||
const data = await response.json();
|
||||
if (data.error) {
|
||||
throw new Error(data.error);
|
||||
}
|
||||
return data;
|
||||
};
|
||||
|
||||
export const fetchService = async (): Promise<ServiceResponse> => {
|
||||
const response = await fetch("/api/v1/service")
|
||||
const data = await response.json()
|
||||
if (data.error) {
|
||||
throw new Error(data.error)
|
||||
}
|
||||
return data
|
||||
}
|
||||
const response = await fetch("/api/v1/service");
|
||||
const data = await response.json();
|
||||
if (data.error) {
|
||||
throw new Error(data.error);
|
||||
}
|
||||
return data;
|
||||
};
|
||||
|
||||
export const fetchSetting = async (): Promise<SettingResponse> => {
|
||||
const response = await fetch("/api/v1/setting")
|
||||
const data = await response.json()
|
||||
if (data.error) {
|
||||
throw new Error(data.error)
|
||||
}
|
||||
return data
|
||||
}
|
||||
const response = await fetch("/api/v1/setting");
|
||||
const data = await response.json();
|
||||
if (data.error) {
|
||||
throw new Error(data.error);
|
||||
}
|
||||
return data;
|
||||
};
|
||||
|
||||
+281
-259
@@ -1,322 +1,344 @@
|
||||
import { NezhaServer } from "@/types/nezha-api"
|
||||
import { type ClassValue, clsx } from "clsx"
|
||||
import dayjs from "dayjs"
|
||||
import { twMerge } from "tailwind-merge"
|
||||
import { type ClassValue, clsx } from "clsx";
|
||||
import dayjs from "dayjs";
|
||||
import { twMerge } from "tailwind-merge";
|
||||
import type { NezhaServer } from "@/types/nezha-api";
|
||||
|
||||
export function cn(...inputs: ClassValue[]) {
|
||||
return twMerge(clsx(inputs))
|
||||
return twMerge(clsx(inputs));
|
||||
}
|
||||
|
||||
export function formatNezhaInfo(now: number, serverInfo: NezhaServer) {
|
||||
const lastActiveTime = serverInfo.last_active.startsWith("000") ? 0 : parseISOTimestamp(serverInfo.last_active)
|
||||
return {
|
||||
...serverInfo,
|
||||
cpu: serverInfo.state.cpu || 0,
|
||||
gpu: serverInfo.state.gpu || [],
|
||||
process: serverInfo.state.process_count || 0,
|
||||
up: serverInfo.state.net_out_speed / 1024 / 1024 || 0,
|
||||
down: serverInfo.state.net_in_speed / 1024 / 1024 || 0,
|
||||
last_active_time_string: lastActiveTime ? dayjs(lastActiveTime).format("YYYY-MM-DD HH:mm:ss") : "",
|
||||
online: now - lastActiveTime <= 30000,
|
||||
uptime: serverInfo.state.uptime || 0,
|
||||
version: serverInfo.host.version || null,
|
||||
tcp: serverInfo.state.tcp_conn_count || 0,
|
||||
udp: serverInfo.state.udp_conn_count || 0,
|
||||
mem: (serverInfo.state.mem_used / serverInfo.host.mem_total) * 100 || 0,
|
||||
swap: (serverInfo.state.swap_used / serverInfo.host.swap_total) * 100 || 0,
|
||||
disk: (serverInfo.state.disk_used / serverInfo.host.disk_total) * 100 || 0,
|
||||
stg: (serverInfo.state.disk_used / serverInfo.host.disk_total) * 100 || 0,
|
||||
country_code: serverInfo.country_code,
|
||||
platform: serverInfo.host.platform || "",
|
||||
net_out_transfer: serverInfo.state.net_out_transfer || 0,
|
||||
net_in_transfer: serverInfo.state.net_in_transfer || 0,
|
||||
arch: serverInfo.host.arch || "",
|
||||
mem_total: serverInfo.host.mem_total || 0,
|
||||
swap_total: serverInfo.host.swap_total || 0,
|
||||
disk_total: serverInfo.host.disk_total || 0,
|
||||
boot_time: serverInfo.host.boot_time || 0,
|
||||
boot_time_string: serverInfo.host.boot_time ? dayjs(serverInfo.host.boot_time * 1000).format("YYYY-MM-DD HH:mm:ss") : "",
|
||||
platform_version: serverInfo.host.platform_version || "",
|
||||
cpu_info: serverInfo.host.cpu || [],
|
||||
gpu_info: serverInfo.host.gpu || [],
|
||||
load_1: serverInfo.state.load_1?.toFixed(2) || 0.0,
|
||||
load_5: serverInfo.state.load_5?.toFixed(2) || 0.0,
|
||||
load_15: serverInfo.state.load_15?.toFixed(2) || 0.0,
|
||||
public_note: handlePublicNote(serverInfo.id, serverInfo.public_note || ""),
|
||||
}
|
||||
const lastActiveTime = serverInfo.last_active.startsWith("000")
|
||||
? 0
|
||||
: parseISOTimestamp(serverInfo.last_active);
|
||||
return {
|
||||
...serverInfo,
|
||||
cpu: serverInfo.state.cpu || 0,
|
||||
gpu: serverInfo.state.gpu || [],
|
||||
process: serverInfo.state.process_count || 0,
|
||||
up: serverInfo.state.net_out_speed / 1024 / 1024 || 0,
|
||||
down: serverInfo.state.net_in_speed / 1024 / 1024 || 0,
|
||||
last_active_time_string: lastActiveTime
|
||||
? dayjs(lastActiveTime).format("YYYY-MM-DD HH:mm:ss")
|
||||
: "",
|
||||
online: now - lastActiveTime <= 30000,
|
||||
uptime: serverInfo.state.uptime || 0,
|
||||
version: serverInfo.host.version || null,
|
||||
tcp: serverInfo.state.tcp_conn_count || 0,
|
||||
udp: serverInfo.state.udp_conn_count || 0,
|
||||
mem: (serverInfo.state.mem_used / serverInfo.host.mem_total) * 100 || 0,
|
||||
swap: (serverInfo.state.swap_used / serverInfo.host.swap_total) * 100 || 0,
|
||||
disk: (serverInfo.state.disk_used / serverInfo.host.disk_total) * 100 || 0,
|
||||
stg: (serverInfo.state.disk_used / serverInfo.host.disk_total) * 100 || 0,
|
||||
country_code: serverInfo.country_code,
|
||||
platform: serverInfo.host.platform || "",
|
||||
net_out_transfer: serverInfo.state.net_out_transfer || 0,
|
||||
net_in_transfer: serverInfo.state.net_in_transfer || 0,
|
||||
arch: serverInfo.host.arch || "",
|
||||
mem_total: serverInfo.host.mem_total || 0,
|
||||
swap_total: serverInfo.host.swap_total || 0,
|
||||
disk_total: serverInfo.host.disk_total || 0,
|
||||
boot_time: serverInfo.host.boot_time || 0,
|
||||
boot_time_string: serverInfo.host.boot_time
|
||||
? dayjs(serverInfo.host.boot_time * 1000).format("YYYY-MM-DD HH:mm:ss")
|
||||
: "",
|
||||
platform_version: serverInfo.host.platform_version || "",
|
||||
cpu_info: serverInfo.host.cpu || [],
|
||||
gpu_info: serverInfo.host.gpu || [],
|
||||
load_1: serverInfo.state.load_1?.toFixed(2) || 0.0,
|
||||
load_5: serverInfo.state.load_5?.toFixed(2) || 0.0,
|
||||
load_15: serverInfo.state.load_15?.toFixed(2) || 0.0,
|
||||
public_note: handlePublicNote(serverInfo.id, serverInfo.public_note || ""),
|
||||
};
|
||||
}
|
||||
|
||||
export function getDaysBetweenDatesWithAutoRenewal({ autoRenewal, cycle, startDate, endDate }: BillingData): {
|
||||
days: number
|
||||
cycleLabel: string
|
||||
remainingPercentage: number
|
||||
export function getDaysBetweenDatesWithAutoRenewal({
|
||||
autoRenewal,
|
||||
cycle,
|
||||
startDate,
|
||||
endDate,
|
||||
}: BillingData): {
|
||||
days: number;
|
||||
cycleLabel: string;
|
||||
remainingPercentage: number;
|
||||
} {
|
||||
let months = 1
|
||||
// 套餐资费
|
||||
let cycleLabel = cycle
|
||||
let months = 1;
|
||||
// 套餐资费
|
||||
let cycleLabel = cycle;
|
||||
|
||||
switch (cycle.toLowerCase()) {
|
||||
case "月":
|
||||
case "m":
|
||||
case "mo":
|
||||
case "month":
|
||||
case "monthly":
|
||||
cycleLabel = "月"
|
||||
months = 1
|
||||
break
|
||||
case "年":
|
||||
case "y":
|
||||
case "yr":
|
||||
case "year":
|
||||
case "annual":
|
||||
cycleLabel = "年"
|
||||
months = 12
|
||||
break
|
||||
case "季":
|
||||
case "q":
|
||||
case "qr":
|
||||
case "quarterly":
|
||||
cycleLabel = "季"
|
||||
months = 3
|
||||
break
|
||||
case "半":
|
||||
case "半年":
|
||||
case "h":
|
||||
case "half":
|
||||
case "semi-annually":
|
||||
cycleLabel = "半年"
|
||||
months = 6
|
||||
break
|
||||
default:
|
||||
cycleLabel = cycle
|
||||
break
|
||||
}
|
||||
switch (cycle.toLowerCase()) {
|
||||
case "月":
|
||||
case "m":
|
||||
case "mo":
|
||||
case "month":
|
||||
case "monthly":
|
||||
cycleLabel = "月";
|
||||
months = 1;
|
||||
break;
|
||||
case "年":
|
||||
case "y":
|
||||
case "yr":
|
||||
case "year":
|
||||
case "annual":
|
||||
cycleLabel = "年";
|
||||
months = 12;
|
||||
break;
|
||||
case "季":
|
||||
case "q":
|
||||
case "qr":
|
||||
case "quarterly":
|
||||
cycleLabel = "季";
|
||||
months = 3;
|
||||
break;
|
||||
case "半":
|
||||
case "半年":
|
||||
case "h":
|
||||
case "half":
|
||||
case "semi-annually":
|
||||
cycleLabel = "半年";
|
||||
months = 6;
|
||||
break;
|
||||
default:
|
||||
cycleLabel = cycle;
|
||||
break;
|
||||
}
|
||||
|
||||
const nowTime = new Date().getTime()
|
||||
const endTime = dayjs(endDate).valueOf()
|
||||
const nowTime = Date.now();
|
||||
const endTime = dayjs(endDate).valueOf();
|
||||
|
||||
if (autoRenewal !== "1") {
|
||||
return {
|
||||
days: getDaysBetweenDates(endDate, new Date(nowTime).toISOString()),
|
||||
cycleLabel: cycleLabel,
|
||||
remainingPercentage:
|
||||
getDaysBetweenDates(endDate, new Date(nowTime).toISOString()) / dayjs(endDate).diff(startDate, "day") > 1
|
||||
? 1
|
||||
: getDaysBetweenDates(endDate, new Date(nowTime).toISOString()) / dayjs(endDate).diff(startDate, "day"),
|
||||
}
|
||||
}
|
||||
if (autoRenewal !== "1") {
|
||||
return {
|
||||
days: getDaysBetweenDates(endDate, new Date(nowTime).toISOString()),
|
||||
cycleLabel: cycleLabel,
|
||||
remainingPercentage:
|
||||
getDaysBetweenDates(endDate, new Date(nowTime).toISOString()) /
|
||||
dayjs(endDate).diff(startDate, "day") >
|
||||
1
|
||||
? 1
|
||||
: getDaysBetweenDates(endDate, new Date(nowTime).toISOString()) /
|
||||
dayjs(endDate).diff(startDate, "day"),
|
||||
};
|
||||
}
|
||||
|
||||
if (nowTime < endTime) {
|
||||
return {
|
||||
days: getDaysBetweenDates(endDate, new Date(nowTime).toISOString()),
|
||||
cycleLabel: cycleLabel,
|
||||
remainingPercentage:
|
||||
getDaysBetweenDates(endDate, new Date(nowTime).toISOString()) / (30 * months) > 1
|
||||
? 1
|
||||
: getDaysBetweenDates(endDate, new Date(nowTime).toISOString()) / (30 * months),
|
||||
}
|
||||
}
|
||||
if (nowTime < endTime) {
|
||||
return {
|
||||
days: getDaysBetweenDates(endDate, new Date(nowTime).toISOString()),
|
||||
cycleLabel: cycleLabel,
|
||||
remainingPercentage:
|
||||
getDaysBetweenDates(endDate, new Date(nowTime).toISOString()) /
|
||||
(30 * months) >
|
||||
1
|
||||
? 1
|
||||
: getDaysBetweenDates(endDate, new Date(nowTime).toISOString()) /
|
||||
(30 * months),
|
||||
};
|
||||
}
|
||||
|
||||
const nextTime = getNextCycleTime(endTime, months, nowTime)
|
||||
const diff = dayjs(nextTime).diff(dayjs(), "day") + 1
|
||||
const remainingPercentage = diff / (30 * months) > 1 ? 1 : diff / (30 * months)
|
||||
const nextTime = getNextCycleTime(endTime, months, nowTime);
|
||||
const diff = dayjs(nextTime).diff(dayjs(), "day") + 1;
|
||||
const remainingPercentage =
|
||||
diff / (30 * months) > 1 ? 1 : diff / (30 * months);
|
||||
|
||||
return {
|
||||
days: diff,
|
||||
cycleLabel: cycleLabel,
|
||||
remainingPercentage: remainingPercentage,
|
||||
}
|
||||
return {
|
||||
days: diff,
|
||||
cycleLabel: cycleLabel,
|
||||
remainingPercentage: remainingPercentage,
|
||||
};
|
||||
}
|
||||
|
||||
// Thanks to hi2shark for the code
|
||||
// https://github.com/hi2shark/nazhua/blob/main/src/utils/date.js#L86
|
||||
export function getNextCycleTime(startDate: number, months: number, specifiedDate: number): number {
|
||||
const start = dayjs(startDate)
|
||||
const checkDate = dayjs(specifiedDate)
|
||||
export function getNextCycleTime(
|
||||
startDate: number,
|
||||
months: number,
|
||||
specifiedDate: number,
|
||||
): number {
|
||||
const start = dayjs(startDate);
|
||||
const checkDate = dayjs(specifiedDate);
|
||||
|
||||
if (!start.isValid() || months <= 0) {
|
||||
throw new Error("参数无效:请检查起始日期、周期月份数和指定日期。")
|
||||
}
|
||||
if (!start.isValid() || months <= 0) {
|
||||
throw new Error("参数无效:请检查起始日期、周期月份数和指定日期。");
|
||||
}
|
||||
|
||||
let nextDate = start
|
||||
let nextDate = start;
|
||||
|
||||
// 循环增加周期直到大于当前日期
|
||||
let whileStatus = true
|
||||
while (whileStatus) {
|
||||
nextDate = nextDate.add(months, "month")
|
||||
whileStatus = nextDate.valueOf() <= checkDate.valueOf()
|
||||
}
|
||||
// 循环增加周期直到大于当前日期
|
||||
let whileStatus = true;
|
||||
while (whileStatus) {
|
||||
nextDate = nextDate.add(months, "month");
|
||||
whileStatus = nextDate.valueOf() <= checkDate.valueOf();
|
||||
}
|
||||
|
||||
return nextDate.valueOf() // 返回时间毫秒数
|
||||
return nextDate.valueOf(); // 返回时间毫秒数
|
||||
}
|
||||
|
||||
export function getDaysBetweenDates(date1: string, date2: string): number {
|
||||
const oneDay = 24 * 60 * 60 * 1000 // 一天的毫秒数
|
||||
const firstDate = new Date(date1)
|
||||
const secondDate = new Date(date2)
|
||||
const oneDay = 24 * 60 * 60 * 1000; // 一天的毫秒数
|
||||
const firstDate = new Date(date1);
|
||||
const secondDate = new Date(date2);
|
||||
|
||||
// 计算两个日期之间的天数差异
|
||||
return Math.round((firstDate.getTime() - secondDate.getTime()) / oneDay)
|
||||
// 计算两个日期之间的天数差异
|
||||
return Math.round((firstDate.getTime() - secondDate.getTime()) / oneDay);
|
||||
}
|
||||
|
||||
export const fetcher = (url: string) =>
|
||||
fetch(url)
|
||||
.then((res) => {
|
||||
if (!res.ok) {
|
||||
throw new Error(res.statusText)
|
||||
}
|
||||
return res.json()
|
||||
})
|
||||
.then((data) => data.data)
|
||||
.catch((err) => {
|
||||
console.error(err)
|
||||
throw err
|
||||
})
|
||||
fetch(url)
|
||||
.then((res) => {
|
||||
if (!res.ok) {
|
||||
throw new Error(res.statusText);
|
||||
}
|
||||
return res.json();
|
||||
})
|
||||
.then((data) => data.data)
|
||||
.catch((err) => {
|
||||
console.error(err);
|
||||
throw err;
|
||||
});
|
||||
|
||||
export const nezhaFetcher = async (url: string) => {
|
||||
const res = await fetch(url)
|
||||
const res = await fetch(url);
|
||||
|
||||
if (!res.ok) {
|
||||
const error = new Error("An error occurred while fetching the data.")
|
||||
// @ts-expect-error - res.json() returns a Promise<any>
|
||||
error.info = await res.json()
|
||||
// @ts-expect-error - res.status is a number
|
||||
error.status = res.status
|
||||
throw error
|
||||
}
|
||||
if (!res.ok) {
|
||||
const error = new Error("An error occurred while fetching the data.");
|
||||
// @ts-expect-error - res.json() returns a Promise<any>
|
||||
error.info = await res.json();
|
||||
// @ts-expect-error - res.status is a number
|
||||
error.status = res.status;
|
||||
throw error;
|
||||
}
|
||||
|
||||
return res.json()
|
||||
}
|
||||
return res.json();
|
||||
};
|
||||
|
||||
export function parseISOTimestamp(isoString: string): number {
|
||||
return new Date(isoString).getTime()
|
||||
return new Date(isoString).getTime();
|
||||
}
|
||||
|
||||
export function formatRelativeTime(timestamp: number): string {
|
||||
const now = Date.now()
|
||||
const diff = now - timestamp
|
||||
const hours = Math.floor(diff / (1000 * 60 * 60))
|
||||
const minutes = Math.floor((diff % (1000 * 60 * 60)) / (1000 * 60))
|
||||
const seconds = Math.floor((diff % (1000 * 60)) / 1000)
|
||||
const now = Date.now();
|
||||
const diff = now - timestamp;
|
||||
const hours = Math.floor(diff / (1000 * 60 * 60));
|
||||
const minutes = Math.floor((diff % (1000 * 60 * 60)) / (1000 * 60));
|
||||
const seconds = Math.floor((diff % (1000 * 60)) / 1000);
|
||||
|
||||
if (hours > 24) {
|
||||
const days = Math.floor(hours / 24)
|
||||
return `${days}d`
|
||||
} else if (hours > 0) {
|
||||
return `${hours}h`
|
||||
} else if (minutes > 0) {
|
||||
return `${minutes}m`
|
||||
} else if (seconds >= 0) {
|
||||
return `${seconds}s`
|
||||
}
|
||||
return "0s"
|
||||
if (hours > 24) {
|
||||
const days = Math.floor(hours / 24);
|
||||
return `${days}d`;
|
||||
} else if (hours > 0) {
|
||||
return `${hours}h`;
|
||||
} else if (minutes > 0) {
|
||||
return `${minutes}m`;
|
||||
} else if (seconds >= 0) {
|
||||
return `${seconds}s`;
|
||||
}
|
||||
return "0s";
|
||||
}
|
||||
|
||||
export function formatTime(timestamp: number): string {
|
||||
const date = new Date(timestamp)
|
||||
const year = date.getFullYear()
|
||||
const month = date.getMonth() + 1
|
||||
const day = date.getDate()
|
||||
const hours = date.getHours().toString().padStart(2, "0")
|
||||
const minutes = date.getMinutes().toString().padStart(2, "0")
|
||||
const seconds = date.getSeconds().toString().padStart(2, "0")
|
||||
return `${year}-${month}-${day} ${hours}:${minutes}:${seconds}`
|
||||
const date = new Date(timestamp);
|
||||
const year = date.getFullYear();
|
||||
const month = date.getMonth() + 1;
|
||||
const day = date.getDate();
|
||||
const hours = date.getHours().toString().padStart(2, "0");
|
||||
const minutes = date.getMinutes().toString().padStart(2, "0");
|
||||
const seconds = date.getSeconds().toString().padStart(2, "0");
|
||||
return `${year}-${month}-${day} ${hours}:${minutes}:${seconds}`;
|
||||
}
|
||||
|
||||
interface BillingData {
|
||||
startDate: string
|
||||
endDate: string
|
||||
autoRenewal: string
|
||||
cycle: string
|
||||
amount: string
|
||||
startDate: string;
|
||||
endDate: string;
|
||||
autoRenewal: string;
|
||||
cycle: string;
|
||||
amount: string;
|
||||
}
|
||||
|
||||
interface PlanData {
|
||||
bandwidth: string
|
||||
trafficVol: string
|
||||
trafficType: string
|
||||
IPv4: string
|
||||
IPv6: string
|
||||
networkRoute: string
|
||||
extra: string
|
||||
bandwidth: string;
|
||||
trafficVol: string;
|
||||
trafficType: string;
|
||||
IPv4: string;
|
||||
IPv6: string;
|
||||
networkRoute: string;
|
||||
extra: string;
|
||||
}
|
||||
|
||||
export interface PublicNoteData {
|
||||
billingDataMod?: BillingData
|
||||
planDataMod?: PlanData
|
||||
billingDataMod?: BillingData;
|
||||
planDataMod?: PlanData;
|
||||
}
|
||||
|
||||
export function parsePublicNote(publicNote: string): PublicNoteData | null {
|
||||
try {
|
||||
if (!publicNote) {
|
||||
return null
|
||||
}
|
||||
const data = JSON.parse(publicNote)
|
||||
if (!data.billingDataMod && !data.planDataMod) {
|
||||
return null
|
||||
}
|
||||
if (data.billingDataMod && !data.planDataMod) {
|
||||
return {
|
||||
billingDataMod: {
|
||||
startDate: data.billingDataMod.startDate || "",
|
||||
endDate: data.billingDataMod.endDate,
|
||||
autoRenewal: data.billingDataMod.autoRenewal || "",
|
||||
cycle: data.billingDataMod.cycle || "",
|
||||
amount: data.billingDataMod.amount || "",
|
||||
},
|
||||
}
|
||||
}
|
||||
if (!data.billingDataMod && data.planDataMod) {
|
||||
return {
|
||||
planDataMod: {
|
||||
bandwidth: data.planDataMod.bandwidth || "",
|
||||
trafficVol: data.planDataMod.trafficVol || "",
|
||||
trafficType: data.planDataMod.trafficType || "",
|
||||
IPv4: data.planDataMod.IPv4 || "",
|
||||
IPv6: data.planDataMod.IPv6 || "",
|
||||
networkRoute: data.planDataMod.networkRoute || "",
|
||||
extra: data.planDataMod.extra || "",
|
||||
},
|
||||
}
|
||||
}
|
||||
try {
|
||||
if (!publicNote) {
|
||||
return null;
|
||||
}
|
||||
const data = JSON.parse(publicNote);
|
||||
if (!data.billingDataMod && !data.planDataMod) {
|
||||
return null;
|
||||
}
|
||||
if (data.billingDataMod && !data.planDataMod) {
|
||||
return {
|
||||
billingDataMod: {
|
||||
startDate: data.billingDataMod.startDate || "",
|
||||
endDate: data.billingDataMod.endDate,
|
||||
autoRenewal: data.billingDataMod.autoRenewal || "",
|
||||
cycle: data.billingDataMod.cycle || "",
|
||||
amount: data.billingDataMod.amount || "",
|
||||
},
|
||||
};
|
||||
}
|
||||
if (!data.billingDataMod && data.planDataMod) {
|
||||
return {
|
||||
planDataMod: {
|
||||
bandwidth: data.planDataMod.bandwidth || "",
|
||||
trafficVol: data.planDataMod.trafficVol || "",
|
||||
trafficType: data.planDataMod.trafficType || "",
|
||||
IPv4: data.planDataMod.IPv4 || "",
|
||||
IPv6: data.planDataMod.IPv6 || "",
|
||||
networkRoute: data.planDataMod.networkRoute || "",
|
||||
extra: data.planDataMod.extra || "",
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
return {
|
||||
billingDataMod: {
|
||||
startDate: data.billingDataMod.startDate || "",
|
||||
endDate: data.billingDataMod.endDate,
|
||||
autoRenewal: data.billingDataMod.autoRenewal || "",
|
||||
cycle: data.billingDataMod.cycle || "",
|
||||
amount: data.billingDataMod.amount || "",
|
||||
},
|
||||
planDataMod: {
|
||||
bandwidth: data.planDataMod.bandwidth || "",
|
||||
trafficVol: data.planDataMod.trafficVol || "",
|
||||
trafficType: data.planDataMod.trafficType || "",
|
||||
IPv4: data.planDataMod.IPv4 || "",
|
||||
IPv6: data.planDataMod.IPv6 || "",
|
||||
networkRoute: data.planDataMod.networkRoute || "",
|
||||
extra: data.planDataMod.extra || "",
|
||||
},
|
||||
}
|
||||
} catch (error) {
|
||||
console.error("Error parsing public note:", error)
|
||||
return null
|
||||
}
|
||||
return {
|
||||
billingDataMod: {
|
||||
startDate: data.billingDataMod.startDate || "",
|
||||
endDate: data.billingDataMod.endDate,
|
||||
autoRenewal: data.billingDataMod.autoRenewal || "",
|
||||
cycle: data.billingDataMod.cycle || "",
|
||||
amount: data.billingDataMod.amount || "",
|
||||
},
|
||||
planDataMod: {
|
||||
bandwidth: data.planDataMod.bandwidth || "",
|
||||
trafficVol: data.planDataMod.trafficVol || "",
|
||||
trafficType: data.planDataMod.trafficType || "",
|
||||
IPv4: data.planDataMod.IPv4 || "",
|
||||
IPv6: data.planDataMod.IPv6 || "",
|
||||
networkRoute: data.planDataMod.networkRoute || "",
|
||||
extra: data.planDataMod.extra || "",
|
||||
},
|
||||
};
|
||||
} catch (error) {
|
||||
console.error("Error parsing public note:", error);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
// Function to handle public_note with sessionStorage
|
||||
export function handlePublicNote(serverId: number, publicNote: string): string {
|
||||
const storageKey = `server_${serverId}_public_note`
|
||||
const storedNote = sessionStorage.getItem(storageKey)
|
||||
const storageKey = `server_${serverId}_public_note`;
|
||||
const storedNote = sessionStorage.getItem(storageKey);
|
||||
|
||||
if (!publicNote && storedNote) {
|
||||
return storedNote
|
||||
}
|
||||
if (!publicNote && storedNote) {
|
||||
return storedNote;
|
||||
}
|
||||
|
||||
if (publicNote) {
|
||||
sessionStorage.setItem(storageKey, publicNote)
|
||||
return publicNote
|
||||
}
|
||||
if (publicNote) {
|
||||
sessionStorage.setItem(storageKey, publicNote);
|
||||
return publicNote;
|
||||
}
|
||||
|
||||
return ""
|
||||
return "";
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user