// 浏览器信息检测 class SystemInfo { constructor() { this.info = { browser: this.getBrowserInfo(), os: this.getOSInfo(), hardware: this.getHardwareInfo(), webgl: this.getWebGLInfo() }; } // 获取浏览器信息 getBrowserInfo() { const ua = navigator.userAgent; let browser = { name: 'Unknown', version: 'Unknown', fullVersion: navigator.appVersion }; // 检测浏览器类型 if (ua.includes('Firefox')) { browser.name = 'Firefox'; browser.version = this.extractVersion(ua, 'Firefox'); } else if (ua.includes('Chrome') && !ua.includes('Edg') && !ua.includes('OPR')) { browser.name = 'Chrome'; browser.version = this.extractVersion(ua, 'Chrome'); } else if (ua.includes('Safari') && !ua.includes('Chrome')) { browser.name = 'Safari'; browser.version = this.extractVersion(ua, 'Version'); } else if (ua.includes('Edg')) { browser.name = 'Edge'; browser.version = this.extractVersion(ua, 'Edg'); } else if (ua.includes('OPR') || ua.includes('Opera')) { browser.name = 'Opera'; browser.version = this.extractVersion(ua, 'OPR') || this.extractVersion(ua, 'Opera'); } else if (ua.includes('Trident') || ua.includes('MSIE')) { browser.name = 'Internet Explorer'; browser.version = this.extractVersion(ua, 'MSIE') || this.extractVersion(ua, 'rv:'); } return browser; } // 提取版本号 extractVersion(userAgent, browserName) { const match = userAgent.match(new RegExp(`${browserName}/([0-9]+(\\.[0-9]+)?)`)); return match ? match[1] : 'Unknown'; } // 获取操作系统信息 getOSInfo() { const ua = navigator.userAgent; let os = { name: 'Unknown', version: 'Unknown', architecture: this.getArchitecture() }; if (ua.includes('Windows')) { os.name = 'Windows'; if (ua.includes('Windows NT 10.0')) os.version = '10'; else if (ua.includes('Windows NT 6.3')) os.version = '8.1'; else if (ua.includes('Windows NT 6.2')) os.version = '8'; else if (ua.includes('Windows NT 6.1')) os.version = '7'; else if (ua.includes('Windows NT 6.0')) os.version = 'Vista'; else if (ua.includes('Windows NT 5.1')) os.version = 'XP'; } else if (ua.includes('Mac OS X')) { os.name = 'macOS'; const match = ua.match(/Mac OS X (\d+[._]\d+)/); if (match) os.version = match[1].replace('_', '.'); } else if (ua.includes('Linux')) { os.name = 'Linux'; } else if (ua.includes('Android')) { os.name = 'Android'; const match = ua.match(/Android ([0-9.]+)/); if (match) os.version = match[1]; } else if (ua.includes('like Mac')) { os.name = 'iOS'; const match = ua.match(/OS (\d+[_]\d+)/); if (match) os.version = match[1].replace('_', '.'); } return os; } // 获取系统架构 getArchitecture() { if (navigator.userAgent.includes('x64') || navigator.userAgent.includes('x86_64')) { return '64-bit'; } else if (navigator.userAgent.includes('x86') || navigator.userAgent.includes('i686')) { return '32-bit'; } else if (navigator.userAgent.includes('ARM')) { return 'ARM'; } else if (navigator.userAgent.includes('Win64')) { return '64-bit'; } return 'Unknown'; } // 获取硬件信息 getHardwareInfo() { return { logicalCores: navigator.hardwareConcurrency || 'Unknown', deviceMemory: navigator.deviceMemory ? `${navigator.deviceMemory} GB` : 'Unknown', maxTouchPoints: navigator.maxTouchPoints || 0 }; } // 获取WebGL和显卡信息 getWebGLInfo() { const webglInfo = { webgl1: this.getWebGLContextInfo('webgl'), webgl2: this.getWebGLContextInfo('webgl2'), supported: false, renderer: 'Unknown', vendor: 'Unknown', version: 'Unknown', shadingLanguage: 'Unknown', extensions: [] }; const canvas = document.createElement('canvas'); let gl = null; // 尝试获取WebGL2上下文 try { gl = canvas.getContext('webgl2') || canvas.getContext('experimental-webgl2'); } catch (e) { console.log('WebGL2 not supported:', e.message); } // 如果WebGL2不可用,尝试WebGL1 if (!gl) { try { gl = canvas.getContext('webgl') || canvas.getContext('experimental-webgl'); } catch (e) { console.log('WebGL not supported:', e.message); } } if (gl) { webglInfo.supported = true; // 获取显卡信息 const debugInfo = gl.getExtension('WEBGL_debug_renderer_info'); if (debugInfo) { webglInfo.renderer = gl.getParameter(debugInfo.UNMASKED_RENDERER_WEBGL) || 'Unknown'; webglInfo.vendor = gl.getParameter(debugInfo.UNMASKED_VENDOR_WEBGL) || 'Unknown'; } // 获取WebGL版本信息 webglInfo.version = gl.getParameter(gl.VERSION) || 'Unknown'; webglInfo.shadingLanguage = gl.getParameter(gl.SHADING_LANGUAGE_VERSION) || 'Unknown'; // 获取支持的扩展 try { webglInfo.extensions = gl.getSupportedExtensions() || []; } catch (e) { console.log('无法获取WebGL扩展:', e.message); } // 检查GPU性能级别 webglInfo.performance = this.getGPUPerformanceInfo(gl); // 检查内存信息(如果支持) webglInfo.memoryInfo = this.getGPUMemoryInfo(gl); // 检查是否使用集成显卡 if (webglInfo.renderer) { webglInfo.gpuType = this.detectGPUType(webglInfo.renderer); } } return webglInfo; } // 获取WebGL上下文的具体信息 getWebGLContextInfo(contextType) { const canvas = document.createElement('canvas'); let gl = null; try { gl = canvas.getContext(contextType) || canvas.getContext(`experimental-${contextType}`); } catch (e) { return { supported: false, error: e.message }; } if (!gl) { return { supported: false }; } return { supported: true, context: gl }; } // 获取GPU性能信息 getGPUPerformanceInfo(gl) { const info = { tier: 'unknown', features: [] }; // 检查是否支持高性能特性 try { // 检查帧缓冲 if (gl.checkFramebufferStatus) { info.features.push('framebuffer'); } // 检查浮点纹理 const floatExt = gl.getExtension('OES_texture_float') || gl.getExtension('EXT_color_buffer_float'); if (floatExt) info.features.push('float_textures'); // 检查多重采样 const msaaExt = gl.getExtension('WEBGL_multisampled_render_to_texture'); if (msaaExt) info.features.push('msaa'); // 检查实例化渲染 const instancingExt = gl.getExtension('ANGLE_instanced_arrays') || gl.getExtension('WEBGL_draw_buffers'); if (instancingExt) info.features.push('instancing'); // 尝试检测性能级别(基于支持的扩展) if (info.features.includes('float_textures') && info.features.includes('msaa') && info.features.includes('instancing')) { info.tier = 'high'; } else if (info.features.length >= 2) { info.tier = 'medium'; } else { info.tier = 'low'; } } catch (e) { console.log('获取GPU性能信息失败:', e); } return info; } // 获取GPU内存信息 getGPUMemoryInfo(gl) { const memoryInfo = { estimatedMemory: 'Unknown' }; // 尝试通过扩展获取内存信息 try { // 检查是否支持内存信息扩展 const memoryExt = gl.getExtension('WEBGL_debug_renderer_info'); if (memoryExt) { // 一些浏览器会通过UNMASKED_RENDERER_WEBGL暴露内存信息 const renderer = gl.getParameter(memoryExt.UNMASKED_RENDERER_WEBGL); if (renderer) { // 尝试从渲染器字符串中提取内存信息 const match = renderer.match(/(\d+)\s*MB|(\d+)\s*GB|VRAM\s*:\s*(\d+)/i); if (match) { memoryInfo.estimatedMemory = match[0]; } } } // 通过创建大纹理测试内存 memoryInfo.maxTextureSize = gl.getParameter(gl.MAX_TEXTURE_SIZE); memoryInfo.maxRenderbufferSize = gl.getParameter(gl.MAX_RENDERBUFFER_SIZE); } catch (e) { // 静默失败 } return memoryInfo; } // 检测GPU类型 detectGPUType(renderer) { const r = renderer.toLowerCase(); if (r.includes('nvidia') || r.includes('geforce') || r.includes('gtx') || r.includes('rtx')) { return { type: 'NVIDIA', discrete: true }; } else if (r.includes('amd') || r.includes('radeon') || r.includes('rx')) { return { type: 'AMD', discrete: true }; } else if (r.includes('intel') || r.includes('hd graphics') || r.includes('iris') || r.includes('uhd')) { return { type: 'Intel', discrete: false }; } else if (r.includes('apple') || r.includes('apple gpu') || r.includes('apple m')) { return { type: 'Apple Silicon', discrete: false }; } else if (r.includes('mali') || r.includes('adreno') || r.includes('powervr')) { return { type: 'Mobile GPU', discrete: false }; } else if (r.includes('microsoft') || r.includes('basic')) { return { type: 'Software Renderer', discrete: false }; } return { type: 'Unknown', discrete: false }; } // 获取屏幕信息 getScreenInfo() { return { width: window.screen.width, height: window.screen.height, colorDepth: window.screen.colorDepth, pixelDepth: window.screen.pixelDepth, devicePixelRatio: window.devicePixelRatio || 1, orientation: window.screen.orientation ? window.screen.orientation.type : 'unknown' }; } // 获取所有系统信息 getAllInfo() { return { ...this.info, screen: this.getScreenInfo(), userAgent: navigator.userAgent, platform: navigator.platform, language: navigator.language, languages: navigator.languages, cookiesEnabled: navigator.cookieEnabled, online: navigator.onLine, javaEnabled: navigator.javaEnabled ? navigator.javaEnabled() : false, pdfViewerEnabled: navigator.pdfViewerEnabled || false, doNotTrack: navigator.doNotTrack || 'unknown', timezone: Intl.DateTimeFormat().resolvedOptions().timeZone, dateTimeFormat: new Date().toString() }; } // 格式化输出 formatAsText() { const info = this.getAllInfo(); let output = '========== 系统信息 ==========\n\n'; // 浏览器信息 output += '=== 浏览器信息 ===\n'; output += `浏览器: ${info.browser.name} ${info.browser.version}\n`; output += `完整版本: ${info.browser.fullVersion}\n`; output += `用户代理: ${info.userAgent}\n\n`; // 操作系统信息 output += '=== 操作系统信息 ===\n'; output += `系统: ${info.os.name} ${info.os.version}\n`; output += `架构: ${info.os.architecture}\n`; output += `平台: ${info.platform}\n\n`; // 硬件信息 output += '=== 硬件信息 ===\n'; output += `逻辑核心数: ${info.hardware.logicalCores}\n`; output += `设备内存: ${info.hardware.deviceMemory}\n`; output += `最大触摸点数: ${info.hardware.maxTouchPoints}\n\n`; // 屏幕信息 output += '=== 屏幕信息 ===\n'; output += `分辨率: ${info.screen.width} × ${info.screen.height}\n`; output += `设备像素比: ${info.screen.devicePixelRatio}\n`; output += `颜色深度: ${info.screen.colorDepth} 位\n`; output += `像素深度: ${info.screen.pixelDepth} 位\n`; output += `方向: ${info.screen.orientation}\n\n`; // WebGL信息 output += '=== WebGL 信息 ===\n'; output += `WebGL 支持: ${info.webgl.supported ? '是' : '否'}\n`; if (info.webgl.supported) { output += `WebGL 版本: ${info.webgl.version}\n`; output += `显卡型号: ${info.webgl.renderer}\n`; output += `显卡厂商: ${info.webgl.vendor}\n`; output += `着色语言: ${info.webgl.shadingLanguage}\n`; if (info.webgl.gpuType) { output += `GPU 类型: ${info.webgl.gpuType.type}\n`; output += `独立显卡: ${info.webgl.gpuType.discrete ? '是' : '否'}\n`; } output += `性能等级: ${info.webgl.performance.tier}\n`; output += `支持特性: ${info.webgl.performance.features.join(', ')}\n`; if (info.webgl.memoryInfo.estimatedMemory !== 'Unknown') { output += `显存估计: ${info.webgl.memoryInfo.estimatedMemory}\n`; } if (info.webgl.memoryInfo.maxTextureSize) { output += `最大纹理尺寸: ${info.webgl.memoryInfo.maxTextureSize}\n`; } output += `WebGL 扩展数: ${info.webgl.extensions.length}\n`; } // 其他信息 output += '\n=== 其他信息 ===\n'; output += `语言: ${info.language}\n`; output += `支持语言: ${info.languages.join(', ')}\n`; output += `时区: ${info.timezone}\n`; output += `Cookie 支持: ${info.cookiesEnabled ? '是' : '否'}\n`; output += `在线状态: ${info.online ? '在线' : '离线'}\n`; output += `Java 支持: ${info.javaEnabled ? '是' : '否'}\n`; output += `PDF 查看器: ${info.pdfViewerEnabled ? '支持' : '不支持'}\n`; output += `Do Not Track: ${info.doNotTrack}\n`; output += `当前时间: ${info.dateTimeFormat}\n`; return output; } // 创建HTML显示 createInfoHTML() { const info = this.getAllInfo(); let html = `

