跳到正文
历史文档/技术原理

长文档建议按当前分组逐页阅读;右侧辅助栏会保留当前位置和快速操作。

技术原理

深入了解 Mini-HBUT 的架构设计、数据流、跨平台实现机制和核心技术方案。

整体架构

技术栈总览

前端

  • • Vue 3 + TypeScript + Composition API
  • • Vite 构建工具(端口 1420)
  • • Vant 4 UI 组件库
  • • Pinia 状态管理
  • • 自定义 CSS 变量主题系统

桌面后端(Tauri 2.x)

  • • Rust + Tokio 异步运行时
  • • reqwest HTTP 客户端
  • • scraper HTML 解析器
  • • SQLite 本地数据库
  • • 本地 HTTP Bridge(127.0.0.1:4399)

移动端(Capacitor 6.x)

  • • Android: Gradle + WebView
  • • iOS: Xcode + WKWebView
  • • Background Fetch 后台任务
  • • Local Notifications 本地通知
  • • Preferences 持久化存储

云服务

  • • Cloudflare Workers 云同步
  • • Cloudflare KV 数据存储
  • • GitHub Actions CI/CD
  • • jsDelivr / unpkg CDN
  • • GitCode 远程配置托管

架构图

┌─────────────────────────────────────────────────────────────┐
│                        用户界面 (Vue 3)                       │
│  ┌──────────┐ ┌──────────┐ ┌──────────┐ ┌──────────┐       │
│  │ 成绩查询  │ │ 课表管理  │ │ 考试安排  │ │  ...更多  │       │
│  └────┬─────┘ └────┬─────┘ └────┬─────┘ └────┬─────┘       │
│       └────────────┼────────────┼────────────┘              │
│                    ▼                                         │
│          ┌──────────────────┐                                │
│          │  平台桥接层        │                                │
│          │  (src/platform/)  │                                │
│          └───┬──────┬───┬───┘                                │
└──────────────┼──────┼───┼───────────────────────────────────┘
               │      │   │
    ┌──────────▼──┐ ┌─▼───▼──────┐ ┌────────────┐
    │  Tauri 2.x  │ │ Capacitor  │ │  Web 模式   │
    │  (Rust)     │ │ (Native)   │ │ (Browser)  │
    │             │ │            │ │            │
    │ • HTTP客户端 │ │ • Native   │ │ • Fetch    │
    │ • SQLite    │ │   Plugins  │ │ • IndexedDB│
    │ • Bridge    │ │ • BGFetch  │ │            │
    └──────┬──────┘ └─────┬──────┘ └─────┬──────┘
           │              │              │
           ▼              ▼              ▼
    ┌──────────────────────────────────────────┐
    │          教务系统 / 电费系统 / ...          │
    │         (学校内网服务)                      │
    └──────────────────────────────────────────┘
           │
    ┌──────▼──────────────────────────────────┐
    │          云服务层                          │
    │  • Cloudflare Workers (云同步)            │
    │  • OCR 服务 (验证码识别)                   │
    │  • 远程配置 (GitCode/GitHub)              │
    │  • CDN (jsDelivr/unpkg)                  │
    └─────────────────────────────────────────┘

跨平台桥接机制

Mini-HBUT 的核心设计原则是「一套前端代码,多平台运行」。通过平台桥接层(src/platform/), 前端组件无需关心底层运行环境,所有平台差异在桥接层统一抽象。

运行时检测

src/platform/runtime.ts 负责在启动时自动检测当前运行平台:

// 检测优先级
1. window.__TAURI__     → 'tauri'     (桌面端)
2. window.Capacitor     → 'capacitor' (移动端)
3. 其他                  → 'web'       (浏览器)

能力抽象

src/platform/types.ts 定义了统一的能力接口,每个平台有对应的适配器实现:

