sequenceDiagram participant C as Client (request.ts) participant S as Server (auth.ts) participant M as Server (auth middleware) participant DB as MySQL (refresh_tokens) Note over C,S: 1. 正常登录 C->>S: POST /auth/login { code } S->>DB: INSERT refresh_tokens (user_id, token_hash, expires_at) S-->>C: { accessToken(2h), refreshToken(30d), userId } Note over C,S: 2. API 调用(Access Token 有效) C->>M: GET /api/xxx Authorization: Bearer accessToken M->>M: 验证 HMAC 签名 + 有效期 M-->>C: 200 OK { code: 0, data } Note over C,S: 3. Access Token 过期 C->>M: GET /api/xxx Authorization: Bearer expiredToken M->>M: 签名有效但已过期 M-->>C: 401 { code: 40101, message: token已过期 } Note over C,S: 4. 自动刷新 C->>S: POST /auth/refresh { refreshToken } S->>DB: SELECT WHERE token_hash=SHA256(refreshToken) AND revoked_at IS NULL AND expires_at>NOW() DB-->>S: 找到记录 S->>DB: UPDATE refresh_tokens SET revoked_at=NOW() WHERE id=oldId S->>DB: INSERT refresh_tokens (新 token_hash) S-->>C: { accessToken, refreshToken, expiresIn } C->>C: 存储新 Token,重试原请求 Note over C,S: 5. Refresh Token 也过期 C->>S: POST /auth/refresh { expiredRefreshToken } S->>DB: SELECT WHERE token_hash=SHA256(...) AND expires_at>NOW() DB-->>S: 未找到记录 S-->>C: 401 { code: 40101, message: refresh token已过期 } C->>C: 清除所有 Token,跳转登录页 Note over C,S: 6. 删除撤销流程 participant U as User participant P as BillsPage participant ST as TransactionStore participant SN as Snackbar participant API as Server API U->>P: 左滑删除记录 P->>ST: pendingDelete(id, item, index) ST->>ST: 从 transactions 列表移除 ST->>SN: 显示 Snackbar 已删除1条记录 撤销 alt 3秒内点击撤销 U->>SN: 点击 撤销 SN->>ST: cancelDelete(id) ST->>ST: 恢复到列表原位置 else 3秒超时 SN->>ST: confirmDelete(id) ST->>API: DELETE /api/transactions/id alt 删除成功 API-->>ST: 200 OK ST->>ST: 清除 pendingDelete 记录 else 删除失败 API-->>ST: 500 Error ST->>ST: 恢复到列表原位置 ST->>U: toast 删除失败 end end Note over C,S: 7. 预算预警流程 participant T as Transaction Route participant BA as BudgetAlert Service participant NS as Notification System participant WX as WeChat API C->>T: POST /api/transactions { amount, type, date } T->>DB: INSERT INTO transactions T->>BA: checkBudgetAlert(userId, month) BA->>DB: SELECT budget FROM budgets WHERE user_id=? AND month=? BA->>DB: SELECT SUM(amount) FROM transactions WHERE user_id=? AND type=expense alt 支出/预算 >= 80% 且未推送过 BA->>DB: INSERT budget_alerts (level=80) BA->>NS: 创建站内通知 else 支出/预算 >= 100% BA->>DB: INSERT budget_alerts (level=100) BA->>NS: 创建站内通知 BA->>WX: 发送微信订阅消息 else 支出/预算 >= 120% BA->>DB: INSERT budget_alerts (level=120) BA->>NS: 创建紧急站内通知 (is_urgent=true) BA->>WX: 发送微信订阅消息 end T-->>C: { code: 0, data: { id } }