系统信息

🌐 浏览器信息

浏览器${info.browser.name} ${info.browser.version}
用户代理${info.userAgent}
平台${info.platform}

💻 操作系统

系统${info.os.name} ${info.os.version}
架构${info.os.architecture}
语言${info.language}
时区${info.timezone}

🖥️ 硬件信息

CPU 核心数${info.hardware.logicalCores}
设备内存${info.hardware.deviceMemory}
屏幕分辨率${info.screen.width} × ${info.screen.height}
设备像素比${info.screen.devicePixelRatio}
`; if (info.webgl.supported) { html += `

🎮 WebGL & 显卡信息

`; if (info.webgl.memoryInfo.estimatedMemory !== 'Unknown') { html += ``; } html += `
WebGL 支持✅ 已支持
WebGL 版本${info.webgl.version}
显卡型号${info.webgl.renderer}
显卡厂商${info.webgl.vendor}
GPU 类型${info.webgl.gpuType.type} ${info.webgl.gpuType.discrete ? '(独立显卡)' : '(集成显卡)'}
着色语言${info.webgl.shadingLanguage}
性能等级${info.webgl.performance.tier}
WebGL 扩展数${info.webgl.extensions.length} 个
显存估计${info.webgl.memoryInfo.estimatedMemory}
`; } else { html += `

