# 学校管理与比赛管理模块 - 产品功能说明、实现思路与开发计划 ## 📋 目录 1. [概述](#概述) 2. [学校管理模块](#学校管理模块) 3. [比赛管理模块](#比赛管理模块) 4. [技术架构](#技术架构) 5. [实现思路](#实现思路) 6. [开发计划](#开发计划) 7. [权限设计](#权限设计) 8. [数据流转](#数据流转) --- ## 概述 ### 系统定位 本系统是一个**多租户的学校管理与比赛管理平台**,支持: - **多租户架构**:每个学校作为一个租户,数据完全隔离 - **统一用户体系**:教师和学生基于统一的 User 表,通过扩展表存储特定信息 - **完整的比赛流程**:从比赛创建、报名、作品提交到评审、结果公布的完整生命周期 - **灵活的权限控制**:基于 RBAC 的权限管理,支持细粒度的功能权限控制 ### 核心价值 1. **学校管理数字化**:实现学校组织架构、人员管理的数字化 2. **比赛管理规范化**:规范比赛流程,提高管理效率 3. **数据安全隔离**:多租户架构确保各学校数据安全隔离 4. **灵活扩展**:模块化设计,易于扩展新功能 --- ## 比赛管理模块 ### 1. 功能概述 比赛管理模块提供完整的比赛生命周期管理,从比赛创建、发布、报名、作品提交、评审到结果公布的完整流程。 ### 2. 核心功能 #### 2.1 比赛管理 **功能描述**: - 创建比赛(基本信息、时间安排、参赛范围等) - 编辑比赛信息 - 发布/撤回比赛 - 查看比赛列表和详情 **用户角色**: - 超级管理员:创建和管理所有比赛 - 比赛管理员:管理指定比赛 **业务规则**: - 比赛名称在系统内唯一 - 时间顺序校验:报名开始 < 报名结束 < 提交开始 < 提交结束 < 评审开始 < 评审结束 < 结果发布 - 只有发布的比赛才能被租户看到 - 已发布的比赛可以撤回,但需检查是否有报名记录 #### 2.2 比赛报名 **功能描述**: - **个人赛报名**:学生或教师个人报名 - **团队赛报名**:创建团队、邀请成员、提交团队报名 - 报名审核(可选) - 查看报名状态 **用户角色**: - 学生:个人报名、创建/加入团队 - 教师:个人报名、代学生报名、创建/管理团队 - 比赛管理员:审核报名 **业务规则**: - 报名时间限制:必须在报名时间窗口内 - 个人赛:一个用户在一个比赛中只能报名一次 - 团队赛: - 团队名称在同一比赛、同一租户内唯一 - 团队成员角色:leader(队长)、member(队员)、mentor(指导教师) - 团队报名时,所有成员状态同步更新 #### 2.3 作品提交 **功能描述**: - 提交参赛作品(标题、说明、文件等) - 支持单次提交和多次提交(根据比赛配置) - 作品版本管理 - 查看作品列表和详情 **用户角色**: - 学生:提交作品 - 教师:代学生提交作品 - 团队队长:提交团队作品 **业务规则**: - 提交时间限制:必须在提交时间窗口内 - 必须已通过报名审核 - **单次提交(submit_rule = 'once')**:只能提交一次 - **多次提交(submit_rule = 'resubmit')**: - 可以多次提交,每次创建新版本 - 只有最新版本参与评审 - 旧版本保留历史记录 #### 2.4 作品评审 **功能描述**: - 配置评审规则(评分维度、权重等) - 分配作品给评委 - 评委评分(多维度评分、评语) - 查看评审进度和结果 **用户角色**: - 比赛管理员:配置评审规则、分配作品 - 评委:查看分配的作品、进行评分 **业务规则**: - 评审时间限制:必须在评审时间窗口内 - 每个作品可以被多个评委评审 - 最终得分计算:根据评审规则计算(平均分、加权平均等) - 评审完成后,作品状态更新为 accepted 或 rejected #### 2.5 结果公布 **功能描述**: - 公布比赛结果(获奖名单、排名等) - 查看比赛结果统计 - 导出结果(Excel/PDF) **用户角色**: - 比赛管理员:公布结果 - 所有用户:查看结果 **业务规则**: - 只有评审已完成的比赛可以公布结果 - 结果公布后,所有用户可以看到排名和获奖信息 #### 2.6 比赛公告 **功能描述**: - 发布比赛公告 - 管理公告(编辑、删除、置顶) - 查看公告列表 **用户角色**: - 比赛管理员:发布和管理公告 - 所有用户:查看公告 **业务规则**: - 支持公告类型:系统公告、人工公告、紧急通知 - 支持优先级设置 ### 3. 数据模型 ``` Contest (比赛) ├── ContestAttachment (比赛附件) [1:N] ├── ContestReviewRule (评审规则) [1:1] ├── ContestTeam (团队) [1:N] │ └── ContestTeamMember (团队成员) [1:N] ├── ContestRegistration (报名记录) [1:N] │ └── ContestWork (作品) [1:N] │ ├── ContestWorkAttachment (作品附件) [1:N] │ ├── ContestWorkJudgeAssignment (作品分配) [1:N] │ └── ContestWorkScore (作品评分) [1:N] └── ContestNotice (比赛公告) [1:N] ``` ### 4. 关键业务规则 1. **租户隔离**:比赛通过 `contest_tenants` 字段控制可见范围 2. **时间管理**:严格的时间顺序校验和状态流转 3. **版本控制**:作品支持版本管理,保留历史记录 4. **评审灵活**:支持多维度评分和自定义评审规则 --- ## 技术架构 ### 1. 后端架构 ``` backend/ ├── src/ │ ├── school/ # 学校管理模块 │ │ ├── schools/ │ │ ├── grades/ │ │ ├── classes/ │ │ ├── departments/ │ │ ├── teachers/ │ │ └── students/ │ ├── contests/ # 比赛管理模块 │ │ ├── contests/ │ │ ├── registrations/ │ │ ├── teams/ │ │ ├── works/ │ │ ├── reviews/ │ │ └── notices/ │ ├── auth/ # 认证授权 │ ├── tenants/ # 租户管理 │ └── common/ # 公共模块 ``` **技术栈**: - **框架**:NestJS - **ORM**:Prisma - **数据库**:MySQL - **认证**:JWT - **权限**:RBAC ### 2. 前端架构 ``` frontend/ ├── src/ │ ├── views/ │ │ ├── school/ # 学校管理页面 │ │ │ ├── schools/ │ │ │ ├── grades/ │ │ │ ├── classes/ │ │ │ ├── departments/ │ │ │ ├── teachers/ │ │ │ └── students/ │ │ └── contests/ # 比赛管理页面 │ │ ├── Index.vue │ │ ├── Create.vue │ │ ├── works/ │ │ ├── registrations/ │ │ └── reviews/ │ ├── api/ # API 接口 │ ├── stores/ # 状态管理 │ └── utils/ # 工具函数 ``` **技术栈**: - **框架**:Vue 3 + TypeScript - **路由**:Vue Router - **状态管理**:Pinia - **UI 框架**:Element Plus / Ant Design Vue - **构建工具**:Vite ### 3. 数据库设计 **设计原则**: 1. **多租户隔离**:所有业务表都包含 `tenantId` 字段 2. **统一用户体系**:教师和学生基于 User 表 3. **数据完整性**:使用外键约束和级联删除 4. **审计追踪**:所有表包含创建人、修改人、时间字段 **核心表**: - 学校管理:`schools`, `grades`, `classes`, `departments`, `teachers`, `students` - 比赛管理:`t_contest`, `t_contest_registration`, `t_contest_work`, `t_contest_work_score` --- ## 实现思路 ### 1. 多租户数据隔离 #### 1.1 租户识别 **实现方式**: 1. **请求头方式**(推荐): - `X-Tenant-Code`: 租户编码 - `X-Tenant-Id`: 租户ID 2. **JWT Token 方式**: - Token 中包含 `tenantId` 字段 - 登录时自动关联租户 3. **子域名方式**: - 从 `Host` 请求头提取子域名 - 匹配租户的 `code` 或 `domain` 字段 #### 1.2 数据过滤 **实现方式**: ```typescript // Service 层自动过滤租户数据 async findAll(tenantId: number) { return this.prisma.model.findMany({ where: { tenantId } }); } // Controller 层获取租户信息 @Get() findAll(@Request() req) { const tenantId = req.tenantId || req.user?.tenantId; return this.service.findAll(tenantId); } ``` ### 2. 统一用户体系 #### 2.1 用户创建流程 **教师创建**: ``` 1. 创建 User 记录(username, password, tenantId) 2. 创建 Teacher 记录(关联 User.id) 3. 分配角色和权限 ``` **学生创建**: ``` 1. 创建 User 记录(username, password, tenantId) 2. 创建 Student 记录(关联 User.id) 3. 分配角色和权限 ``` #### 2.2 用户扩展信息 **实现方式**: - 使用 Prisma 的一对一关系 - 通过 `include` 查询关联数据 - 通过事务保证数据一致性 ### 3. 比赛流程管理 #### 3.1 状态机设计 **比赛状态**: ``` unpublished → published → (可撤回) → unpublished ``` **报名状态**: ``` pending → passed/rejected/withdrawn ``` **作品状态**: ``` submitted → locked → reviewing → accepted/rejected ``` #### 3.2 时间校验 **实现方式**: ```typescript // DTO 验证 @IsDate() @Validate(TimeOrderValidator) registerStartTime: Date; // 自定义验证器 class TimeOrderValidator implements ValidatorConstraintInterface { validate(value: any, args: ValidationArguments) { const dto = args.object as CreateContestDto; return dto.registerStartTime < dto.registerEndTime < dto.submitStartTime < dto.submitEndTime < dto.reviewStartTime < dto.reviewEndTime; } } ``` ### 4. 文件上传 #### 4.1 文件存储 **实现方式**: - 使用对象存储(OSS/S3)或本地存储 - 文件上传接口返回文件 URL - 文件信息存储到数据库 #### 4.2 文件管理 **实现方式**: ```typescript // 文件上传 @Post('upload') @UseInterceptors(FileInterceptor('file')) async uploadFile(@UploadedFile() file: Express.Multer.File) { // 验证文件类型和大小 // 上传到存储 // 返回文件 URL } // 文件删除 @Delete('files/:id') async deleteFile(@Param('id') id: string) { // 删除文件 // 更新数据库记录 } ``` ### 5. 权限控制 #### 5.1 权限编码 **命名规则**:`资源:操作` **示例**: ``` school:create # 创建学校 school:read # 查看学校 teacher:create # 创建教师 student:read # 查看学生 contest:create # 创建比赛 contest:publish # 发布比赛 work:submit # 提交作品 review:score # 评分 ``` #### 5.2 权限验证 **实现方式**: ```typescript // 使用装饰器 @RequirePermission('contest:create') @Post() create(@Body() dto: CreateContestDto) { // ... } // Guard 自动验证权限 @Injectable() export class PermissionsGuard implements CanActivate { async canActivate(context: ExecutionContext) { const requiredPermission = this.reflector.get(PERMISSION_KEY); const userPermissions = await this.getUserPermissions(); return userPermissions.includes(requiredPermission); } } ``` --- ## 开发计划 ### 阶段一:基础架构与学校管理(3-4周) #### 1.1 数据库迁移(1周) **任务**: - [ ] 执行学校管理模块数据库迁移 - [ ] 执行比赛管理模块数据库迁移 - [ ] 验证数据表结构 - [ ] 创建初始化数据脚本 **交付物**: - 数据库迁移文件 - 初始化数据脚本 - 数据库设计文档 #### 1.2 学校管理后端(2周) **任务**: - [ ] 创建 school 模块(Controller、Service、DTO) - [ ] 实现学校信息 CRUD - [ ] 实现年级管理 CRUD - [ ] 实现班级管理 CRUD(支持行政班级和兴趣班) - [ ] 实现部门管理 CRUD(支持树形结构) - [ ] 实现教师管理 CRUD(自动创建 User) - [ ] 实现学生管理 CRUD(自动创建 User) - [ ] 实现学生兴趣班关联管理 - [ ] 实现租户权限控制 - [ ] 编写单元测试 **交付物**: - 学校管理后端 API - API 文档 - 单元测试 #### 1.3 学校管理前端(1-2周) **任务**: - [ ] 创建学校管理页面结构 - [ ] 实现学校信息管理页面 - [ ] 实现年级管理页面 - [ ] 实现班级管理页面(支持类型切换) - [ ] 实现部门管理页面(树形结构) - [ ] 实现教师管理页面(列表、创建、编辑) - [ ] 实现学生管理页面(列表、创建、编辑) - [ ] 实现学生兴趣班管理页面 - [ ] 集成权限控制 - [ ] 实现路由配置 **交付物**: - 学校管理前端页面 - 路由配置 - 权限控制 ### 阶段二:比赛管理基础功能(3-4周) #### 2.1 比赛管理后端(2周) **任务**: - [ ] 创建 contests 模块(Controller、Service、DTO) - [ ] 实现比赛 CRUD 接口 - [ ] 实现比赛发布/撤回接口 - [ ] 实现比赛附件管理接口 - [ ] 实现评审规则管理接口 - [ ] 实现租户权限控制 - [ ] 实现时间校验逻辑 - [ ] 编写单元测试 **交付物**: - 比赛管理后端 API - API 文档 - 单元测试 #### 2.2 比赛管理前端(1-2周) **任务**: - [ ] 创建比赛管理页面结构 - [ ] 实现比赛列表页面 - [ ] 实现比赛创建/编辑页面 - [ ] 实现比赛详情页面 - [ ] 实现比赛发布功能 - [ ] 集成权限控制 - [ ] 实现路由配置 **交付物**: - 比赛管理前端页面 - 路由配置 ### 阶段三:报名功能(2-3周) #### 3.1 报名后端(1.5周) **任务**: - [ ] 创建 registrations 模块 - [ ] 实现个人报名接口 - [ ] 创建 teams 模块 - [ ] 实现团队创建/管理接口 - [ ] 实现团队报名接口 - [ ] 实现报名审核接口 - [ ] 实现报名状态流转逻辑 - [ ] 编写单元测试 **交付物**: - 报名管理后端 API - API 文档 #### 3.2 报名前端(1-1.5周) **任务**: - [ ] 实现比赛报名页面 - [ ] 实现团队管理页面 - [ ] 实现报名审核页面 - [ ] 实现报名状态展示 - [ ] 实现团队邀请功能 **交付物**: - 报名管理前端页面 ### 阶段四:作品提交功能(2-3周) #### 4.1 作品提交后端(1.5周) **任务**: - [ ] 创建 works 模块 - [ ] 实现作品提交接口 - [ ] 实现文件上传功能 - [ ] 实现作品版本控制逻辑 - [ ] 实现作品状态管理 - [ ] 实现作品列表查询(支持筛选) - [ ] 编写单元测试 **交付物**: - 作品管理后端 API - 文件上传功能 #### 4.2 作品提交前端(1-1.5周) **任务**: - [ ] 实现作品提交页面 - [ ] 实现文件上传组件 - [ ] 实现作品列表页面 - [ ] 实现作品详情页面 - [ ] 实现作品版本管理 **交付物**: - 作品管理前端页面 ### 阶段五:评审功能(3-4周) #### 5.1 评审后端(2周) **任务**: - [ ] 创建 reviews 模块 - [ ] 实现评审规则管理接口 - [ ] 实现作品分配接口(手动/自动) - [ ] 实现评分接口 - [ ] 实现评分计算逻辑 - [ ] 实现评审进度统计 - [ ] 编写单元测试 **交付物**: - 评审管理后端 API - 评分计算逻辑 #### 5.2 评审前端(1-2周) **任务**: - [ ] 实现评审规则配置页面 - [ ] 实现作品分配页面 - [ ] 实现评分页面(多维度评分表单) - [ ] 实现评审进度页面 - [ ] 实现评审结果统计 **交付物**: - 评审管理前端页面 ### 阶段六:结果公布与公告(1-2周) #### 6.1 结果公布后端(1周) **任务**: - [ ] 创建 notices 模块 - [ ] 实现公告 CRUD 接口 - [ ] 实现结果公布接口 - [ ] 实现结果统计接口 - [ ] 实现结果导出接口(Excel/PDF) **交付物**: - 公告和结果管理后端 API #### 6.2 结果公布前端(1周) **任务**: - [ ] 实现公告管理页面 - [ ] 实现结果公布页面 - [ ] 实现结果展示页面(排名、获奖名单) - [ ] 实现结果导出功能 **交付物**: - 公告和结果管理前端页面 ### 阶段七:优化与测试(2-3周) #### 7.1 功能优化(1-2周) **任务**: - [ ] 性能优化(数据库查询优化、缓存) - [ ] 用户体验优化 - [ ] 错误处理完善 - [ ] 日志记录完善 #### 7.2 测试(1周) **任务**: - [ ] 单元测试补充 - [ ] 集成测试 - [ ] 端到端测试 - [ ] 压力测试 - [ ] 安全测试 **交付物**: - 测试报告 - 性能报告 --- ## 权限设计 ### 1. 角色规划 #### 1.1 系统角色 **超级管理员(super_admin)**: - 所有权限 - 创建和管理租户 - 创建和管理比赛 **学校管理员(school_admin)**: - 学校管理:school:\* - 年级管理:grade:\* - 班级管理:class:\* - 部门管理:department:\* - 教师管理:teacher:\* - 学生管理:student:\* **比赛管理员(contest_admin)**: - 比赛管理:contest:\* - 公告管理:notice:\* - 结果公布:result:publish **评委(judge)**: - 作品查看:work:read - 评审分配:review:assign - 评分:review:score - 评审查看:review:read **教师(teacher)**: - 比赛查看:contest:read - 比赛报名:contest:register - 作品提交:work:submit - 作品查看:work:read - 学生管理:student:read(本班级) **学生(student)**: - 比赛查看:contest:read - 比赛报名:contest:register - 作品提交:work:submit - 作品查看:work:read(自己的作品) - 结果查看:result:read ### 2. 权限编码 #### 2.2 比赛管理权限 ``` contest:create # 创建比赛 contest:read # 查看比赛 contest:update # 更新比赛 contest:delete # 删除比赛 contest:publish # 发布比赛 contest:register # 报名比赛 team:create # 创建团队 team:read # 查看团队 team:update # 更新团队 team:delete # 删除团队 work:submit # 提交作品 work:read # 查看作品 work:update # 更新作品 review:assign # 分配作品 review:score # 评分 review:read # 查看评审 result:publish # 公布结果 result:read # 查看结果 notice:create # 创建公告 notice:read # 查看公告 notice:update # 更新公告 notice:delete # 删除公告 ``` --- ## 数据流转 ### 1. 学校管理数据流 ``` 创建租户 ↓ 创建学校信息 ↓ 创建年级 ↓ 创建班级(行政班级/兴趣班) ↓ 创建部门 ↓ 创建教师账号(User + Teacher) ↓ 创建学生账号(User + Student) ↓ 学生加入兴趣班(StudentInterestClass) ``` ### 2. 比赛管理数据流 ``` 创建比赛(超级管理员) ↓ 配置评审规则 ↓ 发布比赛 ↓ 学生/教师报名(个人/团队) ↓ 报名审核(可选) ↓ 提交作品 ↓ 分配作品给评委 ↓ 评委评分 ↓ 计算最终得分 ↓ 公布结果 ``` ### 3. 关键数据关联 **用户与学校**: - User.tenantId → Tenant.id - Teacher.userId → User.id - Student.userId → User.id **用户与比赛**: - ContestRegistration.userId → User.id - ContestWork.submitterUserId → User.id - ContestWorkScore.judgeId → User.id **比赛与租户**: - Contest.contestTenants (JSON) → Tenant.id[] - ContestRegistration.tenantId → Tenant.id - ContestWork.tenantId → Tenant.id --- ## 总结 本文档详细描述了学校管理和比赛管理两个核心模块的产品功能、实现思路和开发计划。主要特点: 1. **完整的业务流程**:覆盖从学校管理到比赛全生命周期的所有环节 2. **清晰的架构设计**:多租户、统一用户体系、模块化设计 3. **详细的开发计划**:分阶段实施,每个阶段都有明确的交付物 4. **完善的权限体系**:基于 RBAC 的细粒度权限控制 建议按照开发计划逐步实施,每个阶段完成后进行充分测试,确保系统稳定可靠。