// 浏览器信息检测
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 & 显卡信息
| 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} 个 |
`;
if (info.webgl.memoryInfo.estimatedMemory !== 'Unknown') {
html += `| 显存估计 | ${info.webgl.memoryInfo.estimatedMemory} |
`;
}
html += `
`;
} 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;
}