diff --git a/UPDATELOG.md b/UPDATELOG.md index 7ddefc45..c90a8a4e 100644 --- a/UPDATELOG.md +++ b/UPDATELOG.md @@ -65,6 +65,8 @@ - Mihomo 内核默认日志等级为 warn - Clash Verge Rev 应用默认日志等级为 warn - 重构了原来的 IP 信息请求重试机制,采用轮询检测,解决了 Network Error 和超时问题 + - 对轮询检测机制进行了优化,引入洗牌算法来增强随机性。 + - 对获取系统信息的流程进行了优化,并添加了去重检测机制,确保剔除重复的信息 ## v2.2.3 diff --git a/src/components/home/system-info-card.tsx b/src/components/home/system-info-card.tsx index cd6c0f93..1fe6fe1a 100644 --- a/src/components/home/system-info-card.tsx +++ b/src/components/home/system-info-card.tsx @@ -26,28 +26,34 @@ export const SystemInfoCard = () => { const navigate = useNavigate(); const { isAdminMode, isSidecarMode, mutateRunningMode } = useSystemState(); - // 系统信息状态 - const [systemState, setSystemState] = useState({ - osInfo: "", - lastCheckUpdate: "-", - }); +// 系统信息状态 +const [systemState, setSystemState] = useState({ + osInfo: "", + lastCheckUpdate: "-", +}); - // 初始化系统信息 - useEffect(() => { - // 获取系统信息 - getSystemInfo() - .then((info) => { - const lines = info.split("\n"); - if (lines.length > 0) { - const sysName = lines[0].split(": ")[1] || ""; - const sysVersion = lines[1].split(": ")[1] || ""; - setSystemState((prev) => ({ - ...prev, - osInfo: `${sysName} ${sysVersion}`, - })); +// 初始化系统信息 +useEffect(() => { + // 获取系统信息 + getSystemInfo() + .then((info) => { + const lines = info.split("\n"); + if (lines.length > 0) { + const sysName = lines[0].split(": ")[1] || ""; + let sysVersion = lines[1].split(": ")[1] || ""; + + // 处理sysVersion前缀与sysName相同的情况 + if (sysName && sysVersion.toLowerCase().startsWith(sysName.toLowerCase())) { + sysVersion = sysVersion.substring(sysName.length).trim(); } - }) - .catch(console.error); + + setSystemState((prev) => ({ + ...prev, + osInfo: `${sysName} ${sysVersion}`, + })); + } + }) + .catch(console.error); // 获取最后检查更新时间 const lastCheck = localStorage.getItem("last_check_update"); diff --git a/src/services/api.ts b/src/services/api.ts index 15c895ec..67489d78 100644 --- a/src/services/api.ts +++ b/src/services/api.ts @@ -376,31 +376,97 @@ const IP_CHECK_SERVICES: ServiceConfig[] = [ }), }, { - url: "https://ipinfo.io/json", - mapping: (data) => { - const [asn, ...orgParts] = (data.org || '').split(' '); - const asnOrg = orgParts.join(' '); - - return { - ip: data.ip || '', - country_code: data.country || '', - country: data.country || '', - region: data.region || '', - city: data.city || '', - organization: asnOrg || '', - asn: asn? parseInt(asn.replace('AS', '')) : 0, - asn_organization: asnOrg || '', - longitude: parseFloat(data.loc?.split(',')[1] || '0'), - latitude: parseFloat(data.loc?.split(',')[0] || '0'), - timezone: data.timezone || '', - }; - }, + url: "https://api.ipapi.is/", + mapping: (data) => ({ + ip: data.ip || '', + country_code: data.location?.country_code || '', + country: data.location?.country || '', + region: data.location?.state || '', + city: data.location?.city || '', + organization: data.asn?.org || data.company?.name || '', + asn: data.asn?.asn || 0, + asn_organization: data.asn?.org || '', + longitude: data.location?.longitude || 0, + latitude: data.location?.latitude || 0, + timezone: data.location?.timezone || '', + }), + }, + { + url: "https://ipwho.is/", + mapping: (data) => ({ + ip: data.ip || '', + country_code: data.country_code || '', + country: data.country || '', + region: data.region || '', + city: data.city || '', + organization: data.connection?.org || data.connection?.isp || '', + asn: data.connection?.asn || 0, + asn_organization: data.connection?.isp || '', + longitude: data.longitude || 0, + latitude: data.latitude || 0, + timezone: data.timezone?.id || '', + }), }, ]; -// 随机打乱服务列表顺序 +// 随机性服务列表洗牌函数 function shuffleServices() { - return [...IP_CHECK_SERVICES].sort(() => Math.random() - 0.5); + // 过滤无效服务并确保每个元素符合ServiceConfig接口 + const validServices = IP_CHECK_SERVICES.filter( + (service): service is ServiceConfig => + service !== null && + service !== undefined && + typeof service.url === 'string' && + typeof service.mapping === 'function' // 添加对mapping属性的检查 + ); + + if (validServices.length === 0) { + console.error('No valid services found in IP_CHECK_SERVICES'); + return []; + } + + // 使用单一Fisher-Yates洗牌算法,增强随机性 + const shuffled = [...validServices]; + const length = shuffled.length; + + // 使用多个种子进行多次洗牌 + const seeds = [ + Math.random(), + Date.now() / 1000, + performance.now() / 1000 + ]; + + for (const seed of seeds) { + const prng = createPrng(seed); + + // Fisher-Yates洗牌算法 + for (let i = length - 1; i > 0; i--) { + const j = Math.floor(prng() * (i + 1)); + + // 使用临时变量进行交换,避免解构赋值可能的问题 + const temp = shuffled[i]; + shuffled[i] = shuffled[j]; + shuffled[j] = temp; + } + } + + return shuffled; +} + +// 创建一个简单的随机数生成器 +function createPrng(seed: number): () => number { + // 使用xorshift32算法 + let state = seed >>> 0; + + // 如果种子为0,设置一个默认值 + if (state === 0) state = 123456789; + + return function() { + state ^= state << 13; + state ^= state >>> 17; + state ^= state << 5; + return (state >>> 0) / 4294967296; + }; } // 获取当前IP和地理位置信息