Files
ruoyi-vue-pro/yudao-module-education/README.md

220 lines
7.1 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.

# yudao-module-education
教育业务模块,提供课程、练习、题库、考试等教育业务功能。
## 当前状态:应用外壳 (Shell)
此模块目前处于**应用外壳**阶段,提供:
- 模块骨架与包结构
- 能力探测端点 (`/education/capability`)
- 租户识别端点 (`/education/tenant/resolve`) — 学生端登录前使用
- 教育上下文端点 (`/education/context`) — 学生端已认证状态
- 独立的功能开关配置
- 错误码常量
- 权限与菜单种子数据(角色授权由管理员按租户完成)
- 增量 SQL 交付约定
无业务表,无虚假 CRUD。
## 功能配置
`application.yaml` 或对应 profile 中配置:
```yaml
yudao:
education:
enabled: true # 是否启用教育模块,默认 false
version: 1.0.0 # 模块版本号
hostname-tenant-map: # authority 到租户名的精确映射(可选,键在读取时统一转为小写)
"staging.school.com": "demo-school" # DNS 与 websites 不一致时使用
login-methods: [PASSWORD, SMS] # 当前部署全局启用的 Member 登录入口
```
- `yudao.education.enabled=true`启用模块Controller 注册、Swagger 分组可见)
## API
### 管理后台 - 能力信息
```
GET /admin-api/education/capability
```
- 权限:`education:capability`
- 响应示例:
```json
{
"code": 0,
"msg": "成功",
"data": {
"module": "education",
"enabled": true,
"version": "1.0.0",
"capabilities": ["shell"]
}
}
```
### 用户 APP - 教育租户识别
```
GET /app-api/education/tenant/resolve?hostname=school.example.com
GET /app-api/education/tenant/resolve?tenantName=demo-school
GET /app-api/education/tenant/resolve?hostname=school.example.com&tenantName=demo-school
```
- 权限:无需认证(`@PermitAll`
- 说明:通过主机名或租户名解析租户,返回学生端登录引导所需的基础字段。
hostname 和 tenantName 至少提供一个。解析规则:
1. 如果同时提供两者,它们必须解析到同一个租户,否则拒绝请求
2. hostname 经过标准化(保留端口并转为小写),先查 `EducationProperties.hostnameTenantMap` 配置映射,再按 `system_tenant.websites` 的精确 authority 值查询
- 响应示例(成功):
```json
{
"code": 0,
"msg": "成功",
"data": {
"tenantId": 1024,
"tenantName": "demo-school",
"displayName": "demo-school",
"status": "ACTIVE",
"loginMethods": ["PASSWORD", "SMS"]
}
}
```
- 错误响应:
| 错误码 | 说明 |
|--------|------|
| 1_005_001_001 | 租户不存在 |
| 1_005_001_002 | 租户已被禁用 |
| 1_005_001_003 | 租户识别失败hostname 格式不合法等) |
| 1_005_001_004 | 当前租户不可用(过期等) |
### 用户 APP - 教育当前上下文
```
GET /app-api/education/context
```
- 权限:需要认证(登录态)
- 说明:根据当前认证用户和租户上下文返回教育业务信息。不信任请求体中的 userId一切从安全上下文和 TenantContext 派生。TenantSecurityWebFilter 前置完成租户校验,此处二次验证确保租户处于活跃状态。
- 响应示例:
```json
{
"code": 0,
"msg": "成功",
"data": {
"userId": 1024,
"tenantId": 2048,
"tenantName": "demo-school",
"displayName": "demo-school"
}
}
```
### 错误码
| 错误码 | 说明 |
|--------|------|
| 1_005_001_000 | 教育模块未启用 |
| 1_005_001_001 | 租户不存在 |
| 1_005_001_002 | 租户已被禁用 |
| 1_005_001_003 | 租户识别失败:{原因} |
| 1_005_001_004 | 当前租户不可用,请联系管理员 |
## 构建与运行
### 单独编译测试
```bash
# 编译 education 模块
mvn compile -pl yudao-module-education -am
# 运行 education 模块单元测试
mvn test -pl yudao-module-education -am
```
### 整体编译(含 server
```bash
# 编译全量member + education + system + infra + server
mvn compile -pl yudao-server -am
# 打包(跳过测试加速)
mvn package -pl yudao-server -am -DskipTests
```
### 启动验证
1. 确保 `yudao.education.enabled=true`
2. 启动 `yudao-server`
3. 访问 Swagger UI 查看 `education` 分组
4. 调用 `GET /admin-api/education/capability`
## SQL 应用
```bash
# 应用基础种子数据(菜单 + 权限定义;执行后由管理员为目标租户角色授权)
mysql -u root -p ruoyi-vue-pro < sql/mysql/education/000-education-seed.sql
# 应用租户识别种子数据
mysql -u root -p ruoyi-vue-pro < sql/mysql/education/001-education-tenant-seed.sql
# 回滚
mysql -u root -p ruoyi-vue-pro < sql/mysql/education/000-education-rollback.sql
mysql -u root -p ruoyi-vue-pro < sql/mysql/education/001-education-tenant-rollback.sql
```
## SQL 交付约定
- 所有 Education SQL 文件存放在 `sql/mysql/education/` 目录下
- 文件命名:`NNN-描述.sql`NNN 为三位递增序号)
- 每个正向脚本应有对应的回滚脚本
- schema 文件仅包含 DDLseed 文件仅包含 DML
- **不修改**项目根目录的 `ruoyi-vue-pro.sql` 巨量全量转储
## 前端状态
**当前工作区未检出完整的前端源码。** `yudao-ui/yudao-ui-admin-vue3/` 仅包含部分 MES 相关文件(`src/api/mes/``src/views/mes/`),缺少 `package.json``router/``store/``config/` 等核心框架文件。
因此:
- **管理后台教育菜单项**:基础 SQL 仅注册了 `system_menu` 记录ID 6800-6801。租户解析与当前上下文属于学生端接口不创建虚假的后台权限菜单。前端无路由/页面组件可渲染,菜单在管理后台不会显示。
- **Student Web/H5 应用外壳**:前端源码不存在,无法建立。
### Student 端前端集成契约
前端就位后必须实现以下流程(不能伪造静态页面):
1. **租户识别**(登录前)
- URL: `GET /app-api/education/tenant/resolve`
- 从浏览器 `window.location.host` 获取 authority包含非默认端口传入 `hostname` 参数
- 备用:支持手动输入 `tenantName`
- 根据返回的 `loginMethods` 决定展示哪种登录方式PASSWORD/SMS
- 获得 `tenantId` 后,在后续请求中通过 `tenant-id` header 传递
2. **用户认证**(复用 Member 模块)
- 密码登录: `POST /app-api/member/auth/login`
- 短信登录: `POST /app-api/member/auth/sms-login`
- 刷新令牌: `POST /app-api/member/auth/refresh-token`
- 登出: `POST /app-api/member/auth/logout`
- 所有请求携带 `tenant-id: {tenantId}` header
3. **获取上下文**(登录后)
- URL: `GET /app-api/education/context`
- 携带有效 Bearer Token + `tenant-id` header
- 从响应获取 `userId``tenantId``tenantName` 用于页面展示
4. **跨租户防护**
- 前端不应允许用户手动切换 `tenant-id` header
- 后端通过 `TenantSecurityWebFilter` 拒绝认证用户的跨租户 header 操作
**阻塞项**:完整前端源码(含 router、store、package.json是上述前端集成的必要前提。一旦前端源码就位
1. 在 Vue3 admin 的路由中添加 `/education` 路由项,绑定 Education 菜单组件
2. 添加 `src/api/education/` API 封装层(调用上述教育端点)
3. Student Web/H5 端如需要独立入口,需新建对应前端项目