# 统一消息与通知中心详细设计文档

**版本**: V4.0  
**日期**: 2026-02-22  
**状态**: 最终定稿  
**适用范围**: Android, iOS, Windows, macOS, Web, 第三方业务系统 (OA/ERP等)

---

## 1. 系统概述 (System Overview)

### 1.1 背景与目标
为了增强“统一认证平台”的交互能力，构建一个中心化的消息通知系统。该系统不仅支持用户间的私信，更重要的是连接第三方业务应用（如 OA、CRM）与用户终端，实现业务通知的实时触达和**一键免登跳转处理**。

### 1.2 核心特性
1.  **全平台覆盖**: 一套后端架构同时支持移动端（Android/iOS）和桌面端（Win/Mac/Web）。
2.  **自建实时推送**: 摒弃第三方推送服务，采用 **WebSocket 长连接** 实现应用内实时通知，配合 HTTP 离线拉取策略。
3.  **多媒体支持**: 提供专用的文件上传接口 (`/messages/upload`)，支持图片、视频、文档发送。
4.  **SSO 一键跳转**: 通知的跳转链接 (`action_url`) 自动封装 SSO 逻辑，用户点击通知后，经过统一认证平台鉴权，携带 Ticket 自动登录目标应用并跳转至具体业务详情页。
5.  **账号映射**: 第三方应用无需知道平台的 `User ID`，只需提供其自身的 `App User ID` 即可精准投递消息。

---

## 2. 总体架构 (Architecture)

### 2.1 逻辑架构图
```mermaid
graph TD
    %% 发送端 (聪明的端点)
    Sender[第三方应用 OA/ERP] -->|1. 上传附件| MinIO[(MinIO OSS)]
    Sender -->|2. 携带 User_ID & 完整URL| MsgAPI[统一消息 API]

    %% 处理层：纯粹的哑管道 (解耦)
    subgraph "统一消息中心 (Message Gateway)"
        MsgAPI -->|3. 存入信箱| DB[(MySQL msg_inbox)]
        MsgAPI -->|4. 广播事件| Redis[(Redis Pub/Sub)]
        Redis -->|5. 集群订阅| WS[WebSocket 服务集群]
    end

    %% 接收端
    subgraph "客户端 (多端漫游)"
        Mobile[手机 App]
        Desktop[桌面客户端]
    end

    WS -->|6. 实时推送 JSON 信封| Mobile
    WS -->|6. 实时推送 JSON 信封| Desktop

    %% 客户端触发 SSO 免登 (逻辑在端侧和目标应用侧)
    Mobile -.->|7. 拦截URL, 注入本地 Token| LocalRouter[客户端路由引擎]
    LocalRouter -->|8. 带 Token 访问| TargetApp[目标应用页面/API]
    TargetApp -.->|9. 校验 Token| SSO[统一认证平台]
    TargetApp -->|10. 渲染展示| DetailPage[业务详情页]
```

---

## 3. 数据库设计 (Database Schema)

### 3.1 消息表 (`messages`)

| 字段名 | 类型 | 约束 | 说明 |
| :--- | :--- | :--- | :--- |
| `id` | BigInt | PK | 消息唯一标识 |
| `receiver_id` | Int | FK, NotNull | **接收者 UserID** (统一平台 ID) |
| `app_id` | Int | FK, Nullable | 来源应用 ID (标识消息来源) |
| `type` | Enum | NotNull | `MESSAGE` (私信), `NOTIFICATION` (平台通知) |
| `content_type` | Enum | NotNull | `TEXT`, `IMAGE`, `VIDEO`, `FILE` |
| `content` | Text | NotNull | 文本内容 或 **JSON 结构体** (见下文) |
| `title` | Varchar(255) | NotNull | 标题 (如"工单待审批") |
| `action_url` | Varchar(1000) | Nullable | **SSO 跳转链接** (平台自动生成) |
| `action_text` | Varchar(50) | Nullable | 按钮文案 (如"立即处理") |
| `is_read` | Bool | Default 0 | 是否已读 |
| `created_at` | DateTime | Default Now | 创建时间 |

---

## 4. API 接口规范 (API Specification)

**Base URL**: `/api/v1/messages`

### 4.1 专用文件上传 (Upload Attachment)

专门用于消息附件的上传，支持 MinIO 存储。

*   **URL**: `POST /upload`
*   **权限**: Login User / Service Token
*   **Content-Type**: `multipart/form-data`
*   **Response**:
    ```json
    {
      "url": "http://minio.com/messages/user_1/2026/02/uuid.jpg",
      "filename": "screenshot.jpg",
      "content_type": "image/jpeg",
      "size": 102400
    }
    ```

### 4.2 发送消息 (Send Message)

支持多媒体内容和账号映射。**支持混合权限认证**：既接受用户 Token，也接受应用签名。

*   **URL**: `POST /`
*   **Authentication**:
    *   **User**: Header `Authorization: Bearer <token>`
    *   **App**: Headers `X-App-Id`, `X-Timestamp`, `X-Sign`