🎮 WebGL & 显卡信息

❌ WebGL 不支持

`; } html += `
`; return html; } deepSortObject(obj) { if (obj === null || typeof obj !== 'object') { return obj; } if (Array.isArray(obj)) { return obj.map(deepSortObject); } const sorted = {}; Object.keys(obj).sort().forEach(key => { sorted[key] = this.deepSortObject(obj[key]); }); return sorted; } getCanonicalString(obj) { if (typeof obj !== 'object' || obj === null) { return JSON.stringify(obj); } const sorted = this.deepSortObject(obj); return JSON.stringify(sorted); } // 简单哈希函数 simpleHash(str) { let hash = 0; for (let i = 0; i < str.length; i++) { const char = str.charCodeAt(i); hash = ((hash << 5) - hash) + char; hash = hash & hash; } return hash; } // 简单SHA-256模拟 simpleSHA256(str) { let hash = 0; for (let i = 0; i < str.length; i++) { const char = str.charCodeAt(i); hash = ((hash << 5) - hash) + char; hash = hash & hash; } const hashArray = []; for (let i = 0; i < 8; i++) { hashArray[i] = (hash + i * 2654435761) >>> 0; } return hashArray; } // 格式化哈希为GUID formatHashAsGuid(hashArray) { const hexParts = hashArray.map(h => h.toString(16).padStart(8, '0')); return `${hexParts[0]}${hexParts[1].substring(0, 4)}-${hexParts[1].substring(4)}-${hexParts[2].substring(0, 4)}-${hexParts[3].substring(0, 4)}-${hexParts[3].substring(4)}${hexParts[4]}${hexParts[5]}`; } // 1. 确定性哈希算法 objectToGuidDeterministic(obj) { const canonicalString = this.getCanonicalString(obj); const hash = this.simpleSHA256(canonicalString); return this.formatHashAsGuid(hash).toUpperCase(); } // 2. 伪随机算法 getSeedFromObject(obj) { const str = JSON.stringify(obj); return this.simpleHash(str); } createSeededRandom(seed) { let state = seed; return function () { state = (state * 1664525 + 1013904223) >>> 0; return (state & 0x3FFFFFFF) / 0x3FFFFFFF; }; } generateVersion4Guid(randomFn) { let guid = ''; for (let i = 0; i < 32; i++) { if (i === 8 || i === 12 || i === 16 || i === 20) { guid += '-'; } if (i === 12) { guid += '4'; } else if (i === 16) { const variant = Math.floor(randomFn() * 4); guid += (8 + variant).toString(16).toUpperCase(); } else { const randomHex = Math.floor(randomFn() * 16).toString(16); guid += randomHex; } } return guid.toUpperCase(); } objectToGuidPseudorandom(obj) { const seed = this.getSeedFromObject(obj); const prng = this.createSeededRandom(seed); return this.generateVersion4Guid(prng); } // 3. Crypto API算法(同步版本) objectToGuidCryptoSync(obj) { try { const str = this.getCanonicalString(obj); let hash = 0; for (let i = 0; i < str.length; i++) { const char = str.charCodeAt(i); hash = ((hash << 5) - hash) + char; hash = hash & hash; } const bytes = new Array(16); for (let i = 0; i < 16; i++) { bytes[i] = (hash + i * 2654435761) & 0xFF; } bytes[6] = (bytes[6] & 0x0F) | 0x40; bytes[8] = (bytes[8] & 0x3F) | 0x80; return bytes.map(b => b.toString(16).padStart(2, '0')) .join('') .replace(/(.{8})(.{4})(.{4})(.{4})(.{12})/, '$1-$2-$3-$4-$5') .toUpperCase(); } catch (error) { return this.objectToGuidDeterministic(obj); } } // 4. 组合算法 combineComponents(deterministicHash, namespaceHash, timestamp, randomComponent) { const hashDigits = deterministicHash.replace(/-/g, ''); const bytes = new Array(16); for (let i = 0; i < 16; i++) { const hashByte = parseInt(hashDigits.substr(i * 2, 2), 16) || 0; const nsByte = (namespaceHash >> (i * 2)) & 0xFF; const timeByte = (timestamp >> (i * 2)) & 0xFF; const randomByte = parseInt(randomComponent.substr(i % 8, 1), 16) || 0; bytes[i] = (hashByte ^ nsByte ^ timeByte ^ randomByte) & 0xFF; } bytes[6] = (bytes[6] & 0x0F) | 0x40; bytes[8] = (bytes[8] & 0x3F) | 0x80; return bytes.map(b => b.toString(16).padStart(2, '0')) .join('') .replace(/(.{8})(.{4})(.{4})(.{4})(.{12})/, '$1-$2-$3-$4-$5') .toUpperCase(); } objectToGuidCombined(obj, namespace = '') { const deterministicHash = this.objectToGuidDeterministic(obj); const namespaceHash = namespace ? this.simpleHash(namespace) : 0; const timestamp = Date.now(); const randomComponent = Math.random().toString(16).substr(2, 8); return this.combineComponents(deterministicHash, namespaceHash, timestamp, randomComponent); } // 主生成函数 async generateGuid(inputText, inputType, algorithmType = 'deterministic') { let obj; try { if (inputType === 'json') { obj = JSON.parse(inputText); } else { obj = inputText } } catch (error) { return error; } let guid; let algorithmName; try { switch (algorithmType) { case 'deterministic': guid = this.objectToGuidDeterministic(obj); algorithmName = '确定性哈希算法'; break; case 'pseudorandom': guid = this.objectToGuidPseudorandom(obj); algorithmName = '伪随机算法'; break; case 'crypto': guid = this.objectToGuidCryptoSync(obj); algorithmName = 'Crypto API算法'; break; case 'combined': guid = this.objectToGuidCombined(obj, 'example-namespace'); algorithmName = '组合算法'; break; default: guid = '未知算法'; algorithmName = '未知'; } return guid; } catch (error) { return error } } } if (typeof module !== 'undefined' && module.exports) { module.exports = SystemInfo; } else if (typeof window !== 'undefined') { window.SystemInfo = SystemInfo; }