logger.js 2.5 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374
  1. const isElectron = () =>
  2. typeof window !== 'undefined' &&
  3. window.electronAPI &&
  4. typeof window.electronAPI.writeLog === 'function';
  5. // 检测是否在 Cordova 环境中
  6. const isCordova = () =>
  7. typeof window !== 'undefined' && !!window.cordova;
  8. // 检测是否在 Cypress 测试环境中
  9. const isTestEnvironment = () =>
  10. typeof window !== 'undefined' && window.Cypress;
  11. // 检测是否在浏览器环境中
  12. const isBrowser = () =>
  13. typeof window !== 'undefined' && !isElectron() && !isCordova() && !isTestEnvironment();
  14. //避免obj是递归引用导致崩溃
  15. function safeStringify(obj) {
  16. const cache = new Set();
  17. return JSON.stringify(obj, (key, value) => {
  18. if (typeof value === 'object' && value !== null) {
  19. if (cache.has(value)) {
  20. return '[Circular]';
  21. }
  22. cache.add(value);
  23. }
  24. return value;
  25. });
  26. }
  27. function proxyLog(level) {
  28. const original = console[level];
  29. return (...args) => {
  30. const msg = args.map(v => typeof v === 'object' ? safeStringify(v) : String(v)).join(' ');
  31. let finalMsg = msg;
  32. if (isBrowser()) {
  33. const timestamp = new Date().toISOString();
  34. finalMsg = `[${timestamp}] [${level}] ${msg}`;
  35. original(finalMsg); // ① 浏览器环境:控制台打印带时间戳的格式化消息
  36. } else {
  37. original(...args); // ① Electron/其他环境:控制台打印原始参数
  38. }
  39. // 如果在测试环境中,直接返回,不发送任何网络请求
  40. if (isTestEnvironment()) {
  41. return;
  42. }
  43. if (isElectron()) { // ② Electron 环境
  44. window.electronAPI.writeLog(level, msg).catch(() => {});
  45. } else if (isCordova()) { // ③ Cordova 环境
  46. // 动态导入Cordova日志写入器,避免在非Cordova环境下加载
  47. import('./cordova-log-writer.js').then(({ getCordovaLogWriter }) => {
  48. const writer = getCordovaLogWriter();
  49. writer.writeLog(level, msg).catch(() => {});
  50. }).catch(() => {});
  51. } else if (typeof fetch !== 'undefined') {
  52. // // ④ 纯 Web 或 pkg-static:发一条异步 POST /log,不阻塞、不报错
  53. // fetch('/log', {
  54. // method: 'POST',
  55. // headers: { 'Content-Type': 'application/json' },
  56. // body: safeStringify({ level, msg })
  57. // }).catch(() => {}); // 404 也不抛错
  58. }
  59. };
  60. }
  61. export const logger = {
  62. log: proxyLog('log'),
  63. warn: proxyLog('warn'),
  64. error: proxyLog('error'),
  65. debug: proxyLog('debug'),
  66. fatal: proxyLog('fatal'),
  67. };