*   **Request Body**:
    ```json
    {
      // --- 接收者定位 (二选一) ---
      // 方式 A: 知道统一平台 ID
      // "receiver_id": 10086,
      
      // 方式 B: 只知道业务系统账号 (推荐)
      "app_id": 101,              // 来源应用 ID
      "app_user_id": "zhangsan",  // 该应用内的账号
      
      // --- 消息内容 ---
      "type": "MESSAGE",          // 类型：MESSAGE (私信) 或 NOTIFICATION (通知)
      "content_type": "IMAGE",    // 内容类型：TEXT, IMAGE, VIDEO, FILE
      
      //如果是 TEXT，直接传字符串
      //"content": "你好", 
      
      //如果是 IMAGE/VIDEO，传 JSON 字符串 (通常是 /upload 接口的返回值)
      "content": "{\"url\":\"http://minio...\",\"width\":800,\"height\":600}",
      
      "title": "新图片消息",
      
      // --- 跳转行为 (仅 NOTIFICATION 有效) ---
      "target_url": "http://oa.com/audit/999", // 最终业务页面
      "action_text": "去审批",
      "auto_sso": true // 开启自动 SSO 封装
    }
    ```

### 4.3 获取消息列表 (Get List)

*   **URL**: `GET /?unread_only=true`
*   **Response**:
    ```json
    [
      {
        "id": 501,
        "type": "MESSAGE",
        "content_type": "IMAGE",
        "content": "{\"url\":\"...\"}", // 前端需解析 JSON
        "is_read": false,
        "created_at": "..."
      }
    ]
    ```

### 4.4 SSO 跳转接口 (SSO Jump)

*   **URL**: `GET /api/v1/auth/sso/jump`
*   **Params**: `app_id=101`, `redirect_to=http://oa.com/audit/999`
*   **Logic**:
    1.  检查当前用户登录状态。
    2.  若未登录 -> 跳转登录页 -> 回调。
    3.  若已登录 -> 生成 Ticket -> 跳转 `AppCallback?ticket=ST&next={redirect_to}`。

---

## 5. 权限认证策略 (Authentication Strategy)

为了同时支持用户操作和系统调用，消息接口采用**混合认证策略 (Hybrid Auth)**。

### 5.1 认证优先级
后端 API 将按以下顺序尝试识别调用者身份：

1.  **用户认证 (Bearer Token)**:
    *   **场景**: 用户通过 App/Web 发送私信、查询历史消息。
    *   **机制**: 检查 Header `Authorization: Bearer <JWT>`.
    *   **身份**: 识别为 `User` 对象。

2.  **应用认证 (API Signature)**:
    *   **场景**: OA/ERP 等后端系统调用接口发送业务通知。
    *   **机制**: 检查 Headers `X-App-Id`, `X-Timestamp`, `X-Sign`.
    *   **签名算法**: `MD5(app_id + timestamp + app_secret)`。
    *   **身份**: 识别为 `Application` 对象。

### 5.2 权限控制
*   **User**: 只能发送 `type=MESSAGE` (私信)；只能查询 `receiver_id` 为自己的消息。
*   **Application**: 只能发送 `type=NOTIFICATION` (通知) 或 `MESSAGE`；无法查询消息列表（仅负责投递）。

---

## 6. 客户端集成指南 (Client Guide)

### 6.1 消息内容渲染
前端收到消息后，根据 `content_type` 决定渲染逻辑：
*   `TEXT`: 直接显示 `content` 字符串。
*   `IMAGE`: `JSON.parse(content)` -> `<img src={obj.url} />`。
*   `VIDEO`: `JSON.parse(content)` -> `<video src={obj.url} controls />`。
*   `FILE`: `JSON.parse(content)` -> 显示文件名和下载图标 -> 点击下载。

### 6.2 全平台推送策略
*   **Web 端**: 使用 `Notification API` 弹窗；WebSocket 保持连接。
*   **Android/iOS**:
    *   **在线**: WebSocket 收到消息 -> 弹出 App 内置 Notification Banner。
    *   **离线**: App 启动/回到前台 -> 调用 HTTP 接口拉取未读消息 -> 更新角标。
    *   **跳转**: 点击通知 -> 唤起 App -> WebView 打开 `action_url` (自动完成 SSO 登录)。

### 6.3 文件上传流程
1.  用户选择图片/视频。
2.  调用 `POST /api/v1/messages/upload` 上传文件到 MinIO。
3.  获取返回的 `url` 和元数据。
4.  调用 `POST /api/v1/messages` 发送消息，将元数据填入 `content`。

---

## 7. 实施步骤 (Action Items)

1.  **基础设施**:
    *   部署 MinIO 服务。
    *   在 `config.py` 配置 MinIO 连接信息。
2.  **后端开发**:
    *   实现 `MinIO Client` 模块。
    *   实现 `/messages/upload` 接口。
    *   修改 `Message` 模型支持 `content_type`。
    *   实现 `/auth/sso/jump` 接口。
    *   **实现混合认证依赖 (`get_current_user_or_app`)**。
3.  **前端/客户端开发**:
    *   集成 WebSocket。
    *   实现多媒体消息的气泡组件 (Text/Image/Video)。
    *   实现 SSO 跳转拦截逻辑。