能力Tauri 实现Capacitor 实现Web 实现
打开链接Tauri Shell PluginCapacitor Browserwindow.open
发送通知Tauri NotificationLocalNotificationsNotification API
HTTP 请求Rust reqwestCapacitor HTTPFetch API
屏幕常亮不支持KeepAwake Plugin不支持
文件操作Tauri FS PluginCapacitor FilesystemIndexedDB
分享不支持Capacitor Share不支持
ℹ️ 设计规范:页面层组件不直接调用 @tauri-apps/api@capacitor/*, 而是统一通过 src/platform/ 暴露的接口调用。新增原生能力必须先在 types.ts 中定义接口, 再在各适配器中实现。

登录与会话管理

CAS 登录流程

新融合门户使用 CAS 单点登录协议,完整流程如下:

客户端                    教务系统                  OCR 服务
  │                         │                         │
  │  1. GET 登录页面         │                         │
  │ ─────────────────────▶  │                         │
  │  2. 返回HTML+验证码图片  │                         │
  │ ◀─────────────────────  │                         │
  │                         │                         │
  │  3. 发送验证码图片(base64)│                         │
  │ ──────────────────────────────────────────────▶   │
  │  4. 返回识别结果         │                         │
  │ ◀──────────────────────────────────────────────   │
  │                         │                         │
  │  5. POST 登录请求        │                         │
  │    (账号+密码+验证码)     │                         │
  │ ─────────────────────▶  │                         │
  │  6. 返回Cookie/重定向    │                         │
  │ ◀─────────────────────  │                         │
  │                         │                         │
  │  7. 保存Cookie到本地     │                         │
  │  8. 获取最新成绩/课表    │                         │
  │ ─────────────────────▶  │                         │

会话恢复策略

应用启动时会按以下优先级恢复登录状态:

  1. 本地 Cookie 恢复:尝试使用本地存储的 Cookie 直接访问教务系统,如果 Cookie 仍有效则直接进入。
  2. 最新会话恢复:如果 Cookie 失效,尝试读取最近一次会话的凭据重新建立连接。
  3. 自动重登:如果保存了密码(非加密临时登录),使用保存的密码自动完成登录流程。
  4. 引导登录:如果以上都失败,展示登录页面让用户手动登录。

学习通登录

学习通登录使用超星教育平台 API:

  • 密码使用 AES-128-CBC 加密后传输。
  • 登录成功后通过 SSO 关联到学校教务系统。
  • 学号解析策略:payload 解析 → 缓存读取 → API 查询 → 降级处理。

扫码登录

扫码登录流程(门户/学习通通用):

1. qr_init_login()     → 获取二维码  → 显示在页面上
2. qr_check_status()   → 轮询状态    → 等待用户扫码确认
3. qr_confirm_login()  → 确认登录    → 获取 Cookie → 进入首页

数据流与缓存

请求-缓存-降级 三层策略

Mini-HBUT 所有数据请求遵循统一的三层策略:

用户请求
    │
    ▼
┌──────────────┐  命中    ┌────────────┐
│  检查前端缓存  │────────▶│  返回缓存数据 │
│  (localStorage)│        │  (标注来源)   │
└──────┬───────┘  未命中   └────────────┘
       │
       ▼
┌──────────────┐  成功    ┌─────────────┐
│  网络请求      │────────▶│  更新缓存     │
│  (API/Bridge)  │        │  返回新数据    │
└──────┬───────┘  失败    └─────────────┘
       │
       ▼
┌──────────────┐  有数据   ┌─────────────┐
│  检查后端缓存  │────────▶│  返回离线数据  │
│  (SQLite)     │         │  标注"离线"    │
└──────┬───────┘  无数据   └─────────────┘
       │
       ▼
┌──────────────┐
│  显示错误提示  │
└──────────────┘

缓存 TTL 策略

缓存级别TTL适用场景缓存键前缀
SHORT_TTL30 秒排名、实时余额ranking:
DEFAULT_TTL5 分钟常规查询默认
LONG_TTL3 天成绩、课表、考试grades: / schedule: / exams:
EXTRA_LONG_TTL7 天校历、培养方案calendar: / academic:

缓存容量限制

  • 前端 localStorage 缓存:最多 220 个条目。
  • 单个缓存值大小限制:180KB(超过则不缓存)。
  • 超出容量时自动淘汰最早过期的缓存条目。
  • 后端 SQLite 缓存无条目限制,但会定期清理过期数据。

JWXT 维护模式检测

当教务系统(JWXT)返回维护页面或特定状态码时,前端自动进入维护模式:

  • 所有查询自动回退到离线缓存。
  • 页面顶部显示维护提示横幅。
  • 维护结束后首次请求成功会自动退出维护模式。

HTTP Bridge 原理

Tauri 桌面端在启动时会在本地开启一个 HTTP 服务器(127.0.0.1:4399), 称为 HTTP Bridge。前端通过 Vite 反向代理将 /bridge 路径转发到此服务。

工作原理

┌──────────┐    /api/v2/*     ┌──────────┐    /bridge/*    ┌──────────────┐
│ Vue 前端  │ ──────────────▶ │ Vite Dev │ ────────────▶ │ Rust HTTP    │
│ (组件)    │                 │ Server   │               │ Bridge       │
│           │ ◀────────────── │ :1420    │ ◀──────────── │ :4399        │
└──────────┘    JSON 响应      └──────────┘    JSON 响应   └──────┬───────┘
                                                                  │
                                              ┌───────────────────┘
                                              │
                               ┌──────────────▼──────────────┐
                               │     Rust HTTP Client          │
                               │  • 教务系统请求                │
                               │  • 电费系统 SSO               │
                               │  • 一卡通/图书馆 API          │
                               │  • SQLite 读写               │
                               └──────────────────────────────┘

统一响应格式

interface ApiResponse<T> {
  success: boolean;       // 请求是否成功
  data: T | null;         // 返回数据(成功时)
  error: {                // 错误信息(失败时)
    kind: string;         // 错误类型
    message: string;      // 错误描述
  } | null;
  time: string;           // 服务端时间戳
}

安全边界

  • 仅监听 127.0.0.1,不接受外部连接。
  • 不开放 0.0.0.0 绑定。
  • Cookie 和凭据仅保存在本地,不通过 Bridge 暴露。
  • 外部程序(如 NoneBot)通过 Bridge 调用时,应自行添加鉴权层。

Tauri Commands(Rust 指令)

所有 Tauri Commands 定义在 src-tauri/src/lib.rs 中, 前端通过 @tauri-apps/apiinvoke() 方法直接调用。

指令分组

认证
  • get_login_page - 获取登录页面HTML
  • portal_qr_init_login - 门户扫码初始化
  • portal_qr_check_status - 门户扫码状态检查
  • portal_qr_confirm_login - 门户扫码确认
  • chaoxing_qr_init_login - 学习通扫码初始化
  • chaoxing_qr_check_status - 学习通扫码状态
  • chaoxing_qr_confirm_login - 学习通扫码确认
  • chaoxing_password_login - 学习通密码登录
学业数据
  • sync_grades - 从教务系统同步成绩
  • get_grades_local - 获取本地缓存成绩
  • sync_schedule - 从教务系统同步课表
  • get_schedule_local - 获取本地缓存课表
  • fetch_exams - 查询考试安排
  • fetch_ranking - 查询绩点排名
  • fetch_student_info - 获取学生信息
  • fetch_qxzkb_list - 查询全校课表
校园生活
  • electricity_query_location - 查询电费房间
  • electricity_query_account - 查询电费余额
  • fetch_transaction_history - 查询交易记录
  • fetch_classrooms - 查询空教室
  • search_library_books - 搜索图书馆藏
文件与导出
  • export_schedule_calendar - 导出课表为ICS
  • cache_remote_image - 缓存远程图片
  • save_export_file - 保存导出文件
  • resource_share_fetch_file_payload_native - 获取共享文件
其他
  • hbut_ai_chat - AI 对话
  • campus_code_qrcode - 生成校园码
  • campus_code_order_status - 查询订单状态

后台任务机制

桌面端(Tauri)

桌面端在应用启动时执行一次全量检查,此后按照用户设置的间隔定期轮询。检查逻辑运行在 Rust 后端的 Tokio 异步任务中。

移动端(Capacitor)

移动端使用 @transistorsoft/capacitor-background-fetch 插件实现后台任务。

配置项说明
minimumFetchInterval15 分钟系统允许的最小检查间隔
stopOnTerminatefalse应用被杀后继续运行后台任务
startOnBoottrue开机后自动启动后台任务
enableHeadlesstrue支持无界面后台执行

后台检查项

后台唤醒
    │
    ├─▶ 检查新成绩  → 比较本地缓存 → 有新成绩 → 推送通知
    │
    ├─▶ 检查考试    → 解析日期    → 明天有考试 → 推送提醒
    │
    ├─▶ 检查电费    → 查询余额    → 低于10度  → 推送告警
    │
    └─▶ 刷新课表    → 同步数据    → 更新缓存

通知去重

每条通知根据内容生成签名(hash),已推送的签名记录在本地。同一签名的通知在一个周期内不会重复推送,避免用户被反复打扰。

云同步原理

架构

客户端                     中转服务                  Cloudflare
(Mini-HBUT)               (OCR Service)             Workers + KV
    │                          │                         │
    │  POST /api/cloud-sync    │                         │
    │  {action, student_id,    │                         │
    │   secret_ref, payload}   │                         │
    │ ────────────────────▶    │                         │
    │                          │  POST /sync/upload      │
    │                          │  Authorization: Bearer  │
    │                          │ ──────────────────────▶ │
    │                          │                         │ KV.put(sync:{id})
    │                          │  ◀────────────────────  │
    │  ◀────────────────────   │                         │
    │                          │                         │

为什么需要中转?

  • 安全:Cloudflare Worker 的 API Token 保存在中转服务的 Secrets 中,不下发到客户端,防止泄露。
  • 灵活:中转服务可以做额外的校验(如 challenge 认证)、日志记录和限流。
  • 兼容:客户端只需对接中转服务的统一接口,无需关心后端存储的变化。

同步数据结构

{
  "student_id": "2023123456",
  "updated_at": "2026-03-10T12:00:00.000Z",
  "reason": "auto_login",          // 同步原因
  "device_id": "xxxxx-xxxxx",      // 设备标识
  "client_time": 1741622400000,     // 客户端时间戳
  "payload": {
    "settings": { ... },           // 应用/UI/字体/登录设置
    "custom_courses": { ... },     // 自定义课程(按学期)
    "academic": { ... }            // 成绩/排名/课表缓存
  }
}

速率限制

Cloudflare Worker 内置基于 KV 的速率限制,通过 rate:{action}:{student_id}:{ip} 键记录上次请求时间, 未超过冷却时间的请求会返回 429(Too Many Requests)。

CDN 缓存与按需加载

为减小安装包体积,Mini-HBUT 将部分大型库改为首次使用时按需下载并缓存:

用途加载时机缓存位置
pdf.jsPDF 文件在线预览首次打开 PDF 文件IndexedDB
xgplayer视频播放首次播放视频文件IndexedDB
KaTeX数学公式渲染首次使用 AI 对话IndexedDB
marked-katexMarkdown + LaTeX首次使用 AI 对话IndexedDB
得意黑字体中文装饰字体用户选择并下载IndexedDB

加载器(cdn_loader.js)会按照配置的 CDN 线路(jsDelivr → unpkg)依次尝试下载, 成功后写入 IndexedDB 持久化。后续使用直接从本地读取,实现「首次联网,后续离线」的体验。

项目结构

tauri-app/
├── src/                          # Vue 前端源码
│   ├── App.vue                   # 主应用组件(路由 + 导航)
│   ├── main.ts                   # 应用入口
│   ├── components/               # 30+ 业务组件
│   │   ├── Dashboard.vue         #   首页仪表盘
│   │   ├── GradeView.vue         #   成绩查询
│   │   ├── ScheduleView.vue      #   课表管理
│   │   ├── LoginV3.vue           #   登录页面
│   │   ├── SettingsView.vue      #   设置中心
│   │   └── ...
│   ├── utils/                    # 工具函数库
│   │   ├── api.js                #   API 封装 + 缓存
│   │   ├── app_settings.ts       #   应用设置管理
│   │   ├── remote_config.js      #   远程配置
│   │   ├── cloud_sync.js         #   云同步
│   │   ├── background_fetch.js   #   后台任务
│   │   ├── font_settings.ts      #   字体系统
│   │   ├── updater.js            #   版本更新
│   │   └── ...
│   ├── platform/                 # 平台桥接层
│   │   ├── types.ts              #   能力接口定义
│   │   ├── native.ts             #   原生能力封装
│   │   ├── runtime.ts            #   运行时检测
│   │   └── adapters/             #   平台适配器
│   ├── config/                   # UI 配置
│   └── styles/                   # 样式文件
│
├── src-tauri/                    # Rust 后端
│   ├── src/
│   │   ├── lib.rs                #   命令入口 + 启动逻辑
│   │   ├── http_client/          #   网络请求模块
│   │   ├── http_server.rs        #   HTTP Bridge 服务
│   │   └── db.rs                 #   SQLite 数据库
│   ├── tauri.conf.json           #   Tauri 配置
│   └── Cargo.toml                #   Rust 依赖
│
├── android/                      # Capacitor Android 工程
├── ios/                          # Capacitor iOS 工程
├── cloudflare/worker/            # 云同步 Worker
├── public/                       # 静态资源
│   └── dormitory_data.json       #   宿舍楼层数据
└── remote_config.json            # 远程配置示例
推荐阅读路径

相关文档

当前页面读完后,可以按下面的交叉链接继续。用户文档、开发者文档、故障排查、参考资料和历史文档会互相补充。