Appearance
云学院 P0–P1 实施设计
状态:代码已实现,等待联机验收
日期:2026-10-26 上位需求:功能清单与系统接入设计
1. 交付边界
P0 交付真实登录、角色身份、学校与班级、师生账号和学校范围隔离。P1 交付平台课程、学校副本、班级分配、资源和学习进度,形成跨浏览器闭环。考试、课堂、竞赛与数据大屏的真实能力在后续批次接入。AI 问答与查看历史留作 Gap。
每个业务页面接入时移除 useApp.db 的真实环境读写依赖;本地演示数据只在显式 demo 模式生效。接入前端页面不得在 API 失败时回退到本地数据。
2. 模块与依赖
新增 weiran-education-{api,domain,application,infrastructure,adapter} 五层业务模块,由现有 Gradle 自动发现规则装配。education 使用独立 edu_user 账号仓储并复用上游认证拦截器;课程文件存入 edu_course_file,通过课程引用关系控制下载。新增业务 Controller 采用 /api-backend/education/...,权限码统一用 education:*,响应仍由框架统一封装。
packages/web/ 增加统一的请求客户端、当前身份查询与领域查询 hooks。身份来源为教育模块的当前用户接口与 me;界面导航根据服务端角色显示,服务端重新校验每个操作的资源归属。
3. P0 数据结构
| 表 | 核心字段与约束 | 用途 |
|---|---|---|
edu_school | id、唯一 code、name、stage、region_code、联系人、电话、status、deleted_at、审计字段 | 学校状态为 active/disabled/soft_deleted;硬删除后无记录 |
edu_school_user | 唯一 (user_id)、school_id、student_no(校内唯一,可空)、status | edu_user 是学校端登录账号;学校归属单独保存 |
edu_class | id、school_id、名称、年级、专业、审计字段;唯一 (school_id,name) | 班级 |
edu_class_student | 唯一 user_id、class_id | 学生一个主班;允许未分班 |
edu_class_teacher | 唯一 (class_id,user_id) | 老师可任教多班 |
edu_school_account_status | school_id、user_id、操作批次、停用前状态 | 学校恢复时只恢复原先启用的账号 |
系统 sys_role 增加 ykt_platform_admin/ykt_school_admin/ykt_teacher/ykt_student 四个角色;每个云学院账号恰好持有其中一种云学院角色。四类前台账号统一写入 edu_user;学校管理员、老师、学生另写学校归属,平台管理员不关联学校。内置 super_admin 仅作为系统后台引导账号,可开通首个前台平台管理员,不作为日常云学院平台账号。
4. P0 接口与规则
| 接口组 | 操作 | 授权与要点 |
|---|---|---|
education/me | 查询云学院身份、学校、班级 | 仅登录;无 ykt_* 角色返回 403 |
education/school | 列表、详情、创建、编辑、停用、启用 | 平台管理员;学校编号唯一,停用校内账号并吊销令牌 |
education/school | 软删除、恢复、硬删除预检、硬删除 | 平台管理员;硬删除只对软删除学校执行,独立入口与审计 |
education/account | 本校老师/学生列表、单个开户、批量开户、编辑、启停、重置密码 | 学校管理员只管理本校;平台管理员按学校管理;批量返回逐行结果 |
education/class | 列表、详情、创建、编辑、删除、设置学生/老师 | 学校管理员只管理本校;老师只读任教班 |
学校停用和软删除的认证校验放在教育业务授权入口,不能只依赖登录时的状态快照。只有云学院角色的专属账号随学校停用而禁用系统账号;同时具有其他系统角色的共享账号仍可进入原有系统,但云学院学校范围即时失效。普通系统账号登录仍经现有认证体系;云学院账号访问教育接口时额外检查学校状态。系统管理台限制 ykt_* 专属账号进入管理页面。通用系统接口要逐项确认是否需要权限码,避免仅登录即可读到系统数据。
5. P1 数据结构
| 表 | 核心字段与约束 | 用途 |
|---|---|---|
edu_course_package | 归属学校可空、来源 ID、编号、标题、内容 JSON、状态、修订号 | 平台课程与学校独立副本;内容树中的章节/课程节点有稳定 ID |
edu_course_revision | 课程 ID、不可变版本号、标题与内容快照、发布时间 | 平台发布与历史引用 |
edu_distribution | 来源课程、学校、稳定副本 ID、来源版本、本地修订、allow_edit;唯一 (source_course_id,school_id) | 首次分发/升级 |
edu_class_course | 唯一 (class_id,school_course_id) | 学校副本配给班级 |
课程 content_json | chapters[].lessons[] 与课件、资料、附件引用 | 课程内容整体版本化;资源实体仍由资源库管理 |
edu_lesson_progress | 唯一 (student_id,lesson_id)、完成时间、内容修订 | 学生完成记录 |
课程名称在接口中固定:CoursePackage 对应界面的“章节”,Chapter 对应其中的分组,Lesson 对应界面的“课程”。首次分发创建学校副本;同版重发幂等;升级复用副本 ID,标题与内容树均按三方合并规则预览和确认,班级分配不变。学校副本删除或升级时,历史学习记录引用当时修订,不回写历史。
6. P1 接口与规则
| 接口组 | 操作 | 授权与要点 |
|---|---|---|
education/course | 平台库/学校库列表、详情、编辑、排序、发布 | 平台管理员改默认库;学校管理员和老师仅在 allow_edit 且范围匹配时改副本 |
education/distribution | 首次分发、升级预览、确认升级、编辑权限调整 | 事务、幂等键、副本修订乐观锁、冲突列表 |
education/classCourse | 班级×章节列表、替换分配 | 学校管理员本校操作,学校副本 ID 稳定 |
education/lesson | 课程内容、资料发布/编辑、PDF/附件引用 | 文件存入 edu_course_file;上传成功后关联文件 ID,不持久化浏览器 blob: URL |
education/myCourses、education/progress | 学生/老师可见课程、学生标记完成 | 学生按所属班级;老师按任教班级;完成操作幂等 |
7. 迁移与验收顺序
- 建教育模块及迁移、角色种子;验证 Flyway 和 Gradle 装配。
- P0 学校/账号/班级接口与跨校权限测试;接入
web登录和组织页面。 - P1 平台课程与发布、分发和副本升级;接入课程与分配页面。
- 接入资源库、学生学习与进度;完成两浏览器端到端验收。
- 真实环境移除演示账号切换、重置演示数据和明文密码展示。
最低验收场景:平台管理员建校并分发课程;学校管理员开户、建班、分配学校副本;老师在允许编辑时添加 PDF;学生在另一浏览器登录后能读到 PDF 并标记完成;老师能看到真实进度。跨校访问列表、详情 URL、写接口及文件下载均拒绝。
8. 当前实现与验证
- 已实现上述 P0/P1 接口及页面;老师学习进度按任教班级和课程查询,展示每名学生已完成课时数。
- 课程 PDF 和资料附件采用数据库文件表与课程引用表;文件下载按实际课程可见性授权。单文件上限 16 MB。
web的 TypeScript 检查及 Next.js 生产构建通过;新增教育模块 Java 源文件独立编译通过;三方合并和服务端跨校授权单元场景已验证。- 当前执行环境未能启动 Gradle 后端与 MySQL,因此 Flyway 迁移、真实登录、跨浏览器流程和跨校权限仍须在可运行的后端环境执行验收。此仓库本地配置的服务端代理地址为
http://127.0.0.1:5400,可用WEIRAN_API_ORIGIN覆盖。