Skip to content

系统架构

整体架构

IM 系统采用前后端分离的架构设计。

┌──────────────────────────────────────────────────────────────┐
│                      客户端 (UniApp)                          │
│                                                              │
│  ┌──────────┐  ┌──────────┐  ┌──────────┐  ┌────────────┐  │
│  │  login   │  │   home   │  │   chat   │  │  partner   │  │
│  └──────────┘  └──────────┘  └──────────┘  └────────────┘  │
│                                                              │
│  ┌─────────────────────┐  ┌────────────────────────────┐    │
│  │  im_page_mixin.js   │  │  im-push-listener.vue      │    │
│  │  公共逻辑层          │  │  全局 WebSocket 推送监听    │    │
│  └─────────────────────┘  └────────────────────────────┘    │
│                                                              │
│  ┌──────────────────────────────────────────────────────┐   │
│  │  middleware (this.middle)                             │   │
│  │  http.js → 自动 Token 注入 + 401 处理 + loading 管理 │   │
│  └──────────────────────────────────────────────────────┘   │
└─────────────┬─────────────────────────────┬─────────────────┘
              │ HTTP (REST API)             │ WebSocket
              ▼                             ▼
┌─────────────────────────────────────────────────────────────┐
│                    IM 后端 (Express + ws)                     │
│                                                             │
│  ┌─────────────┐  ┌──────────────┐  ┌───────────────────┐  │
│  │ REST API    │  │ WebSocket    │  │ 静态文件服务       │  │
│  │ 49 个接口   │  │ 17 种事件    │  │ (server/public/)  │  │
│  └──────┬──────┘  └──────┬───────┘  └───────────────────┘  │
│         │                │                                  │
│  ┌──────┴────────────────┴───────────────────────────────┐  │
│  │  中间件层                                               │  │
│  │  CORS → JSON 解析 → 频率限制 → JWT 验证 → 路由处理     │  │
│  └──────────────────────┬────────────────────────────────┘  │
│                         │                                    │
│  ┌──────────────────────┴────────────────────────────────┐  │
│  │  数据库层 (db.js)                                       │  │
│  │  sql.js (SQLite WASM) → 内存数据库 → 防抖写入磁盘      │  │
│  │  WAL 模式 | 8MB 缓存 | NORMAL 同步 | 5s 超时           │  │
│  └───────────────────────────────────────────────────────┘  │
└─────────────────────────────────────────────────────────────┘

认证体系

系统使用两种认证方案:

JWT Bearer Token:面向终端用户。登录或注册后返回 JWT Token,有效期 7 天。用户请求通过 Authorization: Bearer <token> 头认证。WebSocket 连接支持查询参数 ?token=xxxauth 消息两种认证方式。

API Key Bearer Token:面向管理员和第三方系统。首次启动自动生成,存储在数据库 configs 表中。所有 /api/admin/* 接口使用此认证。

安全提示

API Key 是管理员接口的唯一凭证,请妥善保管,不要泄露到客户端代码中。

数据库设计

数据库使用 sql.js(SQLite 的 WebAssembly 编译版本),整个数据库加载到内存中运行,通过防抖机制定期写入磁盘文件。

性能优化:WAL 日志模式减少写锁冲突,8MB 内存缓存加速查询,NORMAL 同步级别平衡性能与安全,10 个索引覆盖高频查询场景。

写入策略:每次写操作触发 100ms 防抖定时器,多个快速写入合并为一次磁盘 IO。进程关闭时通过 forceSave() 立即落盘确保数据不丢失。

数据库详情

详细的数据库表结构请参考 数据库结构

消息投递流程

发送方                  IM 后端                    接收方
  │                       │                         │
  │── WS message ────────▶│                         │
  │                       │── 参数校验               │
  │                       │── 屏蔽/禁言检查          │
  │                       │── 保存消息到 DB          │
  │                       │── 更新未读计数           │
  │◀── WS ack ───────────│                         │
  │                       │                         │
  │                       │── 检查接收方是否在线 ───▶│
  │                       │   │                     │
  │                       │   ├── 在线 → WS 推送    │
  │                       │   └── 离线 → Web Push   │
  │                       │                         │
  1. 发送方通过 WebSocket 发送 message 类型消息
  2. 后端校验参数、检查屏蔽/禁言状态
  3. 消息持久化到 SQLite,更新未读计数
  4. 向发送方返回 ack 确认
  5. 检查接收方 WebSocket 连接状态
  6. 在线则通过 WebSocket 实时推送,离线则触发 Web Push 通知

实时推送机制

除了聊天页面自身的 WebSocket 连接外,系统还提供了 im-push-listener 全局组件。该组件在 home.vue 等页面中嵌入,维护一个独立的 WebSocket 连接用于接收实时通知:

  • 新消息到达时触发 im-push-message 全局事件
  • 好友请求到达时触发 im-push-notification 全局事件
  • 连接断开后自动重连(5 秒间隔)
  • 25 秒心跳保活

这确保了用户在浏览不同页面时都能及时收到消息通知。