# 学生操行分管理API ## 📋 文档说明 **版本**: v1.0 **制定时间**: 2025-01-13 **适用范围**: 学生操行分管理模块API接口 **重要性**: ⚠️ **强制性规范** - API设计必须遵循项目统一接口规范 --- ## 🎯 设计原则 ### 1. RESTful设计 - 使用标准的HTTP方法(GET、POST、PUT、DELETE) - 资源路径清晰,层次分明 - 状态码规范,返回信息明确 ### 2. 统一响应格式 - 所有接口返回统一的JSON格式 - 包含状态码、消息、数据三个部分 - 分页查询使用统一的TableDataInfo格式 ### 3. 权限控制 - 每个接口必须有@SaCheckPermission注解 - 班主任只能操作自己班级的学生 - 学生处管理员可查看全校数据 --- ## 🔌 接口概览 ### 接口分类 #### 基础CRUD接口 | 接口名称 | 请求方式 | 路径 | 权限字符 | 功能描述 | | -------- | -------- | ---- | -------- | -------- | | 查询操行分列表 | GET | /api/xg/conduct-score/list | xg:conduct:score:list | 分页查询操行分记录 | | 查询操行分详情 | GET | /api/xg/conduct-score/{id} | xg:conduct:score:query | 根据ID查询操行分详情 | | 新增操行分 | POST | /api/xg/conduct-score | xg:conduct:score:add | 创建新的操行分记录 | | 更新操行分 | PUT | /api/xg/conduct-score/{id} | xg:conductScore:update | 更新指定操行分记录 | | 删除操行分 | DELETE | /api/xg/conduct-score/{ids} | xg:conduct:score:remove | 删除指定操行分记录 | #### 业务逻辑接口 | 接口名称 | 请求方式 | 路径 | 权限字符 | 功能描述 | | -------- | -------- | ---- | -------- | -------- | | 批量录入操行分 | POST | /api/xg/conduct-score/batch | xg:conduct:score:batchAdd | 批量保存操行分 | | 班主任班级学生 | GET | /api/xg/conduct-score/class-students | xg:conduct:score:classStudents | 获取班主任班级学生列表 | | 学期平均分统计 | GET | /api/xg/conduct-score/semester-average | xg:conduct:score:semester | 查询学期平均分 | | 导出学期统计 | GET | /api/xg/conduct-score/export-semester | xg:conduct:score:export | 导出学期统计数据 | | 验证录入权限 | GET | /api/xg/conduct-score/check-permission | xg:conduct:score:checkPermission | 检查班主任录入权限 | | 获取学生详细记录 | GET | /api/xg/conduct-score/student-records/{studentId} | xg:conduct:score:studentRecords | 获取学生学期内每月操行分详情 | --- ## 📝 接口详细设计 ### 1. 查询操行分列表 #### 接口信息 - **请求方式**: GET - **接口路径**: `/api/xg/conduct-score/list` - **权限字符**: `xg:conduct:score:list` - **接口描述**: 分页查询操行分记录列表 #### 请求参数 | 参数名 | 类型 | 必填 | 说明 | | ------ | ---- | ---- | ---- | | academicYear | Integer | 否 | 学年(如:2024) | | semester | Integer | 否 | 学期(1-第一学期,2-第二学期) | | month | Integer | 否 | 月份(1-12) | | studentName | String | 否 | 学生姓名 | | className | String | 否 | 班级名称 | | scoreMin | BigDecimal | 否 | 最低分数 | | scoreMax | BigDecimal | 否 | 最高分数 | | pageNum | Integer | 否 | 当前页码(默认1) | | pageSize | Integer | 否 | 每页显示数量(默认10) | #### 响应格式 ```json { "code": 200, "msg": "查询成功", "data": { "total": 100, "rows": [ { "id": 1234567890123456789, "academicYear": 2024, "semester": 1, "month": 9, "studentId": 987654321098765432, "studentName": "张三", "studentNo": "2024001", "classId": 876543210987654321, "className": "计算机应用1班", "classTeacherId": 765432109876543210, "classTeacherName": "李老师", "score": 95.50, "remark": "表现优秀,积极参加班级活动", "createTime": "2024-09-01 10:00:00", "createBy": "李老师" } ], "code": 200, "msg": "查询成功" } } ``` ### 2. 批量录入操行分 #### 接口信息 - **请求方式**: POST - **接口路径**: `/api/xg/conduct-score/batch` - **权限字符**: `xg:conduct:score:batchAdd` - **接口描述**: 批量保存操行分记录 #### 请求参数 ```json { "academicYear": 2024, "semester": 1, "month": 9, "classId": 876543210987654321, "scores": [ { "studentId": 987654321098765432, "score": 95.50, "remark": "表现优秀,积极参加班级活动" }, { "studentId": 987654321098765433, "score": 88.00, "remark": "表现良好,需要继续努力" } ] } ``` #### 参数说明 | 参数名 | 类型 | 必填 | 说明 | | ------ | ---- | ---- | ---- | | academicYear | Integer | 是 | 学年(如:2024) | | semester | Integer | 是 | 学期(1-第一学期,2-第二学期) | | month | Integer | 是 | 月份(1-12) | | classId | Long | 是 | 班级ID | | scores | Array | 是 | 操行分记录数组 | | └─studentId | Long | 是 | 学生ID | | └─score | BigDecimal | 是 | 操行分数(0.00-100.00) | | └─remark | String | 否 | 备注信息 | #### 响应格式 ```json { "code": 200, "msg": "批量录入成功", "data": { "successCount": 45, "failCount": 0, "failList": [] } } ``` ### 3. 班主任班级学生列表 #### 接口信息 - **请求方式**: GET - **接口路径**: `/api/xg/conduct-score/class-students` - **权限字符**: `xg:conduct:score:classStudents` - **接口描述**: 获取班主任负责的所有班级及学生列表,用于多Tab页展示 #### 请求参数 | 参数名 | 类型 | 必填 | 说明 | | ------ | ---- | ---- | ---- | | academicYear | Integer | 否 | 学年(如:2024) | | semester | Integer | 否 | 学期(1-第一学期,2-第二学期) | | month | Integer | 否 | 月份(1-12) | #### 响应格式 ```json { "code": 200, "msg": "查询成功", "data": { "classes": [ { "classId": 876543210987654321, "className": "计算机1班", "classCode": "JSJ202401", "studentCount": 45, "enrollmentYear": 2024, "majorName": "计算机应用技术", "students": [ { "studentId": 987654321098765432, "studentNo": "2024001", "studentName": "张三", "gender": "0", "existingScore": null, "lastScore": 95.50, "lastMonth": 8 }, { "studentId": 987654321098765433, "studentNo": "2024002", "studentName": "李四", "gender": "1", "existingScore": { "id": 1234567890123456789, "score": 88.00, "remark": "表现良好", "createTime": "2024-09-01 09:00:00" }, "lastScore": 90.00, "lastMonth": 8 } ] } ], "summary": { "totalClasses": 3, "totalStudents": 125, "recordedStudents": 87, "pendingStudents": 38, "completionRate": 69.6 } } } ``` ### 4. 学期平均分统计 #### 接口信息 - **请求方式**: GET - **接口路径**: `/api/xg/conduct-score/semester-average` - **权限字符**: `xg:conduct:score:semester` - **接口描述**: 查询学生的学期操行平均分 #### 请求参数 | 参数名 | 类型 | 必填 | 说明 | | ------ | ---- | ---- | ---- | | academicYear | Integer | 是 | 学年(如:2024) | | semester | Integer | 是 | 学期(1-第一学期,2-第二学期) | | className | String | 否 | 班级名称筛选 | | studentName | String | 否 | 学生姓名筛选 | | pageNum | Integer | 否 | 当前页码(默认1) | | pageSize | Integer | 否 | 每页显示数量(默认10) | #### 响应格式 ```json { "code": 200, "msg": "查询成功", "data": { "total": 500, "rows": [ { "studentId": 987654321098765432, "studentNo": "2024001", "studentName": "张三", "gender": "0", "classId": 876543210987654321, "className": "计算机应用1班", "academicYear": 2024, "semester": 1, "avgScore": 92.83, "recordCount": 6, "maxScore": 98.00, "minScore": 88.00, "scoreRange": "88.00-98.00", "lastUpdateTime": "2024-09-30 16:00:00" } ], "summary": { "totalStudents": 500, "avgScore": 85.67, "excellentCount": 120, "goodCount": 280, "averageCount": 85, "needImprovementCount": 15 }, "code": 200, "msg": "查询成功" } } ``` ### 5. 获取学生详细记录 #### 接口信息 - **请求方式**: GET - **接口路径**: `/api/xg/conduct-score/student-records/{studentId}` - **权限字符**: `xg:conduct:score:studentRecords` - **接口描述**: 获取指定学生在某学期内1-12月份的操行分详细记录,没有数据的月份显示为空 #### 请求参数 | 参数名 | 类型 | 必填 | 说明 | | ------ | ---- | ---- | ---- | | studentId | Long | 是 | 学生ID(路径参数) | | academicYear | Integer | 否 | 学年(如:2024) | | semester | Integer | 否 | 学期(1-第一学期,2-第二学期) | | tenantId | String | 是 | 租户ID(多租户支持) | #### 响应格式 ```json { "code": 200, "msg": "查询成功", "data": { "studentId": 987654321098765432, "studentNo": "2024001", "studentName": "张三", "gender": "0", "classId": 876543210987654321, "className": "计算机应用1班", "classTeacherId": 765432109876543210, "classTeacherName": "李老师", "semesterAverage": 92.83, "totalRecords": 6, "records": [ { "id": 1234567890123456789, "academicYear": 2024, "semester": 1, "month": 9, "score": 95.50, "remark": "表现优秀,积极参加班级活动", "createBy": 765432109876543210, "createByName": "李老师", "createTime": "2024-09-01 10:00:00", "updateBy": 765432109876543210, "updateByName": "李老师", "updateTime": "2024-09-01 10:00:00" }, { "id": 1234567890123456790, "academicYear": 2024, "semester": 1, "month": 10, "score": 92.00, "remark": "表现良好,继续保持", "createBy": 765432109876543210, "createByName": "李老师", "createTime": "2024-10-01 09:30:00", "updateBy": 765432109876543210, "updateByName": "李老师", "updateTime": "2024-10-01 09:30:00" } ] } } ``` #### 数据说明 - `records` 数组:包含该学生该学期内所有有数据的月份记录 - 没有数据的月份不会出现在 `records` 数组中,前端需要生成1-12月的完整列表 - `semesterAverage`:该学生该学期的平均分 - `totalRecords`:该学生该学期录入的总记录数 --- ## 🔒 权限控制设计 ### 权限字符定义 ```java // 操行分管理权限 xg:conductScore:list // 查看操行分列表 xg:conductScore:list // 查看操行分列表(按部门) xg:conductScore:batchAdd // 批量录入操行分 xg:conductScore:batchUpdate // 批量更新操行分 xg:conductScore:classStudents // 查看班主任班级学生 xg:conductScore:export // 导出操行分数据 xg:conductScore:semesterAverage // 学期平均分统计 xg:conductScore:exportSemester // 导出学期统计 xg:conductScore:studentRecords // 获取学生详细记录 xg:conductScore:classDetail // 查看班级详情 xg:conductScore:update // 更新操行分 xg:conductScore:remove // 删除操行分 xg:conductScore:checkPermission // 验证录入权限 xg:conductScore:importTemplate // 导入模板 xg:conductScore:importData // 导入数据 xg:conduct:score:export // 数据导出 xg:conduct:score:studentRecords // 获取学生详细记录 ``` ### 权限控制逻辑 #### 班主任权限控制 ```java @SaCheckPermission("xg:conduct:score:classStudents") @GetMapping("/class-students") public AjaxResult getClassStudents(@RequestParam Integer academicYear, @RequestParam Integer semester, @RequestParam Integer month) { // 获取当前登录用户ID Long userId = SecurityUtils.getUserId(); // 从 xg_class_msg 表查询该用户作为班主任的所有班级 // WHERE class_teacher_id = #{userId} AND deleted = 0 List classIds = conductScoreService.getTeacherClassIds(userId); // 返回按班级分组的学生信息,用于前端生成Tab页 return AjaxResult.success(conductScoreService.getClassStudentsByTeacher(academicYear, semester, month)); } ``` #### 管理员权限控制 ```java @SaCheckPermission("xg:conduct:score:semester") @GetMapping("/semester-average") public TableDataInfo getSemesterAverage(@RequestParam Integer academicYear, @RequestParam Integer semester, XgConductScoreQueryBo queryBo, PageQuery pageQuery) { // 管理员可以查看全校数据,无班级限制 return xgConductScoreService.getSemesterAverage(academicYear, semester, queryBo, pageQuery); } ``` --- ## 📊 数据验证规则 ### 请求参数验证 ```java public class XgConductScoreBatchBo { @NotNull(message = "学年不能为空") @Min(value = 2020, message = "学年不能小于2020") @Max(value = 2030, message = "学年不能大于2030") private Integer academicYear; @NotNull(message = "学期不能为空") @Min(value = 1, message = "学期只能是1或2") @Max(value = 2, message = "学期只能是1或2") private Integer semester; @NotNull(message = "月份不能为空") @Min(value = 1, message = "月份范围为1-12") @Max(value = 12, message = "月份范围为1-12") private Integer month; @NotNull(message = "班级ID不能为空") private Long classId; @NotEmpty(message = "操行分记录不能为空") @Size(min = 1, max = 100, message = "一次最多录入100条记录") @Valid private List scores; } ``` ### 业务逻辑验证 #### 班主任权限验证 ```java private void validateTeacherPermission(Long classId, Long teacherId) { // 验证班主任是否负责该班级 boolean isResponsible = conductScoreService.checkTeacherClass(teacherId, classId); if (!isResponsible) { throw new ServiceException("您不是该班级的班主任,无权录入操行分"); } } ``` #### 重复录入验证 ```java private void validateNoDuplicate(Long studentId, Integer academicYear, Integer semester, Integer month) { // 检查是否已存在该学生的当月记录 boolean exists = conductScoreService.existsByStudentAndMonth( studentId, academicYear, semester, month); if (exists) { throw new ServiceException("该学生当月操行分已录入,不可重复录入"); } } ``` --- ## 🔄 错误码设计 ### 业务级错误码 | 错误码 | 说明 | | ------ | ---- | | 1001 | 班主任权限不足 | | 1002 | 学生不存在 | | 1003 | 班级不存在 | | 1004 | 操行分已存在,不可重复录入 | | 1005 | 分数范围错误 | | 1006 | 时间参数错误 | ### 错误响应格式 ```json { "code": 1001, "msg": "您不是该班级的班主任,无权录入操行分", "data": null } ``` --- ## 📈 性能优化 ### 接口性能指标 - **响应时间**: 平均 < 200ms,95% < 500ms - **并发处理**: 支持 100+ 并发请求 - **数据量**: 支持万人规模数据查询 ### 缓存策略 ```java // 学期统计缓存 @Cacheable(value = "conductScoreStats", key = "#academicYear + '_' + #semester") public List getSemesterAverage(Integer academicYear, Integer semester) { // 查询逻辑 } ``` --- ## 🧪 接口测试 ### 测试用例设计 #### 正常流程测试 ```bash # 批量录入操行分 curl -X POST "http://localhost:8080/api/xg/conduct-score/batch" \ -H "Authorization: Bearer {token}" \ -H "Content-Type: application/json" \ -d '{ "academicYear": 2024, "semester": 1, "month": 9, "classId": 876543210987654321, "scores": [ {"studentId": 987654321098765432, "score": 95.5, "remark": "优秀"} ] }' ``` #### 异常流程测试 ```bash # 权限不足测试 curl -X GET "http://localhost:8080/api/xg/conduct-score/class-students" \ -H "Authorization: Bearer {invalid_token}" # 响应: {"code": 403, "msg": "权限不足", "data": null} ``` --- ## 📚 相关文档 - **数据库设计**: `../技术设计/数据库设计.md` - **前端设计**: `../前端设计/界面原型图.md` - **项目API总览**: `API文档总览.md` --- **最后更新**: 2025-01-13 **接口版本**: v1.0 **兼容性**: 向后兼容