Files
ele-HeiXiu/src/utils/event-bus.ts
YoungestSongMo ae733016bb feat: 日志模块 + netRequest 封装 + PROJECT.md 更新
日志模块(文件持久化 + 事件总线联动 + 脱敏)
    新增:
      - shared/types/logging.ts         — LogLevel / LogCategory / LogEntry 类型
      - electron/main/logger.ts         — 主进程日志核心(JSON Lines / 每日轮转 / 7天清理)
      - electron/main/log-ipc.ts        — 渲染进程日志 IPC 通道接收
      - src/utils/logger.ts             — 渲染进程日志器(IPC 转发 / DEV 控制台 / 事件总线钩子)
      - shared/utils/sanitize.ts        — 脱敏工具(ID哈希 / 邮箱 / 手机 / 名称 / Token)
    修改:
      - electron/main.ts                — initLogger + flushLogger + uncaughtException
      - src/main.tsx                    — renderer 全局错误捕获
      - src/utils/event-bus.ts          — setEventLogListener 钩子,emit 自动审计
      - src/services/request.ts         — 拦截器结构化错误分级记录
      - electron/main/updater.ts        — 14处 console → logger 迁移
      - src/components/AppProvider.tsx   — 登录/登出/自动登录 auth 事件日志
      - shared/constants/ipc-channels.ts — 新增 LOG_MESSAGE 通道

  netRequest 封装(Electron net.request 的 axios 风格 API)
    新增:
      - electron/main/net-request.ts     — netRequest.get/post/put/del 命名空间
    修改:
      - electron/main/updater.ts         — fetchUpdateInfo 改用 netRequest(22→12行)

  文档更新
    - PROJECT.md                       — 目录结构 / 状态管理 / 日志系统 / IPC 章节同步现状
    - TODO.md                          — 增量更新改造 + 日志模块待办
    - UpdateA.md                       — API blockmap 字段 / 数据库字段说明
2026-06-04 11:03:25 +08:00

73 lines
2.1 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
// ============================================================
// 事件总线 — 跨组件/跨模块事件通信
// 用于 axios 拦截器 → App 触发登录弹窗等解耦场景
// ============================================================
type Listener = (...args: unknown[]) => void;
const listeners = new Map<string, Set<Listener>>();
// ---------- 日志钩子(由 logger 模块注册,避免循环依赖)----------
type EventLogListener = (event: string, ...args: unknown[]) => void;
let eventLogListener: EventLogListener | null = null;
/**
* 注册事件日志监听器(由 logger 模块调用)
* 每次 emit() 时回调,用于审计追踪
*/
export function setEventLogListener(fn: EventLogListener): void {
eventLogListener = fn;
}
// ---------- API ----------
/** 监听事件 */
export function on(event: string, fn: Listener): void {
if (!listeners.has(event)) {
listeners.set(event, new Set());
}
listeners.get(event)!.add(fn);
}
/** 取消监听 */
export function off(event: string, fn: Listener): void {
listeners.get(event)?.delete(fn);
}
/** 触发事件 */
export function emit(event: string, ...args: unknown[]): void {
// ① 通知日志监听器(在触发业务监听器之前记录)
if (eventLogListener) {
try {
eventLogListener(event, ...args);
} catch {
/* 日志钩子异常不影响事件投递 */
}
}
// ② 通知业务监听器
listeners.get(event)?.forEach((fn) => {
try {
fn(...args);
} catch (e) {
console.error(`[EventBus] ${event} 回调出错:`, e);
}
});
}
// ============================================================
// 预定义事件名
// ============================================================
export const EVENTS = {
/** 需要登录axios 返回 401 时触发) */
AUTH_REQUIRED: 'auth:required',
/** 显示登录弹窗(用户点击登录按钮触发) */
SHOW_LOGIN: 'auth:show-login',
/** 登录成功 */
LOGIN_SUCCESS: 'auth:login-success',
/** 退出登录 */
LOGOUT: 'auth:logout',
} as const;