Files
my_site/需求文档_web_desktop_prd.md
yoyuzh d669738967 init
2026-02-27 14:29:05 +08:00

480 lines
17 KiB
Markdown
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.
# 分账户网页版桌面系统 PRD / 需求文档(可上线版)
> 版本v1.1已补齐Rust 校园 API 接口契约 + 错误码规范 + 时序图)
> 目标上线形态可上线、可运维、可扩展OSS 直传 + 校园数据由第三方 Rust 接口提供)
> 当前已确定方案:
> - 校园数据来源:学校学生开发的第三方 **Rust 接口**(建议平台后端做 BFF 统一接入)
> - 网盘上传:**客户端直传**
> - 对象存储:**阿里云 OSS**
> - 校园能力基础Rust 侧可基于 `rsmycqu`Rust 版 `pymycqu`)实现 SSO / 教务网能力与数据模型fileciteturn0file0L1-L20
---
## 1. 背景与目标
### 1.1 产品定位
一个 “Web Desktop网页版桌面” 系统,支持分账户使用。桌面内提供:
- **网盘Cloud Drive**:文件元数据由平台后端管理;文件对象存储在阿里云 OSS上传走客户端直传。
- **校园应用套件Campus Suite**:查课表、查成绩、校园论坛、校园地图。数据通过第三方 Rust API 获取。
- **静态小游戏Games**:作为桌面应用独立运行(你已实现)。
### 1.2 上线目标
- **可上线**:安全、权限隔离、稳定性、可观测性、运维能力具备。
- **分账户隔离**:文件、校园数据缓存、桌面设置、日志审计全部按用户隔离。
- **模块化**:桌面壳与各应用解耦,便于后续接入“远程服务器任务”(转码/解压/扫描/缩略图等)。
### 1.3 非目标(本期不做 / 可延后)
- 在线 Office / 多人实时协作编辑。
- 全量 OCR/全文检索。
- 原生桌面客户端Electron/Flutter Desktop 等)。
---
## 2. 用户、角色与权限
### 2.1 角色
- **普通用户**:使用桌面、网盘、校园套件、小游戏。
- **平台管理员**用户管理、配额、审计、OSS 配置、校园接口配置与健康监控。
> 预留扩展:未来可引入 tenant_id 做组织/学院级隔离;本期以 user_id 强隔离为主。
### 2.2 权限模型RBAC 最小版)
- `USER`仅访问自己的资源files/settings/campus_cache
- `ADMIN`:管理后台权限(用户、配置、审计、系统健康)。
### 2.3 数据隔离硬要求
- 所有资源表都必须带 `user_id`(可选 `tenant_id`),并在后端鉴权层强校验。
- 前端隐藏不是权限控制;必须后端拦截。
---
## 3. 总体功能范围
### 3.1 Web Desktop桌面壳
**功能:**
- 登录/注册/找回密码
- 桌面布局:图标、分组、壁纸、主题、快捷搜索、最近使用
- 窗口系统:打开/最小化/最大化/拖拽/层级管理/多窗口
- 通知中心:上传任务、论坛消息、系统公告、错误提示(携带 request_id
- 全局搜索:应用搜索 + 文件名搜索MVP
**验收:**
- 桌面布局、主题、壁纸可持久化,并在多设备“最终一致”(最后保存覆盖)。
### 3.2 网盘Cloud Drive
#### 3.2.1 核心能力MVP
- 文件/文件夹:新建、重命名、移动、删除(软删除)、恢复
- 上传/下载:支持大文件(分片 + 断点续传)
- 列表与排序:分页,按名称/时间/大小/类型
- 搜索:按文件名模糊搜索
- 预览图片、PDF、文本视频音频后续增强
- 回收站:保留期可配置(默认 30 天)
#### 3.2.2 分享(建议上线即包含)
- 分享链接:可设置有效期、提取码、权限(预览/下载)
- 撤销分享:立即失效
- 分享访问审计IP/UA/时间/次数
#### 3.2.3 配额与风控(上线必备)
- 每用户配额:总容量、单文件最大、日上传量、日下载量
- 限流:上传初始化、下载签名、分享访问
- 滥用处置:异常下载/分享可封禁账号
### 3.3 校园应用Campus Suite第三方 Rust API
> 平台后端建议作为 **BFFBackend For Frontend**:统一鉴权、缓存、熔断、限流、审计与错误码。
> 不建议前端直连 Rust API。
- 查课表:周/日视图、课程详情、导出(可选)
- 查成绩:学期/课程成绩、统计(可选)
- 校园论坛:板块/帖子/评论、发帖/评论、举报/封禁(最小版)
- 校园地图POI 列表、搜索、基础展示
---
## 4. 非功能需求(上线门槛)
### 4.1 性能指标(建议)
- 桌面首屏:≤ 2s常规网络
- 网盘列表P95 ≤ 300ms缓存/索引命中)
- 下载签名接口:≤ 200ms
- 校园数据接口P95 ≤ 1sRust API 正常时)
### 4.2 可靠性与降级
- Rust API 不可用:课表/成绩/POI 返回最近缓存 + 明确提示更新时间
- 熔断Rust API 连续失败达到阈值后短时间熔断,避免雪崩
- 重试仅读接口可重试1~2 次,指数退避)
### 4.3 可观测性(必做)
- 结构化日志:`request_id``user_id`、IP、UA、latency、status
- 指标错误率、P95 延迟、Rust API 成功率、缓存命中率、OSS 上传失败率
- 告警Rust API 健康异常、错误率激增、DB 连接异常、磁盘/内存告警
---
## 5. 安全与合规
### 5.1 身份认证
- access token短期+ refresh token长期或服务端 session二选一
- 密码bcrypt/argon2
- 登录保护:失败次数限制 + 冷却时间
### 5.2 OSS 安全原则(关键)
- 前端 **不得**持有长期 AK/SK
- 仅使用STS 临时凭证 / PostPolicy 签名 / 服务端签名 URL
- 签名 URL短期有效1~10 分钟)
### 5.3 校园凭据安全
- 若平台需保存校园账号凭据:必须服务端加密存储(密钥不入库)
- 提供解绑与删除:删除后不可继续查询
- 绑定/查询限流:避免触发校方风控或 Rust API 封禁
---
## 6. 系统架构(建议落地)
### 6.1 逻辑架构
- **Web 前端**:桌面壳 + 应用(网盘/校园/小游戏)
- **平台后端BFF**Auth、Drive、Campus、Admin、Audit、Task后续
- **第三方 Rust API**对接校内系统SSO/教务/论坛/地图)
- **阿里云 OSS**:文件对象存储
### 6.2 强制约束:平台后端必须做“统一出口”
- 前端只认平台域名Rust API 不对公网直接暴露或至少不暴露给前端(避免绕过鉴权与风控)。
---
## 7. 数据模型(建议表)
### 7.1 核心表MVP
- `users(id, email/phone, password_hash, status, created_at, last_login_at)`
- `user_settings(user_id, desktop_layout_json, theme, wallpaper, updated_at)`
- `files(id, user_id, parent_id, name, size, mime, oss_key, etag, sha256, created_at, deleted_at)`
- `shares(id, owner_user_id, file_id, token, password_hash, perms, expire_at, created_at, revoked_at)`
- `audit_logs(id, user_id, action, target_type, target_id, ip, ua, request_id, created_at, extra_json)`
- `campus_accounts(id, user_id, school_code, encrypted_credential, status, updated_at)`
- `campus_cache(id, user_id, type, payload_json, updated_at, expire_at)`
### 7.2 论坛(若平台侧落库/自建)
- `forum_boards, forum_posts, forum_comments, forum_reports, forum_bans`
---
## 8. API 设计(平台对前端)
> 统一返回格式:见第 10 节《错误码与响应规范》。
> 所有接口默认需要 `Authorization: Bearer <access_token>`(除登录注册、分享页等)。
### 8.1 Auth
- `POST /api/auth/register`
- `POST /api/auth/login`
- `POST /api/auth/refresh`
- `POST /api/auth/logout`
- `GET /api/auth/me`
- (可选)`GET /api/auth/sessions``DELETE /api/auth/sessions/{id}`
### 8.2 Desktop
- `GET /api/desktop/settings`
- `PUT /api/desktop/settings`
- `GET /api/desktop/apps`
### 8.3 DriveOSS 直传)
- `GET /api/drive/list?parent_id=...&page=...`
- `POST /api/drive/folder`
- `POST /api/drive/rename`
- `POST /api/drive/move`
- `DELETE /api/drive/delete`
- `GET /api/drive/trash`
- `POST /api/drive/restore`
- `POST /api/drive/upload/init`
- `POST /api/drive/upload/complete`
- `GET /api/drive/download/{file_id}`
- `POST /api/drive/share`
- `POST /api/drive/share/revoke`
### 8.4 Share匿名访问
- `GET /share/{token}`(分享页元信息)
- `POST /share/{token}/download`(提取码校验后返回签名 URL
### 8.5 Campus平台聚合 Rust API
- `POST /api/campus/bind`
- `POST /api/campus/unbind`
- `GET /api/campus/timetable?term=...&week=...`
- `GET /api/campus/grades?term=...`
- `GET /api/campus/forum/boards`
- `GET /api/campus/forum/posts?board_id=...&page=...`
- `GET /api/campus/forum/posts/{post_id}`
- `POST /api/campus/forum/post`
- `POST /api/campus/forum/comment`
- `GET /api/campus/map/poi?campus=...&q=...`
### 8.6 Admin仅 ADMIN
- `GET /api/admin/users`
- `PUT /api/admin/users/{id}/status`(封禁/解封)
- `GET /api/admin/audit`
- `PUT /api/admin/config/storage`OSS/ST S
- `PUT /api/admin/config/campus`Rust API base_url/超时/熔断阈值等)
- `PUT /api/admin/config/limits`(配额与限流参数)
---
## 9. 校园第三方 Rust API接口契约平台对 Rust
> 这部分是“平台后端”与“Rust API”之间的契约。
> 目标Rust API 改动时平台能通过适配层DTO兜住前端。
> Rust 侧能力可基于 `rsmycqu` 完成 SSO 与教务网权限获取等fileciteturn0file0L21-L48并遵循其 Session/Token 存储方式fileciteturn0file0L49-L77。
### 9.1 通用约束
- 通信:平台 -> Rust API 走内网或 mTLS建议
- 超时2~5s
- 幂等:对写接口支持 `Idempotency-Key`(避免重复发帖/评论)
- Rust API 必须提供健康检查:`GET /healthz`
### 9.2 Rust API 统一返回格式(建议)
```json
{
"ok": true,
"data": {},
"error": null,
"request_id": "rust-req-xxxx"
}
```
### 9.3 Rust API 端点(建议命名,可按实际调整)
#### 9.3.1 绑定与会话
- `POST /v1/session/login`
- 入参:`{ "auth": "...", "password": "...", "force_relogin": false }`
- 出参:`{ "session_token": "...", "expires_at": 1700000000 }`
- 说明Rust 侧内部维护 Session类似 `rsmycqu::Session`fileciteturn0file0L23-L41
- `POST /v1/session/logout`
- 入参:`{ "session_token": "..." }`
- 出参:`{ "success": true }`
> 备注:如果 Rust API 不愿管理 session_token也可让平台保存加密凭据并每次调用由 Rust API 现登;但会更慢、更容易触发风控。
#### 9.3.2 课表
- `GET /v1/timetable?session_token=...&term=...&week=...`
- Response `TimetableResponse`
```json
{
"term": "2025-2026-1",
"week": 3,
"updated_at": 1700000000,
"courses": [
{
"name": "数据结构",
"teacher": "张三",
"location": "A区-第3教学楼-201",
"weekday": 1,
"start_section": 1,
"end_section": 2,
"weeks": [1,2,3,4,5,6,7],
"remark": ""
}
]
}
```
#### 9.3.3 成绩
- `GET /v1/grades?session_token=...&term=...`
- Response `GradesResponse`
```json
{
"term": "2025-2026-1",
"updated_at": 1700000000,
"items": [
{ "course": "高等数学", "credit": 4.0, "grade": 92, "gpa": 4.0, "type": "必修" }
],
"summary": { "gpa": 3.62, "credits": 22.0 }
}
```
#### 9.3.4 论坛(读写按 Rust API 能力提供)
- `GET /v1/forum/boards`
- `GET /v1/forum/posts?board_id=...&page=...`
- `GET /v1/forum/posts/{post_id}`
- `POST /v1/forum/post`
- `POST /v1/forum/comment`
写接口建议入参:
```json
{ "session_token": "...", "title": "...", "content": "...", "board_id": "..." }
```
#### 9.3.5 地图 POI
- `GET /v1/map/poi?campus=...&q=...`
- Response
```json
{
"campus": "A",
"updated_at": 1700000000,
"pois": [
{ "id": "lib_a", "name": "图书馆", "lat": 29.123, "lng": 106.456, "category": "library", "desc": "" }
]
}
```
---
## 10. 错误码与响应规范(平台对前端)
### 10.1 平台统一返回格式
```json
{
"ok": false,
"data": null,
"error": {
"code": "CAMPUS_UPSTREAM_DOWN",
"message": "校园服务暂不可用(已返回缓存数据)",
"detail": { "upstream": "rust_api", "retry_after_sec": 60 }
},
"request_id": "req-20260211-xxxx"
}
```
### 10.2 平台错误码(建议最小集合)
| code | 含义 | 典型场景 |
|---|---|---|
| AUTH_UNAUTHORIZED | 未登录/令牌无效 | access token 过期 |
| AUTH_FORBIDDEN | 无权限 | 非 ADMIN 访问管理接口 |
| RATE_LIMITED | 触发限流 | 刷新成绩过频 |
| DRIVE_QUOTA_EXCEEDED | 超出配额 | 上传超容量/超单文件大小 |
| DRIVE_NOT_FOUND | 文件不存在 | file_id 不存在或无权限 |
| DRIVE_UPLOAD_EXPIRED | 上传凭证过期 | init 后太久未上传 |
| SHARE_INVALID | 分享无效 | token 不存在/已撤销 |
| SHARE_PASSWORD_REQUIRED | 需要提取码 | 未提供/错误 |
| CAMPUS_NOT_BOUND | 未绑定校园账号 | 访问课表/成绩 |
| CAMPUS_UPSTREAM_DOWN | Rust API 不可用 | 熔断/超时/5xx |
| CAMPUS_DATA_STALE | 数据过期 | 返回缓存但超过 max_stale |
| INTERNAL_ERROR | 内部错误 | 未分类异常 |
> Rust API 错误应映射为平台错误码(避免前端理解 Rust 的内部枚举)。
---
## 11. 时序图Mermaid
### 11.1 OSS 直传上传(分片 + 断点续传)
```mermaid
sequenceDiagram
autonumber
participant U as Browser
participant B as Platform BFF
participant O as Aliyun OSS
U->>B: POST /api/drive/upload/init (name,size,mime,parent_id)
B-->>U: {upload_id, oss_key, sts/policy, chunk_size, expires_at}
loop multipart chunks
U->>O: UploadPart(oss_key, partNo, signed/STS)
O-->>U: ETag(partNo)
end
U->>O: CompleteMultipartUpload(oss_key, etag_list)
O-->>U: 200 OK (final etag)
U->>B: POST /api/drive/upload/complete (upload_id, oss_key, size, etag, sha256?)
B-->>U: {file_id, created_at}
```
### 11.2 下载(签名 URL + 审计)
```mermaid
sequenceDiagram
autonumber
participant U as Browser
participant B as Platform BFF
participant O as Aliyun OSS
U->>B: GET /api/drive/download/{file_id}
B->>B: AuthZ check(user_id owns file)
B->>B: Write audit_logs(download_sign)
B-->>U: {signed_url, expires_in}
U->>O: GET signed_url
O-->>U: file bytes
```
### 11.3 校园数据查询BFF 缓存 + 熔断降级)
```mermaid
sequenceDiagram
autonumber
participant U as Browser
participant B as Platform BFF
participant R as Rust API
participant C as Cache/DB
U->>B: GET /api/campus/grades?term=...
B->>C: Read campus_cache(grades, user_id, term)
alt cache fresh
C-->>B: cached payload
B-->>U: cached data (ok=true, from_cache=true)
else cache stale/miss
B->>R: GET /v1/grades?session_token=...&term=...
alt rust ok
R-->>B: grades data
B->>C: Write cache(updated_at, expire_at)
B-->>U: ok=true (from_cache=false)
else rust fail/timeout
B->>B: circuit breaker / fallback
B-->>U: ok=true with stale cache OR ok=false with CAMPUS_UPSTREAM_DOWN
end
end
```
---
## 12. 缓存与熔断策略(建议默认)
- 课表TTL 6~24h默认 12h
- 成绩TTL 24h默认 24h
- POITTL 7d默认 7d
- 论坛列表TTL 30~120s默认 60s
熔断Rust API 在 1 分钟窗口内连续失败 ≥ 10 次触发;触发后 30~120 秒熔断(可配置)。
---
## 13. 管理后台(上线最小集合)
- 用户:封禁/解封、查看用量与最近行为
- 配额:容量/单文件/日上行/日下行/分享默认有效期
- OSSbucket、STS 配置、域名/CDN可选
- CampusRust API base_url、超时、重试、熔断参数、健康状态
- 审计:按 user/action/time 查询(支持导出)
---
## 14. 验收标准(上线验收)
### 14.1 功能
- 分账户隔离A 用户无法访问 B 用户的 files/settings/campus_cache
- 网盘闭环:上传(含断点续传)→ 预览/下载 → 删除 → 回收站恢复
- 分享:创建/访问/提取码/撤销 全链路可用
- 校园Rust API 异常时不白屏,缓存降级提示明确(含更新时间)
- 桌面:布局、主题可持久化,刷新后不丢
### 14.2 安全
- 前端无长期 AK/SK签名 URL 短期有效
- 登录/绑定/成绩刷新/下载签名/分享访问均限流生效
- 校园凭据加密存储,解绑后可彻底删除
- 审计日志完整(关键操作必留痕,带 request_id
### 14.3 稳定性
- Rust API 故障触发熔断,系统不雪崩
- 30 分钟高频操作无明显卡死/内存暴涨
---
## 15. 里程碑建议
- M1Auth + Desktop Shell设置持久化
- M2Drive MVP直传 OSS + 元数据 + 下载签名 + 回收站)
- M3分享 + 审计 + Admin 基础
- M4Campus BFF接 Rust API + 缓存/熔断/限流)+ 课表/成绩
- M5论坛/地图完善 + 监控告警 + staging→prod 演练
---
## 16. 附录:对 `rsmycqu` 的依赖注意
- 若 Rust API 基于 `rsmycqu`,建议沿用其 `Session` 设计与权限检查策略fileciteturn0file0L49-L77避免在缺失 token/权限时“晚失败”。
- `rsmycqu` 仍处于快速开发阶段需在平台侧预留接口变更适配层与回滚策略fileciteturn0file0L17-L20。