const isElectron = () => typeof window !== 'undefined' && window.require && window.require('electron')?.ipcRenderer; // 检测是否在 Cypress 测试环境中 const isTestEnvironment = () => typeof window !== 'undefined' && window.Cypress; let ipcRenderer = null; if (isElectron()) { try { ipcRenderer = window.require('electron').ipcRenderer; } catch {} } //避免obj是递归引用导致崩溃 function safeStringify(obj) { const cache = new Set(); return JSON.stringify(obj, (key, value) => { if (typeof value === 'object' && value !== null) { if (cache.has(value)) { return '[Circular]'; } cache.add(value); } return value; }); } function proxyLog(level) { const original = console[level]; return (...args) => { const msg = args.map(v => typeof v === 'object' ? safeStringify(v) : String(v)).join(' '); original(...args); // ① 控制台始终打印 // 如果在测试环境中,直接返回,不发送任何网络请求 if (isTestEnvironment()) { return; } if (ipcRenderer) { // ② Electron 环境 ipcRenderer.invoke('write-log', level, msg).catch(() => {}); } else if (typeof fetch !== 'undefined') { // ③ 纯 Web 或 pkg-static:发一条异步 POST /log,不阻塞、不报错 fetch('/log', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: safeStringify({ level, msg }) }).catch(() => {}); // 404 也不抛错 } }; } export const logger = { log: proxyLog('log'), warn: proxyLog('warn'), error: proxyLog('error') };