From f40b0e7c943f82068bbddabfcc68fee807420919 Mon Sep 17 00:00:00 2001 From: zhonghua Date: Thu, 2 Apr 2026 14:22:56 +0800 Subject: [PATCH] =?UTF-8?q?=E6=9A=82=E5=AD=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/migration/rbac-audit.sql | 22 - .../common/enums/HomeworkStatusEnum.java | 30 - .../enums/HomeworkSubmissionStatusEnum.java | 31 - .../ContestRegistrationController.java | 18 + .../controller/DepartmentController.java | 97 --- .../creation/controller/GradeController.java | 87 --- .../controller/HomeworkController.java | 292 -------- .../controller/SchoolClassController.java | 89 --- .../creation/controller/SchoolController.java | 71 -- .../controller/StudentController.java | 100 --- .../controller/TeacherController.java | 100 --- .../dto/department/CreateDepartmentDTO.java | 30 - .../dto/department/UpdateDepartmentDTO.java | 30 - .../creation/dto/grade/CreateGradeDTO.java | 29 - .../creation/dto/grade/UpdateGradeDTO.java | 24 - .../dto/homework/CreateHomeworkDTO.java | 40 -- .../creation/dto/homework/CreateScoreDTO.java | 27 - .../dto/homework/DimensionScoreDTO.java | 27 - .../dto/homework/HomeworkQueryDTO.java | 27 - .../dto/homework/ReviewDimensionDTO.java | 27 - .../dto/homework/ReviewHomeworkDTO.java | 26 - .../dto/homework/SubmissionQueryDTO.java | 42 -- .../dto/homework/SubmitHomeworkDTO.java | 26 - .../dto/homework/UpdateHomeworkDTO.java | 37 - .../dto/homework/UpdateReviewRuleDTO.java | 26 - .../creation/dto/school/CreateSchoolDTO.java | 36 - .../creation/dto/school/UpdateSchoolDTO.java | 35 - .../dto/student/CreateStudentDTO.java | 68 -- .../dto/student/UpdateStudentDTO.java | 59 -- .../dto/teacher/CreateTeacherDTO.java | 65 -- .../dto/teacher/UpdateTeacherDTO.java | 56 -- .../lesingle/creation/entity/Department.java | 66 -- .../com/lesingle/creation/entity/Grade.java | 52 -- .../lesingle/creation/entity/Homework.java | 82 --- .../entity/HomeworkReviewDimension.java | 54 -- .../creation/entity/HomeworkReviewRule.java | 48 -- .../creation/entity/HomeworkScore.java | 54 -- .../creation/entity/HomeworkSubmission.java | 90 --- .../com/lesingle/creation/entity/School.java | 72 -- .../lesingle/creation/entity/SchoolClass.java | 64 -- .../com/lesingle/creation/entity/Student.java | 102 --- .../com/lesingle/creation/entity/Teacher.java | 96 --- .../creation/mapper/DepartmentMapper.java | 35 - .../lesingle/creation/mapper/GradeMapper.java | 35 - .../creation/mapper/HomeworkMapper.java | 13 - .../mapper/HomeworkReviewDimensionMapper.java | 26 - .../mapper/HomeworkReviewRuleMapper.java | 13 - .../creation/mapper/HomeworkScoreMapper.java | 13 - .../mapper/HomeworkSubmissionMapper.java | 13 - .../creation/mapper/SchoolClassMapper.java | 35 - .../creation/mapper/SchoolMapper.java | 23 - .../creation/mapper/StudentMapper.java | 33 - .../creation/mapper/TeacherMapper.java | 33 - .../creation/service/DepartmentService.java | 45 -- .../creation/service/GradeService.java | 37 - .../creation/service/HomeworkService.java | 208 ------ .../creation/service/SchoolClassService.java | 37 - .../creation/service/SchoolService.java | 48 -- .../creation/service/StudentService.java | 73 -- .../creation/service/TeacherService.java | 73 -- .../creation/service/UserService.java | 13 + .../service/impl/DepartmentServiceImpl.java | 189 ------ .../service/impl/GradeServiceImpl.java | 152 ----- .../service/impl/HomeworkServiceImpl.java | 633 ------------------ .../service/impl/SchoolClassServiceImpl.java | 173 ----- .../service/impl/SchoolServiceImpl.java | 133 ---- .../service/impl/StudentServiceImpl.java | 293 -------- .../service/impl/TeacherServiceImpl.java | 307 --------- .../service/impl/UserServiceImpl.java | 43 ++ .../creation/vo/department/DepartmentVO.java | 50 -- .../lesingle/creation/vo/grade/GradeVO.java | 41 -- .../vo/homework/HomeworkDetailVO.java | 53 -- .../creation/vo/homework/HomeworkListVO.java | 41 -- .../vo/homework/ReviewDimensionVO.java | 29 - .../creation/vo/homework/ReviewRuleVO.java | 33 - .../creation/vo/homework/SubmissionVO.java | 51 -- .../creation/vo/school/ClassTreeNodeVO.java | 32 - .../lesingle/creation/vo/school/SchoolVO.java | 57 -- .../creation/vo/schoolclass/ClassVO.java | 51 -- .../creation/vo/student/StudentVO.java | 102 --- .../creation/vo/teacher/TeacherVO.java | 99 --- .../src/main/resources/application-dev.yml | 2 +- .../V38__remove_school_homework_ai3d.sql | 68 ++ .../mapper/HomeworkReviewDimensionMapper.xml | 29 - java-frontend/src/api/classes.ts | 91 --- java-frontend/src/api/contests.ts | 30 + java-frontend/src/api/departments.ts | 91 --- java-frontend/src/api/grades.ts | 78 --- java-frontend/src/api/homework.ts | 415 ------------ java-frontend/src/api/schools.ts | 73 -- java-frontend/src/api/students.ts | 150 ----- java-frontend/src/api/teachers.ts | 123 ---- java-frontend/src/router/index.ts | 538 ++++++--------- java-frontend/src/utils/menu.ts | 327 ++++----- .../src/views/contests/RegisterIndividual.vue | 42 +- .../src/views/contests/RegisterTeam.vue | 150 +++-- .../components/AddParticipantDrawer.vue | 141 +--- .../contests/components/AddTeacherDrawer.vue | 126 +--- java-frontend/src/views/homework/Index.vue | 601 ----------------- .../src/views/homework/ReviewRules.vue | 399 ----------- .../src/views/homework/StudentDetail.vue | 507 -------------- .../src/views/homework/StudentList.vue | 495 -------------- .../src/views/homework/Submissions.vue | 537 --------------- .../src/views/school/classes/Index.vue | 369 ---------- .../src/views/school/departments/Index.vue | 351 ---------- .../src/views/school/grades/Index.vue | 280 -------- .../src/views/school/schools/Index.vue | 307 --------- .../src/views/school/students/Index.vue | 552 --------------- .../src/views/school/teachers/Index.vue | 498 -------------- java-frontend/tsconfig.tsbuildinfo | 2 +- 110 files changed, 677 insertions(+), 12517 deletions(-) delete mode 100644 java-backend/src/main/java/com/lesingle/creation/common/enums/HomeworkStatusEnum.java delete mode 100644 java-backend/src/main/java/com/lesingle/creation/common/enums/HomeworkSubmissionStatusEnum.java delete mode 100644 java-backend/src/main/java/com/lesingle/creation/controller/DepartmentController.java delete mode 100644 java-backend/src/main/java/com/lesingle/creation/controller/GradeController.java delete mode 100644 java-backend/src/main/java/com/lesingle/creation/controller/HomeworkController.java delete mode 100644 java-backend/src/main/java/com/lesingle/creation/controller/SchoolClassController.java delete mode 100644 java-backend/src/main/java/com/lesingle/creation/controller/SchoolController.java delete mode 100644 java-backend/src/main/java/com/lesingle/creation/controller/StudentController.java delete mode 100644 java-backend/src/main/java/com/lesingle/creation/controller/TeacherController.java delete mode 100644 java-backend/src/main/java/com/lesingle/creation/dto/department/CreateDepartmentDTO.java delete mode 100644 java-backend/src/main/java/com/lesingle/creation/dto/department/UpdateDepartmentDTO.java delete mode 100644 java-backend/src/main/java/com/lesingle/creation/dto/grade/CreateGradeDTO.java delete mode 100644 java-backend/src/main/java/com/lesingle/creation/dto/grade/UpdateGradeDTO.java delete mode 100644 java-backend/src/main/java/com/lesingle/creation/dto/homework/CreateHomeworkDTO.java delete mode 100644 java-backend/src/main/java/com/lesingle/creation/dto/homework/CreateScoreDTO.java delete mode 100644 java-backend/src/main/java/com/lesingle/creation/dto/homework/DimensionScoreDTO.java delete mode 100644 java-backend/src/main/java/com/lesingle/creation/dto/homework/HomeworkQueryDTO.java delete mode 100644 java-backend/src/main/java/com/lesingle/creation/dto/homework/ReviewDimensionDTO.java delete mode 100644 java-backend/src/main/java/com/lesingle/creation/dto/homework/ReviewHomeworkDTO.java delete mode 100644 java-backend/src/main/java/com/lesingle/creation/dto/homework/SubmissionQueryDTO.java delete mode 100644 java-backend/src/main/java/com/lesingle/creation/dto/homework/SubmitHomeworkDTO.java delete mode 100644 java-backend/src/main/java/com/lesingle/creation/dto/homework/UpdateHomeworkDTO.java delete mode 100644 java-backend/src/main/java/com/lesingle/creation/dto/homework/UpdateReviewRuleDTO.java delete mode 100644 java-backend/src/main/java/com/lesingle/creation/dto/school/CreateSchoolDTO.java delete mode 100644 java-backend/src/main/java/com/lesingle/creation/dto/school/UpdateSchoolDTO.java delete mode 100644 java-backend/src/main/java/com/lesingle/creation/dto/student/CreateStudentDTO.java delete mode 100644 java-backend/src/main/java/com/lesingle/creation/dto/student/UpdateStudentDTO.java delete mode 100644 java-backend/src/main/java/com/lesingle/creation/dto/teacher/CreateTeacherDTO.java delete mode 100644 java-backend/src/main/java/com/lesingle/creation/dto/teacher/UpdateTeacherDTO.java delete mode 100644 java-backend/src/main/java/com/lesingle/creation/entity/Department.java delete mode 100644 java-backend/src/main/java/com/lesingle/creation/entity/Grade.java delete mode 100644 java-backend/src/main/java/com/lesingle/creation/entity/Homework.java delete mode 100644 java-backend/src/main/java/com/lesingle/creation/entity/HomeworkReviewDimension.java delete mode 100644 java-backend/src/main/java/com/lesingle/creation/entity/HomeworkReviewRule.java delete mode 100644 java-backend/src/main/java/com/lesingle/creation/entity/HomeworkScore.java delete mode 100644 java-backend/src/main/java/com/lesingle/creation/entity/HomeworkSubmission.java delete mode 100644 java-backend/src/main/java/com/lesingle/creation/entity/School.java delete mode 100644 java-backend/src/main/java/com/lesingle/creation/entity/SchoolClass.java delete mode 100644 java-backend/src/main/java/com/lesingle/creation/entity/Student.java delete mode 100644 java-backend/src/main/java/com/lesingle/creation/entity/Teacher.java delete mode 100644 java-backend/src/main/java/com/lesingle/creation/mapper/DepartmentMapper.java delete mode 100644 java-backend/src/main/java/com/lesingle/creation/mapper/GradeMapper.java delete mode 100644 java-backend/src/main/java/com/lesingle/creation/mapper/HomeworkMapper.java delete mode 100644 java-backend/src/main/java/com/lesingle/creation/mapper/HomeworkReviewDimensionMapper.java delete mode 100644 java-backend/src/main/java/com/lesingle/creation/mapper/HomeworkReviewRuleMapper.java delete mode 100644 java-backend/src/main/java/com/lesingle/creation/mapper/HomeworkScoreMapper.java delete mode 100644 java-backend/src/main/java/com/lesingle/creation/mapper/HomeworkSubmissionMapper.java delete mode 100644 java-backend/src/main/java/com/lesingle/creation/mapper/SchoolClassMapper.java delete mode 100644 java-backend/src/main/java/com/lesingle/creation/mapper/SchoolMapper.java delete mode 100644 java-backend/src/main/java/com/lesingle/creation/mapper/StudentMapper.java delete mode 100644 java-backend/src/main/java/com/lesingle/creation/mapper/TeacherMapper.java delete mode 100644 java-backend/src/main/java/com/lesingle/creation/service/DepartmentService.java delete mode 100644 java-backend/src/main/java/com/lesingle/creation/service/GradeService.java delete mode 100644 java-backend/src/main/java/com/lesingle/creation/service/HomeworkService.java delete mode 100644 java-backend/src/main/java/com/lesingle/creation/service/SchoolClassService.java delete mode 100644 java-backend/src/main/java/com/lesingle/creation/service/SchoolService.java delete mode 100644 java-backend/src/main/java/com/lesingle/creation/service/StudentService.java delete mode 100644 java-backend/src/main/java/com/lesingle/creation/service/TeacherService.java delete mode 100644 java-backend/src/main/java/com/lesingle/creation/service/impl/DepartmentServiceImpl.java delete mode 100644 java-backend/src/main/java/com/lesingle/creation/service/impl/GradeServiceImpl.java delete mode 100644 java-backend/src/main/java/com/lesingle/creation/service/impl/HomeworkServiceImpl.java delete mode 100644 java-backend/src/main/java/com/lesingle/creation/service/impl/SchoolClassServiceImpl.java delete mode 100644 java-backend/src/main/java/com/lesingle/creation/service/impl/SchoolServiceImpl.java delete mode 100644 java-backend/src/main/java/com/lesingle/creation/service/impl/StudentServiceImpl.java delete mode 100644 java-backend/src/main/java/com/lesingle/creation/service/impl/TeacherServiceImpl.java delete mode 100644 java-backend/src/main/java/com/lesingle/creation/vo/department/DepartmentVO.java delete mode 100644 java-backend/src/main/java/com/lesingle/creation/vo/grade/GradeVO.java delete mode 100644 java-backend/src/main/java/com/lesingle/creation/vo/homework/HomeworkDetailVO.java delete mode 100644 java-backend/src/main/java/com/lesingle/creation/vo/homework/HomeworkListVO.java delete mode 100644 java-backend/src/main/java/com/lesingle/creation/vo/homework/ReviewDimensionVO.java delete mode 100644 java-backend/src/main/java/com/lesingle/creation/vo/homework/ReviewRuleVO.java delete mode 100644 java-backend/src/main/java/com/lesingle/creation/vo/homework/SubmissionVO.java delete mode 100644 java-backend/src/main/java/com/lesingle/creation/vo/school/ClassTreeNodeVO.java delete mode 100644 java-backend/src/main/java/com/lesingle/creation/vo/school/SchoolVO.java delete mode 100644 java-backend/src/main/java/com/lesingle/creation/vo/schoolclass/ClassVO.java delete mode 100644 java-backend/src/main/java/com/lesingle/creation/vo/student/StudentVO.java delete mode 100644 java-backend/src/main/java/com/lesingle/creation/vo/teacher/TeacherVO.java create mode 100644 java-backend/src/main/resources/db/migration/V38__remove_school_homework_ai3d.sql delete mode 100644 java-backend/src/main/resources/mapper/HomeworkReviewDimensionMapper.xml delete mode 100644 java-frontend/src/api/classes.ts delete mode 100644 java-frontend/src/api/departments.ts delete mode 100644 java-frontend/src/api/grades.ts delete mode 100644 java-frontend/src/api/homework.ts delete mode 100644 java-frontend/src/api/schools.ts delete mode 100644 java-frontend/src/api/students.ts delete mode 100644 java-frontend/src/api/teachers.ts delete mode 100644 java-frontend/src/views/homework/Index.vue delete mode 100644 java-frontend/src/views/homework/ReviewRules.vue delete mode 100644 java-frontend/src/views/homework/StudentDetail.vue delete mode 100644 java-frontend/src/views/homework/StudentList.vue delete mode 100644 java-frontend/src/views/homework/Submissions.vue delete mode 100644 java-frontend/src/views/school/classes/Index.vue delete mode 100644 java-frontend/src/views/school/departments/Index.vue delete mode 100644 java-frontend/src/views/school/grades/Index.vue delete mode 100644 java-frontend/src/views/school/schools/Index.vue delete mode 100644 java-frontend/src/views/school/students/Index.vue delete mode 100644 java-frontend/src/views/school/teachers/Index.vue diff --git a/docs/migration/rbac-audit.sql b/docs/migration/rbac-audit.sql index d0676de..298412c 100644 --- a/docs/migration/rbac-audit.sql +++ b/docs/migration/rbac-audit.sql @@ -61,10 +61,6 @@ SELECT FROM t_sys_tenant t JOIN ( SELECT 'activity:read' AS code UNION ALL - SELECT 'ai-3d:create' UNION ALL - SELECT 'class:create' UNION ALL - SELECT 'class:delete' UNION ALL - SELECT 'class:update' UNION ALL SELECT 'config:create' UNION ALL SELECT 'config:delete' UNION ALL SELECT 'config:update' UNION ALL @@ -73,19 +69,9 @@ JOIN ( SELECT 'contest:publish' UNION ALL SELECT 'contest:read' UNION ALL SELECT 'contest:update' UNION ALL - SELECT 'department:create' UNION ALL - SELECT 'department:delete' UNION ALL - SELECT 'department:update' UNION ALL SELECT 'dict:create' UNION ALL SELECT 'dict:delete' UNION ALL SELECT 'dict:update' UNION ALL - SELECT 'grade:create' UNION ALL - SELECT 'grade:delete' UNION ALL - SELECT 'grade:update' UNION ALL - SELECT 'homework:create' UNION ALL - SELECT 'homework:delete' UNION ALL - SELECT 'homework:read' UNION ALL - SELECT 'homework:update' UNION ALL SELECT 'judge:create' UNION ALL SELECT 'judge:delete' UNION ALL SELECT 'judge:read' UNION ALL @@ -105,14 +91,6 @@ JOIN ( SELECT 'role:delete' UNION ALL SELECT 'role:read' UNION ALL SELECT 'role:update' UNION ALL - SELECT 'school:create' UNION ALL - SELECT 'school:update' UNION ALL - SELECT 'student:create' UNION ALL - SELECT 'student:delete' UNION ALL - SELECT 'student:update' UNION ALL - SELECT 'teacher:create' UNION ALL - SELECT 'teacher:delete' UNION ALL - SELECT 'teacher:update' UNION ALL SELECT 'tenant:create' UNION ALL SELECT 'tenant:delete' UNION ALL SELECT 'tenant:update' UNION ALL diff --git a/java-backend/src/main/java/com/lesingle/creation/common/enums/HomeworkStatusEnum.java b/java-backend/src/main/java/com/lesingle/creation/common/enums/HomeworkStatusEnum.java deleted file mode 100644 index be18282..0000000 --- a/java-backend/src/main/java/com/lesingle/creation/common/enums/HomeworkStatusEnum.java +++ /dev/null @@ -1,30 +0,0 @@ -package com.lesingle.creation.common.enums; - -import lombok.AllArgsConstructor; -import lombok.Getter; - -/** - * 作业状态枚举 - */ -@Getter -@AllArgsConstructor -public enum HomeworkStatusEnum { - - UNPUBLISHED("unpublished", "未发布"), - PUBLISHED("published", "已发布"); - - private final String code; - private final String desc; - - public static HomeworkStatusEnum getByCode(String code) { - if (code == null) { - return UNPUBLISHED; - } - for (HomeworkStatusEnum status : values()) { - if (status.getCode().equals(code)) { - return status; - } - } - return UNPUBLISHED; - } -} diff --git a/java-backend/src/main/java/com/lesingle/creation/common/enums/HomeworkSubmissionStatusEnum.java b/java-backend/src/main/java/com/lesingle/creation/common/enums/HomeworkSubmissionStatusEnum.java deleted file mode 100644 index 3bac975..0000000 --- a/java-backend/src/main/java/com/lesingle/creation/common/enums/HomeworkSubmissionStatusEnum.java +++ /dev/null @@ -1,31 +0,0 @@ -package com.lesingle.creation.common.enums; - -import lombok.AllArgsConstructor; -import lombok.Getter; - -/** - * 作业提交状态枚举 - */ -@Getter -@AllArgsConstructor -public enum HomeworkSubmissionStatusEnum { - - PENDING("pending", "待评审"), - REVIEWED("reviewed", "已评审"), - REJECTED("rejected", "已拒绝"); - - private final String code; - private final String desc; - - public static HomeworkSubmissionStatusEnum getByCode(String code) { - if (code == null) { - return PENDING; - } - for (HomeworkSubmissionStatusEnum status : values()) { - if (status.getCode().equals(code)) { - return status; - } - } - return PENDING; - } -} diff --git a/java-backend/src/main/java/com/lesingle/creation/controller/ContestRegistrationController.java b/java-backend/src/main/java/com/lesingle/creation/controller/ContestRegistrationController.java index e55a9d0..f57c7cf 100644 --- a/java-backend/src/main/java/com/lesingle/creation/controller/ContestRegistrationController.java +++ b/java-backend/src/main/java/com/lesingle/creation/controller/ContestRegistrationController.java @@ -5,8 +5,10 @@ import com.lesingle.creation.common.core.Result; import com.lesingle.creation.common.security.UserPrincipal; import com.lesingle.creation.dto.registration.*; import com.lesingle.creation.service.ContestRegistrationService; +import com.lesingle.creation.service.UserService; import com.lesingle.creation.vo.registration.RegistrationStatsVO; import com.lesingle.creation.vo.registration.RegistrationVO; +import com.lesingle.creation.vo.user.UserListVO; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.tags.Tag; import lombok.RequiredArgsConstructor; @@ -25,6 +27,7 @@ import org.springframework.web.bind.annotation.*; public class ContestRegistrationController { private final ContestRegistrationService registrationService; + private final UserService userService; @PostMapping @Operation(summary = "创建报名") @@ -57,6 +60,21 @@ public class ContestRegistrationController { return Result.success(result); } + @GetMapping("/candidate-users") + @Operation(summary = "报名场景:按角色分页查询可选用户(teacher/student)") + @PreAuthorize("hasAnyAuthority('contest:read','contest:register','contest:update','registration:read','user:read')") + public Result> pageCandidateUsers( + @AuthenticationPrincipal UserPrincipal userPrincipal, + @RequestParam String roleCode, + @RequestParam(required = false) String keyword, + @RequestParam(defaultValue = "1") int page, + @RequestParam(defaultValue = "10") int pageSize) { + Long tenantId = userPrincipal.getTenantId(); + Page result = + userService.pageCandidateUsersByRoleCode(tenantId, roleCode, keyword, page, pageSize); + return Result.success(result); + } + @GetMapping("/my/{contestId}") @Operation(summary = "获取用户在某活动中的报名记录") @PreAuthorize("hasAuthority('contest:read')") diff --git a/java-backend/src/main/java/com/lesingle/creation/controller/DepartmentController.java b/java-backend/src/main/java/com/lesingle/creation/controller/DepartmentController.java deleted file mode 100644 index 1541320..0000000 --- a/java-backend/src/main/java/com/lesingle/creation/controller/DepartmentController.java +++ /dev/null @@ -1,97 +0,0 @@ -package com.lesingle.creation.controller; - -import com.lesingle.creation.common.core.Result; -import com.lesingle.creation.common.security.UserPrincipal; -import com.lesingle.creation.dto.department.CreateDepartmentDTO; -import com.lesingle.creation.dto.department.UpdateDepartmentDTO; -import com.lesingle.creation.service.DepartmentService; -import com.lesingle.creation.vo.department.DepartmentVO; -import io.swagger.v3.oas.annotations.Operation; -import io.swagger.v3.oas.annotations.tags.Tag; -import jakarta.validation.Valid; -import lombok.RequiredArgsConstructor; -import org.springframework.security.access.prepost.PreAuthorize; -import org.springframework.security.core.annotation.AuthenticationPrincipal; -import org.springframework.web.bind.annotation.*; - -import java.util.List; - -/** - * 部门管理控制器 - */ -@Tag(name = "部门管理", description = "部门 CRUD 和树形结构接口") -@RestController -@RequestMapping("/api/departments") -@RequiredArgsConstructor -public class DepartmentController { - - private final DepartmentService departmentService; - - @PostMapping - @Operation(summary = "创建部门") - @PreAuthorize("hasAuthority('department:create')") - public Result create( - @AuthenticationPrincipal UserPrincipal userPrincipal, - @RequestBody @Valid CreateDepartmentDTO dto) { - Long tenantId = userPrincipal.getTenantId(); - Long creatorId = userPrincipal.getUserId(); - DepartmentVO result = departmentService.create(dto, tenantId, creatorId); - return Result.success(result); - } - - @GetMapping - @Operation(summary = "查询部门列表") - @PreAuthorize("hasAuthority('department:read')") - public Result> list( - @AuthenticationPrincipal UserPrincipal userPrincipal, - @RequestParam(required = false) Long parentId) { - Long tenantId = userPrincipal.getTenantId(); - List result = departmentService.list(tenantId, parentId); - return Result.success(result); - } - - @GetMapping("/tree") - @Operation(summary = "查询部门树形结构") - @PreAuthorize("hasAuthority('department:read')") - public Result> tree( - @AuthenticationPrincipal UserPrincipal userPrincipal) { - Long tenantId = userPrincipal.getTenantId(); - List result = departmentService.tree(tenantId); - return Result.success(result); - } - - @GetMapping("/{id}") - @Operation(summary = "获取部门详情") - @PreAuthorize("hasAuthority('department:read')") - public Result getDetail( - @AuthenticationPrincipal UserPrincipal userPrincipal, - @PathVariable Long id) { - Long tenantId = userPrincipal.getTenantId(); - DepartmentVO result = departmentService.getDetail(id, tenantId); - return Result.success(result); - } - - @PutMapping("/{id}") - @Operation(summary = "更新部门") - @PreAuthorize("hasAuthority('department:update')") - public Result update( - @AuthenticationPrincipal UserPrincipal userPrincipal, - @PathVariable Long id, - @RequestBody @Valid UpdateDepartmentDTO dto) { - Long tenantId = userPrincipal.getTenantId(); - Long modifierId = userPrincipal.getUserId(); - DepartmentVO result = departmentService.update(id, dto, tenantId, modifierId); - return Result.success(result); - } - - @DeleteMapping("/{id}") - @Operation(summary = "删除部门") - @PreAuthorize("hasAuthority('department:delete')") - public Result delete( - @AuthenticationPrincipal UserPrincipal userPrincipal, - @PathVariable Long id) { - Long tenantId = userPrincipal.getTenantId(); - departmentService.delete(id, tenantId); - return Result.success(null); - } -} diff --git a/java-backend/src/main/java/com/lesingle/creation/controller/GradeController.java b/java-backend/src/main/java/com/lesingle/creation/controller/GradeController.java deleted file mode 100644 index 6bdacac..0000000 --- a/java-backend/src/main/java/com/lesingle/creation/controller/GradeController.java +++ /dev/null @@ -1,87 +0,0 @@ -package com.lesingle.creation.controller; - -import com.baomidou.mybatisplus.extension.plugins.pagination.Page; -import com.lesingle.creation.common.core.Result; -import com.lesingle.creation.common.security.UserPrincipal; -import com.lesingle.creation.dto.grade.CreateGradeDTO; -import com.lesingle.creation.dto.grade.UpdateGradeDTO; -import com.lesingle.creation.service.GradeService; -import com.lesingle.creation.vo.grade.GradeVO; -import io.swagger.v3.oas.annotations.Operation; -import io.swagger.v3.oas.annotations.tags.Tag; -import jakarta.validation.Valid; -import lombok.RequiredArgsConstructor; -import org.springframework.security.access.prepost.PreAuthorize; -import org.springframework.security.core.annotation.AuthenticationPrincipal; -import org.springframework.web.bind.annotation.*; - -/** - * 年级管理控制器 - */ -@Tag(name = "年级管理", description = "年级 CRUD 接口") -@RestController -@RequestMapping("/api/grades") -@RequiredArgsConstructor -public class GradeController { - - private final GradeService gradeService; - - @PostMapping - @Operation(summary = "创建年级") - @PreAuthorize("hasAuthority('grade:create')") - public Result create( - @AuthenticationPrincipal UserPrincipal userPrincipal, - @RequestBody @Valid CreateGradeDTO dto) { - Long tenantId = userPrincipal.getTenantId(); - Long creatorId = userPrincipal.getUserId(); - GradeVO result = gradeService.create(dto, tenantId, creatorId); - return Result.success(result); - } - - @GetMapping - @Operation(summary = "分页查询年级列表") - @PreAuthorize("hasAuthority('grade:read')") - public Result> pageQuery( - @AuthenticationPrincipal UserPrincipal userPrincipal, - @RequestParam(required = false, defaultValue = "1") Integer pageNum, - @RequestParam(required = false, defaultValue = "10") Integer pageSize) { - Long tenantId = userPrincipal.getTenantId(); - Page result = gradeService.pageQuery(pageNum, pageSize, tenantId); - return Result.success(result); - } - - @GetMapping("/{id}") - @Operation(summary = "获取年级详情") - @PreAuthorize("hasAuthority('grade:read')") - public Result getDetail( - @AuthenticationPrincipal UserPrincipal userPrincipal, - @PathVariable Long id) { - Long tenantId = userPrincipal.getTenantId(); - GradeVO result = gradeService.getDetail(id, tenantId); - return Result.success(result); - } - - @PutMapping("/{id}") - @Operation(summary = "更新年级") - @PreAuthorize("hasAuthority('grade:update')") - public Result update( - @AuthenticationPrincipal UserPrincipal userPrincipal, - @PathVariable Long id, - @RequestBody @Valid UpdateGradeDTO dto) { - Long tenantId = userPrincipal.getTenantId(); - Long modifierId = userPrincipal.getUserId(); - GradeVO result = gradeService.update(id, dto, tenantId, modifierId); - return Result.success(result); - } - - @DeleteMapping("/{id}") - @Operation(summary = "删除年级") - @PreAuthorize("hasAuthority('grade:delete')") - public Result delete( - @AuthenticationPrincipal UserPrincipal userPrincipal, - @PathVariable Long id) { - Long tenantId = userPrincipal.getTenantId(); - gradeService.delete(id, tenantId); - return Result.success(null); - } -} diff --git a/java-backend/src/main/java/com/lesingle/creation/controller/HomeworkController.java b/java-backend/src/main/java/com/lesingle/creation/controller/HomeworkController.java deleted file mode 100644 index 8a94d3b..0000000 --- a/java-backend/src/main/java/com/lesingle/creation/controller/HomeworkController.java +++ /dev/null @@ -1,292 +0,0 @@ -package com.lesingle.creation.controller; - -import com.baomidou.mybatisplus.extension.plugins.pagination.Page; -import com.lesingle.creation.common.core.Result; -import com.lesingle.creation.dto.homework.*; -import com.lesingle.creation.vo.school.ClassTreeNodeVO; -import com.lesingle.creation.service.HomeworkService; -import com.lesingle.creation.vo.homework.HomeworkDetailVO; -import com.lesingle.creation.vo.homework.HomeworkListVO; -import com.lesingle.creation.vo.homework.ReviewRuleVO; -import com.lesingle.creation.vo.homework.SubmissionVO; -import io.swagger.v3.oas.annotations.Operation; -import io.swagger.v3.oas.annotations.Parameter; -import io.swagger.v3.oas.annotations.tags.Tag; -import lombok.RequiredArgsConstructor; -import com.lesingle.creation.common.security.UserPrincipal; -import org.springframework.security.access.prepost.PreAuthorize; -import org.springframework.security.core.annotation.AuthenticationPrincipal; -import org.springframework.validation.annotation.Validated; -import org.springframework.web.bind.annotation.*; - -import java.util.List; - -/** - * 作业管理控制器 - */ -@Tag(name = "作业管理") -@RestController -@RequestMapping("/api/homeworks") -@RequiredArgsConstructor -public class HomeworkController { - - private final HomeworkService homeworkService; - - @PostMapping - @Operation(summary = "创建作业") - @PreAuthorize("hasAuthority('homework:create')") - public Result create( - @AuthenticationPrincipal UserPrincipal userPrincipal, - @RequestBody @Validated CreateHomeworkDTO dto) { - Long tenantId = userPrincipal.getTenantId(); - Long creatorId = userPrincipal.getUserId(); - HomeworkDetailVO result = homeworkService.create(dto, tenantId, creatorId); - return Result.success(result); - } - - @PutMapping("/{id}") - @Operation(summary = "更新作业") - @PreAuthorize("hasAuthority('homework:update')") - public Result update( - @AuthenticationPrincipal UserPrincipal userPrincipal, - @PathVariable Long id, - @RequestBody @Validated UpdateHomeworkDTO dto) { - Long tenantId = userPrincipal.getTenantId(); - HomeworkDetailVO result = homeworkService.update(id, dto, tenantId); - return Result.success(result); - } - - @PostMapping("/{id}/publish") - @Operation(summary = "发布作业") - @PreAuthorize("hasAuthority('homework:publish')") - public Result publish( - @AuthenticationPrincipal UserPrincipal userPrincipal, - @PathVariable Long id) { - Long tenantId = userPrincipal.getTenantId(); - HomeworkDetailVO result = homeworkService.publish(id, tenantId); - return Result.success(result); - } - - @DeleteMapping("/{id}") - @Operation(summary = "删除作业") - @PreAuthorize("hasAuthority('homework:delete')") - public Result delete( - @AuthenticationPrincipal UserPrincipal userPrincipal, - @PathVariable Long id) { - Long tenantId = userPrincipal.getTenantId(); - homeworkService.delete(id, tenantId); - return Result.success(null); - } - - @GetMapping("/{id}") - @Operation(summary = "获取作业详情") - @PreAuthorize("hasAuthority('homework:read')") - public Result getDetail( - @AuthenticationPrincipal UserPrincipal userPrincipal, - @PathVariable Long id) { - Long tenantId = userPrincipal.getTenantId(); - HomeworkDetailVO result = homeworkService.getDetail(id, tenantId); - return Result.success(result); - } - - @GetMapping("/page") - @Operation(summary = "分页查询作业列表") - @PreAuthorize("hasAuthority('homework:read')") - public Result> pageQuery( - @AuthenticationPrincipal UserPrincipal userPrincipal, - @ModelAttribute HomeworkQueryDTO queryDTO) { - Long tenantId = userPrincipal.getTenantId(); - Page result = homeworkService.pageQuery(queryDTO, tenantId); - return Result.success(result); - } - - @PostMapping("/submit") - @Operation(summary = "提交作业") - public Result submit( - @AuthenticationPrincipal UserPrincipal userPrincipal, - @RequestBody @Validated SubmitHomeworkDTO dto) { - Long tenantId = userPrincipal.getTenantId(); - Long studentId = userPrincipal.getUserId(); - SubmissionVO result = homeworkService.submit(dto, tenantId, studentId); - return Result.success(result); - } - - @PostMapping("/review") - @Operation(summary = "批改作业") - @PreAuthorize("hasAuthority('homework:review')") - public Result review( - @AuthenticationPrincipal UserPrincipal userPrincipal, - @RequestBody @Validated ReviewHomeworkDTO dto) { - Long tenantId = userPrincipal.getTenantId(); - Long reviewerId = userPrincipal.getUserId(); - SubmissionVO result = homeworkService.review(dto, tenantId, reviewerId); - return Result.success(result); - } - - @GetMapping("/{homeworkId}/submissions") - @Operation(summary = "获取作业提交列表") - @PreAuthorize("hasAuthority('homework:review')") - public Result> getSubmissions( - @AuthenticationPrincipal UserPrincipal userPrincipal, - @PathVariable Long homeworkId) { - Long tenantId = userPrincipal.getTenantId(); - List result = homeworkService.getSubmissions(homeworkId, tenantId); - return Result.success(result); - } - - @PostMapping("/review-rules") - @Operation(summary = "创建评审规则") - @PreAuthorize("hasAuthority('homework:review-rule:create')") - public Result createReviewRule( - @AuthenticationPrincipal UserPrincipal userPrincipal, - @RequestParam String ruleName, - @RequestParam(required = false, defaultValue = "custom") String ruleType, - @RequestParam(required = false) java.math.BigDecimal totalScore, - @RequestParam(required = false) String description) { - Long tenantId = userPrincipal.getTenantId(); - ReviewRuleVO result = homeworkService.createReviewRule( - ruleName, ruleType, totalScore, description, tenantId); - return Result.success(result); - } - - @GetMapping("/review-rules") - @Operation(summary = "获取评审规则列表") - public Result> getReviewRules( - @AuthenticationPrincipal UserPrincipal userPrincipal) { - Long tenantId = userPrincipal.getTenantId(); - List result = homeworkService.getReviewRules(tenantId); - return Result.success(result); - } - - @GetMapping("/review-rules/select") - @Operation(summary = "获取可选的评审规则") - public Result> getReviewRulesForSelect( - @AuthenticationPrincipal UserPrincipal userPrincipal) { - Long tenantId = userPrincipal.getTenantId(); - List result = homeworkService.getReviewRulesForSelect(tenantId); - return Result.success(result); - } - - @PutMapping("/review-rules/{id}") - @Operation(summary = "更新评审规则") - @PreAuthorize("hasAuthority('homework:review-rule:update')") - public Result updateReviewRule( - @AuthenticationPrincipal UserPrincipal userPrincipal, - @PathVariable Long id, - @RequestBody @Validated UpdateReviewRuleDTO dto) { - Long tenantId = userPrincipal.getTenantId(); - ReviewRuleVO result = homeworkService.updateReviewRule(id, dto, tenantId); - return Result.success(result); - } - - @DeleteMapping("/review-rules/{id}") - @Operation(summary = "删除评审规则") - @PreAuthorize("hasAuthority('homework:review-rule:delete')") - public Result deleteReviewRule( - @AuthenticationPrincipal UserPrincipal userPrincipal, - @PathVariable Long id) { - Long tenantId = userPrincipal.getTenantId(); - homeworkService.deleteReviewRule(id, tenantId); - return Result.success(null); - } - - @GetMapping("/my") - @Operation(summary = "我的作业列表(学生端)") - public Result> getMyHomeworks( - @AuthenticationPrincipal UserPrincipal userPrincipal, - @ModelAttribute HomeworkQueryDTO queryDTO) { - Long userId = userPrincipal.getUserId(); - Long tenantId = userPrincipal.getTenantId(); - Page result = homeworkService.getMyHomeworks(queryDTO, userId, tenantId); - return Result.success(result); - } - - @PostMapping("/{id}/unpublish") - @Operation(summary = "取消发布作业") - @PreAuthorize("hasAuthority('homework:publish')") - public Result unpublish( - @AuthenticationPrincipal UserPrincipal userPrincipal, - @PathVariable Long id) { - Long tenantId = userPrincipal.getTenantId(); - HomeworkDetailVO result = homeworkService.unpublish(id, tenantId); - return Result.success(result); - } - - @GetMapping("/submissions") - @Operation(summary = "获取提交记录列表") - @PreAuthorize("hasAuthority('homework:review')") - public Result> getSubmissionsList( - @AuthenticationPrincipal UserPrincipal userPrincipal, - @ModelAttribute SubmissionQueryDTO queryDTO) { - Long tenantId = userPrincipal.getTenantId(); - Page result = homeworkService.getSubmissionsList(queryDTO, tenantId); - return Result.success(result); - } - - @GetMapping("/submissions/{id}") - @Operation(summary = "获取提交记录详情") - @PreAuthorize("hasAuthority('homework:review')") - public Result getSubmissionDetail( - @AuthenticationPrincipal UserPrincipal userPrincipal, - @PathVariable Long id) { - Long tenantId = userPrincipal.getTenantId(); - SubmissionVO result = homeworkService.getSubmissionDetail(id, tenantId); - return Result.success(result); - } - - @GetMapping("/submissions/class-tree") - @Operation(summary = "获取班级树结构") - @PreAuthorize("hasAuthority('homework:review')") - public Result> getClassTree( - @AuthenticationPrincipal UserPrincipal userPrincipal) { - Long tenantId = userPrincipal.getTenantId(); - List result = homeworkService.getClassTree(tenantId); - return Result.success(result); - } - - @GetMapping("/submissions/my/{homeworkId}") - @Operation(summary = "获取我的提交记录") - public Result getMySubmission( - @AuthenticationPrincipal UserPrincipal userPrincipal, - @PathVariable Long homeworkId) { - Long userId = userPrincipal.getUserId(); - Long tenantId = userPrincipal.getTenantId(); - SubmissionVO result = homeworkService.getMySubmission(homeworkId, userId, tenantId); - return result != null ? Result.success(result) : Result.success(null); - } - - @PostMapping("/scores") - @Operation(summary = "提交评分") - @PreAuthorize("hasAuthority('homework:review')") - public Result createScore( - @AuthenticationPrincipal UserPrincipal userPrincipal, - @RequestBody @Validated CreateScoreDTO dto) { - Long tenantId = userPrincipal.getTenantId(); - Long reviewerId = userPrincipal.getUserId(); - SubmissionVO result = homeworkService.createScore(dto, tenantId, reviewerId); - return Result.success(result); - } - - @PostMapping("/scores/{submissionId}/violation") - @Operation(summary = "标记作品违规") - @PreAuthorize("hasAuthority('homework:review')") - public Result markViolation( - @AuthenticationPrincipal UserPrincipal userPrincipal, - @PathVariable Long submissionId, - @RequestParam(required = false) String reason) { - Long tenantId = userPrincipal.getTenantId(); - homeworkService.markViolation(submissionId, reason, tenantId); - return Result.success(null); - } - - @PostMapping("/scores/{submissionId}/reset") - @Operation(summary = "重置评分") - @PreAuthorize("hasAuthority('homework:review')") - public Result resetScore( - @AuthenticationPrincipal UserPrincipal userPrincipal, - @PathVariable Long submissionId) { - Long tenantId = userPrincipal.getTenantId(); - homeworkService.resetScore(submissionId, tenantId); - return Result.success(null); - } -} diff --git a/java-backend/src/main/java/com/lesingle/creation/controller/SchoolClassController.java b/java-backend/src/main/java/com/lesingle/creation/controller/SchoolClassController.java deleted file mode 100644 index 28d4d13..0000000 --- a/java-backend/src/main/java/com/lesingle/creation/controller/SchoolClassController.java +++ /dev/null @@ -1,89 +0,0 @@ -package com.lesingle.creation.controller; - -import com.baomidou.mybatisplus.extension.plugins.pagination.Page; -import com.lesingle.creation.common.core.Result; -import com.lesingle.creation.common.security.UserPrincipal; -import com.lesingle.creation.dto.schoolclass.CreateClassDTO; -import com.lesingle.creation.dto.schoolclass.UpdateClassDTO; -import com.lesingle.creation.service.SchoolClassService; -import com.lesingle.creation.vo.schoolclass.ClassVO; -import io.swagger.v3.oas.annotations.Operation; -import io.swagger.v3.oas.annotations.tags.Tag; -import jakarta.validation.Valid; -import lombok.RequiredArgsConstructor; -import org.springframework.security.access.prepost.PreAuthorize; -import org.springframework.security.core.annotation.AuthenticationPrincipal; -import org.springframework.web.bind.annotation.*; - -/** - * 班级管理控制器 - */ -@Tag(name = "班级管理", description = "班级 CRUD 接口") -@RestController -@RequestMapping("/api/classes") -@RequiredArgsConstructor -public class SchoolClassController { - - private final SchoolClassService schoolClassService; - - @PostMapping - @Operation(summary = "创建班级") - @PreAuthorize("hasAuthority('class:create')") - public Result create( - @AuthenticationPrincipal UserPrincipal userPrincipal, - @RequestBody @Valid CreateClassDTO dto) { - Long tenantId = userPrincipal.getTenantId(); - Long creatorId = userPrincipal.getUserId(); - ClassVO result = schoolClassService.create(dto, tenantId, creatorId); - return Result.success(result); - } - - @GetMapping - @Operation(summary = "分页查询班级列表") - @PreAuthorize("hasAuthority('class:read')") - public Result> pageQuery( - @AuthenticationPrincipal UserPrincipal userPrincipal, - @RequestParam(required = false, defaultValue = "1") Integer pageNum, - @RequestParam(required = false, defaultValue = "10") Integer pageSize, - @RequestParam(required = false) Long gradeId, - @RequestParam(required = false) Integer type) { - Long tenantId = userPrincipal.getTenantId(); - Page result = schoolClassService.pageQuery(pageNum, pageSize, tenantId, gradeId, type); - return Result.success(result); - } - - @GetMapping("/{id}") - @Operation(summary = "获取班级详情") - @PreAuthorize("hasAuthority('class:read')") - public Result getDetail( - @AuthenticationPrincipal UserPrincipal userPrincipal, - @PathVariable Long id) { - Long tenantId = userPrincipal.getTenantId(); - ClassVO result = schoolClassService.getDetail(id, tenantId); - return Result.success(result); - } - - @PutMapping("/{id}") - @Operation(summary = "更新班级") - @PreAuthorize("hasAuthority('class:update')") - public Result update( - @AuthenticationPrincipal UserPrincipal userPrincipal, - @PathVariable Long id, - @RequestBody @Valid UpdateClassDTO dto) { - Long tenantId = userPrincipal.getTenantId(); - Long modifierId = userPrincipal.getUserId(); - ClassVO result = schoolClassService.update(id, dto, tenantId, modifierId); - return Result.success(result); - } - - @DeleteMapping("/{id}") - @Operation(summary = "删除班级") - @PreAuthorize("hasAuthority('class:delete')") - public Result delete( - @AuthenticationPrincipal UserPrincipal userPrincipal, - @PathVariable Long id) { - Long tenantId = userPrincipal.getTenantId(); - schoolClassService.delete(id, tenantId); - return Result.success(null); - } -} diff --git a/java-backend/src/main/java/com/lesingle/creation/controller/SchoolController.java b/java-backend/src/main/java/com/lesingle/creation/controller/SchoolController.java deleted file mode 100644 index 0b94d41..0000000 --- a/java-backend/src/main/java/com/lesingle/creation/controller/SchoolController.java +++ /dev/null @@ -1,71 +0,0 @@ -package com.lesingle.creation.controller; - -import com.lesingle.creation.common.core.Result; -import com.lesingle.creation.common.security.UserPrincipal; -import com.lesingle.creation.dto.school.CreateSchoolDTO; -import com.lesingle.creation.dto.school.UpdateSchoolDTO; -import com.lesingle.creation.service.SchoolService; -import com.lesingle.creation.vo.school.SchoolVO; -import io.swagger.v3.oas.annotations.Operation; -import io.swagger.v3.oas.annotations.tags.Tag; -import lombok.RequiredArgsConstructor; -import org.springframework.security.access.prepost.PreAuthorize; -import org.springframework.security.core.annotation.AuthenticationPrincipal; -import org.springframework.validation.annotation.Validated; -import org.springframework.web.bind.annotation.*; - -/** - * 学校管理控制器 - */ -@Tag(name = "学校管理") -@RestController -@RequestMapping("/api/schools") -@RequiredArgsConstructor -public class SchoolController { - - private final SchoolService schoolService; - - @PostMapping - @Operation(summary = "创建学校") - @PreAuthorize("hasAuthority('school:create')") - public Result create( - @AuthenticationPrincipal UserPrincipal userPrincipal, - @RequestBody @Validated CreateSchoolDTO dto) { - Long tenantId = userPrincipal.getTenantId(); - Long creatorId = userPrincipal.getUserId(); - SchoolVO result = schoolService.create(dto, tenantId, creatorId); - return Result.success(result); - } - - @GetMapping - @Operation(summary = "获取学校信息(未创建时 data 为 null)") - @PreAuthorize("hasAuthority('school:read')") - public Result get( - @AuthenticationPrincipal UserPrincipal userPrincipal) { - Long tenantId = userPrincipal.getTenantId(); - SchoolVO result = schoolService.getByTenantId(tenantId); - return Result.success(result); - } - - @PutMapping - @Operation(summary = "更新学校") - @PreAuthorize("hasAuthority('school:update')") - public Result update( - @AuthenticationPrincipal UserPrincipal userPrincipal, - @RequestBody @Validated UpdateSchoolDTO dto) { - Long tenantId = userPrincipal.getTenantId(); - Long modifierId = userPrincipal.getUserId(); - SchoolVO result = schoolService.update(dto, tenantId, modifierId); - return Result.success(result); - } - - @DeleteMapping - @Operation(summary = "删除学校") - @PreAuthorize("hasAuthority('school:delete')") - public Result delete( - @AuthenticationPrincipal UserPrincipal userPrincipal) { - Long tenantId = userPrincipal.getTenantId(); - schoolService.delete(tenantId); - return Result.success(); - } -} diff --git a/java-backend/src/main/java/com/lesingle/creation/controller/StudentController.java b/java-backend/src/main/java/com/lesingle/creation/controller/StudentController.java deleted file mode 100644 index 0c16edd..0000000 --- a/java-backend/src/main/java/com/lesingle/creation/controller/StudentController.java +++ /dev/null @@ -1,100 +0,0 @@ -package com.lesingle.creation.controller; - -import com.lesingle.creation.common.core.Result; -import com.lesingle.creation.common.security.UserPrincipal; -import com.lesingle.creation.dto.student.CreateStudentDTO; -import com.lesingle.creation.dto.student.UpdateStudentDTO; -import com.lesingle.creation.service.StudentService; -import com.lesingle.creation.vo.student.StudentVO; -import io.swagger.v3.oas.annotations.Operation; -import io.swagger.v3.oas.annotations.tags.Tag; -import jakarta.validation.Valid; -import lombok.RequiredArgsConstructor; -import org.springframework.security.access.prepost.PreAuthorize; -import org.springframework.security.core.annotation.AuthenticationPrincipal; -import org.springframework.web.bind.annotation.*; - -import java.util.List; - -/** - * 学生管理控制器 - */ -@Tag(name = "学生管理", description = "学生 CRUD 和查询接口") -@RestController -@RequestMapping("/api/students") -@RequiredArgsConstructor -public class StudentController { - - private final StudentService studentService; - - @PostMapping - @Operation(summary = "创建学生") - @PreAuthorize("hasAuthority('student:create')") - public Result create( - @AuthenticationPrincipal UserPrincipal userPrincipal, - @RequestBody @Valid CreateStudentDTO dto) { - Long tenantId = userPrincipal.getTenantId(); - Long creatorId = userPrincipal.getUserId(); - StudentVO result = studentService.create(dto, tenantId, creatorId); - return Result.success(result); - } - - @GetMapping - @Operation(summary = "查询学生列表") - @PreAuthorize("hasAuthority('student:read')") - public Result> list( - @AuthenticationPrincipal UserPrincipal userPrincipal, - @RequestParam(defaultValue = "1") Integer page, - @RequestParam(defaultValue = "10") Integer pageSize, - @RequestParam(required = false) Long classId) { - Long tenantId = userPrincipal.getTenantId(); - List result = studentService.list(tenantId, page, pageSize, classId); - return Result.success(result); - } - - @GetMapping("/{id}") - @Operation(summary = "获取学生详情") - @PreAuthorize("hasAuthority('student:read')") - public Result getDetail( - @AuthenticationPrincipal UserPrincipal userPrincipal, - @PathVariable Long id) { - Long tenantId = userPrincipal.getTenantId(); - StudentVO result = studentService.getDetail(id, tenantId); - return Result.success(result); - } - - @GetMapping("/user/{userId}") - @Operation(summary = "根据用户 ID 获取学生信息") - @PreAuthorize("hasAuthority('student:read')") - public Result getByUserId( - @AuthenticationPrincipal UserPrincipal userPrincipal, - @PathVariable Long userId) { - Long tenantId = userPrincipal.getTenantId(); - StudentVO result = studentService.getByUserId(userId, tenantId); - return Result.success(result); - } - - @PutMapping("/{id}") - @Operation(summary = "更新学生") - @PreAuthorize("hasAuthority('student:update')") - public Result update( - @AuthenticationPrincipal UserPrincipal userPrincipal, - @PathVariable Long id, - @RequestBody @Valid UpdateStudentDTO dto) { - Long tenantId = userPrincipal.getTenantId(); - Long modifierId = userPrincipal.getUserId(); - StudentVO result = studentService.update(id, dto, tenantId, modifierId); - return Result.success(result); - } - - @DeleteMapping("/{id}") - @Operation(summary = "删除学生") - @PreAuthorize("hasAuthority('student:delete')") - public Result delete( - @AuthenticationPrincipal UserPrincipal userPrincipal, - @PathVariable Long id) { - Long tenantId = userPrincipal.getTenantId(); - studentService.delete(id, tenantId); - return Result.success(null); - } -} diff --git a/java-backend/src/main/java/com/lesingle/creation/controller/TeacherController.java b/java-backend/src/main/java/com/lesingle/creation/controller/TeacherController.java deleted file mode 100644 index c83238d..0000000 --- a/java-backend/src/main/java/com/lesingle/creation/controller/TeacherController.java +++ /dev/null @@ -1,100 +0,0 @@ -package com.lesingle.creation.controller; - -import com.lesingle.creation.common.core.Result; -import com.lesingle.creation.common.security.UserPrincipal; -import com.lesingle.creation.dto.teacher.CreateTeacherDTO; -import com.lesingle.creation.dto.teacher.UpdateTeacherDTO; -import com.lesingle.creation.service.TeacherService; -import com.lesingle.creation.vo.teacher.TeacherVO; -import io.swagger.v3.oas.annotations.Operation; -import io.swagger.v3.oas.annotations.tags.Tag; -import jakarta.validation.Valid; -import lombok.RequiredArgsConstructor; -import org.springframework.security.access.prepost.PreAuthorize; -import org.springframework.security.core.annotation.AuthenticationPrincipal; -import org.springframework.web.bind.annotation.*; - -import java.util.List; - -/** - * 教师管理控制器 - */ -@Tag(name = "教师管理", description = "教师 CRUD 和查询接口") -@RestController -@RequestMapping("/api/teachers") -@RequiredArgsConstructor -public class TeacherController { - - private final TeacherService teacherService; - - @PostMapping - @Operation(summary = "创建教师") - @PreAuthorize("hasAuthority('teacher:create')") - public Result create( - @AuthenticationPrincipal UserPrincipal userPrincipal, - @RequestBody @Valid CreateTeacherDTO dto) { - Long tenantId = userPrincipal.getTenantId(); - Long creatorId = userPrincipal.getUserId(); - TeacherVO result = teacherService.create(dto, tenantId, creatorId); - return Result.success(result); - } - - @GetMapping - @Operation(summary = "查询教师列表") - @PreAuthorize("hasAuthority('teacher:read')") - public Result> list( - @AuthenticationPrincipal UserPrincipal userPrincipal, - @RequestParam(required = false) Long departmentId, - @RequestParam(required = false) String nickname, - @RequestParam(required = false) String username) { - Long tenantId = userPrincipal.getTenantId(); - List result = teacherService.list(tenantId, departmentId, nickname, username); - return Result.success(result); - } - - @GetMapping("/{id}") - @Operation(summary = "获取教师详情") - @PreAuthorize("hasAuthority('teacher:read')") - public Result getDetail( - @AuthenticationPrincipal UserPrincipal userPrincipal, - @PathVariable Long id) { - Long tenantId = userPrincipal.getTenantId(); - TeacherVO result = teacherService.getDetail(id, tenantId); - return Result.success(result); - } - - @GetMapping("/user/{userId}") - @Operation(summary = "根据用户 ID 获取教师信息") - @PreAuthorize("hasAuthority('teacher:read')") - public Result getByUserId( - @AuthenticationPrincipal UserPrincipal userPrincipal, - @PathVariable Long userId) { - Long tenantId = userPrincipal.getTenantId(); - TeacherVO result = teacherService.getByUserId(userId, tenantId); - return Result.success(result); - } - - @PutMapping("/{id}") - @Operation(summary = "更新教师") - @PreAuthorize("hasAuthority('teacher:update')") - public Result update( - @AuthenticationPrincipal UserPrincipal userPrincipal, - @PathVariable Long id, - @RequestBody @Valid UpdateTeacherDTO dto) { - Long tenantId = userPrincipal.getTenantId(); - Long modifierId = userPrincipal.getUserId(); - TeacherVO result = teacherService.update(id, dto, tenantId, modifierId); - return Result.success(result); - } - - @DeleteMapping("/{id}") - @Operation(summary = "删除教师") - @PreAuthorize("hasAuthority('teacher:delete')") - public Result delete( - @AuthenticationPrincipal UserPrincipal userPrincipal, - @PathVariable Long id) { - Long tenantId = userPrincipal.getTenantId(); - teacherService.delete(id, tenantId); - return Result.success(null); - } -} diff --git a/java-backend/src/main/java/com/lesingle/creation/dto/department/CreateDepartmentDTO.java b/java-backend/src/main/java/com/lesingle/creation/dto/department/CreateDepartmentDTO.java deleted file mode 100644 index 4d5b6e9..0000000 --- a/java-backend/src/main/java/com/lesingle/creation/dto/department/CreateDepartmentDTO.java +++ /dev/null @@ -1,30 +0,0 @@ -package com.lesingle.creation.dto.department; - -import io.swagger.v3.oas.annotations.media.Schema; -import jakarta.validation.constraints.NotBlank; -import lombok.Data; - -/** - * 创建部门 DTO - */ -@Data -@Schema(description = "创建部门请求") -public class CreateDepartmentDTO { - - @NotBlank(message = "部门名称不能为空") - @Schema(description = "部门名称") - private String name; - - @NotBlank(message = "部门编码不能为空") - @Schema(description = "部门编码") - private String code; - - @Schema(description = "父部门 ID") - private Long parentId; - - @Schema(description = "部门描述") - private String description; - - @Schema(description = "排序") - private Integer sort = 0; -} diff --git a/java-backend/src/main/java/com/lesingle/creation/dto/department/UpdateDepartmentDTO.java b/java-backend/src/main/java/com/lesingle/creation/dto/department/UpdateDepartmentDTO.java deleted file mode 100644 index 1cad0cf..0000000 --- a/java-backend/src/main/java/com/lesingle/creation/dto/department/UpdateDepartmentDTO.java +++ /dev/null @@ -1,30 +0,0 @@ -package com.lesingle.creation.dto.department; - -import io.swagger.v3.oas.annotations.media.Schema; -import lombok.Data; - -/** - * 更新部门 DTO - */ -@Data -@Schema(description = "更新部门请求") -public class UpdateDepartmentDTO { - - @Schema(description = "部门名称") - private String name; - - @Schema(description = "部门编码") - private String code; - - @Schema(description = "父部门 ID") - private Long parentId; - - @Schema(description = "部门描述") - private String description; - - @Schema(description = "排序") - private Integer sort; - - @Schema(description = "有效状态:1-有效,2-失效") - private Integer validState; -} diff --git a/java-backend/src/main/java/com/lesingle/creation/dto/grade/CreateGradeDTO.java b/java-backend/src/main/java/com/lesingle/creation/dto/grade/CreateGradeDTO.java deleted file mode 100644 index 79948b7..0000000 --- a/java-backend/src/main/java/com/lesingle/creation/dto/grade/CreateGradeDTO.java +++ /dev/null @@ -1,29 +0,0 @@ -package com.lesingle.creation.dto.grade; - -import io.swagger.v3.oas.annotations.media.Schema; -import jakarta.validation.constraints.NotBlank; -import jakarta.validation.constraints.NotNull; -import lombok.Data; - -/** - * 创建年级 DTO - */ -@Data -@Schema(description = "创建年级请求") -public class CreateGradeDTO { - - @NotBlank(message = "年级名称不能为空") - @Schema(description = "年级名称") - private String name; - - @NotBlank(message = "年级编码不能为空") - @Schema(description = "年级编码") - private String code; - - @NotNull(message = "年级级别不能为空") - @Schema(description = "年级级别") - private Integer level; - - @Schema(description = "年级描述") - private String description; -} diff --git a/java-backend/src/main/java/com/lesingle/creation/dto/grade/UpdateGradeDTO.java b/java-backend/src/main/java/com/lesingle/creation/dto/grade/UpdateGradeDTO.java deleted file mode 100644 index 15f9350..0000000 --- a/java-backend/src/main/java/com/lesingle/creation/dto/grade/UpdateGradeDTO.java +++ /dev/null @@ -1,24 +0,0 @@ -package com.lesingle.creation.dto.grade; - -import io.swagger.v3.oas.annotations.media.Schema; -import lombok.Data; - -/** - * 更新年级 DTO - */ -@Data -@Schema(description = "更新年级请求") -public class UpdateGradeDTO { - - @Schema(description = "年级名称") - private String name; - - @Schema(description = "年级编码") - private String code; - - @Schema(description = "年级级别") - private Integer level; - - @Schema(description = "年级描述") - private String description; -} diff --git a/java-backend/src/main/java/com/lesingle/creation/dto/homework/CreateHomeworkDTO.java b/java-backend/src/main/java/com/lesingle/creation/dto/homework/CreateHomeworkDTO.java deleted file mode 100644 index 6730ed3..0000000 --- a/java-backend/src/main/java/com/lesingle/creation/dto/homework/CreateHomeworkDTO.java +++ /dev/null @@ -1,40 +0,0 @@ -package com.lesingle.creation.dto.homework; - -import io.swagger.v3.oas.annotations.media.Schema; -import lombok.Data; - -import jakarta.validation.constraints.NotBlank; -import jakarta.validation.constraints.NotNull; -import java.time.LocalDateTime; - -/** - * 创建作业请求 DTO - */ -@Data -@Schema(description = "创建作业请求") -public class CreateHomeworkDTO { - - @NotBlank(message = "作业名称不能为空") - @Schema(description = "作业名称", example = "创意绘画练习") - private String name; - - @Schema(description = "作业内容(富文本)") - private String content; - - @NotNull(message = "提交开始时间不能为空") - @Schema(description = "提交开始时间") - private LocalDateTime submitStartTime; - - @NotNull(message = "提交结束时间不能为空") - @Schema(description = "提交结束时间") - private LocalDateTime submitEndTime; - - @Schema(description = "附件列表(JSON 数组)") - private String attachments; - - @Schema(description = "公开范围(班级 ID 数组 JSON)") - private String publishScope; - - @Schema(description = "评审规则 ID") - private Long reviewRuleId; -} diff --git a/java-backend/src/main/java/com/lesingle/creation/dto/homework/CreateScoreDTO.java b/java-backend/src/main/java/com/lesingle/creation/dto/homework/CreateScoreDTO.java deleted file mode 100644 index 5ac2cd4..0000000 --- a/java-backend/src/main/java/com/lesingle/creation/dto/homework/CreateScoreDTO.java +++ /dev/null @@ -1,27 +0,0 @@ -package com.lesingle.creation.dto.homework; - -import io.swagger.v3.oas.annotations.media.Schema; -import lombok.Data; - -import jakarta.validation.constraints.NotBlank; -import jakarta.validation.constraints.NotNull; -import java.math.BigDecimal; -import java.util.List; - -/** - * 创建评分请求 DTO - */ -@Data -@Schema(description = "创建评分请求") -public class CreateScoreDTO { - - @NotNull(message = "提交 ID 不能为空") - @Schema(description = "提交 ID") - private Long submissionId; - - @Schema(description = "维度评分列表") - private List dimensionScores; - - @Schema(description = "评语") - private String comments; -} diff --git a/java-backend/src/main/java/com/lesingle/creation/dto/homework/DimensionScoreDTO.java b/java-backend/src/main/java/com/lesingle/creation/dto/homework/DimensionScoreDTO.java deleted file mode 100644 index 867302f..0000000 --- a/java-backend/src/main/java/com/lesingle/creation/dto/homework/DimensionScoreDTO.java +++ /dev/null @@ -1,27 +0,0 @@ -package com.lesingle.creation.dto.homework; - -import io.swagger.v3.oas.annotations.media.Schema; -import lombok.Data; - -import jakarta.validation.constraints.NotBlank; -import jakarta.validation.constraints.NotNull; -import java.math.BigDecimal; - -/** - * 维度评分 DTO - */ -@Data -@Schema(description = "维度评分") -public class DimensionScoreDTO { - - @NotBlank(message = "维度名称不能为空") - @Schema(description = "维度名称") - private String name; - - @NotNull(message = "得分不能为空") - @Schema(description = "得分") - private BigDecimal score; - - @Schema(description = "满分") - private BigDecimal maxScore; -} diff --git a/java-backend/src/main/java/com/lesingle/creation/dto/homework/HomeworkQueryDTO.java b/java-backend/src/main/java/com/lesingle/creation/dto/homework/HomeworkQueryDTO.java deleted file mode 100644 index c803880..0000000 --- a/java-backend/src/main/java/com/lesingle/creation/dto/homework/HomeworkQueryDTO.java +++ /dev/null @@ -1,27 +0,0 @@ -package com.lesingle.creation.dto.homework; - -import io.swagger.v3.oas.annotations.media.Schema; -import lombok.Data; - -/** - * 作业查询 DTO - */ -@Data -@Schema(description = "作业查询参数") -public class HomeworkQueryDTO { - - @Schema(description = "页码", example = "1") - private Integer pageNum = 1; - - @Schema(description = "每页数量", example = "10") - private Integer pageSize = 10; - - @Schema(description = "作业名称关键字") - private String nameKeyword; - - @Schema(description = "作业状态:unpublished/published") - private String status; - - @Schema(description = "有效状态:1-有效,2-失效") - private Integer validState; -} diff --git a/java-backend/src/main/java/com/lesingle/creation/dto/homework/ReviewDimensionDTO.java b/java-backend/src/main/java/com/lesingle/creation/dto/homework/ReviewDimensionDTO.java deleted file mode 100644 index 16c42de..0000000 --- a/java-backend/src/main/java/com/lesingle/creation/dto/homework/ReviewDimensionDTO.java +++ /dev/null @@ -1,27 +0,0 @@ -package com.lesingle.creation.dto.homework; - -import io.swagger.v3.oas.annotations.media.Schema; -import lombok.Data; - -import jakarta.validation.constraints.NotBlank; -import jakarta.validation.constraints.NotNull; -import java.math.BigDecimal; - -/** - * 评审维度 DTO - */ -@Data -@Schema(description = "评审维度") -public class ReviewDimensionDTO { - - @Schema(description = "维度名称") - @NotBlank(message = "维度名称不能为空") - private String name; - - @Schema(description = "满分") - @NotNull(message = "满分不能为空") - private BigDecimal maxScore; - - @Schema(description = "维度描述") - private String description; -} diff --git a/java-backend/src/main/java/com/lesingle/creation/dto/homework/ReviewHomeworkDTO.java b/java-backend/src/main/java/com/lesingle/creation/dto/homework/ReviewHomeworkDTO.java deleted file mode 100644 index bc25155..0000000 --- a/java-backend/src/main/java/com/lesingle/creation/dto/homework/ReviewHomeworkDTO.java +++ /dev/null @@ -1,26 +0,0 @@ -package com.lesingle.creation.dto.homework; - -import io.swagger.v3.oas.annotations.media.Schema; -import lombok.Data; - -import jakarta.validation.constraints.NotBlank; -import jakarta.validation.constraints.NotNull; -import java.math.BigDecimal; - -/** - * 批改作业请求 DTO - */ -@Data -@Schema(description = "批改作业请求") -public class ReviewHomeworkDTO { - - @NotNull(message = "提交 ID 不能为空") - @Schema(description = "提交 ID") - private Long submissionId; - - @Schema(description = "批改分数") - private BigDecimal score; - - @Schema(description = "批改评语") - private String comment; -} diff --git a/java-backend/src/main/java/com/lesingle/creation/dto/homework/SubmissionQueryDTO.java b/java-backend/src/main/java/com/lesingle/creation/dto/homework/SubmissionQueryDTO.java deleted file mode 100644 index 3cf00b0..0000000 --- a/java-backend/src/main/java/com/lesingle/creation/dto/homework/SubmissionQueryDTO.java +++ /dev/null @@ -1,42 +0,0 @@ -package com.lesingle.creation.dto.homework; - -import io.swagger.v3.oas.annotations.media.Schema; -import lombok.Data; - -/** - * 提交记录查询 DTO - */ -@Data -@Schema(description = "提交记录查询参数") -public class SubmissionQueryDTO { - - @Schema(description = "页码", example = "1") - private Integer pageNum = 1; - - @Schema(description = "每页大小", example = "10") - private Integer pageSize = 10; - - @Schema(description = "作业 ID") - private Long homeworkId; - - @Schema(description = "作品编号") - private String workNo; - - @Schema(description = "作品名称") - private String workName; - - @Schema(description = "学生账号") - private String studentAccount; - - @Schema(description = "学生姓名") - private String studentName; - - @Schema(description = "提交状态") - private String status; - - @Schema(description = "班级 ID 列表") - private java.util.List classIds; - - @Schema(description = "年级 ID") - private Long gradeId; -} diff --git a/java-backend/src/main/java/com/lesingle/creation/dto/homework/SubmitHomeworkDTO.java b/java-backend/src/main/java/com/lesingle/creation/dto/homework/SubmitHomeworkDTO.java deleted file mode 100644 index a747361..0000000 --- a/java-backend/src/main/java/com/lesingle/creation/dto/homework/SubmitHomeworkDTO.java +++ /dev/null @@ -1,26 +0,0 @@ -package com.lesingle.creation.dto.homework; - -import io.swagger.v3.oas.annotations.media.Schema; -import lombok.Data; - -import jakarta.validation.constraints.NotBlank; -import jakarta.validation.constraints.NotNull; -import java.math.BigDecimal; - -/** - * 提交作业请求 DTO - */ -@Data -@Schema(description = "提交作业请求") -public class SubmitHomeworkDTO { - - @NotNull(message = "作业 ID 不能为空") - @Schema(description = "作业 ID") - private Long homeworkId; - - @Schema(description = "提交内容") - private String content; - - @Schema(description = "提交附件列表(JSON 数组)") - private String attachments; -} diff --git a/java-backend/src/main/java/com/lesingle/creation/dto/homework/UpdateHomeworkDTO.java b/java-backend/src/main/java/com/lesingle/creation/dto/homework/UpdateHomeworkDTO.java deleted file mode 100644 index 98f6b58..0000000 --- a/java-backend/src/main/java/com/lesingle/creation/dto/homework/UpdateHomeworkDTO.java +++ /dev/null @@ -1,37 +0,0 @@ -package com.lesingle.creation.dto.homework; - -import io.swagger.v3.oas.annotations.media.Schema; -import lombok.Data; - -import jakarta.validation.constraints.NotBlank; -import java.time.LocalDateTime; - -/** - * 更新作业请求 DTO - */ -@Data -@Schema(description = "更新作业请求") -public class UpdateHomeworkDTO { - - @NotBlank(message = "作业名称不能为空") - @Schema(description = "作业名称", example = "创意绘画练习") - private String name; - - @Schema(description = "作业内容(富文本)") - private String content; - - @Schema(description = "提交开始时间") - private LocalDateTime submitStartTime; - - @Schema(description = "提交结束时间") - private LocalDateTime submitEndTime; - - @Schema(description = "附件列表(JSON 数组)") - private String attachments; - - @Schema(description = "公开范围(班级 ID 数组 JSON)") - private String publishScope; - - @Schema(description = "评审规则 ID") - private Long reviewRuleId; -} diff --git a/java-backend/src/main/java/com/lesingle/creation/dto/homework/UpdateReviewRuleDTO.java b/java-backend/src/main/java/com/lesingle/creation/dto/homework/UpdateReviewRuleDTO.java deleted file mode 100644 index b7fad0a..0000000 --- a/java-backend/src/main/java/com/lesingle/creation/dto/homework/UpdateReviewRuleDTO.java +++ /dev/null @@ -1,26 +0,0 @@ -package com.lesingle.creation.dto.homework; - -import io.swagger.v3.oas.annotations.media.Schema; -import lombok.Data; - -import jakarta.validation.constraints.NotBlank; -import jakarta.validation.constraints.NotNull; -import java.math.BigDecimal; -import java.util.List; - -/** - * 更新评审规则请求 DTO - */ -@Data -@Schema(description = "更新评审规则请求") -public class UpdateReviewRuleDTO { - - @Schema(description = "规则名称") - private String ruleName; - - @Schema(description = "规则描述") - private String description; - - @Schema(description = "评审维度列表") - private List dimensions; -} diff --git a/java-backend/src/main/java/com/lesingle/creation/dto/school/CreateSchoolDTO.java b/java-backend/src/main/java/com/lesingle/creation/dto/school/CreateSchoolDTO.java deleted file mode 100644 index 82a970a..0000000 --- a/java-backend/src/main/java/com/lesingle/creation/dto/school/CreateSchoolDTO.java +++ /dev/null @@ -1,36 +0,0 @@ -package com.lesingle.creation.dto.school; - -import io.swagger.v3.oas.annotations.media.Schema; -import lombok.Data; - -import jakarta.validation.constraints.NotBlank; -import java.time.LocalDate; - -/** - * 创建学校 DTO - */ -@Data -@Schema(description = "创建学校请求") -public class CreateSchoolDTO { - - @Schema(description = "学校地址") - private String address; - - @Schema(description = "联系电话") - private String phone; - - @Schema(description = "校长姓名") - private String principal; - - @Schema(description = "建校时间") - private LocalDate established; - - @Schema(description = "学校描述") - private String description; - - @Schema(description = "学校 Logo URL") - private String logo; - - @Schema(description = "学校网站") - private String website; -} diff --git a/java-backend/src/main/java/com/lesingle/creation/dto/school/UpdateSchoolDTO.java b/java-backend/src/main/java/com/lesingle/creation/dto/school/UpdateSchoolDTO.java deleted file mode 100644 index a59458e..0000000 --- a/java-backend/src/main/java/com/lesingle/creation/dto/school/UpdateSchoolDTO.java +++ /dev/null @@ -1,35 +0,0 @@ -package com.lesingle.creation.dto.school; - -import io.swagger.v3.oas.annotations.media.Schema; -import lombok.Data; - -import java.time.LocalDate; - -/** - * 更新学校 DTO - */ -@Data -@Schema(description = "更新学校请求") -public class UpdateSchoolDTO { - - @Schema(description = "学校地址") - private String address; - - @Schema(description = "联系电话") - private String phone; - - @Schema(description = "校长姓名") - private String principal; - - @Schema(description = "建校时间") - private LocalDate established; - - @Schema(description = "学校描述") - private String description; - - @Schema(description = "学校 Logo URL") - private String logo; - - @Schema(description = "学校网站") - private String website; -} diff --git a/java-backend/src/main/java/com/lesingle/creation/dto/student/CreateStudentDTO.java b/java-backend/src/main/java/com/lesingle/creation/dto/student/CreateStudentDTO.java deleted file mode 100644 index db489a2..0000000 --- a/java-backend/src/main/java/com/lesingle/creation/dto/student/CreateStudentDTO.java +++ /dev/null @@ -1,68 +0,0 @@ -package com.lesingle.creation.dto.student; - -import io.swagger.v3.oas.annotations.media.Schema; -import jakarta.validation.constraints.NotBlank; -import jakarta.validation.constraints.NotNull; -import lombok.Data; - -import java.time.LocalDate; - -/** - * 创建学生 DTO - */ -@Data -@Schema(description = "创建学生请求") -public class CreateStudentDTO { - - @NotBlank(message = "用户名不能为空") - @Schema(description = "用户名") - private String username; - - @NotBlank(message = "密码不能为空") - @Schema(description = "密码") - private String password; - - @NotBlank(message = "昵称不能为空") - @Schema(description = "昵称") - private String nickname; - - @Schema(description = "邮箱") - private String email; - - @Schema(description = "头像 URL") - private String avatar; - - @NotNull(message = "行政班级 ID 不能为空") - @Schema(description = "行政班级 ID") - private Long classId; - - @Schema(description = "学号") - private String studentNo; - - @Schema(description = "联系电话") - private String phone; - - @Schema(description = "身份证号") - private String idCard; - - @Schema(description = "性别:1-男,2-女") - private Integer gender; - - @Schema(description = "出生日期") - private LocalDate birthDate; - - @Schema(description = "入学日期") - private LocalDate enrollmentDate; - - @Schema(description = "家长姓名") - private String parentName; - - @Schema(description = "家长电话") - private String parentPhone; - - @Schema(description = "家庭地址") - private String address; - - @Schema(description = "学生描述") - private String description; -} diff --git a/java-backend/src/main/java/com/lesingle/creation/dto/student/UpdateStudentDTO.java b/java-backend/src/main/java/com/lesingle/creation/dto/student/UpdateStudentDTO.java deleted file mode 100644 index 102c94f..0000000 --- a/java-backend/src/main/java/com/lesingle/creation/dto/student/UpdateStudentDTO.java +++ /dev/null @@ -1,59 +0,0 @@ -package com.lesingle.creation.dto.student; - -import io.swagger.v3.oas.annotations.media.Schema; -import lombok.Data; - -import java.time.LocalDate; - -/** - * 更新学生 DTO - */ -@Data -@Schema(description = "更新学生请求") -public class UpdateStudentDTO { - - @Schema(description = "昵称") - private String nickname; - - @Schema(description = "邮箱") - private String email; - - @Schema(description = "头像 URL") - private String avatar; - - @Schema(description = "行政班级 ID") - private Long classId; - - @Schema(description = "学号") - private String studentNo; - - @Schema(description = "联系电话") - private String phone; - - @Schema(description = "身份证号") - private String idCard; - - @Schema(description = "性别:1-男,2-女") - private Integer gender; - - @Schema(description = "出生日期") - private LocalDate birthDate; - - @Schema(description = "入学日期") - private LocalDate enrollmentDate; - - @Schema(description = "家长姓名") - private String parentName; - - @Schema(description = "家长电话") - private String parentPhone; - - @Schema(description = "家庭地址") - private String address; - - @Schema(description = "学生描述") - private String description; - - @Schema(description = "有效状态:1-有效,2-失效") - private Integer validState; -} diff --git a/java-backend/src/main/java/com/lesingle/creation/dto/teacher/CreateTeacherDTO.java b/java-backend/src/main/java/com/lesingle/creation/dto/teacher/CreateTeacherDTO.java deleted file mode 100644 index 4f2c25c..0000000 --- a/java-backend/src/main/java/com/lesingle/creation/dto/teacher/CreateTeacherDTO.java +++ /dev/null @@ -1,65 +0,0 @@ -package com.lesingle.creation.dto.teacher; - -import io.swagger.v3.oas.annotations.media.Schema; -import jakarta.validation.constraints.NotBlank; -import jakarta.validation.constraints.NotNull; -import lombok.Data; - -import java.time.LocalDate; - -/** - * 创建教师 DTO - */ -@Data -@Schema(description = "创建教师请求") -public class CreateTeacherDTO { - - @NotBlank(message = "用户名不能为空") - @Schema(description = "用户名") - private String username; - - @NotBlank(message = "密码不能为空") - @Schema(description = "密码") - private String password; - - @NotBlank(message = "昵称不能为空") - @Schema(description = "昵称") - private String nickname; - - @Schema(description = "邮箱") - private String email; - - @Schema(description = "头像 URL") - private String avatar; - - @NotNull(message = "部门 ID 不能为空") - @Schema(description = "部门 ID") - private Long departmentId; - - @Schema(description = "工号") - private String employeeNo; - - @Schema(description = "联系电话") - private String phone; - - @Schema(description = "身份证号") - private String idCard; - - @Schema(description = "性别:1-男,2-女") - private Integer gender; - - @Schema(description = "出生日期") - private LocalDate birthDate; - - @Schema(description = "入职日期") - private LocalDate hireDate; - - @Schema(description = "任教科目") - private String subject; - - @Schema(description = "职称") - private String title; - - @Schema(description = "教师描述") - private String description; -} diff --git a/java-backend/src/main/java/com/lesingle/creation/dto/teacher/UpdateTeacherDTO.java b/java-backend/src/main/java/com/lesingle/creation/dto/teacher/UpdateTeacherDTO.java deleted file mode 100644 index 7b7b83c..0000000 --- a/java-backend/src/main/java/com/lesingle/creation/dto/teacher/UpdateTeacherDTO.java +++ /dev/null @@ -1,56 +0,0 @@ -package com.lesingle.creation.dto.teacher; - -import io.swagger.v3.oas.annotations.media.Schema; -import lombok.Data; - -import java.time.LocalDate; - -/** - * 更新教师 DTO - */ -@Data -@Schema(description = "更新教师请求") -public class UpdateTeacherDTO { - - @Schema(description = "昵称") - private String nickname; - - @Schema(description = "邮箱") - private String email; - - @Schema(description = "头像 URL") - private String avatar; - - @Schema(description = "部门 ID") - private Long departmentId; - - @Schema(description = "工号") - private String employeeNo; - - @Schema(description = "联系电话") - private String phone; - - @Schema(description = "身份证号") - private String idCard; - - @Schema(description = "性别:1-男,2-女") - private Integer gender; - - @Schema(description = "出生日期") - private LocalDate birthDate; - - @Schema(description = "入职日期") - private LocalDate hireDate; - - @Schema(description = "任教科目") - private String subject; - - @Schema(description = "职称") - private String title; - - @Schema(description = "教师描述") - private String description; - - @Schema(description = "有效状态:1-有效,2-失效") - private Integer validState; -} diff --git a/java-backend/src/main/java/com/lesingle/creation/entity/Department.java b/java-backend/src/main/java/com/lesingle/creation/entity/Department.java deleted file mode 100644 index 366b8b8..0000000 --- a/java-backend/src/main/java/com/lesingle/creation/entity/Department.java +++ /dev/null @@ -1,66 +0,0 @@ -package com.lesingle.creation.entity; - -import com.baomidou.mybatisplus.annotation.TableField; -import com.baomidou.mybatisplus.annotation.TableName; -import com.lesingle.creation.common.base.BaseEntity; -import lombok.Data; -import lombok.EqualsAndHashCode; - -import java.util.List; - -/** - * 部门表实体类 - */ -@Data -@EqualsAndHashCode(callSuper = true) -@TableName("t_biz_department") -public class Department extends BaseEntity { - - /** - * 租户 ID - */ - @TableField("tenant_id") - private Long tenantId; - - /** - * 部门名称 - */ - @TableField("name") - private String name; - - /** - * 部门编码(在租户内唯一) - */ - @TableField("code") - private String code; - - /** - * 父部门 ID(支持树形结构) - */ - @TableField("parent_id") - private Long parentId; - - /** - * 部门描述 - */ - @TableField("description") - private String description; - - /** - * 排序 - */ - @TableField("sort") - private Integer sort; - - /** - * 有效状态:1-有效,2-失效 - */ - @TableField("valid_state") - private Integer validState; - - /** - * 子部门列表(非数据库字段) - */ - @TableField(exist = false) - private List children; -} diff --git a/java-backend/src/main/java/com/lesingle/creation/entity/Grade.java b/java-backend/src/main/java/com/lesingle/creation/entity/Grade.java deleted file mode 100644 index 33edee8..0000000 --- a/java-backend/src/main/java/com/lesingle/creation/entity/Grade.java +++ /dev/null @@ -1,52 +0,0 @@ -package com.lesingle.creation.entity; - -import com.baomidou.mybatisplus.annotation.TableField; -import com.baomidou.mybatisplus.annotation.TableName; -import com.lesingle.creation.common.base.BaseEntity; -import lombok.Data; -import lombok.EqualsAndHashCode; - -/** - * 年级表实体类 - */ -@Data -@EqualsAndHashCode(callSuper = true) -@TableName("t_biz_grade") -public class Grade extends BaseEntity { - - /** - * 租户 ID - */ - @TableField("tenant_id") - private Long tenantId; - - /** - * 年级名称(如:一年级、二年级) - */ - @TableField("name") - private String name; - - /** - * 年级编码(在租户内唯一,如:grade_1, grade_2) - */ - @TableField("code") - private String code; - - /** - * 年级级别(用于排序,如:1, 2, 3) - */ - @TableField("level") - private Integer level; - - /** - * 年级描述 - */ - @TableField("description") - private String description; - - /** - * 有效状态:1-有效,2-失效 - */ - @TableField("valid_state") - private Integer validState; -} diff --git a/java-backend/src/main/java/com/lesingle/creation/entity/Homework.java b/java-backend/src/main/java/com/lesingle/creation/entity/Homework.java deleted file mode 100644 index 4c82d63..0000000 --- a/java-backend/src/main/java/com/lesingle/creation/entity/Homework.java +++ /dev/null @@ -1,82 +0,0 @@ -package com.lesingle.creation.entity; - -import com.baomidou.mybatisplus.annotation.TableField; -import com.baomidou.mybatisplus.annotation.TableName; -import com.lesingle.creation.common.base.BaseEntity; -import lombok.Data; -import lombok.EqualsAndHashCode; - -/** - * 作业表实体类 - */ -@Data -@EqualsAndHashCode(callSuper = true) -@TableName("t_biz_homework") -public class Homework extends BaseEntity { - - /** - * 租户 ID - */ - @TableField("tenant_id") - private Long tenantId; - - /** - * 作业名称 - */ - @TableField("name") - private String name; - - /** - * 作业内容(富文本) - */ - @TableField("content") - private String content; - - /** - * 作业状态:unpublished/published - */ - @TableField("status") - private String status; - - /** - * 发布时间 - */ - @TableField("publish_time") - private java.time.LocalDateTime publishTime; - - /** - * 提交开始时间 - */ - @TableField("submit_start_time") - private java.time.LocalDateTime submitStartTime; - - /** - * 提交结束时间 - */ - @TableField("submit_end_time") - private java.time.LocalDateTime submitEndTime; - - /** - * 附件列表(JSON 格式) - */ - @TableField("attachments") - private String attachments; - - /** - * 公开范围(班级 ID 数组 JSON 格式) - */ - @TableField("publish_scope") - private String publishScope; - - /** - * 评审规则 ID - */ - @TableField("review_rule_id") - private Long reviewRuleId; - - /** - * 有效状态:1-有效,2-失效 - */ - @TableField("valid_state") - private Integer validState; -} diff --git a/java-backend/src/main/java/com/lesingle/creation/entity/HomeworkReviewDimension.java b/java-backend/src/main/java/com/lesingle/creation/entity/HomeworkReviewDimension.java deleted file mode 100644 index 20c6a4a..0000000 --- a/java-backend/src/main/java/com/lesingle/creation/entity/HomeworkReviewDimension.java +++ /dev/null @@ -1,54 +0,0 @@ -package com.lesingle.creation.entity; - -import com.baomidou.mybatisplus.annotation.TableField; -import com.baomidou.mybatisplus.annotation.TableName; -import com.lesingle.creation.common.base.BaseEntity; -import lombok.Data; -import lombok.EqualsAndHashCode; - -import java.math.BigDecimal; - -/** - * 作业评审维度实体类 - */ -@Data -@EqualsAndHashCode(callSuper = true) -@TableName("t_biz_homework_review_dimension") -public class HomeworkReviewDimension extends BaseEntity { - - /** - * 规则 ID - */ - @TableField("rule_id") - private Long ruleId; - - /** - * 租户 ID - */ - @TableField("tenant_id") - private Long tenantId; - - /** - * 维度名称 - */ - @TableField("name") - private String name; - - /** - * 满分 - */ - @TableField("max_score") - private BigDecimal maxScore; - - /** - * 维度描述 - */ - @TableField("description") - private String description; - - /** - * 排序顺序 - */ - @TableField("sort_order") - private Integer sortOrder; -} diff --git a/java-backend/src/main/java/com/lesingle/creation/entity/HomeworkReviewRule.java b/java-backend/src/main/java/com/lesingle/creation/entity/HomeworkReviewRule.java deleted file mode 100644 index 9fe0fcd..0000000 --- a/java-backend/src/main/java/com/lesingle/creation/entity/HomeworkReviewRule.java +++ /dev/null @@ -1,48 +0,0 @@ -package com.lesingle.creation.entity; - -import com.baomidou.mybatisplus.annotation.TableField; -import com.baomidou.mybatisplus.annotation.TableName; -import com.lesingle.creation.common.base.BaseEntity; -import lombok.Data; -import lombok.EqualsAndHashCode; - -import java.math.BigDecimal; - -/** - * 作业评审规则表实体类 - */ -@Data -@EqualsAndHashCode(callSuper = true) -@TableName("t_biz_homework_review_rule") -public class HomeworkReviewRule extends BaseEntity { - - /** - * 租户 ID - */ - @TableField("tenant_id") - private Long tenantId; - - /** - * 规则名称 - */ - @TableField("rule_name") - private String ruleName; - - /** - * 规则类型:default/custom - */ - @TableField("rule_type") - private String ruleType; - - /** - * 总分 - */ - @TableField("total_score") - private BigDecimal totalScore; - - /** - * 规则描述 - */ - @TableField("description") - private String description; -} diff --git a/java-backend/src/main/java/com/lesingle/creation/entity/HomeworkScore.java b/java-backend/src/main/java/com/lesingle/creation/entity/HomeworkScore.java deleted file mode 100644 index 4f1d676..0000000 --- a/java-backend/src/main/java/com/lesingle/creation/entity/HomeworkScore.java +++ /dev/null @@ -1,54 +0,0 @@ -package com.lesingle.creation.entity; - -import com.baomidou.mybatisplus.annotation.TableField; -import com.baomidou.mybatisplus.annotation.TableName; -import com.lesingle.creation.common.base.BaseEntity; -import lombok.Data; -import lombok.EqualsAndHashCode; - -import java.math.BigDecimal; - -/** - * 作业评分表实体类 - */ -@Data -@EqualsAndHashCode(callSuper = true) -@TableName("t_biz_homework_score") -public class HomeworkScore extends BaseEntity { - - /** - * 租户 ID - */ - @TableField("tenant_id") - private Long tenantId; - - /** - * 提交 ID - */ - @TableField("submission_id") - private Long submissionId; - - /** - * 作业 ID - */ - @TableField("homework_id") - private Long homeworkId; - - /** - * 评分人 ID - */ - @TableField("reviewer_id") - private Long reviewerId; - - /** - * 得分 - */ - @TableField("score") - private BigDecimal score; - - /** - * 评语 - */ - @TableField("comment") - private String comment; -} diff --git a/java-backend/src/main/java/com/lesingle/creation/entity/HomeworkSubmission.java b/java-backend/src/main/java/com/lesingle/creation/entity/HomeworkSubmission.java deleted file mode 100644 index 3e88557..0000000 --- a/java-backend/src/main/java/com/lesingle/creation/entity/HomeworkSubmission.java +++ /dev/null @@ -1,90 +0,0 @@ -package com.lesingle.creation.entity; - -import com.baomidou.mybatisplus.annotation.TableField; -import com.baomidou.mybatisplus.annotation.TableName; -import com.lesingle.creation.common.base.BaseEntity; -import lombok.Data; -import lombok.EqualsAndHashCode; - -import java.math.BigDecimal; - -/** - * 作业提交表实体类 - */ -@Data -@EqualsAndHashCode(callSuper = true) -@TableName("t_biz_homework_submission") -public class HomeworkSubmission extends BaseEntity { - - /** - * 租户 ID - */ - @TableField("tenant_id") - private Long tenantId; - - /** - * 作业 ID - */ - @TableField("homework_id") - private Long homeworkId; - - /** - * 学生用户 ID - */ - @TableField("student_id") - private Long studentId; - - /** - * 学生姓名 - */ - @TableField("student_name") - private String studentName; - - /** - * 提交内容 - */ - @TableField("content") - private String content; - - /** - * 提交附件列表(JSON 格式) - */ - @TableField("attachments") - private String attachments; - - /** - * 提交状态:submitted/reviewing/returned - */ - @TableField("status") - private String status; - - /** - * 提交时间 - */ - @TableField("submit_time") - private java.time.LocalDateTime submitTime; - - /** - * 批改时间 - */ - @TableField("review_time") - private java.time.LocalDateTime reviewTime; - - /** - * 批改人 ID - */ - @TableField("reviewer_id") - private Long reviewerId; - - /** - * 批改评语 - */ - @TableField("review_comment") - private String reviewComment; - - /** - * 批改分数 - */ - @TableField("review_score") - private BigDecimal reviewScore; -} diff --git a/java-backend/src/main/java/com/lesingle/creation/entity/School.java b/java-backend/src/main/java/com/lesingle/creation/entity/School.java deleted file mode 100644 index 45f5de0..0000000 --- a/java-backend/src/main/java/com/lesingle/creation/entity/School.java +++ /dev/null @@ -1,72 +0,0 @@ -package com.lesingle.creation.entity; - -import com.baomidou.mybatisplus.annotation.TableField; -import com.baomidou.mybatisplus.annotation.TableName; -import com.lesingle.creation.common.base.BaseEntity; -import lombok.Data; -import lombok.EqualsAndHashCode; - -import java.time.LocalDate; - -/** - * 学校信息表实体类 - */ -@Data -@EqualsAndHashCode(callSuper = true) -@TableName("t_biz_school") -public class School extends BaseEntity { - - /** - * 租户 ID(一对一) - */ - @TableField("tenant_id") - private Long tenantId; - - /** - * 学校地址 - */ - @TableField("address") - private String address; - - /** - * 联系电话 - */ - @TableField("phone") - private String phone; - - /** - * 校长姓名 - */ - @TableField("principal") - private String principal; - - /** - * 建校时间 - */ - @TableField("established") - private LocalDate established; - - /** - * 学校描述 - */ - @TableField("description") - private String description; - - /** - * 学校 Logo URL - */ - @TableField("logo") - private String logo; - - /** - * 学校网站 - */ - @TableField("website") - private String website; - - /** - * 有效状态:1-有效,2-失效 - */ - @TableField("valid_state") - private Integer validState; -} diff --git a/java-backend/src/main/java/com/lesingle/creation/entity/SchoolClass.java b/java-backend/src/main/java/com/lesingle/creation/entity/SchoolClass.java deleted file mode 100644 index 14fdd89..0000000 --- a/java-backend/src/main/java/com/lesingle/creation/entity/SchoolClass.java +++ /dev/null @@ -1,64 +0,0 @@ -package com.lesingle.creation.entity; - -import com.baomidou.mybatisplus.annotation.TableField; -import com.baomidou.mybatisplus.annotation.TableName; -import com.lesingle.creation.common.base.BaseEntity; -import lombok.Data; -import lombok.EqualsAndHashCode; - -/** - * 班级表实体类 - */ -@Data -@EqualsAndHashCode(callSuper = true) -@TableName("t_biz_class") -public class SchoolClass extends BaseEntity { - - /** - * 租户 ID - */ - @TableField("tenant_id") - private Long tenantId; - - /** - * 年级 ID - */ - @TableField("grade_id") - private Long gradeId; - - /** - * 班级名称(如:一年级 1 班、二年级 2 班) - */ - @TableField("name") - private String name; - - /** - * 班级编码(在租户内唯一) - */ - @TableField("code") - private String code; - - /** - * 班级类型:1-行政班级(教学班级),2-兴趣班 - */ - @TableField("type") - private Integer type; - - /** - * 班级容量(可选) - */ - @TableField("capacity") - private Integer capacity; - - /** - * 班级描述 - */ - @TableField("description") - private String description; - - /** - * 有效状态:1-有效,2-失效 - */ - @TableField("valid_state") - private Integer validState; -} diff --git a/java-backend/src/main/java/com/lesingle/creation/entity/Student.java b/java-backend/src/main/java/com/lesingle/creation/entity/Student.java deleted file mode 100644 index 3c4b139..0000000 --- a/java-backend/src/main/java/com/lesingle/creation/entity/Student.java +++ /dev/null @@ -1,102 +0,0 @@ -package com.lesingle.creation.entity; - -import com.baomidou.mybatisplus.annotation.TableField; -import com.baomidou.mybatisplus.annotation.TableName; -import com.lesingle.creation.common.base.BaseEntity; -import lombok.Data; -import lombok.EqualsAndHashCode; - -import java.time.LocalDate; - -/** - * 学生表实体类 - */ -@Data -@EqualsAndHashCode(callSuper = true) -@TableName("t_biz_student") -public class Student extends BaseEntity { - - /** - * 用户 ID(一对一) - */ - @TableField("user_id") - private Long userId; - - /** - * 租户 ID - */ - @TableField("tenant_id") - private Long tenantId; - - /** - * 行政班级 ID - */ - @TableField("class_id") - private Long classId; - - /** - * 学号(在租户内唯一) - */ - @TableField("student_no") - private String studentNo; - - /** - * 联系电话 - */ - @TableField("phone") - private String phone; - - /** - * 身份证号 - */ - @TableField("id_card") - private String idCard; - - /** - * 性别:1-男,2-女 - */ - @TableField("gender") - private Integer gender; - - /** - * 出生日期 - */ - @TableField("birth_date") - private LocalDate birthDate; - - /** - * 入学日期 - */ - @TableField("enrollment_date") - private LocalDate enrollmentDate; - - /** - * 家长姓名 - */ - @TableField("parent_name") - private String parentName; - - /** - * 家长电话 - */ - @TableField("parent_phone") - private String parentPhone; - - /** - * 家庭地址 - */ - @TableField("address") - private String address; - - /** - * 学生描述 - */ - @TableField("description") - private String description; - - /** - * 有效状态:1-有效,2-失效 - */ - @TableField("valid_state") - private Integer validState; -} diff --git a/java-backend/src/main/java/com/lesingle/creation/entity/Teacher.java b/java-backend/src/main/java/com/lesingle/creation/entity/Teacher.java deleted file mode 100644 index 8ada535..0000000 --- a/java-backend/src/main/java/com/lesingle/creation/entity/Teacher.java +++ /dev/null @@ -1,96 +0,0 @@ -package com.lesingle.creation.entity; - -import com.baomidou.mybatisplus.annotation.TableField; -import com.baomidou.mybatisplus.annotation.TableName; -import com.lesingle.creation.common.base.BaseEntity; -import lombok.Data; -import lombok.EqualsAndHashCode; - -import java.time.LocalDate; - -/** - * 教师表实体类 - */ -@Data -@EqualsAndHashCode(callSuper = true) -@TableName("t_biz_teacher") -public class Teacher extends BaseEntity { - - /** - * 用户 ID(一对一) - */ - @TableField("user_id") - private Long userId; - - /** - * 租户 ID - */ - @TableField("tenant_id") - private Long tenantId; - - /** - * 部门 ID - */ - @TableField("department_id") - private Long departmentId; - - /** - * 工号(在租户内唯一) - */ - @TableField("employee_no") - private String employeeNo; - - /** - * 联系电话 - */ - @TableField("phone") - private String phone; - - /** - * 身份证号 - */ - @TableField("id_card") - private String idCard; - - /** - * 性别:1-男,2-女 - */ - @TableField("gender") - private Integer gender; - - /** - * 出生日期 - */ - @TableField("birth_date") - private LocalDate birthDate; - - /** - * 入职日期 - */ - @TableField("hire_date") - private LocalDate hireDate; - - /** - * 任教科目(可选,如:语文、数学) - */ - @TableField("subject") - private String subject; - - /** - * 职称(可选,如:高级教师、一级教师) - */ - @TableField("title") - private String title; - - /** - * 教师描述 - */ - @TableField("description") - private String description; - - /** - * 有效状态:1-有效,2-失效 - */ - @TableField("valid_state") - private Integer validState; -} diff --git a/java-backend/src/main/java/com/lesingle/creation/mapper/DepartmentMapper.java b/java-backend/src/main/java/com/lesingle/creation/mapper/DepartmentMapper.java deleted file mode 100644 index eb24749..0000000 --- a/java-backend/src/main/java/com/lesingle/creation/mapper/DepartmentMapper.java +++ /dev/null @@ -1,35 +0,0 @@ -package com.lesingle.creation.mapper; - -import com.baomidou.mybatisplus.core.mapper.BaseMapper; -import com.lesingle.creation.entity.Department; -import org.apache.ibatis.annotations.Mapper; -import org.apache.ibatis.annotations.Param; -import org.apache.ibatis.annotations.Select; - -import java.util.List; - -/** - * 部门 Mapper 接口 - */ -@Mapper -public interface DepartmentMapper extends BaseMapper { - - /** - * 根据租户 ID 和部门编码查询部门 - * - * @param tenantId 租户 ID - * @param code 部门编码 - * @return 部门实体 - */ - @Select("SELECT * FROM t_biz_department WHERE tenant_id = #{tenantId} AND code = #{code} AND deleted = 0") - Department selectByCode(@Param("tenantId") Long tenantId, @Param("code") String code); - - /** - * 根据租户 ID 查询部门列表 - * - * @param tenantId 租户 ID - * @return 部门列表 - */ - @Select("SELECT * FROM t_biz_department WHERE tenant_id = #{tenantId} AND deleted = 0 ORDER BY sort ASC") - List selectByTenantId(@Param("tenantId") Long tenantId); -} diff --git a/java-backend/src/main/java/com/lesingle/creation/mapper/GradeMapper.java b/java-backend/src/main/java/com/lesingle/creation/mapper/GradeMapper.java deleted file mode 100644 index 0459eb9..0000000 --- a/java-backend/src/main/java/com/lesingle/creation/mapper/GradeMapper.java +++ /dev/null @@ -1,35 +0,0 @@ -package com.lesingle.creation.mapper; - -import com.baomidou.mybatisplus.core.mapper.BaseMapper; -import com.lesingle.creation.entity.Grade; -import org.apache.ibatis.annotations.Mapper; -import org.apache.ibatis.annotations.Param; -import org.apache.ibatis.annotations.Select; - -import java.util.List; - -/** - * 年级 Mapper 接口 - */ -@Mapper -public interface GradeMapper extends BaseMapper { - - /** - * 根据租户 ID 和年级编码查询年级 - * - * @param tenantId 租户 ID - * @param code 年级编码 - * @return 年级实体 - */ - @Select("SELECT * FROM t_biz_grade WHERE tenant_id = #{tenantId} AND code = #{code} AND deleted = 0") - Grade selectByCode(@Param("tenantId") Long tenantId, @Param("code") String code); - - /** - * 根据租户 ID 查询年级列表 - * - * @param tenantId 租户 ID - * @return 年级列表 - */ - @Select("SELECT * FROM t_biz_grade WHERE tenant_id = #{tenantId} AND deleted = 0 ORDER BY level ASC") - List selectByTenantId(@Param("tenantId") Long tenantId); -} diff --git a/java-backend/src/main/java/com/lesingle/creation/mapper/HomeworkMapper.java b/java-backend/src/main/java/com/lesingle/creation/mapper/HomeworkMapper.java deleted file mode 100644 index 10a679a..0000000 --- a/java-backend/src/main/java/com/lesingle/creation/mapper/HomeworkMapper.java +++ /dev/null @@ -1,13 +0,0 @@ -package com.lesingle.creation.mapper; - -import com.baomidou.mybatisplus.core.mapper.BaseMapper; -import com.lesingle.creation.entity.Homework; -import org.apache.ibatis.annotations.Mapper; - -/** - * 作业 Mapper 接口 - */ -@Mapper -public interface HomeworkMapper extends BaseMapper { - -} diff --git a/java-backend/src/main/java/com/lesingle/creation/mapper/HomeworkReviewDimensionMapper.java b/java-backend/src/main/java/com/lesingle/creation/mapper/HomeworkReviewDimensionMapper.java deleted file mode 100644 index b55284d..0000000 --- a/java-backend/src/main/java/com/lesingle/creation/mapper/HomeworkReviewDimensionMapper.java +++ /dev/null @@ -1,26 +0,0 @@ -package com.lesingle.creation.mapper; - -import com.baomidou.mybatisplus.core.mapper.BaseMapper; -import com.lesingle.creation.entity.HomeworkReviewDimension; -import org.apache.ibatis.annotations.Mapper; -import org.apache.ibatis.annotations.Param; - -import java.math.BigDecimal; -import java.util.List; - -/** - * 作业评审维度 Mapper 接口 - */ -@Mapper -public interface HomeworkReviewDimensionMapper extends BaseMapper { - - /** - * 根据规则 ID 删除维度 - */ - void deleteByRuleId(@Param("ruleId") Long ruleId); - - /** - * 根据规则 ID 查询维度列表 - */ - List selectByRuleId(@Param("ruleId") Long ruleId); -} diff --git a/java-backend/src/main/java/com/lesingle/creation/mapper/HomeworkReviewRuleMapper.java b/java-backend/src/main/java/com/lesingle/creation/mapper/HomeworkReviewRuleMapper.java deleted file mode 100644 index 46d9359..0000000 --- a/java-backend/src/main/java/com/lesingle/creation/mapper/HomeworkReviewRuleMapper.java +++ /dev/null @@ -1,13 +0,0 @@ -package com.lesingle.creation.mapper; - -import com.baomidou.mybatisplus.core.mapper.BaseMapper; -import com.lesingle.creation.entity.HomeworkReviewRule; -import org.apache.ibatis.annotations.Mapper; - -/** - * 作业评审规则 Mapper 接口 - */ -@Mapper -public interface HomeworkReviewRuleMapper extends BaseMapper { - -} diff --git a/java-backend/src/main/java/com/lesingle/creation/mapper/HomeworkScoreMapper.java b/java-backend/src/main/java/com/lesingle/creation/mapper/HomeworkScoreMapper.java deleted file mode 100644 index 52b71f1..0000000 --- a/java-backend/src/main/java/com/lesingle/creation/mapper/HomeworkScoreMapper.java +++ /dev/null @@ -1,13 +0,0 @@ -package com.lesingle.creation.mapper; - -import com.baomidou.mybatisplus.core.mapper.BaseMapper; -import com.lesingle.creation.entity.HomeworkScore; -import org.apache.ibatis.annotations.Mapper; - -/** - * 作业评分 Mapper 接口 - */ -@Mapper -public interface HomeworkScoreMapper extends BaseMapper { - -} diff --git a/java-backend/src/main/java/com/lesingle/creation/mapper/HomeworkSubmissionMapper.java b/java-backend/src/main/java/com/lesingle/creation/mapper/HomeworkSubmissionMapper.java deleted file mode 100644 index a82040f..0000000 --- a/java-backend/src/main/java/com/lesingle/creation/mapper/HomeworkSubmissionMapper.java +++ /dev/null @@ -1,13 +0,0 @@ -package com.lesingle.creation.mapper; - -import com.baomidou.mybatisplus.core.mapper.BaseMapper; -import com.lesingle.creation.entity.HomeworkSubmission; -import org.apache.ibatis.annotations.Mapper; - -/** - * 作业提交 Mapper 接口 - */ -@Mapper -public interface HomeworkSubmissionMapper extends BaseMapper { - -} diff --git a/java-backend/src/main/java/com/lesingle/creation/mapper/SchoolClassMapper.java b/java-backend/src/main/java/com/lesingle/creation/mapper/SchoolClassMapper.java deleted file mode 100644 index d0ca96f..0000000 --- a/java-backend/src/main/java/com/lesingle/creation/mapper/SchoolClassMapper.java +++ /dev/null @@ -1,35 +0,0 @@ -package com.lesingle.creation.mapper; - -import com.baomidou.mybatisplus.core.mapper.BaseMapper; -import com.lesingle.creation.entity.SchoolClass; -import org.apache.ibatis.annotations.Mapper; -import org.apache.ibatis.annotations.Param; -import org.apache.ibatis.annotations.Select; - -import java.util.List; - -/** - * 班级 Mapper 接口 - */ -@Mapper -public interface SchoolClassMapper extends BaseMapper { - - /** - * 根据租户 ID 和班级编码查询班级 - * - * @param tenantId 租户 ID - * @param code 班级编码 - * @return 班级实体 - */ - @Select("SELECT * FROM t_biz_class WHERE tenant_id = #{tenantId} AND code = #{code} AND deleted = 0") - SchoolClass selectByCode(@Param("tenantId") Long tenantId, @Param("code") String code); - - /** - * 根据年级 ID 查询班级列表 - * - * @param gradeId 年级 ID - * @return 班级列表 - */ - @Select("SELECT * FROM t_biz_class WHERE grade_id = #{gradeId} AND deleted = 0 ORDER BY name ASC") - List selectByGradeId(@Param("gradeId") Long gradeId); -} diff --git a/java-backend/src/main/java/com/lesingle/creation/mapper/SchoolMapper.java b/java-backend/src/main/java/com/lesingle/creation/mapper/SchoolMapper.java deleted file mode 100644 index b9fa279..0000000 --- a/java-backend/src/main/java/com/lesingle/creation/mapper/SchoolMapper.java +++ /dev/null @@ -1,23 +0,0 @@ -package com.lesingle.creation.mapper; - -import com.baomidou.mybatisplus.core.mapper.BaseMapper; -import com.lesingle.creation.entity.School; -import org.apache.ibatis.annotations.Mapper; -import org.apache.ibatis.annotations.Param; -import org.apache.ibatis.annotations.Select; - -/** - * 学校信息 Mapper 接口 - */ -@Mapper -public interface SchoolMapper extends BaseMapper { - - /** - * 根据租户 ID 查询学校 - * - * @param tenantId 租户 ID - * @return 学校实体 - */ - @Select("SELECT * FROM t_biz_school WHERE tenant_id = #{tenantId} AND deleted = 0") - School selectByTenantId(@Param("tenantId") Long tenantId); -} diff --git a/java-backend/src/main/java/com/lesingle/creation/mapper/StudentMapper.java b/java-backend/src/main/java/com/lesingle/creation/mapper/StudentMapper.java deleted file mode 100644 index 9f48aa0..0000000 --- a/java-backend/src/main/java/com/lesingle/creation/mapper/StudentMapper.java +++ /dev/null @@ -1,33 +0,0 @@ -package com.lesingle.creation.mapper; - -import com.baomidou.mybatisplus.core.mapper.BaseMapper; -import com.lesingle.creation.entity.Student; -import org.apache.ibatis.annotations.Mapper; -import org.apache.ibatis.annotations.Param; -import org.apache.ibatis.annotations.Select; - -/** - * 学生 Mapper 接口 - */ -@Mapper -public interface StudentMapper extends BaseMapper { - - /** - * 根据用户 ID 查询学生 - * - * @param userId 用户 ID - * @return 学生实体 - */ - @Select("SELECT * FROM t_biz_student WHERE user_id = #{userId} AND deleted = 0") - Student selectByUserId(@Param("userId") Long userId); - - /** - * 根据租户 ID 和学号查询学生 - * - * @param tenantId 租户 ID - * @param studentNo 学号 - * @return 学生实体 - */ - @Select("SELECT * FROM t_biz_student WHERE tenant_id = #{tenantId} AND student_no = #{studentNo} AND deleted = 0") - Student selectByStudentNo(@Param("tenantId") Long tenantId, @Param("studentNo") String studentNo); -} diff --git a/java-backend/src/main/java/com/lesingle/creation/mapper/TeacherMapper.java b/java-backend/src/main/java/com/lesingle/creation/mapper/TeacherMapper.java deleted file mode 100644 index ebd9a0f..0000000 --- a/java-backend/src/main/java/com/lesingle/creation/mapper/TeacherMapper.java +++ /dev/null @@ -1,33 +0,0 @@ -package com.lesingle.creation.mapper; - -import com.baomidou.mybatisplus.core.mapper.BaseMapper; -import com.lesingle.creation.entity.Teacher; -import org.apache.ibatis.annotations.Mapper; -import org.apache.ibatis.annotations.Param; -import org.apache.ibatis.annotations.Select; - -/** - * 教师 Mapper 接口 - */ -@Mapper -public interface TeacherMapper extends BaseMapper { - - /** - * 根据用户 ID 查询教师 - * - * @param userId 用户 ID - * @return 教师实体 - */ - @Select("SELECT * FROM t_biz_teacher WHERE user_id = #{userId} AND deleted = 0") - Teacher selectByUserId(@Param("userId") Long userId); - - /** - * 根据租户 ID 和工号查询教师 - * - * @param tenantId 租户 ID - * @param employeeNo 工号 - * @return 教师实体 - */ - @Select("SELECT * FROM t_biz_teacher WHERE tenant_id = #{tenantId} AND employee_no = #{employeeNo} AND deleted = 0") - Teacher selectByEmployeeNo(@Param("tenantId") Long tenantId, @Param("employeeNo") String employeeNo); -} diff --git a/java-backend/src/main/java/com/lesingle/creation/service/DepartmentService.java b/java-backend/src/main/java/com/lesingle/creation/service/DepartmentService.java deleted file mode 100644 index 1203ca4..0000000 --- a/java-backend/src/main/java/com/lesingle/creation/service/DepartmentService.java +++ /dev/null @@ -1,45 +0,0 @@ -package com.lesingle.creation.service; - -import com.baomidou.mybatisplus.extension.service.IService; -import com.lesingle.creation.entity.Department; -import com.lesingle.creation.dto.department.CreateDepartmentDTO; -import com.lesingle.creation.dto.department.UpdateDepartmentDTO; -import com.lesingle.creation.vo.department.DepartmentVO; - -import java.util.List; - -/** - * 部门服务接口 - */ -public interface DepartmentService extends IService { - - /** - * 创建部门 - */ - DepartmentVO create(CreateDepartmentDTO dto, Long tenantId, Long creatorId); - - /** - * 查询部门列表(分页) - */ - List list(Long tenantId, Long parentId); - - /** - * 查询部门树形结构 - */ - List tree(Long tenantId); - - /** - * 获取部门详情 - */ - DepartmentVO getDetail(Long id, Long tenantId); - - /** - * 更新部门 - */ - DepartmentVO update(Long id, UpdateDepartmentDTO dto, Long tenantId, Long modifierId); - - /** - * 删除部门 - */ - void delete(Long id, Long tenantId); -} diff --git a/java-backend/src/main/java/com/lesingle/creation/service/GradeService.java b/java-backend/src/main/java/com/lesingle/creation/service/GradeService.java deleted file mode 100644 index a05f09a..0000000 --- a/java-backend/src/main/java/com/lesingle/creation/service/GradeService.java +++ /dev/null @@ -1,37 +0,0 @@ -package com.lesingle.creation.service; - -import com.baomidou.mybatisplus.extension.plugins.pagination.Page; -import com.lesingle.creation.dto.grade.CreateGradeDTO; -import com.lesingle.creation.dto.grade.UpdateGradeDTO; -import com.lesingle.creation.vo.grade.GradeVO; - -/** - * 年级服务接口 - */ -public interface GradeService { - - /** - * 创建年级 - */ - GradeVO create(CreateGradeDTO dto, Long tenantId, Long creatorId); - - /** - * 分页查询年级列表 - */ - Page pageQuery(Integer pageNum, Integer pageSize, Long tenantId); - - /** - * 获取年级详情 - */ - GradeVO getDetail(Long id, Long tenantId); - - /** - * 更新年级 - */ - GradeVO update(Long id, UpdateGradeDTO dto, Long tenantId, Long modifierId); - - /** - * 删除年级 - */ - void delete(Long id, Long tenantId); -} diff --git a/java-backend/src/main/java/com/lesingle/creation/service/HomeworkService.java b/java-backend/src/main/java/com/lesingle/creation/service/HomeworkService.java deleted file mode 100644 index 3d8acb9..0000000 --- a/java-backend/src/main/java/com/lesingle/creation/service/HomeworkService.java +++ /dev/null @@ -1,208 +0,0 @@ -package com.lesingle.creation.service; - -import com.baomidou.mybatisplus.extension.plugins.pagination.Page; -import com.baomidou.mybatisplus.extension.service.IService; -import com.lesingle.creation.dto.homework.*; -import com.lesingle.creation.entity.Homework; -import com.lesingle.creation.vo.homework.HomeworkDetailVO; -import com.lesingle.creation.vo.homework.HomeworkListVO; -import com.lesingle.creation.vo.homework.ReviewRuleVO; -import com.lesingle.creation.vo.homework.SubmissionVO; - -import java.util.List; - -/** - * 作业服务接口 - */ -public interface HomeworkService extends IService { - - /** - * 创建作业 - * @param dto 创建作业请求 - * @param tenantId 租户 ID - * @param creatorId 创建人 ID - * @return 作业详情 - */ - HomeworkDetailVO create(CreateHomeworkDTO dto, Long tenantId, Long creatorId); - - /** - * 更新作业 - * @param id 作业 ID - * @param dto 更新作业请求 - * @param tenantId 租户 ID - * @return 作业详情 - */ - HomeworkDetailVO update(Long id, UpdateHomeworkDTO dto, Long tenantId); - - /** - * 发布作业 - * @param id 作业 ID - * @param tenantId 租户 ID - * @return 作业详情 - */ - HomeworkDetailVO publish(Long id, Long tenantId); - - /** - * 删除作业 - * @param id 作业 ID - * @param tenantId 租户 ID - */ - void delete(Long id, Long tenantId); - - /** - * 获取作业详情 - * @param id 作业 ID - * @param tenantId 租户 ID - * @return 作业详情 - */ - HomeworkDetailVO getDetail(Long id, Long tenantId); - - /** - * 分页查询作业列表 - * @param queryDTO 查询参数 - * @param tenantId 租户 ID - * @return 作业列表 - */ - Page pageQuery(HomeworkQueryDTO queryDTO, Long tenantId); - - /** - * 提交作业 - * @param dto 提交作业请求 - * @param tenantId 租户 ID - * @param studentId 学生 ID - * @return 提交详情 - */ - SubmissionVO submit(SubmitHomeworkDTO dto, Long tenantId, Long studentId); - - /** - * 批改作业 - * @param dto 批改作业请求 - * @param tenantId 租户 ID - * @param reviewerId 批改人 ID - * @return 提交详情 - */ - SubmissionVO review(ReviewHomeworkDTO dto, Long tenantId, Long reviewerId); - - /** - * 获取作业提交列表 - * @param homeworkId 作业 ID - * @param tenantId 租户 ID - * @return 提交列表 - */ - List getSubmissions(Long homeworkId, Long tenantId); - - /** - * 创建评审规则 - * @param ruleName 规则名称 - * @param ruleType 规则类型 - * @param totalScore 总分 - * @param description 规则描述 - * @param tenantId 租户 ID - * @return 评审规则 - */ - ReviewRuleVO createReviewRule(String ruleName, String ruleType, - java.math.BigDecimal totalScore, String description, Long tenantId); - - /** - * 获取评审规则列表 - * @param tenantId 租户 ID - * @return 评审规则列表 - */ - List getReviewRules(Long tenantId); - - /** - * 获取可选的评审规则 - * @param tenantId 租户 ID - * @return 评审规则列表 - */ - List getReviewRulesForSelect(Long tenantId); - - /** - * 更新评审规则 - * @param id 规则 ID - * @param dto 更新请求 - * @param tenantId 租户 ID - * @return 评审规则 - */ - ReviewRuleVO updateReviewRule(Long id, UpdateReviewRuleDTO dto, Long tenantId); - - /** - * 删除评审规则 - * @param id 规则 ID - * @param tenantId 租户 ID - */ - void deleteReviewRule(Long id, Long tenantId); - - /** - * 我的作业列表(学生端) - * @param queryDTO 查询参数 - * @param userId 用户 ID - * @param tenantId 租户 ID - * @return 作业列表 - */ - Page getMyHomeworks(HomeworkQueryDTO queryDTO, Long userId, Long tenantId); - - /** - * 取消发布作业 - * @param id 作业 ID - * @param tenantId 租户 ID - * @return 作业详情 - */ - HomeworkDetailVO unpublish(Long id, Long tenantId); - - /** - * 获取提交记录列表 - * @param queryDTO 查询参数 - * @param tenantId 租户 ID - * @return 提交记录列表 - */ - Page getSubmissionsList(SubmissionQueryDTO queryDTO, Long tenantId); - - /** - * 获取提交记录详情 - * @param id 提交 ID - * @param tenantId 租户 ID - * @return 提交详情 - */ - SubmissionVO getSubmissionDetail(Long id, Long tenantId); - - /** - * 获取班级树结构 - * @param tenantId 租户 ID - * @return 班级树 - */ - List getClassTree(Long tenantId); - - /** - * 获取我的提交记录 - * @param homeworkId 作业 ID - * @param userId 用户 ID - * @param tenantId 租户 ID - * @return 提交详情 - */ - SubmissionVO getMySubmission(Long homeworkId, Long userId, Long tenantId); - - /** - * 提交评分 - * @param dto 评分请求 - * @param tenantId 租户 ID - * @param reviewerId 批改人 ID - * @return 提交详情 - */ - SubmissionVO createScore(CreateScoreDTO dto, Long tenantId, Long reviewerId); - - /** - * 标记作品违规 - * @param submissionId 提交 ID - * @param reason 原因 - * @param tenantId 租户 ID - */ - void markViolation(Long submissionId, String reason, Long tenantId); - - /** - * 重置评分 - * @param submissionId 提交 ID - * @param tenantId 租户 ID - */ - void resetScore(Long submissionId, Long tenantId); -} diff --git a/java-backend/src/main/java/com/lesingle/creation/service/SchoolClassService.java b/java-backend/src/main/java/com/lesingle/creation/service/SchoolClassService.java deleted file mode 100644 index 1881027..0000000 --- a/java-backend/src/main/java/com/lesingle/creation/service/SchoolClassService.java +++ /dev/null @@ -1,37 +0,0 @@ -package com.lesingle.creation.service; - -import com.baomidou.mybatisplus.extension.plugins.pagination.Page; -import com.lesingle.creation.dto.schoolclass.CreateClassDTO; -import com.lesingle.creation.dto.schoolclass.UpdateClassDTO; -import com.lesingle.creation.vo.schoolclass.ClassVO; - -/** - * 班级服务接口 - */ -public interface SchoolClassService { - - /** - * 创建班级 - */ - ClassVO create(CreateClassDTO dto, Long tenantId, Long creatorId); - - /** - * 分页查询班级列表 - */ - Page pageQuery(Integer pageNum, Integer pageSize, Long tenantId, Long gradeId, Integer type); - - /** - * 获取班级详情 - */ - ClassVO getDetail(Long id, Long tenantId); - - /** - * 更新班级 - */ - ClassVO update(Long id, UpdateClassDTO dto, Long tenantId, Long modifierId); - - /** - * 删除班级 - */ - void delete(Long id, Long tenantId); -} diff --git a/java-backend/src/main/java/com/lesingle/creation/service/SchoolService.java b/java-backend/src/main/java/com/lesingle/creation/service/SchoolService.java deleted file mode 100644 index fd3dec4..0000000 --- a/java-backend/src/main/java/com/lesingle/creation/service/SchoolService.java +++ /dev/null @@ -1,48 +0,0 @@ -package com.lesingle.creation.service; - -import com.baomidou.mybatisplus.extension.service.IService; -import com.lesingle.creation.dto.school.CreateSchoolDTO; -import com.lesingle.creation.dto.school.UpdateSchoolDTO; -import com.lesingle.creation.entity.School; -import com.lesingle.creation.vo.school.SchoolVO; - -/** - * 学校服务接口 - */ -public interface SchoolService extends IService { - - /** - * 创建学校 - * - * @param dto 创建学校 DTO - * @param tenantId 租户 ID - * @param creatorId 创建人 ID - * @return 学校 VO - */ - SchoolVO create(CreateSchoolDTO dto, Long tenantId, Long creatorId); - - /** - * 根据租户 ID 查询学校 - * - * @param tenantId 租户 ID - * @return 学校 VO;尚未创建时返回 {@code null} - */ - SchoolVO getByTenantId(Long tenantId); - - /** - * 更新学校 - * - * @param dto 更新学校 DTO - * @param tenantId 租户 ID - * @param modifierId 修改人 ID - * @return 学校 VO - */ - SchoolVO update(UpdateSchoolDTO dto, Long tenantId, Long modifierId); - - /** - * 删除学校 - * - * @param tenantId 租户 ID - */ - void delete(Long tenantId); -} diff --git a/java-backend/src/main/java/com/lesingle/creation/service/StudentService.java b/java-backend/src/main/java/com/lesingle/creation/service/StudentService.java deleted file mode 100644 index 7d9f89a..0000000 --- a/java-backend/src/main/java/com/lesingle/creation/service/StudentService.java +++ /dev/null @@ -1,73 +0,0 @@ -package com.lesingle.creation.service; - -import com.baomidou.mybatisplus.extension.service.IService; -import com.lesingle.creation.dto.student.CreateStudentDTO; -import com.lesingle.creation.dto.student.UpdateStudentDTO; -import com.lesingle.creation.entity.Student; -import com.lesingle.creation.vo.student.StudentVO; - -import java.util.List; - -/** - * 学生服务接口 - */ -public interface StudentService extends IService { - - /** - * 创建学生 - * - * @param dto 创建学生请求 - * @param tenantId 租户 ID - * @param creatorId 创建人 ID - * @return 学生 VO - */ - StudentVO create(CreateStudentDTO dto, Long tenantId, Long creatorId); - - /** - * 查询学生列表(分页) - * - * @param tenantId 租户 ID - * @param page 页码 - * @param pageSize 每页大小 - * @param classId 班级 ID(可选) - * @return 学生 VO 列表 - */ - List list(Long tenantId, Integer page, Integer pageSize, Long classId); - - /** - * 获取学生详情 - * - * @param id 学生 ID - * @param tenantId 租户 ID - * @return 学生 VO - */ - StudentVO getDetail(Long id, Long tenantId); - - /** - * 根据用户 ID 获取学生信息 - * - * @param userId 用户 ID - * @param tenantId 租户 ID - * @return 学生 VO - */ - StudentVO getByUserId(Long userId, Long tenantId); - - /** - * 更新学生 - * - * @param id 学生 ID - * @param dto 更新学生请求 - * @param tenantId 租户 ID - * @param modifierId 修改人 ID - * @return 学生 VO - */ - StudentVO update(Long id, UpdateStudentDTO dto, Long tenantId, Long modifierId); - - /** - * 删除学生 - * - * @param id 学生 ID - * @param tenantId 租户 ID - */ - void delete(Long id, Long tenantId); -} diff --git a/java-backend/src/main/java/com/lesingle/creation/service/TeacherService.java b/java-backend/src/main/java/com/lesingle/creation/service/TeacherService.java deleted file mode 100644 index 93189fd..0000000 --- a/java-backend/src/main/java/com/lesingle/creation/service/TeacherService.java +++ /dev/null @@ -1,73 +0,0 @@ -package com.lesingle.creation.service; - -import com.baomidou.mybatisplus.extension.service.IService; -import com.lesingle.creation.dto.teacher.CreateTeacherDTO; -import com.lesingle.creation.dto.teacher.UpdateTeacherDTO; -import com.lesingle.creation.entity.Teacher; -import com.lesingle.creation.vo.teacher.TeacherVO; - -import java.util.List; - -/** - * 教师服务接口 - */ -public interface TeacherService extends IService { - - /** - * 创建教师 - * - * @param dto 创建教师请求 - * @param tenantId 租户 ID - * @param creatorId 创建人 ID - * @return 教师 VO - */ - TeacherVO create(CreateTeacherDTO dto, Long tenantId, Long creatorId); - - /** - * 查询教师列表 - * - * @param tenantId 租户 ID - * @param departmentId 部门 ID(可选) - * @param nickname 昵称(可选) - * @param username 用户名(可选) - * @return 教师 VO 列表 - */ - List list(Long tenantId, Long departmentId, String nickname, String username); - - /** - * 获取教师详情 - * - * @param id 教师 ID - * @param tenantId 租户 ID - * @return 教师 VO - */ - TeacherVO getDetail(Long id, Long tenantId); - - /** - * 根据用户 ID 获取教师信息 - * - * @param userId 用户 ID - * @param tenantId 租户 ID - * @return 教师 VO - */ - TeacherVO getByUserId(Long userId, Long tenantId); - - /** - * 更新教师 - * - * @param id 教师 ID - * @param dto 更新教师请求 - * @param tenantId 租户 ID - * @param modifierId 修改人 ID - * @return 教师 VO - */ - TeacherVO update(Long id, UpdateTeacherDTO dto, Long tenantId, Long modifierId); - - /** - * 删除教师 - * - * @param id 教师 ID - * @param tenantId 租户 ID - */ - void delete(Long id, Long tenantId); -} diff --git a/java-backend/src/main/java/com/lesingle/creation/service/UserService.java b/java-backend/src/main/java/com/lesingle/creation/service/UserService.java index a17813f..d1a01c0 100644 --- a/java-backend/src/main/java/com/lesingle/creation/service/UserService.java +++ b/java-backend/src/main/java/com/lesingle/creation/service/UserService.java @@ -79,4 +79,17 @@ public interface UserService extends IService { * @return 用户统计 VO */ UserStatsVO getStats(); + + /** + * 报名/组队场景:按租户角色编码分页查询可选用户(仅允许 teacher、student) + * + * @param tenantId 租户 ID + * @param roleCode 角色编码,如 teacher、student + * @param keyword 用户名/昵称/邮箱/手机号关键字 + * @param page 页码 + * @param pageSize 每页条数 + * @return 分页列表 + */ + Page pageCandidateUsersByRoleCode( + Long tenantId, String roleCode, String keyword, int page, int pageSize); } diff --git a/java-backend/src/main/java/com/lesingle/creation/service/impl/DepartmentServiceImpl.java b/java-backend/src/main/java/com/lesingle/creation/service/impl/DepartmentServiceImpl.java deleted file mode 100644 index 8d53040..0000000 --- a/java-backend/src/main/java/com/lesingle/creation/service/impl/DepartmentServiceImpl.java +++ /dev/null @@ -1,189 +0,0 @@ -package com.lesingle.creation.service.impl; - -import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; -import com.lesingle.creation.dto.department.CreateDepartmentDTO; -import com.lesingle.creation.dto.department.UpdateDepartmentDTO; -import com.lesingle.creation.entity.Department; -import com.lesingle.creation.common.exception.BusinessException; -import com.lesingle.creation.mapper.DepartmentMapper; -import com.lesingle.creation.service.DepartmentService; -import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; -import com.lesingle.creation.vo.department.DepartmentVO; -import lombok.RequiredArgsConstructor; -import lombok.extern.slf4j.Slf4j; -import org.springframework.stereotype.Service; -import org.springframework.transaction.annotation.Transactional; - -import java.util.ArrayList; -import java.util.Comparator; -import java.util.List; -import java.util.stream.Collectors; - -/** - * 部门服务实现类 - */ -@Slf4j -@Service -@RequiredArgsConstructor -public class DepartmentServiceImpl extends ServiceImpl implements DepartmentService { - - private final DepartmentMapper departmentMapper; - - @Override - @Transactional(rollbackFor = Exception.class) - public DepartmentVO create(CreateDepartmentDTO dto, Long tenantId, Long creatorId) { - // 检查部门编码是否已存在 - Department existing = departmentMapper.selectByCode(tenantId, dto.getCode()); - if (existing != null) { - throw new BusinessException("部门编码已存在"); - } - - Department department = new Department(); - department.setTenantId(tenantId); - department.setName(dto.getName()); - department.setCode(dto.getCode()); - department.setParentId(dto.getParentId()); - department.setDescription(dto.getDescription()); - department.setSort(dto.getSort() != null ? dto.getSort() : 0); - department.setValidState(1); - - departmentMapper.insert(department); - log.info("创建部门成功,ID={}, 名称={}", department.getId(), dto.getName()); - - return convertToVO(department); - } - - @Override - public List list(Long tenantId, Long parentId) { - LambdaQueryWrapper wrapper = new LambdaQueryWrapper() - .eq(Department::getTenantId, tenantId) - .eq(Department::getDeleted, 0) - .eq(parentId != null, Department::getParentId, parentId) - .orderByAsc(Department::getSort); - - List departments = this.list(wrapper); - return departments.stream().map(this::convertToVO).collect(Collectors.toList()); - } - - @Override - public List tree(Long tenantId) { - // 查询所有顶级部门(parentId 为 null 或 0) - List allDepartments = this.list(new LambdaQueryWrapper() - .eq(Department::getTenantId, tenantId) - .eq(Department::getDeleted, 0) - .orderByAsc(Department::getSort)); - - // 构建树形结构 - return buildDepartmentTree(allDepartments, null); - } - - @Override - public DepartmentVO getDetail(Long id, Long tenantId) { - Department department = this.getById(id); - if (department == null || !department.getTenantId().equals(tenantId)) { - throw new BusinessException("部门不存在"); - } - return convertToVO(department); - } - - @Override - @Transactional(rollbackFor = Exception.class) - public DepartmentVO update(Long id, UpdateDepartmentDTO dto, Long tenantId, Long modifierId) { - Department department = this.getById(id); - if (department == null || !department.getTenantId().equals(tenantId)) { - throw new BusinessException("部门不存在"); - } - - if (dto.getCode() != null) { - // 检查新编码是否已被其他部门使用 - Department existing = departmentMapper.selectByCode(tenantId, dto.getCode()); - if (existing != null && !existing.getId().equals(id)) { - throw new BusinessException("部门编码已存在"); - } - department.setCode(dto.getCode()); - } - if (dto.getName() != null) { - department.setName(dto.getName()); - } - if (dto.getParentId() != null) { - // 不能将自己设置为父部门 - if (dto.getParentId().equals(id)) { - throw new BusinessException("不能将自己设置为父部门"); - } - department.setParentId(dto.getParentId()); - } - if (dto.getDescription() != null) { - department.setDescription(dto.getDescription()); - } - if (dto.getSort() != null) { - department.setSort(dto.getSort()); - } - if (dto.getValidState() != null) { - department.setValidState(dto.getValidState()); - } - - this.updateById(department); - log.info("更新部门成功,ID={}", id); - - return convertToVO(department); - } - - @Override - @Transactional(rollbackFor = Exception.class) - public void delete(Long id, Long tenantId) { - Department department = this.getById(id); - if (department == null || !department.getTenantId().equals(tenantId)) { - throw new BusinessException("部门不存在"); - } - - // 检查是否有子部门 - Long childCount = this.count(new LambdaQueryWrapper() - .eq(Department::getParentId, id) - .eq(Department::getDeleted, 0)); - if (childCount > 0) { - throw new BusinessException("存在子部门,无法删除"); - } - - department.setDeleted(1); - this.updateById(department); - log.info("删除部门成功,ID={}", id); - } - - private DepartmentVO convertToVO(Department department) { - DepartmentVO vo = new DepartmentVO(); - vo.setId(department.getId()); - vo.setTenantId(department.getTenantId()); - vo.setName(department.getName()); - vo.setCode(department.getCode()); - vo.setParentId(department.getParentId()); - vo.setDescription(department.getDescription()); - vo.setSort(department.getSort()); - vo.setValidState(department.getValidState()); - vo.setCreateTime(department.getCreateTime()); - vo.setUpdateTime(department.getUpdateTime()); - return vo; - } - - private List buildDepartmentTree(List allDepartments, Long parentId) { - List tree = allDepartments.stream() - .filter(dept -> { - if (parentId == null) { - return dept.getParentId() == null || dept.getParentId() == 0; - } - return parentId.equals(dept.getParentId()); - }) - .map(this::convertToVO) - .sorted(Comparator.comparing(DepartmentVO::getSort)) - .collect(Collectors.toList()); - - // 递归构建子部门 - for (DepartmentVO node : tree) { - List children = buildDepartmentTree(allDepartments, node.getId()); - if (!children.isEmpty()) { - node.setChildren(children); - } - } - - return tree; - } -} diff --git a/java-backend/src/main/java/com/lesingle/creation/service/impl/GradeServiceImpl.java b/java-backend/src/main/java/com/lesingle/creation/service/impl/GradeServiceImpl.java deleted file mode 100644 index 39fe952..0000000 --- a/java-backend/src/main/java/com/lesingle/creation/service/impl/GradeServiceImpl.java +++ /dev/null @@ -1,152 +0,0 @@ -package com.lesingle.creation.service.impl; - -import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; -import com.baomidou.mybatisplus.extension.plugins.pagination.Page; -import com.lesingle.creation.dto.grade.CreateGradeDTO; -import com.lesingle.creation.dto.grade.UpdateGradeDTO; -import com.lesingle.creation.entity.Grade; -import com.lesingle.creation.common.exception.BusinessException; -import com.lesingle.creation.mapper.GradeMapper; -import com.lesingle.creation.service.GradeService; -import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; -import com.lesingle.creation.vo.grade.GradeVO; -import lombok.RequiredArgsConstructor; -import lombok.extern.slf4j.Slf4j; -import org.springframework.stereotype.Service; -import org.springframework.transaction.annotation.Transactional; - -/** - * 年级服务实现类 - */ -@Slf4j -@Service -@RequiredArgsConstructor -public class GradeServiceImpl extends ServiceImpl implements GradeService { - - private final GradeMapper gradeMapper; - - @Override - @Transactional(rollbackFor = Exception.class) - public GradeVO create(CreateGradeDTO dto, Long tenantId, Long creatorId) { - // 检查年级编码是否已存在 - Grade existing = gradeMapper.selectByCode(tenantId, dto.getCode()); - if (existing != null) { - throw new BusinessException("年级编码已存在"); - } - - // 检查年级级别是否已存在 - Grade existingByLevel = this.getOne(new LambdaQueryWrapper() - .eq(Grade::getTenantId, tenantId) - .eq(Grade::getLevel, dto.getLevel()) - .eq(Grade::getDeleted, 0)); - if (existingByLevel != null) { - throw new BusinessException("年级级别已存在"); - } - - Grade grade = new Grade(); - grade.setTenantId(tenantId); - grade.setName(dto.getName()); - grade.setCode(dto.getCode()); - grade.setLevel(dto.getLevel()); - grade.setDescription(dto.getDescription()); - grade.setValidState(1); - - gradeMapper.insert(grade); - log.info("创建年级成功,ID={}, 名称={}", grade.getId(), dto.getName()); - - return convertToVO(grade); - } - - @Override - public Page pageQuery(Integer pageNum, Integer pageSize, Long tenantId) { - Page page = new Page<>(pageNum, pageSize); - - LambdaQueryWrapper wrapper = new LambdaQueryWrapper() - .eq(Grade::getTenantId, tenantId) - .eq(Grade::getDeleted, 0) - .orderByAsc(Grade::getLevel); - - Page resultPage = this.page(page, wrapper); - - Page voPage = new Page<>(resultPage.getCurrent(), resultPage.getSize(), resultPage.getTotal()); - voPage.setRecords(resultPage.getRecords().stream().map(this::convertToVO).toList()); - return voPage; - } - - @Override - public GradeVO getDetail(Long id, Long tenantId) { - Grade grade = this.getById(id); - if (grade == null || !grade.getTenantId().equals(tenantId)) { - throw new BusinessException("年级不存在"); - } - return convertToVO(grade); - } - - @Override - @Transactional(rollbackFor = Exception.class) - public GradeVO update(Long id, UpdateGradeDTO dto, Long tenantId, Long modifierId) { - Grade grade = this.getById(id); - if (grade == null || !grade.getTenantId().equals(tenantId)) { - throw new BusinessException("年级不存在"); - } - - if (dto.getName() != null) { - grade.setName(dto.getName()); - } - if (dto.getCode() != null) { - // 检查新编码是否已被其他年级使用 - Grade existing = gradeMapper.selectByCode(tenantId, dto.getCode()); - if (existing != null && !existing.getId().equals(id)) { - throw new BusinessException("年级编码已存在"); - } - grade.setCode(dto.getCode()); - } - if (dto.getLevel() != null) { - // 检查新级别是否已被其他年级使用 - Grade existing = this.getOne(new LambdaQueryWrapper() - .eq(Grade::getTenantId, tenantId) - .eq(Grade::getLevel, dto.getLevel()) - .eq(Grade::getDeleted, 0) - .ne(Grade::getId, id)); - if (existing != null) { - throw new BusinessException("年级级别已存在"); - } - grade.setLevel(dto.getLevel()); - } - if (dto.getDescription() != null) { - grade.setDescription(dto.getDescription()); - } - - this.updateById(grade); - log.info("更新年级成功,ID={}", id); - - return convertToVO(grade); - } - - @Override - @Transactional(rollbackFor = Exception.class) - public void delete(Long id, Long tenantId) { - Grade grade = this.getById(id); - if (grade == null || !grade.getTenantId().equals(tenantId)) { - throw new BusinessException("年级不存在"); - } - - grade.setDeleted(1); - this.updateById(grade); - log.info("删除年级成功,ID={}", id); - } - - private GradeVO convertToVO(Grade grade) { - GradeVO vo = new GradeVO(); - vo.setId(grade.getId()); - vo.setTenantId(grade.getTenantId()); - vo.setName(grade.getName()); - vo.setCode(grade.getCode()); - vo.setLevel(grade.getLevel()); - vo.setDescription(grade.getDescription()); - vo.setValidState(grade.getValidState()); - vo.setCreateTime(grade.getCreateTime()); - vo.setUpdateTime(grade.getUpdateTime()); - return vo; - } -} diff --git a/java-backend/src/main/java/com/lesingle/creation/service/impl/HomeworkServiceImpl.java b/java-backend/src/main/java/com/lesingle/creation/service/impl/HomeworkServiceImpl.java deleted file mode 100644 index 9a2f68b..0000000 --- a/java-backend/src/main/java/com/lesingle/creation/service/impl/HomeworkServiceImpl.java +++ /dev/null @@ -1,633 +0,0 @@ -package com.lesingle.creation.service.impl; - -import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; -import com.baomidou.mybatisplus.extension.plugins.pagination.Page; -import lombok.RequiredArgsConstructor; -import lombok.extern.slf4j.Slf4j; -import org.springframework.stereotype.Service; -import org.springframework.transaction.annotation.Transactional; - -import com.lesingle.creation.common.enums.ValidStateEnum; -import com.lesingle.creation.dto.homework.*; -import com.lesingle.creation.entity.Homework; -import com.lesingle.creation.entity.HomeworkReviewDimension; -import com.lesingle.creation.entity.HomeworkReviewRule; -import com.lesingle.creation.entity.HomeworkSubmission; -import com.lesingle.creation.common.exception.BusinessException; -import com.lesingle.creation.mapper.HomeworkMapper; -import com.lesingle.creation.mapper.HomeworkReviewDimensionMapper; -import com.lesingle.creation.mapper.HomeworkReviewRuleMapper; -import com.lesingle.creation.mapper.HomeworkSubmissionMapper; -import com.lesingle.creation.service.HomeworkService; -import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; -import com.lesingle.creation.vo.homework.HomeworkDetailVO; -import com.lesingle.creation.vo.homework.HomeworkListVO; -import com.lesingle.creation.vo.homework.ReviewDimensionVO; -import com.lesingle.creation.vo.homework.ReviewRuleVO; -import com.lesingle.creation.vo.homework.SubmissionVO; -import com.lesingle.creation.vo.school.ClassTreeNodeVO; - -import java.time.LocalDateTime; -import java.util.List; -import java.util.stream.Collectors; - -/** - * 作业服务实现类 - */ -@Slf4j -@Service -public class HomeworkServiceImpl extends ServiceImpl - implements HomeworkService { - - private final HomeworkSubmissionMapper homeworkSubmissionMapper; - private final HomeworkReviewRuleMapper homeworkReviewRuleMapper; - private final HomeworkReviewDimensionMapper homeworkReviewDimensionMapper; - - public HomeworkServiceImpl(HomeworkSubmissionMapper homeworkSubmissionMapper, - HomeworkReviewRuleMapper homeworkReviewRuleMapper, - HomeworkReviewDimensionMapper homeworkReviewDimensionMapper) { - this.homeworkSubmissionMapper = homeworkSubmissionMapper; - this.homeworkReviewRuleMapper = homeworkReviewRuleMapper; - this.homeworkReviewDimensionMapper = homeworkReviewDimensionMapper; - } - - @Override - @Transactional(rollbackFor = Exception.class) - public HomeworkDetailVO create(CreateHomeworkDTO dto, Long tenantId, Long creatorId) { - // 验证时间顺序 - if (dto.getSubmitStartTime().isAfter(dto.getSubmitEndTime())) { - throw new BusinessException("提交开始时间不能晚于结束时间"); - } - - // 检查作业名称是否已存在 - Homework existing = this.getOne(new LambdaQueryWrapper() - .eq(Homework::getTenantId, tenantId) - .eq(Homework::getName, dto.getName()) - .eq(Homework::getDeleted, 0)); - if (existing != null) { - throw new BusinessException("作业名称已存在"); - } - - // 创建作业 - Homework homework = new Homework(); - homework.setTenantId(tenantId); - homework.setName(dto.getName()); - homework.setContent(dto.getContent()); - homework.setStatus("unpublished"); - homework.setSubmitStartTime(dto.getSubmitStartTime()); - homework.setSubmitEndTime(dto.getSubmitEndTime()); - homework.setAttachments(dto.getAttachments()); - homework.setPublishScope(dto.getPublishScope()); - homework.setReviewRuleId(dto.getReviewRuleId()); - homework.setValidState(ValidStateEnum.VALID.getCode()); - - this.save(homework); - log.info("创建作业成功,ID={}, 名称={}", homework.getId(), dto.getName()); - - return convertToDetailVO(homework); - } - - @Override - @Transactional(rollbackFor = Exception.class) - public HomeworkDetailVO update(Long id, UpdateHomeworkDTO dto, Long tenantId) { - Homework homework = this.getById(id); - if (homework == null || !homework.getTenantId().equals(tenantId)) { - throw new BusinessException("作业不存在"); - } - - // 已发布的作业不能修改 - if ("published".equals(homework.getStatus())) { - throw new BusinessException("已发布的作业不能修改"); - } - - homework.setName(dto.getName()); - homework.setContent(dto.getContent()); - if (dto.getSubmitStartTime() != null) { - homework.setSubmitStartTime(dto.getSubmitStartTime()); - } - if (dto.getSubmitEndTime() != null) { - homework.setSubmitEndTime(dto.getSubmitEndTime()); - } - homework.setAttachments(dto.getAttachments()); - homework.setPublishScope(dto.getPublishScope()); - if (dto.getReviewRuleId() != null) { - homework.setReviewRuleId(dto.getReviewRuleId()); - } - - this.updateById(homework); - log.info("更新作业成功,ID={}", id); - - return convertToDetailVO(homework); - } - - @Override - @Transactional(rollbackFor = Exception.class) - public HomeworkDetailVO publish(Long id, Long tenantId) { - Homework homework = this.getById(id); - if (homework == null || !homework.getTenantId().equals(tenantId)) { - throw new BusinessException("作业不存在"); - } - - homework.setStatus("published"); - homework.setPublishTime(LocalDateTime.now()); - this.updateById(homework); - log.info("发布作业成功,ID={}", id); - - return convertToDetailVO(homework); - } - - @Override - @Transactional(rollbackFor = Exception.class) - public void delete(Long id, Long tenantId) { - Homework homework = this.getById(id); - if (homework == null || !homework.getTenantId().equals(tenantId)) { - throw new BusinessException("作业不存在"); - } - - this.removeById(id); - log.info("删除作业成功,ID={}", id); - } - - @Override - public HomeworkDetailVO getDetail(Long id, Long tenantId) { - Homework homework = this.getById(id); - if (homework == null || !homework.getTenantId().equals(tenantId)) { - throw new BusinessException("作业不存在"); - } - - return convertToDetailVO(homework); - } - - @Override - public Page pageQuery(HomeworkQueryDTO queryDTO, Long tenantId) { - Page page = new Page<>(queryDTO.getPageNum(), queryDTO.getPageSize()); - - LambdaQueryWrapper wrapper = new LambdaQueryWrapper() - .eq(Homework::getTenantId, tenantId) - .eq(Homework::getDeleted, 0) - .like(queryDTO.getNameKeyword() != null, Homework::getName, queryDTO.getNameKeyword()) - .eq(queryDTO.getStatus() != null, Homework::getStatus, queryDTO.getStatus()) - .eq(queryDTO.getValidState() != null, Homework::getValidState, queryDTO.getValidState()) - .orderByDesc(Homework::getCreateTime); - - Page resultPage = this.page(page, wrapper); - - // 转换为 VO - List voList = resultPage.getRecords().stream() - .map(this::convertToListVO) - .collect(Collectors.toList()); - - Page voPage = new Page<>( - resultPage.getCurrent(), - resultPage.getSize(), - resultPage.getTotal() - ); - voPage.setRecords(voList); - return voPage; - } - - @Override - @Transactional(rollbackFor = Exception.class) - public SubmissionVO submit(SubmitHomeworkDTO dto, Long tenantId, Long studentId) { - Homework homework = this.getById(dto.getHomeworkId()); - if (homework == null || !homework.getTenantId().equals(tenantId)) { - throw new BusinessException("作业不存在"); - } - - // 检查是否已提交 - HomeworkSubmission existing = homeworkSubmissionMapper.selectOne(new LambdaQueryWrapper() - .eq(HomeworkSubmission::getHomeworkId, dto.getHomeworkId()) - .eq(HomeworkSubmission::getStudentId, studentId) - .eq(HomeworkSubmission::getDeleted, 0)); - if (existing != null) { - throw new BusinessException("您已经提交过该作业"); - } - - // 检查提交时间 - LocalDateTime now = LocalDateTime.now(); - if (now.isBefore(homework.getSubmitStartTime())) { - throw new BusinessException("还未到提交开始时间"); - } - if (now.isAfter(homework.getSubmitEndTime())) { - throw new BusinessException("已错过提交截止时间"); - } - - HomeworkSubmission submission = new HomeworkSubmission(); - submission.setTenantId(tenantId); - submission.setHomeworkId(dto.getHomeworkId()); - submission.setStudentId(studentId); - submission.setContent(dto.getContent()); - submission.setAttachments(dto.getAttachments()); - submission.setStatus("submitted"); - submission.setSubmitTime(LocalDateTime.now()); - - homeworkSubmissionMapper.insert(submission); - log.info("提交作业成功,ID={}, 学生 ID={}", submission.getId(), studentId); - - return convertToSubmissionVO(submission); - } - - @Override - @Transactional(rollbackFor = Exception.class) - public SubmissionVO review(ReviewHomeworkDTO dto, Long tenantId, Long reviewerId) { - HomeworkSubmission submission = homeworkSubmissionMapper.selectById(dto.getSubmissionId()); - if (submission == null || !submission.getTenantId().equals(tenantId)) { - throw new BusinessException("提交记录不存在"); - } - - submission.setReviewerId(reviewerId); - submission.setReviewComment(dto.getComment()); - submission.setReviewScore(dto.getScore()); - submission.setReviewTime(LocalDateTime.now()); - submission.setStatus("reviewing"); - - homeworkSubmissionMapper.updateById(submission); - log.info("批改作业成功,提交 ID={}, 分数={}", dto.getSubmissionId(), dto.getScore()); - - return convertToSubmissionVO(submission); - } - - @Override - public List getSubmissions(Long homeworkId, Long tenantId) { - List submissions = homeworkSubmissionMapper.selectList( - new LambdaQueryWrapper() - .eq(HomeworkSubmission::getHomeworkId, homeworkId) - .eq(HomeworkSubmission::getTenantId, tenantId) - .eq(HomeworkSubmission::getDeleted, 0) - .orderByDesc(HomeworkSubmission::getSubmitTime) - ); - - return submissions.stream() - .map(this::convertToSubmissionVO) - .collect(Collectors.toList()); - } - - @Override - @Transactional(rollbackFor = Exception.class) - public ReviewRuleVO createReviewRule(String ruleName, String ruleType, - java.math.BigDecimal totalScore, String description, Long tenantId) { - HomeworkReviewRule rule = new HomeworkReviewRule(); - rule.setTenantId(tenantId); - rule.setRuleName(ruleName); - rule.setRuleType(ruleType); - rule.setTotalScore(totalScore); - rule.setDescription(description); - - homeworkReviewRuleMapper.insert(rule); - log.info("创建评审规则成功,ID={}", rule.getId()); - - return convertToReviewRuleVO(rule); - } - - @Override - public List getReviewRules(Long tenantId) { - List rules = homeworkReviewRuleMapper.selectList( - new LambdaQueryWrapper() - .eq(HomeworkReviewRule::getTenantId, tenantId) - .eq(HomeworkReviewRule::getDeleted, 0) - .orderByDesc(HomeworkReviewRule::getCreateTime) - ); - - return rules.stream() - .map(this::convertToReviewRuleVO) - .collect(Collectors.toList()); - } - - // ========== 转换方法 ========== - - private HomeworkDetailVO convertToDetailVO(Homework homework) { - HomeworkDetailVO vo = new HomeworkDetailVO(); - vo.setId(homework.getId()); - vo.setName(homework.getName()); - vo.setContent(homework.getContent()); - vo.setStatus(homework.getStatus()); - vo.setPublishTime(homework.getPublishTime()); - vo.setSubmitStartTime(homework.getSubmitStartTime()); - vo.setSubmitEndTime(homework.getSubmitEndTime()); - vo.setAttachments(homework.getAttachments()); - vo.setPublishScope(homework.getPublishScope()); - vo.setReviewRuleId(homework.getReviewRuleId()); - vo.setCreateTime(homework.getCreateTime()); - - // 统计提交人数和批改人数 - Long submissionCount = homeworkSubmissionMapper.selectCount( - new LambdaQueryWrapper() - .eq(HomeworkSubmission::getHomeworkId, homework.getId()) - .eq(HomeworkSubmission::getDeleted, 0) - ); - Long reviewedCount = homeworkSubmissionMapper.selectCount( - new LambdaQueryWrapper() - .eq(HomeworkSubmission::getHomeworkId, homework.getId()) - .eq(HomeworkSubmission::getStatus, "reviewing") - .eq(HomeworkSubmission::getDeleted, 0) - ); - vo.setSubmissionCount(submissionCount.intValue()); - vo.setReviewedCount(reviewedCount.intValue()); - - return vo; - } - - private HomeworkListVO convertToListVO(Homework homework) { - HomeworkListVO vo = new HomeworkListVO(); - vo.setId(homework.getId()); - vo.setName(homework.getName()); - vo.setStatus(homework.getStatus()); - vo.setPublishTime(homework.getPublishTime()); - vo.setSubmitStartTime(homework.getSubmitStartTime()); - vo.setSubmitEndTime(homework.getSubmitEndTime()); - vo.setCreateTime(homework.getCreateTime()); - - // 统计提交人数和批改人数 - Long submissionCount = homeworkSubmissionMapper.selectCount( - new LambdaQueryWrapper() - .eq(HomeworkSubmission::getHomeworkId, homework.getId()) - .eq(HomeworkSubmission::getDeleted, 0) - ); - Long reviewedCount = homeworkSubmissionMapper.selectCount( - new LambdaQueryWrapper() - .eq(HomeworkSubmission::getHomeworkId, homework.getId()) - .eq(HomeworkSubmission::getStatus, "reviewing") - .eq(HomeworkSubmission::getDeleted, 0) - ); - vo.setSubmissionCount(submissionCount.intValue()); - vo.setReviewedCount(reviewedCount.intValue()); - - return vo; - } - - private SubmissionVO convertToSubmissionVO(HomeworkSubmission submission) { - SubmissionVO vo = new SubmissionVO(); - vo.setId(submission.getId()); - vo.setHomeworkId(submission.getHomeworkId()); - vo.setStudentId(submission.getStudentId()); - vo.setStudentName(submission.getStudentName()); - vo.setContent(submission.getContent()); - vo.setAttachments(submission.getAttachments()); - vo.setStatus(submission.getStatus()); - vo.setSubmitTime(submission.getSubmitTime()); - vo.setReviewTime(submission.getReviewTime()); - vo.setReviewerId(submission.getReviewerId()); - vo.setReviewComment(submission.getReviewComment()); - vo.setReviewScore(submission.getReviewScore()); - return vo; - } - - private ReviewRuleVO convertToReviewRuleVO(HomeworkReviewRule rule) { - ReviewRuleVO vo = new ReviewRuleVO(); - vo.setId(rule.getId()); - vo.setRuleName(rule.getRuleName()); - vo.setRuleType(rule.getRuleType()); - vo.setTotalScore(rule.getTotalScore()); - vo.setDescription(rule.getDescription()); - - // 查询关联的维度列表 - List dimensions = homeworkReviewDimensionMapper.selectByRuleId(rule.getId()); - if (dimensions != null && !dimensions.isEmpty()) { - vo.setDimensions(dimensions.stream().map(this::convertToReviewDimensionVO).collect(Collectors.toList())); - } - - return vo; - } - - private ReviewDimensionVO convertToReviewDimensionVO(HomeworkReviewDimension dimension) { - ReviewDimensionVO vo = new ReviewDimensionVO(); - vo.setId(dimension.getId()); - vo.setName(dimension.getName()); - vo.setMaxScore(dimension.getMaxScore()); - vo.setDescription(dimension.getDescription()); - vo.setSortOrder(dimension.getSortOrder()); - return vo; - } - - // ========== 新增方法实现 ========== - - @Override - public List getReviewRulesForSelect(Long tenantId) { - // 获取所有有效的评审规则,用于下拉选择 - List rules = homeworkReviewRuleMapper.selectList( - new LambdaQueryWrapper() - .eq(HomeworkReviewRule::getTenantId, tenantId) - .eq(HomeworkReviewRule::getDeleted, 0) - .orderByDesc(HomeworkReviewRule::getCreateTime) - ); - return rules.stream() - .map(this::convertToReviewRuleVO) - .collect(Collectors.toList()); - } - - @Override - @Transactional(rollbackFor = Exception.class) - public ReviewRuleVO updateReviewRule(Long id, UpdateReviewRuleDTO dto, Long tenantId) { - HomeworkReviewRule rule = homeworkReviewRuleMapper.selectById(id); - if (rule == null || !rule.getTenantId().equals(tenantId)) { - throw new BusinessException("评审规则不存在"); - } - - if (dto.getRuleName() != null) { - rule.setRuleName(dto.getRuleName()); - } - if (dto.getDescription() != null) { - rule.setDescription(dto.getDescription()); - } - // 注意:维度列表需要单独处理 - if (dto.getDimensions() != null && !dto.getDimensions().isEmpty()) { - // 删除原有维度 - homeworkReviewDimensionMapper.deleteByRuleId(id); - // 插入新维度 - int sortOrder = 0; - for (ReviewDimensionDTO dim : dto.getDimensions()) { - HomeworkReviewDimension dimension = new HomeworkReviewDimension(); - dimension.setRuleId(id); - dimension.setTenantId(tenantId); - dimension.setName(dim.getName()); - dimension.setMaxScore(dim.getMaxScore()); - dimension.setDescription(dim.getDescription()); - dimension.setSortOrder(sortOrder++); - homeworkReviewDimensionMapper.insert(dimension); - } - } - - homeworkReviewRuleMapper.updateById(rule); - log.info("更新评审规则成功,ID={}", id); - - return convertToReviewRuleVO(rule); - } - - @Override - @Transactional(rollbackFor = Exception.class) - public void deleteReviewRule(Long id, Long tenantId) { - HomeworkReviewRule rule = homeworkReviewRuleMapper.selectById(id); - if (rule == null || !rule.getTenantId().equals(tenantId)) { - throw new BusinessException("评审规则不存在"); - } - - // 删除关联的维度 - homeworkReviewDimensionMapper.deleteByRuleId(id); - // 逻辑删除规则 - rule.setDeleted(1); - homeworkReviewRuleMapper.updateById(rule); - log.info("删除评审规则成功,ID={}", id); - } - - @Override - public Page getMyHomeworks(HomeworkQueryDTO queryDTO, Long userId, Long tenantId) { - Page page = new Page<>(queryDTO.getPageNum(), queryDTO.getPageSize()); - - // TODO: 需要根据用户 ID 查询关联的班级/年级,进而查询作业 - // 这里简化处理:查询所有已发布的作业 - LambdaQueryWrapper wrapper = new LambdaQueryWrapper() - .eq(Homework::getTenantId, tenantId) - .eq(Homework::getDeleted, 0) - .eq(Homework::getStatus, "published") - .like(queryDTO.getNameKeyword() != null, Homework::getName, queryDTO.getNameKeyword()) - .orderByDesc(Homework::getCreateTime); - - Page resultPage = this.page(page, wrapper); - - List voList = resultPage.getRecords().stream() - .map(this::convertToListVO) - .collect(Collectors.toList()); - - Page voPage = new Page<>( - resultPage.getCurrent(), - resultPage.getSize(), - resultPage.getTotal() - ); - voPage.setRecords(voList); - return voPage; - } - - @Override - @Transactional(rollbackFor = Exception.class) - public HomeworkDetailVO unpublish(Long id, Long tenantId) { - Homework homework = this.getById(id); - if (homework == null || !homework.getTenantId().equals(tenantId)) { - throw new BusinessException("作业不存在"); - } - - homework.setStatus("unpublished"); - this.updateById(homework); - log.info("撤销发布作业成功,ID={}", id); - - return convertToDetailVO(homework); - } - - @Override - public Page getSubmissionsList(SubmissionQueryDTO queryDTO, Long tenantId) { - Page page = new Page<>(queryDTO.getPageNum(), queryDTO.getPageSize()); - - LambdaQueryWrapper wrapper = new LambdaQueryWrapper() - .eq(HomeworkSubmission::getTenantId, tenantId) - .eq(HomeworkSubmission::getDeleted, 0) - .eq(queryDTO.getHomeworkId() != null, HomeworkSubmission::getHomeworkId, queryDTO.getHomeworkId()) - .like(queryDTO.getStudentName() != null, HomeworkSubmission::getStudentName, queryDTO.getStudentName()) - .eq(queryDTO.getStatus() != null, HomeworkSubmission::getStatus, queryDTO.getStatus()) - .orderByDesc(HomeworkSubmission::getSubmitTime); - - Page resultPage = homeworkSubmissionMapper.selectPage(page, wrapper); - - List voList = resultPage.getRecords().stream() - .map(this::convertToSubmissionVO) - .collect(Collectors.toList()); - - Page voPage = new Page<>( - resultPage.getCurrent(), - resultPage.getSize(), - resultPage.getTotal() - ); - voPage.setRecords(voList); - return voPage; - } - - @Override - public SubmissionVO getSubmissionDetail(Long id, Long tenantId) { - HomeworkSubmission submission = homeworkSubmissionMapper.selectById(id); - if (submission == null || !submission.getTenantId().equals(tenantId)) { - throw new BusinessException("提交记录不存在"); - } - - return convertToSubmissionVO(submission); - } - - @Override - public List getClassTree(Long tenantId) { - // TODO: 需要实现班级树查询逻辑 - // 这里返回空列表,后续需要根据实际的班级/年级表实现 - log.warn("getClassTree 方法暂未实现,tenantId={}", tenantId); - return List.of(); - } - - @Override - public SubmissionVO getMySubmission(Long homeworkId, Long userId, Long tenantId) { - HomeworkSubmission submission = homeworkSubmissionMapper.selectOne( - new LambdaQueryWrapper() - .eq(HomeworkSubmission::getTenantId, tenantId) - .eq(HomeworkSubmission::getHomeworkId, homeworkId) - .eq(HomeworkSubmission::getStudentId, userId) - .eq(HomeworkSubmission::getDeleted, 0) - ); - - if (submission == null) { - return null; - } - - return convertToSubmissionVO(submission); - } - - @Override - @Transactional(rollbackFor = Exception.class) - public SubmissionVO createScore(CreateScoreDTO dto, Long tenantId, Long reviewerId) { - HomeworkSubmission submission = homeworkSubmissionMapper.selectById(dto.getSubmissionId()); - if (submission == null || !submission.getTenantId().equals(tenantId)) { - throw new BusinessException("提交记录不存在"); - } - - // TODO: 保存维度评分到 homework_dimension_scores 表 - // 这里先更新总分和评语 - if (dto.getDimensionScores() != null && !dto.getDimensionScores().isEmpty()) { - java.math.BigDecimal totalScore = dto.getDimensionScores().stream() - .map(com.lesingle.creation.dto.homework.DimensionScoreDTO::getScore) - .reduce(java.math.BigDecimal.ZERO, java.math.BigDecimal::add); - submission.setReviewScore(totalScore); - } - submission.setReviewComment(dto.getComments()); - submission.setReviewerId(reviewerId); - submission.setStatus("reviewing"); - submission.setReviewTime(LocalDateTime.now()); - - homeworkSubmissionMapper.updateById(submission); - log.info("创建评分成功,提交 ID={}, 评审人 ID={}", dto.getSubmissionId(), reviewerId); - - return convertToSubmissionVO(submission); - } - - @Override - @Transactional(rollbackFor = Exception.class) - public void markViolation(Long submissionId, String reason, Long tenantId) { - HomeworkSubmission submission = homeworkSubmissionMapper.selectById(submissionId); - if (submission == null || !submission.getTenantId().equals(tenantId)) { - throw new BusinessException("提交记录不存在"); - } - - submission.setStatus("violation"); - submission.setReviewComment("违规:" + reason); - homeworkSubmissionMapper.updateById(submission); - log.info("标记违规成功,提交 ID={}, 原因={}", submissionId, reason); - } - - @Override - @Transactional(rollbackFor = Exception.class) - public void resetScore(Long submissionId, Long tenantId) { - HomeworkSubmission submission = homeworkSubmissionMapper.selectById(submissionId); - if (submission == null || !submission.getTenantId().equals(tenantId)) { - throw new BusinessException("提交记录不存在"); - } - - submission.setReviewScore(null); - submission.setReviewComment(null); - submission.setReviewerId(null); - submission.setStatus("submitted"); - homeworkSubmissionMapper.updateById(submission); - log.info("重置评分成功,提交 ID={}", submissionId); - } -} diff --git a/java-backend/src/main/java/com/lesingle/creation/service/impl/SchoolClassServiceImpl.java b/java-backend/src/main/java/com/lesingle/creation/service/impl/SchoolClassServiceImpl.java deleted file mode 100644 index 761b226..0000000 --- a/java-backend/src/main/java/com/lesingle/creation/service/impl/SchoolClassServiceImpl.java +++ /dev/null @@ -1,173 +0,0 @@ -package com.lesingle.creation.service.impl; - -import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; -import com.baomidou.mybatisplus.extension.plugins.pagination.Page; -import com.lesingle.creation.dto.schoolclass.CreateClassDTO; -import com.lesingle.creation.dto.schoolclass.UpdateClassDTO; -import com.lesingle.creation.entity.Grade; -import com.lesingle.creation.entity.SchoolClass; -import com.lesingle.creation.common.exception.BusinessException; -import com.lesingle.creation.mapper.GradeMapper; -import com.lesingle.creation.mapper.SchoolClassMapper; -import com.lesingle.creation.service.SchoolClassService; -import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; -import com.lesingle.creation.vo.grade.GradeVO; -import com.lesingle.creation.vo.schoolclass.ClassVO; -import lombok.RequiredArgsConstructor; -import lombok.extern.slf4j.Slf4j; -import org.springframework.stereotype.Service; -import org.springframework.transaction.annotation.Transactional; - -/** - * 班级服务实现类 - */ -@Slf4j -@Service -@RequiredArgsConstructor -public class SchoolClassServiceImpl extends ServiceImpl implements SchoolClassService { - - private final SchoolClassMapper schoolClassMapper; - private final GradeMapper gradeMapper; - - @Override - @Transactional(rollbackFor = Exception.class) - public ClassVO create(CreateClassDTO dto, Long tenantId, Long creatorId) { - // 检查班级编码是否已存在 - SchoolClass existing = schoolClassMapper.selectByCode(tenantId, dto.getCode()); - if (existing != null) { - throw new BusinessException("班级编码已存在"); - } - - // 验证年级是否存在 - Grade grade = gradeMapper.selectById(dto.getGradeId()); - if (grade == null) { - throw new BusinessException("年级不存在"); - } - - SchoolClass schoolClass = new SchoolClass(); - schoolClass.setTenantId(tenantId); - schoolClass.setGradeId(dto.getGradeId()); - schoolClass.setName(dto.getName()); - schoolClass.setCode(dto.getCode()); - schoolClass.setType(dto.getType()); - schoolClass.setCapacity(dto.getCapacity()); - schoolClass.setDescription(dto.getDescription()); - schoolClass.setValidState(1); - - schoolClassMapper.insert(schoolClass); - log.info("创建班级成功,ID={}, 名称={}", schoolClass.getId(), dto.getName()); - - return convertToVO(schoolClass); - } - - @Override - public Page pageQuery(Integer pageNum, Integer pageSize, Long tenantId, Long gradeId, Integer type) { - Page page = new Page<>(pageNum, pageSize); - - LambdaQueryWrapper wrapper = new LambdaQueryWrapper() - .eq(SchoolClass::getTenantId, tenantId) - .eq(SchoolClass::getDeleted, 0) - .eq(gradeId != null, SchoolClass::getGradeId, gradeId) - .eq(type != null, SchoolClass::getType, type) - .orderByAsc(SchoolClass::getName); - - Page resultPage = this.page(page, wrapper); - - Page voPage = new Page<>(resultPage.getCurrent(), resultPage.getSize(), resultPage.getTotal()); - voPage.setRecords(resultPage.getRecords().stream().map(this::convertToVO).toList()); - return voPage; - } - - @Override - public ClassVO getDetail(Long id, Long tenantId) { - SchoolClass schoolClass = this.getById(id); - if (schoolClass == null || !schoolClass.getTenantId().equals(tenantId)) { - throw new BusinessException("班级不存在"); - } - return convertToVO(schoolClass); - } - - @Override - @Transactional(rollbackFor = Exception.class) - public ClassVO update(Long id, UpdateClassDTO dto, Long tenantId, Long modifierId) { - SchoolClass schoolClass = this.getById(id); - if (schoolClass == null || !schoolClass.getTenantId().equals(tenantId)) { - throw new BusinessException("班级不存在"); - } - - if (dto.getGradeId() != null) { - // 验证年级是否存在 - Grade grade = gradeMapper.selectById(dto.getGradeId()); - if (grade == null) { - throw new BusinessException("年级不存在"); - } - schoolClass.setGradeId(dto.getGradeId()); - } - if (dto.getName() != null) { - schoolClass.setName(dto.getName()); - } - if (dto.getCode() != null) { - // 检查新编码是否已被其他班级使用 - SchoolClass existing = schoolClassMapper.selectByCode(tenantId, dto.getCode()); - if (existing != null && !existing.getId().equals(id)) { - throw new BusinessException("班级编码已存在"); - } - schoolClass.setCode(dto.getCode()); - } - if (dto.getType() != null) { - schoolClass.setType(dto.getType()); - } - if (dto.getCapacity() != null) { - schoolClass.setCapacity(dto.getCapacity()); - } - if (dto.getDescription() != null) { - schoolClass.setDescription(dto.getDescription()); - } - - this.updateById(schoolClass); - log.info("更新班级成功,ID={}", id); - - return convertToVO(schoolClass); - } - - @Override - @Transactional(rollbackFor = Exception.class) - public void delete(Long id, Long tenantId) { - SchoolClass schoolClass = this.getById(id); - if (schoolClass == null || !schoolClass.getTenantId().equals(tenantId)) { - throw new BusinessException("班级不存在"); - } - - schoolClass.setDeleted(1); - this.updateById(schoolClass); - log.info("删除班级成功,ID={}", id); - } - - private ClassVO convertToVO(SchoolClass schoolClass) { - ClassVO vo = new ClassVO(); - vo.setId(schoolClass.getId()); - vo.setTenantId(schoolClass.getTenantId()); - vo.setGradeId(schoolClass.getGradeId()); - vo.setName(schoolClass.getName()); - vo.setCode(schoolClass.getCode()); - vo.setType(schoolClass.getType()); - vo.setCapacity(schoolClass.getCapacity()); - vo.setDescription(schoolClass.getDescription()); - vo.setValidState(schoolClass.getValidState()); - vo.setCreateTime(schoolClass.getCreateTime()); - vo.setUpdateTime(schoolClass.getUpdateTime()); - - // 关联查询年级信息 - Grade grade = gradeMapper.selectById(schoolClass.getGradeId()); - if (grade != null) { - GradeVO gradeVO = new GradeVO(); - gradeVO.setId(grade.getId()); - gradeVO.setName(grade.getName()); - gradeVO.setCode(grade.getCode()); - gradeVO.setLevel(grade.getLevel()); - vo.setGrade(gradeVO); - } - - return vo; - } -} diff --git a/java-backend/src/main/java/com/lesingle/creation/service/impl/SchoolServiceImpl.java b/java-backend/src/main/java/com/lesingle/creation/service/impl/SchoolServiceImpl.java deleted file mode 100644 index d6c670e..0000000 --- a/java-backend/src/main/java/com/lesingle/creation/service/impl/SchoolServiceImpl.java +++ /dev/null @@ -1,133 +0,0 @@ -package com.lesingle.creation.service.impl; - -import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; -import com.lesingle.creation.common.exception.BusinessException; -import com.lesingle.creation.dto.school.CreateSchoolDTO; -import com.lesingle.creation.dto.school.UpdateSchoolDTO; -import com.lesingle.creation.entity.School; -import com.lesingle.creation.mapper.SchoolMapper; -import com.lesingle.creation.service.SchoolService; -import com.lesingle.creation.vo.school.SchoolVO; -import lombok.RequiredArgsConstructor; -import lombok.extern.slf4j.Slf4j; -import org.springframework.stereotype.Service; -import org.springframework.transaction.annotation.Transactional; - -/** - * 学校服务实现类 - */ -@Slf4j -@Service -@RequiredArgsConstructor -public class SchoolServiceImpl extends ServiceImpl implements SchoolService { - - private final SchoolMapper schoolMapper; - - @Override - @Transactional(rollbackFor = Exception.class) - public SchoolVO create(CreateSchoolDTO dto, Long tenantId, Long creatorId) { - log.info("开始创建学校,租户 ID: {}", tenantId); - - // 检查租户是否已有学校信息 - School existingSchool = schoolMapper.selectByTenantId(tenantId); - if (existingSchool != null) { - throw new BusinessException("该租户已存在学校信息"); - } - - // 创建学校 - School school = new School(); - school.setTenantId(tenantId); - school.setAddress(dto.getAddress()); - school.setPhone(dto.getPhone()); - school.setPrincipal(dto.getPrincipal()); - school.setEstablished(dto.getEstablished()); - school.setDescription(dto.getDescription()); - school.setLogo(dto.getLogo()); - school.setWebsite(dto.getWebsite()); - school.setValidState(1); - school.setCreateBy(String.valueOf(creatorId)); - - schoolMapper.insert(school); - log.info("学校创建成功,学校 ID: {}", school.getId()); - - return convertToVO(school); - } - - @Override - public SchoolVO getByTenantId(Long tenantId) { - log.info("查询学校信息,租户 ID: {}", tenantId); - - School school = schoolMapper.selectByTenantId(tenantId); - if (school == null) { - log.debug("当前租户尚未创建学校,租户 ID: {}", tenantId); - return null; - } - - return convertToVO(school); - } - - @Override - @Transactional(rollbackFor = Exception.class) - public SchoolVO update(UpdateSchoolDTO dto, Long tenantId, Long modifierId) { - log.info("更新学校信息,租户 ID: {}", tenantId); - - School existingSchool = schoolMapper.selectByTenantId(tenantId); - if (existingSchool == null) { - throw new BusinessException("学校信息不存在"); - } - - // 更新学校信息 - School school = new School(); - school.setId(existingSchool.getId()); - school.setAddress(dto.getAddress()); - school.setPhone(dto.getPhone()); - school.setPrincipal(dto.getPrincipal()); - school.setEstablished(dto.getEstablished()); - school.setDescription(dto.getDescription()); - school.setLogo(dto.getLogo()); - school.setWebsite(dto.getWebsite()); - school.setUpdateBy(String.valueOf(modifierId)); - - schoolMapper.updateById(school); - log.info("学校更新成功,学校 ID: {}", school.getId()); - - return convertToVO(schoolMapper.selectById(school.getId())); - } - - @Override - @Transactional(rollbackFor = Exception.class) - public void delete(Long tenantId) { - log.info("删除学校信息,租户 ID: {}", tenantId); - - School school = schoolMapper.selectByTenantId(tenantId); - if (school == null) { - throw new BusinessException("学校信息不存在"); - } - - // 删除学校(逻辑删除) - schoolMapper.deleteById(school.getId()); - log.info("学校删除成功,学校 ID: {}", school.getId()); - } - - /** - * 转换为 VO - */ - private SchoolVO convertToVO(School school) { - SchoolVO vo = new SchoolVO(); - vo.setId(school.getId()); - vo.setTenantId(school.getTenantId()); - vo.setAddress(school.getAddress()); - vo.setPhone(school.getPhone()); - vo.setPrincipal(school.getPrincipal()); - vo.setEstablished(school.getEstablished()); - vo.setDescription(school.getDescription()); - vo.setLogo(school.getLogo()); - vo.setWebsite(school.getWebsite()); - vo.setValidState(school.getValidState()); - vo.setCreateBy(school.getCreateBy()); - vo.setCreateTime(school.getCreateTime()); - vo.setUpdateBy(school.getUpdateBy()); - vo.setUpdateTime(school.getUpdateTime()); - return vo; - } -} diff --git a/java-backend/src/main/java/com/lesingle/creation/service/impl/StudentServiceImpl.java b/java-backend/src/main/java/com/lesingle/creation/service/impl/StudentServiceImpl.java deleted file mode 100644 index 2c11dd5..0000000 --- a/java-backend/src/main/java/com/lesingle/creation/service/impl/StudentServiceImpl.java +++ /dev/null @@ -1,293 +0,0 @@ -package com.lesingle.creation.service.impl; - -import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; -import com.baomidou.mybatisplus.extension.plugins.pagination.Page; -import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; -import com.lesingle.creation.dto.student.CreateStudentDTO; -import com.lesingle.creation.dto.student.UpdateStudentDTO; -import com.lesingle.creation.entity.SchoolClass; -import com.lesingle.creation.entity.Student; -import com.lesingle.creation.entity.User; -import com.lesingle.creation.common.exception.BusinessException; -import com.lesingle.creation.mapper.StudentMapper; -import com.lesingle.creation.mapper.UserMapper; -import com.lesingle.creation.mapper.SchoolClassMapper; -import com.lesingle.creation.service.SchoolClassService; -import com.lesingle.creation.service.StudentService; -import com.lesingle.creation.vo.student.StudentVO; -import lombok.RequiredArgsConstructor; -import lombok.extern.slf4j.Slf4j; -import org.springframework.security.crypto.password.PasswordEncoder; -import org.springframework.stereotype.Service; -import org.springframework.transaction.annotation.Transactional; - -import java.util.List; -import java.util.stream.Collectors; - -/** - * 学生服务实现类 - */ -@Slf4j -@Service -@RequiredArgsConstructor -public class StudentServiceImpl extends ServiceImpl implements StudentService { - - private final StudentMapper studentMapper; - private final UserMapper userMapper; - private final SchoolClassService schoolClassService; - private final SchoolClassMapper schoolClassMapper; - private final PasswordEncoder passwordEncoder; - - @Override - @Transactional(rollbackFor = Exception.class) - public StudentVO create(CreateStudentDTO dto, Long tenantId, Long creatorId) { - // 检查用户名是否已存在 - User existingUser = userMapper.selectByUsername(dto.getUsername()); - if (existingUser != null) { - throw new BusinessException("用户名已存在"); - } - - // 检查学号是否已存在 - Student existingStudent = studentMapper.selectByStudentNo(tenantId, dto.getStudentNo()); - if (existingStudent != null) { - throw new BusinessException("学号已存在"); - } - - // 检查班级是否存在 - SchoolClass schoolClass = schoolClassMapper.selectById(dto.getClassId()); - if (schoolClass == null || !schoolClass.getTenantId().equals(tenantId)) { - throw new BusinessException("班级不存在"); - } - - // 创建用户账号 - User user = new User(); - user.setTenantId(tenantId); - user.setUsername(dto.getUsername()); - user.setPassword(passwordEncoder.encode(dto.getPassword())); - user.setNickname(dto.getNickname()); - user.setEmail(dto.getEmail()); - user.setAvatar(dto.getAvatar()); - user.setUserType("student"); // 学生用户 - user.setStatus("active"); - user.setUserSource("admin_created"); - - userMapper.insert(user); - log.info("创建用户账号成功,ID={}, 用户名={}", user.getId(), dto.getUsername()); - - // 创建学生信息 - Student student = new Student(); - student.setTenantId(tenantId); - student.setUserId(user.getId()); - student.setClassId(dto.getClassId()); - student.setStudentNo(dto.getStudentNo()); - student.setPhone(dto.getPhone()); - student.setIdCard(dto.getIdCard()); - student.setGender(dto.getGender()); - student.setBirthDate(dto.getBirthDate()); - student.setEnrollmentDate(dto.getEnrollmentDate()); - student.setParentName(dto.getParentName()); - student.setParentPhone(dto.getParentPhone()); - student.setAddress(dto.getAddress()); - student.setDescription(dto.getDescription()); - student.setValidState(1); - - studentMapper.insert(student); - log.info("创建学生成功,ID={}, 学号={}", student.getId(), dto.getStudentNo()); - - return convertToVO(student, user, schoolClass); - } - - @Override - public List list(Long tenantId, Integer page, Integer pageSize, Long classId) { - LambdaQueryWrapper wrapper = new LambdaQueryWrapper() - .eq(Student::getTenantId, tenantId) - .eq(Student::getDeleted, 0) - .eq(classId != null, Student::getClassId, classId) - .orderByDesc(Student::getCreateTime); - - Page studentPage = this.page(new Page<>(page, pageSize), wrapper); - - // 转换为 VO - return studentPage.getRecords().stream() - .map(student -> { - User user = userMapper.selectById(student.getUserId()); - SchoolClass schoolClass = schoolClassMapper.selectById(student.getClassId()); - return convertToVO(student, user, schoolClass); - }) - .collect(Collectors.toList()); - } - - @Override - public StudentVO getDetail(Long id, Long tenantId) { - Student student = this.getById(id); - if (student == null || !student.getTenantId().equals(tenantId)) { - throw new BusinessException("学生不存在"); - } - - User user = userMapper.selectById(student.getUserId()); - SchoolClass schoolClass = schoolClassMapper.selectById(student.getClassId()); - - return convertToVO(student, user, schoolClass); - } - - @Override - public StudentVO getByUserId(Long userId, Long tenantId) { - Student student = studentMapper.selectByUserId(userId); - if (student == null || !student.getTenantId().equals(tenantId)) { - throw new BusinessException("学生不存在"); - } - - User user = userMapper.selectById(student.getUserId()); - SchoolClass schoolClass = schoolClassMapper.selectById(student.getClassId()); - - return convertToVO(student, user, schoolClass); - } - - @Override - @Transactional(rollbackFor = Exception.class) - public StudentVO update(Long id, UpdateStudentDTO dto, Long tenantId, Long modifierId) { - Student student = this.getById(id); - if (student == null || !student.getTenantId().equals(tenantId)) { - throw new BusinessException("学生不存在"); - } - - // 检查学号是否已被其他学生使用 - if (dto.getStudentNo() != null) { - Student existingStudent = studentMapper.selectByStudentNo(tenantId, dto.getStudentNo()); - if (existingStudent != null && !existingStudent.getId().equals(id)) { - throw new BusinessException("学号已存在"); - } - student.setStudentNo(dto.getStudentNo()); - } - - // 更新学生信息 - if (dto.getClassId() != null) { - SchoolClass schoolClass = schoolClassMapper.selectById(dto.getClassId()); - if (schoolClass == null || !schoolClass.getTenantId().equals(tenantId)) { - throw new BusinessException("班级不存在"); - } - student.setClassId(dto.getClassId()); - } - if (dto.getPhone() != null) { - student.setPhone(dto.getPhone()); - } - if (dto.getIdCard() != null) { - student.setIdCard(dto.getIdCard()); - } - if (dto.getGender() != null) { - student.setGender(dto.getGender()); - } - if (dto.getBirthDate() != null) { - student.setBirthDate(dto.getBirthDate()); - } - if (dto.getEnrollmentDate() != null) { - student.setEnrollmentDate(dto.getEnrollmentDate()); - } - if (dto.getParentName() != null) { - student.setParentName(dto.getParentName()); - } - if (dto.getParentPhone() != null) { - student.setParentPhone(dto.getParentPhone()); - } - if (dto.getAddress() != null) { - student.setAddress(dto.getAddress()); - } - if (dto.getDescription() != null) { - student.setDescription(dto.getDescription()); - } - if (dto.getValidState() != null) { - student.setValidState(dto.getValidState()); - } - - // 更新用户信息(如果有) - if (dto.getNickname() != null || dto.getEmail() != null || dto.getAvatar() != null) { - User user = userMapper.selectById(student.getUserId()); - if (user != null) { - if (dto.getNickname() != null) { - user.setNickname(dto.getNickname()); - } - if (dto.getEmail() != null) { - user.setEmail(dto.getEmail()); - } - if (dto.getAvatar() != null) { - user.setAvatar(dto.getAvatar()); - } - userMapper.updateById(user); - } - } - - this.updateById(student); - log.info("更新学生成功,ID={}", id); - - User user = userMapper.selectById(student.getUserId()); - SchoolClass schoolClass = schoolClassMapper.selectById(student.getClassId()); - return convertToVO(student, user, schoolClass); - } - - @Override - @Transactional(rollbackFor = Exception.class) - public void delete(Long id, Long tenantId) { - Student student = this.getById(id); - if (student == null || !student.getTenantId().equals(tenantId)) { - throw new BusinessException("学生不存在"); - } - - // 逻辑删除学生 - student.setDeleted(1); - this.updateById(student); - - // 同时禁用关联的用户账号 - User user = userMapper.selectById(student.getUserId()); - if (user != null) { - user.setStatus("disabled"); // 禁用状态 - userMapper.updateById(user); - } - - log.info("删除学生成功,ID={}, 用户 ID={}", id, student.getUserId()); - } - - /** - * 转换为 VO - */ - private StudentVO convertToVO(Student student, User user, SchoolClass schoolClass) { - StudentVO vo = new StudentVO(); - vo.setId(student.getId()); - vo.setUserId(student.getUserId()); - vo.setTenantId(student.getTenantId()); - vo.setClassId(student.getClassId()); - vo.setStudentNo(student.getStudentNo()); - vo.setPhone(student.getPhone()); - vo.setIdCard(student.getIdCard()); - vo.setGender(student.getGender()); - vo.setBirthDate(student.getBirthDate()); - vo.setEnrollmentDate(student.getEnrollmentDate()); - vo.setParentName(student.getParentName()); - vo.setParentPhone(student.getParentPhone()); - vo.setAddress(student.getAddress()); - vo.setDescription(student.getDescription()); - vo.setValidState(student.getValidState()); - vo.setCreateTime(student.getCreateTime()); - vo.setUpdateTime(student.getUpdateTime()); - - // 用户信息 - if (user != null) { - StudentVO.UserInfo userInfo = new StudentVO.UserInfo(); - userInfo.setUsername(user.getUsername()); - userInfo.setNickname(user.getNickname()); - userInfo.setEmail(user.getEmail()); - userInfo.setAvatar(user.getAvatar()); - vo.setUserInfo(userInfo); - } - - // 班级信息 - if (schoolClass != null) { - StudentVO.ClassInfo classInfo = new StudentVO.ClassInfo(); - classInfo.setId(schoolClass.getId()); - classInfo.setName(schoolClass.getName()); - classInfo.setCode(schoolClass.getCode()); - vo.setClassInfo(classInfo); - } - - return vo; - } -} diff --git a/java-backend/src/main/java/com/lesingle/creation/service/impl/TeacherServiceImpl.java b/java-backend/src/main/java/com/lesingle/creation/service/impl/TeacherServiceImpl.java deleted file mode 100644 index f4e94be..0000000 --- a/java-backend/src/main/java/com/lesingle/creation/service/impl/TeacherServiceImpl.java +++ /dev/null @@ -1,307 +0,0 @@ -package com.lesingle.creation.service.impl; - -import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; -import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; -import com.lesingle.creation.dto.teacher.CreateTeacherDTO; -import com.lesingle.creation.dto.teacher.UpdateTeacherDTO; -import com.lesingle.creation.entity.Department; -import com.lesingle.creation.entity.Teacher; -import com.lesingle.creation.entity.User; -import com.lesingle.creation.common.exception.BusinessException; -import com.lesingle.creation.mapper.TeacherMapper; -import com.lesingle.creation.mapper.UserMapper; -import com.lesingle.creation.service.DepartmentService; -import com.lesingle.creation.service.TeacherService; -import com.lesingle.creation.vo.teacher.TeacherVO; -import lombok.RequiredArgsConstructor; -import lombok.extern.slf4j.Slf4j; -import org.springframework.security.crypto.password.PasswordEncoder; -import org.springframework.stereotype.Service; -import org.springframework.transaction.annotation.Transactional; - -import java.util.List; -import java.util.stream.Collectors; - -/** - * 教师服务实现类 - */ -@Slf4j -@Service -@RequiredArgsConstructor -public class TeacherServiceImpl extends ServiceImpl implements TeacherService { - - private final TeacherMapper teacherMapper; - private final UserMapper userMapper; - private final DepartmentService departmentService; - private final PasswordEncoder passwordEncoder; - - @Override - @Transactional(rollbackFor = Exception.class) - public TeacherVO create(CreateTeacherDTO dto, Long tenantId, Long creatorId) { - // 检查用户名是否已存在 - User existingUser = userMapper.selectByUsername(dto.getUsername()); - if (existingUser != null) { - throw new BusinessException("用户名已存在"); - } - - // 检查工号是否已存在 - Teacher existingTeacher = teacherMapper.selectByEmployeeNo(tenantId, dto.getEmployeeNo()); - if (existingTeacher != null) { - throw new BusinessException("工号已存在"); - } - - // 检查部门是否存在 - Department department = departmentService.getById(dto.getDepartmentId()); - if (department == null || !department.getTenantId().equals(tenantId)) { - throw new BusinessException("部门不存在"); - } - - // 创建用户账号 - User user = new User(); - user.setTenantId(tenantId); - user.setUsername(dto.getUsername()); - user.setPassword(passwordEncoder.encode(dto.getPassword())); - user.setNickname(dto.getNickname()); - user.setEmail(dto.getEmail()); - user.setAvatar(dto.getAvatar()); - user.setUserType("teacher"); // 教师用户 - user.setStatus("active"); - user.setUserSource("admin_created"); - - userMapper.insert(user); - log.info("创建用户账号成功,ID={}, 用户名={}", user.getId(), dto.getUsername()); - - // 创建教师信息 - Teacher teacher = new Teacher(); - teacher.setTenantId(tenantId); - teacher.setUserId(user.getId()); - teacher.setDepartmentId(dto.getDepartmentId()); - teacher.setEmployeeNo(dto.getEmployeeNo()); - teacher.setPhone(dto.getPhone()); - teacher.setIdCard(dto.getIdCard()); - teacher.setGender(dto.getGender()); - teacher.setBirthDate(dto.getBirthDate()); - teacher.setHireDate(dto.getHireDate()); - teacher.setSubject(dto.getSubject()); - teacher.setTitle(dto.getTitle()); - teacher.setDescription(dto.getDescription()); - teacher.setValidState(1); - - teacherMapper.insert(teacher); - log.info("创建教师成功,ID={}, 工号={}", teacher.getId(), dto.getEmployeeNo()); - - return convertToVO(teacher, user, department); - } - - @Override - public List list(Long tenantId, Long departmentId, String nickname, String username) { - LambdaQueryWrapper wrapper = new LambdaQueryWrapper() - .eq(Teacher::getTenantId, tenantId) - .eq(Teacher::getDeleted, 0) - .eq(departmentId != null, Teacher::getDepartmentId, departmentId) - .orderByDesc(Teacher::getCreateTime); - - List teachers = this.list(wrapper); - - // 过滤用户名和昵称 - if (username != null || nickname != null) { - List userIds = teachers.stream().map(Teacher::getUserId).collect(Collectors.toList()); - LambdaQueryWrapper userWrapper = new LambdaQueryWrapper() - .in(User::getId, userIds) - .eq(User::getDeleted, 0); - - if (username != null && !username.isEmpty()) { - userWrapper.like(User::getUsername, username); - } - if (nickname != null && !nickname.isEmpty()) { - userWrapper.like(User::getNickname, nickname); - } - - List users = userMapper.selectList(userWrapper); - List validUserIds = users.stream().map(User::getId).collect(Collectors.toList()); - - teachers = teachers.stream() - .filter(t -> validUserIds.contains(t.getUserId())) - .collect(Collectors.toList()); - } - - // 转换为 VO - return teachers.stream() - .map(teacher -> { - User user = userMapper.selectById(teacher.getUserId()); - Department dept = departmentService.getById(teacher.getDepartmentId()); - return convertToVO(teacher, user, dept); - }) - .collect(Collectors.toList()); - } - - @Override - public TeacherVO getDetail(Long id, Long tenantId) { - Teacher teacher = this.getById(id); - if (teacher == null || !teacher.getTenantId().equals(tenantId)) { - throw new BusinessException("教师不存在"); - } - - User user = userMapper.selectById(teacher.getUserId()); - Department department = departmentService.getById(teacher.getDepartmentId()); - - return convertToVO(teacher, user, department); - } - - @Override - public TeacherVO getByUserId(Long userId, Long tenantId) { - Teacher teacher = teacherMapper.selectByUserId(userId); - if (teacher == null || !teacher.getTenantId().equals(tenantId)) { - throw new BusinessException("教师不存在"); - } - - User user = userMapper.selectById(teacher.getUserId()); - Department department = departmentService.getById(teacher.getDepartmentId()); - - return convertToVO(teacher, user, department); - } - - @Override - @Transactional(rollbackFor = Exception.class) - public TeacherVO update(Long id, UpdateTeacherDTO dto, Long tenantId, Long modifierId) { - Teacher teacher = this.getById(id); - if (teacher == null || !teacher.getTenantId().equals(tenantId)) { - throw new BusinessException("教师不存在"); - } - - // 检查工号是否已被其他教师使用 - if (dto.getEmployeeNo() != null) { - Teacher existingTeacher = teacherMapper.selectByEmployeeNo(tenantId, dto.getEmployeeNo()); - if (existingTeacher != null && !existingTeacher.getId().equals(id)) { - throw new BusinessException("工号已存在"); - } - teacher.setEmployeeNo(dto.getEmployeeNo()); - } - - // 更新教师信息 - if (dto.getDepartmentId() != null) { - Department department = departmentService.getById(dto.getDepartmentId()); - if (department == null || !department.getTenantId().equals(tenantId)) { - throw new BusinessException("部门不存在"); - } - teacher.setDepartmentId(dto.getDepartmentId()); - } - if (dto.getPhone() != null) { - teacher.setPhone(dto.getPhone()); - } - if (dto.getIdCard() != null) { - teacher.setIdCard(dto.getIdCard()); - } - if (dto.getGender() != null) { - teacher.setGender(dto.getGender()); - } - if (dto.getBirthDate() != null) { - teacher.setBirthDate(dto.getBirthDate()); - } - if (dto.getHireDate() != null) { - teacher.setHireDate(dto.getHireDate()); - } - if (dto.getSubject() != null) { - teacher.setSubject(dto.getSubject()); - } - if (dto.getTitle() != null) { - teacher.setTitle(dto.getTitle()); - } - if (dto.getDescription() != null) { - teacher.setDescription(dto.getDescription()); - } - if (dto.getValidState() != null) { - teacher.setValidState(dto.getValidState()); - } - - // 更新用户信息(如果有) - if (dto.getNickname() != null || dto.getEmail() != null || dto.getAvatar() != null) { - User user = userMapper.selectById(teacher.getUserId()); - if (user != null) { - if (dto.getNickname() != null) { - user.setNickname(dto.getNickname()); - } - if (dto.getEmail() != null) { - user.setEmail(dto.getEmail()); - } - if (dto.getAvatar() != null) { - user.setAvatar(dto.getAvatar()); - } - userMapper.updateById(user); - } - } - - this.updateById(teacher); - log.info("更新教师成功,ID={}", id); - - User user = userMapper.selectById(teacher.getUserId()); - Department department = departmentService.getById(teacher.getDepartmentId()); - return convertToVO(teacher, user, department); - } - - @Override - @Transactional(rollbackFor = Exception.class) - public void delete(Long id, Long tenantId) { - Teacher teacher = this.getById(id); - if (teacher == null || !teacher.getTenantId().equals(tenantId)) { - throw new BusinessException("教师不存在"); - } - - // 逻辑删除教师 - teacher.setDeleted(1); - this.updateById(teacher); - - // 同时禁用关联的用户账号 - User user = userMapper.selectById(teacher.getUserId()); - if (user != null) { - user.setStatus("disabled"); // 禁用状态 - userMapper.updateById(user); - } - - log.info("删除教师成功,ID={}, 用户 ID={}", id, teacher.getUserId()); - } - - /** - * 转换为 VO - */ - private TeacherVO convertToVO(Teacher teacher, User user, Department department) { - TeacherVO vo = new TeacherVO(); - vo.setId(teacher.getId()); - vo.setUserId(teacher.getUserId()); - vo.setTenantId(teacher.getTenantId()); - vo.setDepartmentId(teacher.getDepartmentId()); - vo.setEmployeeNo(teacher.getEmployeeNo()); - vo.setPhone(teacher.getPhone()); - vo.setIdCard(teacher.getIdCard()); - vo.setGender(teacher.getGender()); - vo.setBirthDate(teacher.getBirthDate()); - vo.setHireDate(teacher.getHireDate()); - vo.setSubject(teacher.getSubject()); - vo.setTitle(teacher.getTitle()); - vo.setDescription(teacher.getDescription()); - vo.setValidState(teacher.getValidState()); - vo.setCreateTime(teacher.getCreateTime()); - vo.setUpdateTime(teacher.getUpdateTime()); - - // 用户信息 - if (user != null) { - TeacherVO.UserInfo userInfo = new TeacherVO.UserInfo(); - userInfo.setUsername(user.getUsername()); - userInfo.setNickname(user.getNickname()); - userInfo.setEmail(user.getEmail()); - userInfo.setAvatar(user.getAvatar()); - vo.setUserInfo(userInfo); - } - - // 部门信息 - if (department != null) { - TeacherVO.DepartmentInfo deptInfo = new TeacherVO.DepartmentInfo(); - deptInfo.setId(department.getId()); - deptInfo.setName(department.getName()); - deptInfo.setCode(department.getCode()); - vo.setDepartment(deptInfo); - } - - return vo; - } -} diff --git a/java-backend/src/main/java/com/lesingle/creation/service/impl/UserServiceImpl.java b/java-backend/src/main/java/com/lesingle/creation/service/impl/UserServiceImpl.java index a067db9..4773ecf 100644 --- a/java-backend/src/main/java/com/lesingle/creation/service/impl/UserServiceImpl.java +++ b/java-backend/src/main/java/com/lesingle/creation/service/impl/UserServiceImpl.java @@ -288,6 +288,49 @@ public class UserServiceImpl extends ServiceImpl implements Us return stats; } + @Override + public Page pageCandidateUsersByRoleCode( + Long tenantId, String roleCode, String keyword, int page, int pageSize) { + if (!"teacher".equals(roleCode) && !"student".equals(roleCode)) { + throw new BusinessException("不支持的角色类型,仅允许 teacher 或 student"); + } + log.info("报名场景分页查询用户,租户:{},角色:{}", tenantId, roleCode); + + Page userPage = new Page<>(page, pageSize); + LambdaQueryWrapper wrapper = new LambdaQueryWrapper<>(); + wrapper.eq(User::getTenantId, tenantId); + wrapper.eq(User::getValidState, 1); + wrapper.eq(User::getStatus, "enabled"); + wrapper.apply( + "EXISTS (SELECT 1 FROM t_auth_user_role ur " + + "INNER JOIN t_auth_role r ON ur.role_id = r.id " + + "WHERE ur.user_id = t_sys_user.id AND r.tenant_id = {0} AND r.code = {1} " + + "AND r.deleted = 0 AND r.valid_state = 1)", + tenantId, roleCode); + + if (StringUtils.hasText(keyword)) { + String kw = keyword.trim(); + wrapper.and(w -> w + .like(User::getUsername, kw) + .or() + .like(User::getNickname, kw) + .or() + .like(User::getEmail, kw) + .or() + .like(User::getPhone, kw)); + } + + wrapper.orderByDesc(User::getCreateTime); + Page resultPage = userMapper.selectPage(userPage, wrapper); + + List voList = resultPage.getRecords().stream() + .map(this::convertToListVO) + .collect(Collectors.toList()); + Page voPage = new Page<>(resultPage.getCurrent(), resultPage.getSize(), resultPage.getTotal()); + voPage.setRecords(voList); + return voPage; + } + /** * 转换为详情 VO */ diff --git a/java-backend/src/main/java/com/lesingle/creation/vo/department/DepartmentVO.java b/java-backend/src/main/java/com/lesingle/creation/vo/department/DepartmentVO.java deleted file mode 100644 index 983a69b..0000000 --- a/java-backend/src/main/java/com/lesingle/creation/vo/department/DepartmentVO.java +++ /dev/null @@ -1,50 +0,0 @@ -package com.lesingle.creation.vo.department; - -import com.fasterxml.jackson.annotation.JsonInclude; -import io.swagger.v3.oas.annotations.media.Schema; -import lombok.Data; - -import java.time.LocalDateTime; -import java.util.List; - -/** - * 部门响应 VO - */ -@Data -@Schema(description = "部门响应") -@JsonInclude(JsonInclude.Include.NON_NULL) -public class DepartmentVO { - - @Schema(description = "部门 ID") - private Long id; - - @Schema(description = "租户 ID") - private Long tenantId; - - @Schema(description = "部门名称") - private String name; - - @Schema(description = "部门编码") - private String code; - - @Schema(description = "父部门 ID") - private Long parentId; - - @Schema(description = "部门描述") - private String description; - - @Schema(description = "排序") - private Integer sort; - - @Schema(description = "有效状态") - private Integer validState; - - @Schema(description = "创建时间") - private LocalDateTime createTime; - - @Schema(description = "更新时间") - private LocalDateTime updateTime; - - @Schema(description = "子部门列表") - private List children; -} diff --git a/java-backend/src/main/java/com/lesingle/creation/vo/grade/GradeVO.java b/java-backend/src/main/java/com/lesingle/creation/vo/grade/GradeVO.java deleted file mode 100644 index 59e89fe..0000000 --- a/java-backend/src/main/java/com/lesingle/creation/vo/grade/GradeVO.java +++ /dev/null @@ -1,41 +0,0 @@ -package com.lesingle.creation.vo.grade; - -import io.swagger.v3.oas.annotations.media.Schema; -import lombok.Data; - -import java.time.LocalDateTime; - -/** - * 年级响应 VO - */ -@Data -@Schema(description = "年级响应") -public class GradeVO { - - @Schema(description = "年级 ID") - private Long id; - - @Schema(description = "租户 ID") - private Long tenantId; - - @Schema(description = "年级名称") - private String name; - - @Schema(description = "年级编码") - private String code; - - @Schema(description = "年级级别") - private Integer level; - - @Schema(description = "年级描述") - private String description; - - @Schema(description = "有效状态") - private Integer validState; - - @Schema(description = "创建时间") - private LocalDateTime createTime; - - @Schema(description = "更新时间") - private LocalDateTime updateTime; -} diff --git a/java-backend/src/main/java/com/lesingle/creation/vo/homework/HomeworkDetailVO.java b/java-backend/src/main/java/com/lesingle/creation/vo/homework/HomeworkDetailVO.java deleted file mode 100644 index 3e2e46b..0000000 --- a/java-backend/src/main/java/com/lesingle/creation/vo/homework/HomeworkDetailVO.java +++ /dev/null @@ -1,53 +0,0 @@ -package com.lesingle.creation.vo.homework; - -import io.swagger.v3.oas.annotations.media.Schema; -import lombok.Data; - -import java.time.LocalDateTime; - -/** - * 作业详情 VO - */ -@Data -@Schema(description = "作业详情响应") -public class HomeworkDetailVO { - - @Schema(description = "作业 ID") - private Long id; - - @Schema(description = "作业名称") - private String name; - - @Schema(description = "作业内容(富文本)") - private String content; - - @Schema(description = "作业状态:unpublished/published") - private String status; - - @Schema(description = "发布时间") - private LocalDateTime publishTime; - - @Schema(description = "提交开始时间") - private LocalDateTime submitStartTime; - - @Schema(description = "提交结束时间") - private LocalDateTime submitEndTime; - - @Schema(description = "附件列表(JSON 数组)") - private String attachments; - - @Schema(description = "公开范围(班级 ID 数组 JSON)") - private String publishScope; - - @Schema(description = "评审规则 ID") - private Long reviewRuleId; - - @Schema(description = "提交人数") - private Integer submissionCount; - - @Schema(description = "已批改人数") - private Integer reviewedCount; - - @Schema(description = "创建时间") - private LocalDateTime createTime; -} diff --git a/java-backend/src/main/java/com/lesingle/creation/vo/homework/HomeworkListVO.java b/java-backend/src/main/java/com/lesingle/creation/vo/homework/HomeworkListVO.java deleted file mode 100644 index c90f3ad..0000000 --- a/java-backend/src/main/java/com/lesingle/creation/vo/homework/HomeworkListVO.java +++ /dev/null @@ -1,41 +0,0 @@ -package com.lesingle.creation.vo.homework; - -import io.swagger.v3.oas.annotations.media.Schema; -import lombok.Data; - -import java.time.LocalDateTime; - -/** - * 作业列表 VO - */ -@Data -@Schema(description = "作业列表响应") -public class HomeworkListVO { - - @Schema(description = "作业 ID") - private Long id; - - @Schema(description = "作业名称") - private String name; - - @Schema(description = "作业状态:unpublished/published") - private String status; - - @Schema(description = "发布时间") - private LocalDateTime publishTime; - - @Schema(description = "提交开始时间") - private LocalDateTime submitStartTime; - - @Schema(description = "提交结束时间") - private LocalDateTime submitEndTime; - - @Schema(description = "提交人数") - private Integer submissionCount; - - @Schema(description = "已批改人数") - private Integer reviewedCount; - - @Schema(description = "创建时间") - private LocalDateTime createTime; -} diff --git a/java-backend/src/main/java/com/lesingle/creation/vo/homework/ReviewDimensionVO.java b/java-backend/src/main/java/com/lesingle/creation/vo/homework/ReviewDimensionVO.java deleted file mode 100644 index ab19548..0000000 --- a/java-backend/src/main/java/com/lesingle/creation/vo/homework/ReviewDimensionVO.java +++ /dev/null @@ -1,29 +0,0 @@ -package com.lesingle.creation.vo.homework; - -import io.swagger.v3.oas.annotations.media.Schema; -import lombok.Data; - -import java.math.BigDecimal; - -/** - * 作业评审维度 VO - */ -@Data -@Schema(description = "作业评审维度响应") -public class ReviewDimensionVO { - - @Schema(description = "维度 ID") - private Long id; - - @Schema(description = "维度名称") - private String name; - - @Schema(description = "满分") - private BigDecimal maxScore; - - @Schema(description = "维度描述") - private String description; - - @Schema(description = "排序顺序") - private Integer sortOrder; -} diff --git a/java-backend/src/main/java/com/lesingle/creation/vo/homework/ReviewRuleVO.java b/java-backend/src/main/java/com/lesingle/creation/vo/homework/ReviewRuleVO.java deleted file mode 100644 index 9fedc2e..0000000 --- a/java-backend/src/main/java/com/lesingle/creation/vo/homework/ReviewRuleVO.java +++ /dev/null @@ -1,33 +0,0 @@ -package com.lesingle.creation.vo.homework; - -import io.swagger.v3.oas.annotations.media.Schema; -import lombok.Data; - -import java.math.BigDecimal; -import java.util.List; - -/** - * 作业评审规则 VO - */ -@Data -@Schema(description = "作业评审规则响应") -public class ReviewRuleVO { - - @Schema(description = "规则 ID") - private Long id; - - @Schema(description = "规则名称") - private String ruleName; - - @Schema(description = "规则类型:default/custom") - private String ruleType; - - @Schema(description = "总分") - private BigDecimal totalScore; - - @Schema(description = "规则描述") - private String description; - - @Schema(description = "评审维度列表") - private List dimensions; -} diff --git a/java-backend/src/main/java/com/lesingle/creation/vo/homework/SubmissionVO.java b/java-backend/src/main/java/com/lesingle/creation/vo/homework/SubmissionVO.java deleted file mode 100644 index 68e464d..0000000 --- a/java-backend/src/main/java/com/lesingle/creation/vo/homework/SubmissionVO.java +++ /dev/null @@ -1,51 +0,0 @@ -package com.lesingle.creation.vo.homework; - -import io.swagger.v3.oas.annotations.media.Schema; -import lombok.Data; - -import java.math.BigDecimal; -import java.time.LocalDateTime; - -/** - * 作业提交 VO - */ -@Data -@Schema(description = "作业提交响应") -public class SubmissionVO { - - @Schema(description = "提交 ID") - private Long id; - - @Schema(description = "作业 ID") - private Long homeworkId; - - @Schema(description = "学生 ID") - private Long studentId; - - @Schema(description = "学生姓名") - private String studentName; - - @Schema(description = "提交内容") - private String content; - - @Schema(description = "提交附件列表(JSON 数组)") - private String attachments; - - @Schema(description = "提交状态:submitted/reviewing/returned") - private String status; - - @Schema(description = "提交时间") - private LocalDateTime submitTime; - - @Schema(description = "批改时间") - private LocalDateTime reviewTime; - - @Schema(description = "批改人 ID") - private Long reviewerId; - - @Schema(description = "批改评语") - private String reviewComment; - - @Schema(description = "批改分数") - private BigDecimal reviewScore; -} diff --git a/java-backend/src/main/java/com/lesingle/creation/vo/school/ClassTreeNodeVO.java b/java-backend/src/main/java/com/lesingle/creation/vo/school/ClassTreeNodeVO.java deleted file mode 100644 index 2bb2b71..0000000 --- a/java-backend/src/main/java/com/lesingle/creation/vo/school/ClassTreeNodeVO.java +++ /dev/null @@ -1,32 +0,0 @@ -package com.lesingle.creation.vo.school; - -import io.swagger.v3.oas.annotations.media.Schema; -import lombok.Data; - -import java.util.List; - -/** - * 班级树节点 VO - */ -@Data -@Schema(description = "班级树节点") -public class ClassTreeNodeVO { - - @Schema(description = "班级 ID") - private Long id; - - @Schema(description = "班级名称") - private String name; - - @Schema(description = "班级编码") - private String code; - - @Schema(description = "年级 ID") - private Long gradeId; - - @Schema(description = "年级名称") - private String gradeName; - - @Schema(description = "子节点(小班、中班、大班等)") - private List children; -} diff --git a/java-backend/src/main/java/com/lesingle/creation/vo/school/SchoolVO.java b/java-backend/src/main/java/com/lesingle/creation/vo/school/SchoolVO.java deleted file mode 100644 index 6662a1c..0000000 --- a/java-backend/src/main/java/com/lesingle/creation/vo/school/SchoolVO.java +++ /dev/null @@ -1,57 +0,0 @@ -package com.lesingle.creation.vo.school; - -import io.swagger.v3.oas.annotations.media.Schema; -import lombok.Data; - -import java.time.LocalDate; -import java.time.LocalDateTime; - -/** - * 学校信息 VO - */ -@Data -@Schema(description = "学校信息响应") -public class SchoolVO { - - @Schema(description = "学校 ID") - private Long id; - - @Schema(description = "租户 ID") - private Long tenantId; - - @Schema(description = "学校地址") - private String address; - - @Schema(description = "联系电话") - private String phone; - - @Schema(description = "校长姓名") - private String principal; - - @Schema(description = "建校时间") - private LocalDate established; - - @Schema(description = "学校描述") - private String description; - - @Schema(description = "学校 Logo URL") - private String logo; - - @Schema(description = "学校网站") - private String website; - - @Schema(description = "有效状态:1-有效,2-失效") - private Integer validState; - - @Schema(description = "创建人") - private String createBy; - - @Schema(description = "创建时间") - private LocalDateTime createTime; - - @Schema(description = "更新人") - private String updateBy; - - @Schema(description = "更新时间") - private LocalDateTime updateTime; -} diff --git a/java-backend/src/main/java/com/lesingle/creation/vo/schoolclass/ClassVO.java b/java-backend/src/main/java/com/lesingle/creation/vo/schoolclass/ClassVO.java deleted file mode 100644 index f2a0f20..0000000 --- a/java-backend/src/main/java/com/lesingle/creation/vo/schoolclass/ClassVO.java +++ /dev/null @@ -1,51 +0,0 @@ -package com.lesingle.creation.vo.schoolclass; - -import com.lesingle.creation.vo.grade.GradeVO; -import io.swagger.v3.oas.annotations.media.Schema; -import lombok.Data; - -import java.time.LocalDateTime; - -/** - * 班级响应 VO - */ -@Data -@Schema(description = "班级响应") -public class ClassVO { - - @Schema(description = "班级 ID") - private Long id; - - @Schema(description = "租户 ID") - private Long tenantId; - - @Schema(description = "年级 ID") - private Long gradeId; - - @Schema(description = "班级名称") - private String name; - - @Schema(description = "班级编码") - private String code; - - @Schema(description = "班级类型:1-行政班级,2-兴趣班") - private Integer type; - - @Schema(description = "班级容量") - private Integer capacity; - - @Schema(description = "班级描述") - private String description; - - @Schema(description = "有效状态") - private Integer validState; - - @Schema(description = "创建时间") - private LocalDateTime createTime; - - @Schema(description = "更新时间") - private LocalDateTime updateTime; - - @Schema(description = "关联年级信息") - private GradeVO grade; -} diff --git a/java-backend/src/main/java/com/lesingle/creation/vo/student/StudentVO.java b/java-backend/src/main/java/com/lesingle/creation/vo/student/StudentVO.java deleted file mode 100644 index 7747825..0000000 --- a/java-backend/src/main/java/com/lesingle/creation/vo/student/StudentVO.java +++ /dev/null @@ -1,102 +0,0 @@ -package com.lesingle.creation.vo.student; - -import io.swagger.v3.oas.annotations.media.Schema; -import lombok.Data; - -import java.time.LocalDate; -import java.time.LocalDateTime; - -/** - * 学生响应 VO - */ -@Data -@Schema(description = "学生响应") -public class StudentVO { - - @Schema(description = "学生 ID") - private Long id; - - @Schema(description = "用户 ID") - private Long userId; - - @Schema(description = "租户 ID") - private Long tenantId; - - @Schema(description = "行政班级 ID") - private Long classId; - - @Schema(description = "学号") - private String studentNo; - - @Schema(description = "联系电话") - private String phone; - - @Schema(description = "身份证号") - private String idCard; - - @Schema(description = "性别:1-男,2-女") - private Integer gender; - - @Schema(description = "出生日期") - private LocalDate birthDate; - - @Schema(description = "入学日期") - private LocalDate enrollmentDate; - - @Schema(description = "家长姓名") - private String parentName; - - @Schema(description = "家长电话") - private String parentPhone; - - @Schema(description = "家庭地址") - private String address; - - @Schema(description = "学生描述") - private String description; - - @Schema(description = "有效状态") - private Integer validState; - - @Schema(description = "创建时间") - private LocalDateTime createTime; - - @Schema(description = "更新时间") - private LocalDateTime updateTime; - - @Schema(description = "用户信息") - private UserInfo userInfo; - - @Schema(description = "班级信息") - private ClassInfo classInfo; - - /** - * 用户信息嵌套 VO - */ - @Data - @Schema(description = "用户信息") - public static class UserInfo { - @Schema(description = "用户名") - private String username; - @Schema(description = "昵称") - private String nickname; - @Schema(description = "邮箱") - private String email; - @Schema(description = "头像 URL") - private String avatar; - } - - /** - * 班级信息嵌套 VO - */ - @Data - @Schema(description = "班级信息") - public static class ClassInfo { - @Schema(description = "班级 ID") - private Long id; - @Schema(description = "班级名称") - private String name; - @Schema(description = "班级编码") - private String code; - } -} diff --git a/java-backend/src/main/java/com/lesingle/creation/vo/teacher/TeacherVO.java b/java-backend/src/main/java/com/lesingle/creation/vo/teacher/TeacherVO.java deleted file mode 100644 index 9ce7515..0000000 --- a/java-backend/src/main/java/com/lesingle/creation/vo/teacher/TeacherVO.java +++ /dev/null @@ -1,99 +0,0 @@ -package com.lesingle.creation.vo.teacher; - -import io.swagger.v3.oas.annotations.media.Schema; -import lombok.Data; - -import java.time.LocalDate; -import java.time.LocalDateTime; - -/** - * 教师响应 VO - */ -@Data -@Schema(description = "教师响应") -public class TeacherVO { - - @Schema(description = "教师 ID") - private Long id; - - @Schema(description = "用户 ID") - private Long userId; - - @Schema(description = "租户 ID") - private Long tenantId; - - @Schema(description = "部门 ID") - private Long departmentId; - - @Schema(description = "工号") - private String employeeNo; - - @Schema(description = "联系电话") - private String phone; - - @Schema(description = "身份证号") - private String idCard; - - @Schema(description = "性别:1-男,2-女") - private Integer gender; - - @Schema(description = "出生日期") - private LocalDate birthDate; - - @Schema(description = "入职日期") - private LocalDate hireDate; - - @Schema(description = "任教科目") - private String subject; - - @Schema(description = "职称") - private String title; - - @Schema(description = "教师描述") - private String description; - - @Schema(description = "有效状态") - private Integer validState; - - @Schema(description = "创建时间") - private LocalDateTime createTime; - - @Schema(description = "更新时间") - private LocalDateTime updateTime; - - @Schema(description = "用户信息") - private UserInfo userInfo; - - @Schema(description = "部门信息") - private DepartmentInfo department; - - /** - * 用户信息嵌套 VO - */ - @Data - @Schema(description = "用户信息") - public static class UserInfo { - @Schema(description = "用户名") - private String username; - @Schema(description = "昵称") - private String nickname; - @Schema(description = "邮箱") - private String email; - @Schema(description = "头像 URL") - private String avatar; - } - - /** - * 部门信息嵌套 VO - */ - @Data - @Schema(description = "部门信息") - public static class DepartmentInfo { - @Schema(description = "部门 ID") - private Long id; - @Schema(description = "部门名称") - private String name; - @Schema(description = "部门编码") - private String code; - } -} diff --git a/java-backend/src/main/resources/application-dev.yml b/java-backend/src/main/resources/application-dev.yml index 9c66914..b6c7d4a 100644 --- a/java-backend/src/main/resources/application-dev.yml +++ b/java-backend/src/main/resources/application-dev.yml @@ -4,7 +4,7 @@ spring: datasource: type: com.alibaba.druid.pool.DruidDataSource driver-class-name: com.mysql.cj.jdbc.Driver - url: jdbc:mysql://192.168.1.250:3306/lesingle-creation-test?useUnicode=true&characterEncoding=utf8&useSSL=false&serverTimezone=Asia/Shanghai&allowPublicKeyRetrieval=true + url: jdbc:mysql://192.168.1.250:3306/lesingle-creation-test-2?useUnicode=true&characterEncoding=utf8&useSSL=false&serverTimezone=Asia/Shanghai&allowPublicKeyRetrieval=true username: lesingle-creation-test password: 8ErFZiPBGbyrTHsy druid: diff --git a/java-backend/src/main/resources/db/migration/V38__remove_school_homework_ai3d.sql b/java-backend/src/main/resources/db/migration/V38__remove_school_homework_ai3d.sql new file mode 100644 index 0000000..7a3bede --- /dev/null +++ b/java-backend/src/main/resources/db/migration/V38__remove_school_homework_ai3d.sql @@ -0,0 +1,68 @@ +-- ========================================================= +-- 下线:学校组织、作业模块、AI 3D 任务表及相关 RBAC +-- 说明:不修改历史脚本;幂等尽量通过 DELETE/UPDATE 可重复执行 +-- ========================================================= + +-- 1) 角色-菜单:学校管理树(id=12)、作业中心树(id=31) +DELETE rm FROM t_auth_role_menu rm +INNER JOIN t_auth_menu m ON rm.menu_id = m.id +WHERE m.id IN (12, 31) OR m.parent_id IN (12, 31); + +-- 2) 租户-菜单:同上 +DELETE tm FROM t_auth_tenant_menu tm +INNER JOIN t_auth_menu m ON tm.menu_id = m.id +WHERE m.id IN (12, 31) OR m.parent_id IN (12, 31); + +-- 3) 角色-权限:移除待下线权限码(全租户 permission 行) +DELETE rp FROM t_auth_role_permission rp +INNER JOIN t_auth_permission p ON rp.permission_id = p.id +WHERE p.code IN ( + 'school:create', 'school:read', 'school:update', 'school:delete', + 'department:create', 'department:read', 'department:update', 'department:delete', + 'grade:create', 'grade:read', 'grade:update', 'grade:delete', + 'class:create', 'class:read', 'class:update', 'class:delete', + 'teacher:create', 'teacher:read', 'teacher:update', 'teacher:delete', + 'student:create', 'student:read', 'student:update', 'student:delete', + 'homework:create', 'homework:read', 'homework:update', 'homework:publish', 'homework:delete', + 'homework:review', + 'homework:review-rule:create', 'homework:review-rule:update', 'homework:review-rule:delete', + 'ai-3d:delete' +); + +-- 4) 权限行标记失效 +UPDATE t_auth_permission +SET valid_state = 2, deleted = 1, update_time = CURRENT_TIMESTAMP +WHERE code IN ( + 'school:create', 'school:read', 'school:update', 'school:delete', + 'department:create', 'department:read', 'department:update', 'department:delete', + 'grade:create', 'grade:read', 'grade:update', 'grade:delete', + 'class:create', 'class:read', 'class:update', 'class:delete', + 'teacher:create', 'teacher:read', 'teacher:update', 'teacher:delete', + 'student:create', 'student:read', 'student:update', 'student:delete', + 'homework:create', 'homework:read', 'homework:update', 'homework:publish', 'homework:delete', + 'homework:review', + 'homework:review-rule:create', 'homework:review-rule:update', 'homework:review-rule:delete', + 'ai-3d:delete' +); + +-- 5) 菜单标记删除 +UPDATE t_auth_menu +SET valid_state = 2, deleted = 1, update_time = CURRENT_TIMESTAMP +WHERE id IN (12, 31) OR parent_id IN (12, 31); + +-- 6) 业务表(先子后父) +DROP TABLE IF EXISTS t_biz_homework_score; +DROP TABLE IF EXISTS t_biz_homework_review_dimension; +DROP TABLE IF EXISTS t_biz_homework_submission; +DROP TABLE IF EXISTS t_biz_homework; +DROP TABLE IF EXISTS t_biz_homework_review_rule; + +DROP TABLE IF EXISTS t_biz_student_interest_class; +DROP TABLE IF EXISTS t_biz_student; +DROP TABLE IF EXISTS t_biz_teacher; +DROP TABLE IF EXISTS t_biz_class; +DROP TABLE IF EXISTS t_biz_grade; +DROP TABLE IF EXISTS t_biz_department; +DROP TABLE IF EXISTS t_biz_school; + +DROP TABLE IF EXISTS t_biz_ai3d_task; diff --git a/java-backend/src/main/resources/mapper/HomeworkReviewDimensionMapper.xml b/java-backend/src/main/resources/mapper/HomeworkReviewDimensionMapper.xml deleted file mode 100644 index 2f1b1e8..0000000 --- a/java-backend/src/main/resources/mapper/HomeworkReviewDimensionMapper.xml +++ /dev/null @@ -1,29 +0,0 @@ - - - - - - - - - - - - - - - - - - - UPDATE t_biz_homework_review_dimension SET deleted = 1 WHERE rule_id = #{ruleId} - - - - - - diff --git a/java-frontend/src/api/classes.ts b/java-frontend/src/api/classes.ts deleted file mode 100644 index b7fd8e2..0000000 --- a/java-frontend/src/api/classes.ts +++ /dev/null @@ -1,91 +0,0 @@ -import request from "@/utils/request"; -import type { PaginationParams, PaginationResponse } from "@/types/api"; - -export interface Class { - id: number; - tenantId: number; - gradeId: number; - name: string; - code: string; - type: number; // 1-行政班级,2-兴趣班 - capacity?: number; - description?: string; - validState: number; - createBy?: number; - updateBy?: number; - createTime?: string; - updateTime?: string; - grade?: { - id: number; - name: string; - code: string; - level: number; - }; - _count?: { - students: number; - studentInterestClasses: number; - }; -} - -export interface CreateClassForm { - gradeId: number; - name: string; - code: string; - type: number; - capacity?: number; - description?: string; -} - -export interface UpdateClassForm { - gradeId?: number; - name?: string; - code?: string; - type?: number; - capacity?: number; - description?: string; -} - -// 获取班级列表 -export async function getClassesList( - params: PaginationParams & { gradeId?: number; type?: number } -): Promise> { - const response = await request.get>("/api/classes", { - params, - }); - return response; -} - -// 获取单个班级详情 -export async function getClassDetail(id: number): Promise { - const response = await request.get(`/api/classes/${id}`); - return response; -} - -// 创建班级 -export async function createClass(data: CreateClassForm): Promise { - const response = await request.post("/api/classes", data); - return response; -} - -// 更新班级 -export async function updateClass( - id: number, - data: UpdateClassForm -): Promise { - const response = await request.put(`/api/classes/${id}`, data); - return response; -} - -// 删除班级 -export async function deleteClass(id: number): Promise { - return await request.delete(`/api/classes/${id}`); -} - -export const classesApi = { - getList: getClassesList, - getDetail: getClassDetail, - create: createClass, - update: updateClass, - delete: deleteClass, -}; - diff --git a/java-frontend/src/api/contests.ts b/java-frontend/src/api/contests.ts index 0abe360..307ee22 100644 --- a/java-frontend/src/api/contests.ts +++ b/java-frontend/src/api/contests.ts @@ -754,8 +754,38 @@ export const reviewRulesApi = { }, }; +/** 报名场景选人(后端 UserListVO,id 即用户 ID) */ +export interface RegistrationCandidateUser { + id: number; + tenantId?: number; + username: string; + nickname: string; + email?: string; + phone?: string; + gender?: string; + avatar?: string; + userType?: string; + status?: string; + createTime?: string; + roleNames?: string[]; +} + // 报名管理 export const registrationsApi = { + /** 按角色(teacher/student)分页查询本租户可选用户 */ + getCandidateUsers: async (params: { + roleCode: "teacher" | "student"; + keyword?: string; + page?: number; + pageSize?: number; + }): Promise> => { + const response = await request.get< + any, + PaginationResponse + >("/api/contests/registrations/candidate-users", { params }); + return response; + }, + // 报名统计 getStats: async (contestId?: number): Promise => { const params: any = {}; diff --git a/java-frontend/src/api/departments.ts b/java-frontend/src/api/departments.ts deleted file mode 100644 index ac43451..0000000 --- a/java-frontend/src/api/departments.ts +++ /dev/null @@ -1,91 +0,0 @@ -import request from "@/utils/request"; -import type { PaginationParams, PaginationResponse } from "@/types/api"; - -export interface Department { - id: number; - tenantId: number; - name: string; - code: string; - parentId?: number | null; - description?: string; - sort: number; - validState: number; - createBy?: number; - updateBy?: number; - createTime?: string; - updateTime?: string; - parent?: Department; - children?: Department[]; - _count?: { - teachers: number; - children: number; - }; -} - -export interface CreateDepartmentForm { - name: string; - code: string; - parentId?: number; - description?: string; - sort?: number; -} - -export interface UpdateDepartmentForm { - name?: string; - code?: string; - parentId?: number | null; - description?: string; - sort?: number; -} - -// 获取部门列表 -export async function getDepartmentsList( - params: PaginationParams & { parentId?: number } -): Promise> { - const response = await request.get>("/api/departments", { - params, - }); - return response; -} - -// 获取部门树 -export async function getDepartmentsTree(): Promise { - const response = await request.get("/api/departments/tree"); - return response; -} - -// 获取单个部门详情 -export async function getDepartmentDetail(id: number): Promise { - const response = await request.get(`/api/departments/${id}`); - return response; -} - -// 创建部门 -export async function createDepartment(data: CreateDepartmentForm): Promise { - const response = await request.post("/api/departments", data); - return response; -} - -// 更新部门 -export async function updateDepartment( - id: number, - data: UpdateDepartmentForm -): Promise { - const response = await request.put(`/api/departments/${id}`, data); - return response; -} - -// 删除部门 -export async function deleteDepartment(id: number): Promise { - return await request.delete(`/api/departments/${id}`); -} - -export const departmentsApi = { - getList: getDepartmentsList, - getTree: getDepartmentsTree, - getDetail: getDepartmentDetail, - create: createDepartment, - update: updateDepartment, - delete: deleteDepartment, -}; - diff --git a/java-frontend/src/api/grades.ts b/java-frontend/src/api/grades.ts deleted file mode 100644 index 8fb07bd..0000000 --- a/java-frontend/src/api/grades.ts +++ /dev/null @@ -1,78 +0,0 @@ -import request from "@/utils/request"; -import type { PaginationParams, PaginationResponse } from "@/types/api"; - -export interface Grade { - id: number; - tenantId: number; - name: string; - code: string; - level: number; - description?: string; - validState: number; - createBy?: number; - updateBy?: number; - createTime?: string; - updateTime?: string; - _count?: { - classes: number; - }; -} - -export interface CreateGradeForm { - name: string; - code: string; - level: number; - description?: string; -} - -export interface UpdateGradeForm { - name?: string; - code?: string; - level?: number; - description?: string; -} - -// 获取年级列表 -export async function getGradesList( - params: PaginationParams -): Promise> { - const response = await request.get>("/api/grades", { - params, - }); - return response; -} - -// 获取单个年级详情 -export async function getGradeDetail(id: number): Promise { - const response = await request.get(`/api/grades/${id}`); - return response; -} - -// 创建年级 -export async function createGrade(data: CreateGradeForm): Promise { - const response = await request.post("/api/grades", data); - return response; -} - -// 更新年级 -export async function updateGrade( - id: number, - data: UpdateGradeForm -): Promise { - const response = await request.put(`/api/grades/${id}`, data); - return response; -} - -// 删除年级 -export async function deleteGrade(id: number): Promise { - return await request.delete(`/api/grades/${id}`); -} - -export const gradesApi = { - getList: getGradesList, - getDetail: getGradeDetail, - create: createGrade, - update: updateGrade, - delete: deleteGrade, -}; - diff --git a/java-frontend/src/api/homework.ts b/java-frontend/src/api/homework.ts deleted file mode 100644 index 63d1a93..0000000 --- a/java-frontend/src/api/homework.ts +++ /dev/null @@ -1,415 +0,0 @@ -import request from "@/utils/request"; -import type { PaginationParams, PaginationResponse } from "@/types/api"; - -// ==================== 作业相关类型 ==================== -export interface Homework { - id: number; - tenantId: number; - name: string; - content?: string; - status: "unpublished" | "published"; - publishTime?: string; - submitStartTime: string; - submitEndTime: string; - attachments?: HomeworkAttachment[]; - publishScope?: number[]; - publishScopeNames?: string[]; - reviewRuleId?: number; - reviewRule?: HomeworkReviewRule; - createBy?: number; - updateBy?: number; - createTime?: string; - updateTime?: string; - validState?: number; - _count?: { - submissions: number; - }; - // 学生端:我的提交记录 - submission?: { - id: number; - workName: string; - submitTime: string; - totalScore?: number; - } | null; -} - -export interface HomeworkAttachment { - fileName: string; - fileUrl: string; - size?: string; -} - -export interface CreateHomeworkForm { - name: string; - content?: string; - submitStartTime: string; - submitEndTime: string; - attachments?: HomeworkAttachment[]; - publishScope?: number[]; - reviewRuleId?: number; -} - -export interface UpdateHomeworkForm extends Partial {} - -export interface QueryHomeworkParams extends PaginationParams { - name?: string; - status?: string; - submitStartTime?: string; - submitEndTime?: string; -} - -// ==================== 提交记录相关类型 ==================== -export interface HomeworkSubmission { - id: number; - tenantId: number; - homeworkId: number; - studentId: number; - workNo?: string; - workName: string; - workDescription?: string; - files?: any[]; - attachments?: any[]; - submitTime: string; - status: "pending" | "reviewed" | "rejected"; - totalScore?: number; - createBy?: number; - updateBy?: number; - createTime?: string; - updateTime?: string; - validState?: number; - homework?: { - id: number; - name: string; - reviewRuleId?: number; - reviewRule?: HomeworkReviewRule; - }; - student?: { - id: number; - username: string; - nickname: string; - student?: { - studentNo?: string; - class?: { - id: number; - name: string; - grade?: { - id: number; - name: string; - }; - }; - }; - }; - scores?: HomeworkScore[]; - _count?: { - scores: number; - }; -} - -export interface QuerySubmissionParams extends PaginationParams { - homeworkId?: number; - workNo?: string; - workName?: string; - studentAccount?: string; - studentName?: string; - status?: string; - classIds?: number[]; - gradeId?: number; -} - -// ==================== 评审规则相关类型 ==================== -export interface HomeworkReviewRule { - id: number; - tenantId: number; - name: string; - description?: string; - criteria: ReviewCriterion[]; - createBy?: number; - updateBy?: number; - createTime?: string; - updateTime?: string; - validState?: number; - homeworks?: Array<{ - id: number; - name: string; - }>; -} - -export interface ReviewCriterion { - name: string; - maxScore: number; - description?: string; -} - -export interface CreateReviewRuleForm { - name: string; - description?: string; - criteria: ReviewCriterion[]; -} - -// ==================== 评分相关类型 ==================== -export interface HomeworkScore { - id: number; - tenantId: number; - submissionId: number; - reviewerId: number; - dimensionScores: DimensionScore[]; - totalScore: number; - comments?: string; - scoreTime: string; - createBy?: number; - updateBy?: number; - createTime?: string; - updateTime?: string; - validState?: number; - reviewer?: { - id: number; - nickname: string; - }; -} - -export interface DimensionScore { - name: string; - score: number; - maxScore: number; -} - -export interface CreateScoreForm { - submissionId: number; - dimensionScores: DimensionScore[]; - comments?: string; -} - -// ==================== 班级树相关类型 ==================== -export interface ClassTreeNode { - id: string | number; - name: string; - type: "grade" | "class"; - gradeId?: number; - classId?: number; - children?: ClassTreeNode[]; -} - -// ==================== API 函数 ==================== - -// 作业管理 -export const homeworksApi = { - // 获取作业列表(教师端) - getList: async ( - params: QueryHomeworkParams - ): Promise> => { - const response = await request.get>( - "/api/homeworks/page", - { params } - ); - return response; - }, - - // 获取我的作业列表(学生端) - getMyList: async ( - params: QueryHomeworkParams - ): Promise> => { - const response = await request.get>( - "/api/homeworks/my", - { params } - ); - return response; - }, - - // 获取作业详情 - getDetail: async (id: number): Promise => { - const response = await request.get( - `/api/homeworks/${id}` - ); - return response; - }, - - // 创建作业 - create: async (data: CreateHomeworkForm): Promise => { - const response = await request.post( - "/api/homeworks", - data - ); - return response; - }, - - // 更新作业 - update: async (id: number, data: UpdateHomeworkForm): Promise => { - const response = await request.put( - `/api/homeworks/${id}`, - data - ); - return response; - }, - - // 发布作业 - publish: async (id: number, publishScope: number[]): Promise => { - const response = await request.post( - `/api/homeworks/${id}/publish`, - { publishScope } - ); - return response; - }, - - // 取消发布作业 - unpublish: async (id: number): Promise => { - const response = await request.post( - `/api/homeworks/${id}/unpublish` - ); - return response; - }, - - // 删除作业 - delete: async (id: number): Promise => { - return await request.delete(`/api/homeworks/${id}`); - }, -}; - -// 学生提交作业表单 -export interface SubmitHomeworkForm { - homeworkId: number; - workName: string; - workDescription?: string; - files?: HomeworkAttachment[]; -} - -// 提交记录管理 -export const submissionsApi = { - // 获取提交记录列表 - getList: async ( - params: QuerySubmissionParams - ): Promise> => { - const response = await request.get< - any, - PaginationResponse - >("/api/homeworks/submissions", { params }); - return response; - }, - - // 获取提交记录详情 - getDetail: async (id: number): Promise => { - const response = await request.get( - `/api/homeworks/submissions/${id}` - ); - return response; - }, - - // 获取班级树结构 - getClassTree: async (): Promise => { - const response = await request.get( - "/api/homeworks/submissions/class-tree" - ); - return response; - }, - - // 获取当前用户对某作业的提交记录 - getMySubmission: async (homeworkId: number): Promise => { - const response = await request.get( - `/api/homeworks/submissions/my/${homeworkId}` - ); - return response; - }, - - // 提交作业 - submit: async (data: SubmitHomeworkForm): Promise => { - const response = await request.post( - "/api/homeworks/submissions", - data - ); - return response; - }, -}; - -// 评审规则管理 -export const reviewRulesApi = { - // 获取评审规则列表 - getList: async (params?: { - name?: string; - page?: number; - pageSize?: number; - }): Promise<{ - list: HomeworkReviewRule[]; - total: number; - page: number; - pageSize: number; - }> => { - const response = await request.get< - any, - { - list: HomeworkReviewRule[]; - total: number; - page: number; - pageSize: number; - } - >("/api/homeworks/review-rules", { params }); - return response; - }, - - // 获取所有可用的评审规则(用于选择) - getForSelect: async (): Promise => { - const response = await request.get( - "/api/homeworks/review-rules/select" - ); - return response; - }, - - // 获取评审规则详情 - getDetail: async (id: number): Promise => { - const response = await request.get( - `/api/homeworks/review-rules/${id}` - ); - return response; - }, - - // 创建评审规则 - create: async (data: CreateReviewRuleForm): Promise => { - const response = await request.post( - "/api/homeworks/review-rules", - data - ); - return response; - }, - - // 更新评审规则 - update: async ( - id: number, - data: Partial - ): Promise => { - const response = await request.put( - `/api/homeworks/review-rules/${id}`, - data - ); - return response; - }, - - // 删除评审规则 - delete: async (id: number): Promise => { - await request.delete(`/api/homeworks/review-rules/${id}`); - }, -}; - -// 评分管理 -export const scoresApi = { - // 提交评分 - create: async (data: CreateScoreForm): Promise => { - const response = await request.post( - "/api/homeworks/scores", - data - ); - return response; - }, - - // 标记作品违规 - markViolation: async ( - submissionId: number, - reason?: string - ): Promise => { - await request.post(`/api/homeworks/scores/${submissionId}/violation`, { - reason, - }); - }, - - // 重置评分 - resetScore: async (submissionId: number): Promise => { - await request.post(`/api/homeworks/scores/${submissionId}/reset`); - }, -}; diff --git a/java-frontend/src/api/schools.ts b/java-frontend/src/api/schools.ts deleted file mode 100644 index a531e4a..0000000 --- a/java-frontend/src/api/schools.ts +++ /dev/null @@ -1,73 +0,0 @@ -import request from "@/utils/request"; - -export interface School { - id: number; - tenantId: number; - address?: string; - phone?: string; - principal?: string; - established?: string; - description?: string; - logo?: string; - website?: string; - createBy?: number; - updateBy?: number; - createTime?: string; - updateTime?: string; - tenant?: { - id: number; - name: string; - code: string; - }; -} - -export interface CreateSchoolForm { - address?: string; - phone?: string; - principal?: string; - established?: string; - description?: string; - logo?: string; - website?: string; -} - -export interface UpdateSchoolForm { - address?: string; - phone?: string; - principal?: string; - established?: string; - description?: string; - logo?: string; - website?: string; -} - -// 获取学校信息 -export async function getSchool(): Promise { - const response = await request.get("/api/schools"); - return response; -} - -// 创建学校信息 -export async function createSchool(data: CreateSchoolForm): Promise { - const response = await request.post("/api/schools", data); - return response; -} - -// 更新学校信息 -export async function updateSchool(data: UpdateSchoolForm): Promise { - const response = await request.put("/api/schools", data); - return response; -} - -// 删除学校信息 -export async function deleteSchool(): Promise { - return await request.delete("/api/schools"); -} - -export const schoolsApi = { - get: getSchool, - create: createSchool, - update: updateSchool, - delete: deleteSchool, -}; - diff --git a/java-frontend/src/api/students.ts b/java-frontend/src/api/students.ts deleted file mode 100644 index d0843f8..0000000 --- a/java-frontend/src/api/students.ts +++ /dev/null @@ -1,150 +0,0 @@ -import request from "@/utils/request"; -import type { PaginationParams, PaginationResponse } from "@/types/api"; - -export interface Student { - id: number; - userId: number; - tenantId: number; - classId: number; - studentNo?: string; - phone?: string; - idCard?: string; - gender?: number; // 1-男,2-女 - birthDate?: string; - enrollmentDate?: string; - parentName?: string; - parentPhone?: string; - address?: string; - description?: string; - validState: number; - createBy?: number; - updateBy?: number; - createTime?: string; - updateTime?: string; - user?: { - id: number; - username: string; - nickname: string; - email?: string; - avatar?: string; - validState: number; - }; - class?: { - id: number; - name: string; - code: string; - type: number; - grade?: { - id: number; - name: string; - code: string; - level: number; - }; - }; - interestClasses?: Array<{ - id: number; - class: { - id: number; - name: string; - code: string; - type: number; - grade?: { - id: number; - name: string; - code: string; - level: number; - }; - }; - }>; -} - -export interface CreateStudentForm { - username: string; - password: string; - nickname: string; - email?: string; - avatar?: string; - classId: number; - studentNo?: string; - phone?: string; - idCard?: string; - gender?: number; - birthDate?: string; - enrollmentDate?: string; - parentName?: string; - parentPhone?: string; - address?: string; - description?: string; - interestClassIds?: number[]; -} - -export interface UpdateStudentForm { - nickname?: string; - email?: string; - avatar?: string; - classId?: number; - studentNo?: string; - phone?: string; - idCard?: string; - gender?: number; - birthDate?: string; - enrollmentDate?: string; - parentName?: string; - parentPhone?: string; - address?: string; - description?: string; - validState?: number; - interestClassIds?: number[]; -} - -// 获取学生列表 -export async function getStudentsList( - params: PaginationParams & { classId?: number } -): Promise> { - const response = await request.get>("/api/students", { - params, - }); - return response; -} - -// 获取单个学生详情 -export async function getStudentDetail(id: number): Promise { - const response = await request.get(`/api/students/${id}`); - return response; -} - -// 根据用户ID获取学生信息 -export async function getStudentByUserId(userId: number): Promise { - const response = await request.get(`/api/students/user/${userId}`); - return response; -} - -// 创建学生 -export async function createStudent(data: CreateStudentForm): Promise { - const response = await request.post("/api/students", data); - return response; -} - -// 更新学生 -export async function updateStudent( - id: number, - data: UpdateStudentForm -): Promise { - const response = await request.put(`/api/students/${id}`, data); - return response; -} - -// 删除学生 -export async function deleteStudent(id: number): Promise { - return await request.delete(`/api/students/${id}`); -} - -export const studentsApi = { - getList: getStudentsList, - getDetail: getStudentDetail, - getByUserId: getStudentByUserId, - create: createStudent, - update: updateStudent, - delete: deleteStudent, -}; - diff --git a/java-frontend/src/api/teachers.ts b/java-frontend/src/api/teachers.ts deleted file mode 100644 index 649f31f..0000000 --- a/java-frontend/src/api/teachers.ts +++ /dev/null @@ -1,123 +0,0 @@ -import request from "@/utils/request"; -import type { PaginationParams, PaginationResponse } from "@/types/api"; - -export interface Teacher { - id: number; - userId: number; - tenantId: number; - departmentId: number; - employeeNo?: string; - phone?: string; - idCard?: string; - gender?: number; // 1-男,2-女 - birthDate?: string; - hireDate?: string; - subject?: string; - title?: string; - description?: string; - validState: number; - createBy?: number; - updateBy?: number; - createTime?: string; - updateTime?: string; - user?: { - id: number; - username: string; - nickname: string; - email?: string; - avatar?: string; - validState: number; - }; - department?: { - id: number; - name: string; - code: string; - }; -} - -export interface CreateTeacherForm { - username: string; - password: string; - nickname: string; - email?: string; - avatar?: string; - departmentId: number; - employeeNo?: string; - phone?: string; - idCard?: string; - gender?: number; - birthDate?: string; - hireDate?: string; - subject?: string; - title?: string; - description?: string; -} - -export interface UpdateTeacherForm { - nickname?: string; - email?: string; - avatar?: string; - departmentId?: number; - employeeNo?: string; - phone?: string; - idCard?: string; - gender?: number; - birthDate?: string; - hireDate?: string; - subject?: string; - title?: string; - description?: string; - validState?: number; -} - -// 获取教师列表 -export async function getTeachersList( - params: PaginationParams & { departmentId?: number; nickname?: string; username?: string } -): Promise> { - const response = await request.get>("/api/teachers", { - params, - }); - return response; -} - -// 获取单个教师详情 -export async function getTeacherDetail(id: number): Promise { - const response = await request.get(`/api/teachers/${id}`); - return response; -} - -// 根据用户ID获取教师信息 -export async function getTeacherByUserId(userId: number): Promise { - const response = await request.get(`/api/teachers/user/${userId}`); - return response; -} - -// 创建教师 -export async function createTeacher(data: CreateTeacherForm): Promise { - const response = await request.post("/api/teachers", data); - return response; -} - -// 更新教师 -export async function updateTeacher( - id: number, - data: UpdateTeacherForm -): Promise { - const response = await request.put(`/api/teachers/${id}`, data); - return response; -} - -// 删除教师 -export async function deleteTeacher(id: number): Promise { - return await request.delete(`/api/teachers/${id}`); -} - -export const teachersApi = { - getList: getTeachersList, - getDetail: getTeacherDetail, - getByUserId: getTeacherByUserId, - create: createTeacher, - update: updateTeacher, - delete: deleteTeacher, -}; - diff --git a/java-frontend/src/router/index.ts b/java-frontend/src/router/index.ts index 0442b10..8e8cf03 100644 --- a/java-frontend/src/router/index.ts +++ b/java-frontend/src/router/index.ts @@ -1,11 +1,10 @@ -import { createRouter, createWebHistory } from "vue-router" -import type { RouteRecordRaw } from "vue-router" -import { nextTick } from "vue" -import { useAuthStore } from "@/stores/auth" -import { convertMenusToRoutes } from "@/utils/menu" -import "@/types/router" +import { createRouter, createWebHistory } from "vue-router"; +import type { RouteRecordRaw } from "vue-router"; +import { nextTick } from "vue"; +import { useAuthStore } from "@/stores/auth"; +import { convertMenusToRoutes } from "@/utils/menu"; +import "@/types/router"; -// 基础路由(不需要动态加载的) const baseRoutes: RouteRecordRaw[] = [ { path: "/:tenantCode/login", @@ -19,7 +18,6 @@ const baseRoutes: RouteRecordRaw[] = [ component: () => import("@/views/auth/Login.vue"), meta: { requiresAuth: false }, }, - // ========== 公众端路由 ========== { path: "/p/login", name: "PublicLogin", @@ -78,7 +76,6 @@ const baseRoutes: RouteRecordRaw[] = [ component: () => import("@/views/public/mine/Favorites.vue"), meta: { title: "我的收藏" }, }, - // ========== 创作与作品库 ========== { path: "create", name: "PublicCreate", @@ -111,15 +108,12 @@ const baseRoutes: RouteRecordRaw[] = [ }, ], }, - // ========== 管理端路由 ========== { path: "/:tenantCode", name: "Main", component: () => import("@/layouts/BasicLayout.vue"), - // 不设置固定redirect,由路由守卫根据用户菜单动态跳转到第一个可见菜单 meta: {}, children: [ - // 创建活动路由(不需要在菜单中显示) { path: "contests/create", name: "ContestsCreate", @@ -130,7 +124,6 @@ const baseRoutes: RouteRecordRaw[] = [ permissions: ["contest:create"], }, }, - // 超管活动详情路由 { path: "contests/:id/overview", name: "SuperContestOverview", @@ -140,7 +133,6 @@ const baseRoutes: RouteRecordRaw[] = [ requiresAuth: true, }, }, - // 活动详情路由(不需要在菜单中显示) { path: "contests/:id", name: "ContestsDetail", @@ -151,7 +143,6 @@ const baseRoutes: RouteRecordRaw[] = [ permissions: ["contest:read", "activity:read"], }, }, - // 编辑活动路由(不需要在菜单中显示) { path: "contests/:id/edit", name: "ContestsEdit", @@ -162,7 +153,6 @@ const baseRoutes: RouteRecordRaw[] = [ permissions: ["contest:update"], }, }, - // 活动评委管理路由(不需要在菜单中显示) { path: "contests/:id/judges", name: "ContestsJudges", @@ -173,7 +163,6 @@ const baseRoutes: RouteRecordRaw[] = [ permissions: ["contest:read"], }, }, - // 个人参与报名路由 { path: "contests/:id/register/individual", name: "ContestsRegisterIndividual", @@ -183,7 +172,6 @@ const baseRoutes: RouteRecordRaw[] = [ requiresAuth: true, }, }, - // 团队参与报名路由 { path: "contests/:id/register/team", name: "ContestsRegisterTeam", @@ -193,7 +181,6 @@ const baseRoutes: RouteRecordRaw[] = [ requiresAuth: true, }, }, - // 报名管理列表路由 { path: "contests/registrations", name: "ContestsRegistrations", @@ -204,7 +191,6 @@ const baseRoutes: RouteRecordRaw[] = [ permissions: ["registration:read", "contest:read"], }, }, - // 报名记录路由 { path: "contests/registrations/:id/records", name: "RegistrationRecords", @@ -215,7 +201,6 @@ const baseRoutes: RouteRecordRaw[] = [ permissions: ["registration:read", "contest:read"], }, }, - // 评委评审详情路由(从评审任务列表进入) { path: "activities/review/:id", name: "ActivitiesReviewDetail", @@ -226,7 +211,6 @@ const baseRoutes: RouteRecordRaw[] = [ permissions: ["review:score"], }, }, - // 评审进度详情路由 { path: "contests/reviews/:id/progress", name: "ReviewProgressDetail", @@ -236,7 +220,6 @@ const baseRoutes: RouteRecordRaw[] = [ requiresAuth: true, }, }, - // 成果发布详情路由 { path: "contests/results/:id", name: "ContestsResultsDetail", @@ -246,7 +229,6 @@ const baseRoutes: RouteRecordRaw[] = [ requiresAuth: true, }, }, - // 参赛作品详情列表路由 { path: "contests/works/:id/list", name: "WorksDetail", @@ -257,29 +239,6 @@ const baseRoutes: RouteRecordRaw[] = [ permissions: ["work:read"], }, }, - // 作业提交记录路由 - { - path: "homework/submissions", - name: "HomeworkSubmissions", - component: () => import("@/views/homework/Submissions.vue"), - meta: { - title: "作业提交记录", - requiresAuth: true, - permissions: ["homework:read"], - }, - }, - // 学生作业详情路由 - { - path: "homework/detail/:id", - name: "HomeworkDetail", - component: () => import("@/views/homework/StudentDetail.vue"), - meta: { - title: "作业详情", - requiresAuth: true, - permissions: ["homework:read"], - }, - }, - // 教师我的指导路由 { path: "student-activities/guidance", name: "TeacherGuidance", @@ -290,17 +249,6 @@ const baseRoutes: RouteRecordRaw[] = [ permissions: ["activity:read"], }, }, - // 评委评审详情页 - { - path: "activities/review/:id", - name: "ReviewDetail", - component: () => import("@/views/activities/ReviewDetail.vue"), - meta: { - title: "作品评审", - requiresAuth: true, - }, - }, - // 预设评语页面 { path: "activities/preset-comments", name: "PresetComments", @@ -310,7 +258,6 @@ const baseRoutes: RouteRecordRaw[] = [ requiresAuth: true, }, }, - // ========== 数据统计 ========== { path: "analytics/overview", name: "AnalyticsOverview", @@ -331,7 +278,6 @@ const baseRoutes: RouteRecordRaw[] = [ permissions: ["contest:read"], }, }, - // 动态路由将在这里添加 ], }, { @@ -345,523 +291,461 @@ const baseRoutes: RouteRecordRaw[] = [ name: "NotFound", component: () => import("@/views/error/404.vue"), }, -] +]; const router = createRouter({ history: createWebHistory(import.meta.env.BASE_URL), routes: baseRoutes, -}) +}); -// 标记是否已经添加了动态路由 -let dynamicRoutesAdded = false -// 保存已添加的路由名称,用于清理 -let addedRouteNames: string[] = [] -// 保存上次的菜单数据,用于检测变化 -let lastMenusHash: string = "" +let dynamicRoutesAdded = false; +let addedRouteNames: string[] = []; +let lastMenusHash = ""; -/** - * 重置动态路由标记(用于登出或切换用户时) - */ export function resetDynamicRoutes(): void { - dynamicRoutesAdded = false - addedRouteNames = [] - lastMenusHash = "" + dynamicRoutesAdded = false; + addedRouteNames = []; + lastMenusHash = ""; } -/** - * 添加动态路由 - * @returns Promise,当路由添加完成并生效后 resolve - */ export async function addDynamicRoutes(): Promise { - const authStore = useAuthStore() + const authStore = useAuthStore(); + if (!authStore.menus || authStore.menus.length === 0) { - // 如果没有菜单,重置标记 if (dynamicRoutesAdded) { - resetDynamicRoutes() + resetDynamicRoutes(); } - return + return; } - // 计算菜单数据的哈希值,用于检测变化 const menusHash = JSON.stringify( - authStore.menus.map((m) => ({ id: m.id, path: m.path })) - ) + authStore.menus.map((m) => ({ id: m.id, path: m.path })), + ); - // 如果菜单数据没有变化且已经添加过路由,直接返回 if (dynamicRoutesAdded && menusHash === lastMenusHash) { - return + return; } - // 如果已经添加过路由,先移除旧路由 if (dynamicRoutesAdded && addedRouteNames.length > 0) { addedRouteNames.forEach((routeName) => { if (router.hasRoute(routeName)) { - router.removeRoute(routeName) + router.removeRoute(routeName); } - }) - addedRouteNames = [] + }); + addedRouteNames = []; } - // 将菜单转换为路由 - const dynamicRoutes = convertMenusToRoutes(authStore.menus) + const dynamicRoutes = convertMenusToRoutes(authStore.menus); if (dynamicRoutes.length === 0) { - return + return; } - // 添加动态路由到根路由下 dynamicRoutes.forEach((route) => { - router.addRoute("Main", route) + router.addRoute("Main", route); if (route.name) { - addedRouteNames.push(route.name as string) + addedRouteNames.push(route.name as string); } - }) + }); - dynamicRoutesAdded = true - lastMenusHash = menusHash + dynamicRoutesAdded = true; + lastMenusHash = menusHash; - // 等待多个 tick,确保路由已完全注册 - await nextTick() - await nextTick() - await nextTick() - - // 额外等待一小段时间,确保路由系统完全更新 - await new Promise((resolve) => setTimeout(resolve, 50)) + await nextTick(); + await nextTick(); + await nextTick(); + await new Promise((resolve) => setTimeout(resolve, 50)); } -/** - * 从路径中提取租户编码 - */ function extractTenantCodeFromPath(path: string): string | null { - const match = path.match(/^\/([^/]+)/) - return match ? match[1] : null + const match = path.match(/^\/([^/]+)/); + return match ? match[1] : null; } -/** - * 构建带租户编码的路径 - */ function buildPathWithTenantCode(tenantCode: string, path: string): string { - // 如果路径已经包含租户编码,直接返回 if (path.startsWith(`/${tenantCode}/`)) { - return path + return path; } - // 移除开头的斜杠(如果有) - const cleanPath = path.startsWith("/") ? path.slice(1) : path - // 如果路径是根路径,返回租户编码根路径(路由守卫会处理跳转到第一个菜单) + const cleanPath = path.startsWith("/") ? path.slice(1) : path; if (cleanPath === "" || cleanPath === tenantCode) { - return `/${tenantCode}` + return `/${tenantCode}`; } - return `/${tenantCode}/${cleanPath}` + return `/${tenantCode}/${cleanPath}`; } router.beforeEach(async (to, _from, next) => { - // 公众端路由不走管理端认证逻辑,直接放行 if (to.path.startsWith("/p/") || to.path === "/p") { - next() - return + next(); + return; } - const authStore = useAuthStore() + const authStore = useAuthStore(); + const tenantCodeFromUrl = extractTenantCodeFromPath(to.path); - // 从URL中提取租户编码 - const tenantCodeFromUrl = extractTenantCodeFromPath(to.path) - - // 如果 token 存在但用户信息不存在,先获取用户信息 if (authStore.token && !authStore.user) { try { - const userInfo = await authStore.fetchUserInfo() + const userInfo = await authStore.fetchUserInfo(); - // 如果获取用户信息失败或用户信息为空,跳转到登录页 if (!userInfo) { - authStore.logout() + authStore.logout(); const tenantCode = - tenantCodeFromUrl || extractTenantCodeFromPath(to.path) + tenantCodeFromUrl || extractTenantCodeFromPath(to.path); if (tenantCode) { next({ path: `/${tenantCode}/login`, query: { redirect: to.fullPath }, - }) + }); } else { - next({ name: "LoginFallback", query: { redirect: to.fullPath } }) + next({ name: "LoginFallback", query: { redirect: to.fullPath } }); } - return + return; } - // 获取用户信息后,检查租户编码一致性 - const userTenantCode = userInfo?.tenantCode + const userTenantCode = userInfo?.tenantCode; if (userTenantCode) { - // 如果URL中的租户编码与用户信息不一致,更正URL if (tenantCodeFromUrl && tenantCodeFromUrl !== userTenantCode) { const correctedPath = buildPathWithTenantCode( userTenantCode, - to.path.replace(`/${tenantCodeFromUrl}`, "") - ) - next({ path: correctedPath, query: to.query, replace: true }) - return + to.path.replace(`/${tenantCodeFromUrl}`, ""), + ); + next({ path: correctedPath, query: to.query, replace: true }); + return; } - // 如果URL中没有租户编码,添加租户编码 if (!tenantCodeFromUrl) { - const correctedPath = buildPathWithTenantCode(userTenantCode, to.path) - next({ path: correctedPath, query: to.query, replace: true }) - return + const correctedPath = buildPathWithTenantCode( + userTenantCode, + to.path, + ); + next({ path: correctedPath, query: to.query, replace: true }); + return; } } - // 获取用户信息后,添加动态路由并等待生效 - await addDynamicRoutes() - // 保存原始目标路径 - const targetPath = to.fullPath - // 路由已生效,重新解析目标路由 - const resolved = router.resolve(targetPath) - // 如果目标是租户根路径(如 /judge、/super),直接跳转到第一个菜单 - const isRootPath = to.matched.length === 1 && to.matched[0].name === "Main" + await addDynamicRoutes(); + const targetPath = to.fullPath; + const resolved = router.resolve(targetPath); + + const isRootPath = + to.matched.length === 1 && to.matched[0].name === "Main"; if (isRootPath && authStore.menus?.length) { - const findFirst = (menus: any[]): string | null => { + const findFirst = (menus: { path?: string; component?: string; children?: typeof menus }[]): string | null => { for (const m of menus) { - if (m.path && m.component) return m.path.startsWith("/") ? m.path.slice(1) : m.path - if (m.children?.length) { const c = findFirst(m.children); if (c) return c } + if (m.path && m.component) + return m.path.startsWith("/") ? m.path.slice(1) : m.path; + if (m.children?.length) { + const c = findFirst(m.children); + if (c) return c; + } } - return null - } - const first = findFirst(authStore.menus) + return null; + }; + const first = findFirst(authStore.menus); if (first) { - const tc = tenantCodeFromUrl || authStore.user?.tenantCode - if (tc) { next({ path: `/${tc}/${first}`, replace: true }); return } + const tc = tenantCodeFromUrl || userInfo.tenantCode; + if (tc) { + next({ path: `/${tc}/${first}`, replace: true }); + return; + } } } - // 如果解析后的路由不是404,说明路由存在,重新导航 if (resolved.name !== "NotFound") { - next({ path: targetPath, replace: true }) + next({ path: targetPath, replace: true }); } else { - // 如果路由不存在,尝试重定向到用户第一个菜单 if (authStore.menus && authStore.menus.length > 0) { - const findFirstMenuPath = (menus: any[]): string | null => { + const findFirstMenuPath = ( + menus: { + path?: string; + component?: string; + children?: typeof menus; + }[], + ): string | null => { for (const menu of menus) { if (menu.path && menu.component) { - // 移除开头的斜杠 return menu.path.startsWith("/") ? menu.path.slice(1) - : menu.path + : menu.path; } if (menu.children && menu.children.length > 0) { - const childPath = findFirstMenuPath(menu.children) - if (childPath) return childPath + const childPath = findFirstMenuPath(menu.children); + if (childPath) return childPath; } } - return null - } + return null; + }; - const firstMenuPath = findFirstMenuPath(authStore.menus) + const firstMenuPath = findFirstMenuPath(authStore.menus); if (firstMenuPath) { - const user = authStore.user as { tenantCode?: string } | null - const userTenantCode = user?.tenantCode + const userTenant = userInfo.tenantCode; const tenantCode = tenantCodeFromUrl || extractTenantCodeFromPath(to.path) || - userTenantCode + userTenant; if (tenantCode) { - next({ path: `/${tenantCode}/${firstMenuPath}`, replace: true }) - return + next({ path: `/${tenantCode}/${firstMenuPath}`, replace: true }); + return; } } } - // 如果路由不存在,但需要认证,跳转到登录页(而不是404) if (to.meta.requiresAuth === false) { - // 路由确实不存在,允许继续(会显示404页面) - next() + next(); } else { const tenantCode = - tenantCodeFromUrl || extractTenantCodeFromPath(to.path) + tenantCodeFromUrl || extractTenantCodeFromPath(to.path); if (tenantCode) { next({ path: `/${tenantCode}/login`, query: { redirect: to.fullPath }, - }) + }); } else { - next({ name: "LoginFallback", query: { redirect: to.fullPath } }) + next({ name: "LoginFallback", query: { redirect: to.fullPath } }); } } } - return + return; } catch (error) { - // 获取失败,清除 token 并跳转到登录页 - console.error("获取用户信息失败:", error) - authStore.logout() - const tenantCode = tenantCodeFromUrl || extractTenantCodeFromPath(to.path) + console.error("获取用户信息失败:", error); + authStore.logout(); + const tenantCode = tenantCodeFromUrl || extractTenantCodeFromPath(to.path); if (tenantCode) { next({ path: `/${tenantCode}/login`, query: { redirect: to.fullPath }, - }) + }); } else { - next({ name: "LoginFallback", query: { redirect: to.fullPath } }) + next({ name: "LoginFallback", query: { redirect: to.fullPath } }); } - return + return; } } - // 如果 token 不存在,但需要认证,跳转到登录页 if (!authStore.token && to.meta.requiresAuth !== false) { - const tenantCode = tenantCodeFromUrl || extractTenantCodeFromPath(to.path) + const tenantCode = tenantCodeFromUrl || extractTenantCodeFromPath(to.path); if (tenantCode) { next({ path: `/${tenantCode}/login`, query: { redirect: to.fullPath }, - }) + }); } else { - next({ name: "LoginFallback", query: { redirect: to.fullPath } }) + next({ name: "LoginFallback", query: { redirect: to.fullPath } }); } - return + return; } - // 如果已登录,检查租户编码一致性 if (authStore.isAuthenticated && authStore.user) { - const userTenantCode = authStore.user.tenantCode + const userTenantCode = authStore.user.tenantCode; if (userTenantCode) { - // 如果URL中的租户编码与用户信息不一致,更正URL if (tenantCodeFromUrl && tenantCodeFromUrl !== userTenantCode) { const correctedPath = buildPathWithTenantCode( userTenantCode, - to.path.replace(`/${tenantCodeFromUrl}`, "") - ) - next({ path: correctedPath, query: to.query, replace: true }) - return + to.path.replace(`/${tenantCodeFromUrl}`, ""), + ); + next({ path: correctedPath, query: to.query, replace: true }); + return; } - // 如果URL中没有租户编码,添加租户编码(排除不需要认证的特殊路由) - const skipTenantCodePaths = ["/login", "/403"] - const shouldSkipTenantCode = skipTenantCodePaths.some(p => to.path.startsWith(p)) + const skipTenantCodePaths = ["/login", "/403"]; + const shouldSkipTenantCode = skipTenantCodePaths.some((p) => + to.path.startsWith(p), + ); if (!tenantCodeFromUrl && !shouldSkipTenantCode) { - const correctedPath = buildPathWithTenantCode(userTenantCode, to.path) - next({ path: correctedPath, query: to.query, replace: true }) - return + const correctedPath = buildPathWithTenantCode(userTenantCode, to.path); + next({ path: correctedPath, query: to.query, replace: true }); + return; } } } - // 如果已登录且有菜单数据,添加或更新动态路由 if (authStore.isAuthenticated && authStore.menus.length > 0) { - // 保存添加路由前的状态 - const wasRoutesAdded = dynamicRoutesAdded + const wasRoutesAdded = dynamicRoutesAdded; + await addDynamicRoutes(); - // 添加或更新动态路由 - await addDynamicRoutes() - - // 如果这是第一次添加路由,需要重新导航 if (!wasRoutesAdded && dynamicRoutesAdded) { - // 等待路由完全生效 - await nextTick() - await nextTick() + await nextTick(); + await nextTick(); - // 保存原始目标路径 - const targetPath = to.fullPath - // 路由已生效,重新解析目标路由 - const resolved = router.resolve(targetPath) + const targetPath = to.fullPath; + const resolved = router.resolve(targetPath); + const isMainRoute = to.name === "Main"; - // 如果访问的是主路由,重定向到第一个菜单 - const isMainRoute = to.name === "Main" - - console.log('Route guard debug:', { - targetPath, - resolvedName: resolved.name, - resolvedPath: resolved.path, - isMainRoute, - toName: to.name, - toPath: to.path, - }) - - // 如果解析后的路由不是404,说明路由存在,重新导航 if (resolved.name !== "NotFound" && !isMainRoute) { - next({ path: targetPath, replace: true }) - return + next({ path: targetPath, replace: true }); + return; } - // 如果路由不存在或是主路由,尝试重定向到用户第一个菜单 if (authStore.menus && authStore.menus.length > 0) { - const findFirstMenuPath = (menus: any[]): string | null => { + const findFirstMenuPath = ( + menus: { + path?: string; + component?: string; + children?: typeof menus; + }[], + ): string | null => { for (const menu of menus) { if (menu.path && menu.component) { - // 移除开头的斜杠 - return menu.path.startsWith("/") ? menu.path.slice(1) : menu.path + return menu.path.startsWith("/") + ? menu.path.slice(1) + : menu.path; } if (menu.children && menu.children.length > 0) { - const childPath = findFirstMenuPath(menu.children) - if (childPath) return childPath + const childPath = findFirstMenuPath(menu.children); + if (childPath) return childPath; } } - return null - } + return null; + }; - const firstMenuPath = findFirstMenuPath(authStore.menus) + const firstMenuPath = findFirstMenuPath(authStore.menus); if (firstMenuPath) { - const userTenantCode = authStore.user - ? (authStore.user.tenantCode as string | undefined) - : undefined + const userTenantCode = authStore.user?.tenantCode; const tenantCode = tenantCodeFromUrl || extractTenantCodeFromPath(to.path) || - userTenantCode + userTenantCode; if (tenantCode) { - // 再次等待,确保路由完全注册 - await nextTick() - next({ path: `/${tenantCode}/${firstMenuPath}`, replace: true }) - return + await nextTick(); + next({ path: `/${tenantCode}/${firstMenuPath}`, replace: true }); + return; } } } - // 如果没有任何菜单,跳转到404页面 const tenantCodeFor404 = tenantCodeFromUrl || extractTenantCodeFromPath(to.path) || - (authStore.user - ? (authStore.user.tenantCode as string | undefined) - : undefined) + authStore.user?.tenantCode; if (tenantCodeFor404) { - next({ path: `/${tenantCodeFor404}/404`, replace: true }) + next({ path: `/${tenantCodeFor404}/404`, replace: true }); } else { - next({ name: "NotFound" }) + next({ name: "NotFound" }); } - return + return; } } - // 如果已登录且有菜单,但路由已添加,检查当前路由是否存在 if ( authStore.isAuthenticated && authStore.menus.length > 0 && dynamicRoutesAdded ) { - const resolved = router.resolve(to.fullPath) - // 如果访问的是 Main 路由(无具体子路径)或路由不存在,重定向到用户第一个菜单 - const isMainRouteWithoutChild = to.name === "Main" || to.matched.length === 1 && to.matched[0].name === "Main" + const resolved = router.resolve(to.fullPath); + const isMainRouteWithoutChild = + to.name === "Main" || + (to.matched.length === 1 && to.matched[0].name === "Main"); if ( (resolved.name === "NotFound" || isMainRouteWithoutChild) && to.name !== "Login" && to.name !== "LoginFallback" ) { - const findFirstMenuPath = (menus: any[]): string | null => { + const findFirstMenuPath = ( + menus: { + path?: string; + component?: string; + children?: typeof menus; + }[], + ): string | null => { for (const menu of menus) { if (menu.path && menu.component) { - return menu.path.startsWith("/") ? menu.path.slice(1) : menu.path + return menu.path.startsWith("/") ? menu.path.slice(1) : menu.path; } if (menu.children && menu.children.length > 0) { - const childPath = findFirstMenuPath(menu.children) - if (childPath) return childPath + const childPath = findFirstMenuPath(menu.children); + if (childPath) return childPath; } } - return null - } + return null; + }; - const firstMenuPath = findFirstMenuPath(authStore.menus) + const firstMenuPath = findFirstMenuPath(authStore.menus); if (firstMenuPath) { - const userTenantCode = authStore.user - ? (authStore.user.tenantCode as string | undefined) - : undefined + const userTenantCode = authStore.user?.tenantCode; const tenantCode = tenantCodeFromUrl || extractTenantCodeFromPath(to.path) || - userTenantCode + userTenantCode; if (tenantCode) { - next({ path: `/${tenantCode}/${firstMenuPath}`, replace: true }) - return + next({ path: `/${tenantCode}/${firstMenuPath}`, replace: true }); + return; } } - // 如果没有任何菜单,跳转到404页面 const tenantCodeFor404 = tenantCodeFromUrl || extractTenantCodeFromPath(to.path) || - (authStore.user - ? (authStore.user.tenantCode as string | undefined) - : undefined) + authStore.user?.tenantCode; if (tenantCodeFor404) { - next({ path: `/${tenantCodeFor404}/404`, replace: true }) - return + next({ path: `/${tenantCodeFor404}/404`, replace: true }); + return; } } } - // 检查是否需要认证 if (to.meta.requiresAuth !== false) { - // 如果没有 token,跳转到登录页 if (!authStore.token) { - const tenantCode = tenantCodeFromUrl || extractTenantCodeFromPath(to.path) + const tenantCode = tenantCodeFromUrl || extractTenantCodeFromPath(to.path); if (tenantCode) { next({ path: `/${tenantCode}/login`, query: { redirect: to.fullPath }, - }) + }); } else { - next({ name: "LoginFallback", query: { redirect: to.fullPath } }) + next({ name: "LoginFallback", query: { redirect: to.fullPath } }); } - return + return; } - // 如果有 token 但没有用户信息,跳转到登录页 if (!authStore.user) { - const tenantCode = tenantCodeFromUrl || extractTenantCodeFromPath(to.path) + const tenantCode = tenantCodeFromUrl || extractTenantCodeFromPath(to.path); if (tenantCode) { next({ path: `/${tenantCode}/login`, query: { redirect: to.fullPath }, - }) + }); } else { - next({ name: "LoginFallback", query: { redirect: to.fullPath } }) + next({ name: "LoginFallback", query: { redirect: to.fullPath } }); } - return + return; } } - // 如果已登录,访问登录页则重定向到首页 if ( (to.name === "Login" || to.name === "LoginFallback") && authStore.isAuthenticated ) { - // 确保动态路由已添加并等待生效 if (!dynamicRoutesAdded && authStore.menus.length > 0) { - await addDynamicRoutes() + await addDynamicRoutes(); } - // 重定向到带租户编码的根路径(路由守卫会处理跳转到第一个菜单) - const userTenantCode = authStore.user?.tenantCode || "default" - next({ path: `/${userTenantCode}` }) - return + const userTenantCode = authStore.user?.tenantCode || "default"; + next({ path: `/${userTenantCode}` }); + return; } - // 处理登录页面的租户编码 if (to.name === "LoginFallback" && !tenantCodeFromUrl) { - // 如果访问的是 /login,但没有租户编码,检查是否有用户信息中的租户编码 if (authStore.isAuthenticated && authStore.user?.tenantCode) { - const userTenantCode = authStore.user.tenantCode - next({ path: `/${userTenantCode}/login`, replace: true }) - return + const userTenantCode = authStore.user.tenantCode; + next({ path: `/${userTenantCode}/login`, replace: true }); + return; } - // 如果没有租户编码,允许访问(会显示租户输入框) - next() - return + next(); + return; } - // 检查角色权限 - const requiredRoles = to.meta.roles + const requiredRoles = to.meta.roles as string[] | undefined; if (requiredRoles && requiredRoles.length > 0) { if (!authStore.hasAnyRole(requiredRoles)) { - // 没有所需角色,跳转到 403 页面 - next({ name: "Forbidden" }) - return + next({ name: "Forbidden" }); + return; } } - // 检查权限 - const requiredPermissions = to.meta.permissions + const requiredPermissions = to.meta.permissions as string[] | undefined; if (requiredPermissions && requiredPermissions.length > 0) { if (!authStore.hasAnyPermission(requiredPermissions)) { - // 没有所需权限,跳转到 403 页面 - next({ name: "Forbidden" }) - return + next({ name: "Forbidden" }); + return; } } - next() -}) + next(); +}); -export default router +export default router; diff --git a/java-frontend/src/utils/menu.ts b/java-frontend/src/utils/menu.ts index b2775ad..3d8445e 100644 --- a/java-frontend/src/utils/menu.ts +++ b/java-frontend/src/utils/menu.ts @@ -1,29 +1,16 @@ -import { h } from "vue" -import type { RouteRecordRaw } from "vue-router" -import type { MenuProps } from "ant-design-vue" -import type { Menu } from "@/api/menus" -import * as Icons from "@ant-design/icons-vue" +import { h } from "vue"; +import type { RouteRecordRaw } from "vue-router"; +import type { MenuProps } from "ant-design-vue"; +import type { Menu } from "@/api/menus"; +import * as Icons from "@ant-design/icons-vue"; /** - * 组件路径映射 - * 将数据库中的组件路径映射到实际的导入函数 - * 注意:Vite 的动态 import() 不支持路径别名,所以需要在这里预先定义所有组件 + * 组件路径映射(Vite 需静态分析 import,故在此集中声明) */ -// 空布局组件,用于父级菜单 -const EmptyLayout = () => import("@/layouts/EmptyLayout.vue") +const EmptyLayout = () => import("@/layouts/EmptyLayout.vue"); -const componentMap: Record Promise> = { - // 工作台模块 +const componentMap: Record Promise> = { "workbench/Index": () => import("@/views/workbench/Index.vue"), - // 学校管理模块 - "school/schools/Index": () => import("@/views/school/schools/Index.vue"), - "school/departments/Index": () => - import("@/views/school/departments/Index.vue"), - "school/grades/Index": () => import("@/views/school/grades/Index.vue"), - "school/classes/Index": () => import("@/views/school/classes/Index.vue"), - "school/teachers/Index": () => import("@/views/school/teachers/Index.vue"), - "school/students/Index": () => import("@/views/school/students/Index.vue"), - // 活动管理模块 "contests/Index": () => import("@/views/contests/Index.vue"), "contests/Activities": () => import("@/views/contests/Activities.vue"), "contests/Create": () => import("@/views/contests/Create.vue"), @@ -42,28 +29,18 @@ const componentMap: Record Promise> = { "contests/judges/Index": () => import("@/views/contests/judges/Index.vue"), "contests/results/Index": () => import("@/views/contests/results/Index.vue"), "contests/notices/Index": () => import("@/views/contests/notices/Index.vue"), - "contests/ReviewRules": () => import("@/views/contests/Index.vue"), // 评审规则临时使用活动列表 - // 内容管理模块 + "contests/ReviewRules": () => import("@/views/contests/Index.vue"), "content/WorkReview": () => import("@/views/content/WorkReview.vue"), "content/WorkManagement": () => import("@/views/content/WorkManagement.vue"), "content/TagManagement": () => import("@/views/content/TagManagement.vue"), - // 数据统计模块 "analytics/Overview": () => import("@/views/analytics/Overview.vue"), "analytics/Review": () => import("@/views/analytics/Review.vue"), - // 作业管理模块 - "homework/Index": () => import("@/views/homework/Index.vue"), - "homework/Submissions": () => import("@/views/homework/Submissions.vue"), - "homework/ReviewRules": () => import("@/views/homework/ReviewRules.vue"), - // 学生端作业模块 - "homework/StudentList": () => import("@/views/homework/StudentList.vue"), - "homework/StudentDetail": () => import("@/views/homework/StudentDetail.vue"), - // 我的评审模块(评委) "activities/Guidance": () => import("@/views/activities/Guidance.vue"), "activities/Review": () => import("@/views/activities/Review.vue"), "activities/ReviewDetail": () => import("@/views/activities/ReviewDetail.vue"), "activities/Comments": () => import("@/views/activities/Comments.vue"), - "activities/PresetComments": () => import("@/views/activities/PresetComments.vue"), - // 系统管理模块 + "activities/PresetComments": () => + import("@/views/activities/PresetComments.vue"), "system/users/Index": () => import("@/views/system/users/Index.vue"), "system/roles/Index": () => import("@/views/system/roles/Index.vue"), "system/permissions/Index": () => @@ -72,304 +49,244 @@ const componentMap: Record Promise> = { "system/tenants/Index": () => import("@/views/system/tenants/Index.vue"), "system/dict/Index": () => import("@/views/system/dict/Index.vue"), "system/config/Index": () => import("@/views/system/config/Index.vue"), - "system/logs/Index": () => import("@/views/system/logs/Index.vue"), "system/public-users/Index": () => import("@/views/system/public-users/Index.vue"), -} +}; -// 用于兜底加载未在 componentMap 中声明的视图组件(避免 Vite 动态 import 分析警告) const viewComponentModules = import.meta.glob( - "@/views/**/*.vue" -) as Record Promise> + "@/views/**/*.vue", +) as Record Promise>; -/** - * 获取图标组件 - */ +/** Ant Design 菜单图标 */ export function getIconComponent(iconName: string | null | undefined) { - if (!iconName) return null - const IconComponent = (Icons as any)[iconName] + if (!iconName) return null; + const IconComponent = (Icons as Record)[iconName]; if (IconComponent) { - return () => h(IconComponent) + return () => h(IconComponent as object); } - return null + return null; } /** - * 从菜单路径生成路由名称(与 convertMenusToRoutes 中的逻辑一致) - * 使用菜单ID来区分,避免路由名称冲突(同一路径可能出现在不同菜单树分支) + * 路由 name 生成规则(须与 BasicLayout 中 handleMenuClick 一致) */ function getRouteNameFromPath( path: string | null | undefined, menuId: number, - isChild: boolean = false ): string { if (path) { const baseName = path .split("/") .map((part) => part.charAt(0).toUpperCase() + part.slice(1)) - .join("") - // 统一添加 menuId,避免顶级菜单同名(例如多个“/contests”菜单)导致路由被覆盖 - return `${baseName}${menuId}` + .join(""); + return `${baseName}${menuId}`; } - return `Menu${menuId}` + return `Menu${menuId}`; } -/** - * 将数据库菜单转换为 Ant Design Vue Menu 的 items 格式 - * key 使用路由名称而不是路径 - * 当父菜单只有一个子菜单时,直接显示子菜单,不显示父级折叠结构 - */ -export function convertMenusToMenuItems( - menus: Menu[], - isChild: boolean = false -): MenuProps["items"] { - const result: any[] = [] +function removeParentPathFromRoutePath( + routePath: string, + parentPath: string, +): string { + if (!parentPath) { + return routePath; + } + const normalizedRoutePath = routePath.startsWith("/") + ? routePath.slice(1) + : routePath; + const normalizedParentPath = parentPath.startsWith("/") + ? parentPath.slice(1) + : parentPath; + + if (normalizedRoutePath.startsWith(normalizedParentPath + "/")) { + return normalizedRoutePath.slice(normalizedParentPath.length + 1); + } + if (normalizedRoutePath === normalizedParentPath) { + return ""; + } + + return normalizedRoutePath; +} + +/** 后端菜单树 → Ant Design Menu items(key 为路由 name) */ +export function convertMenusToMenuItems(menus: Menu[]): MenuProps["items"] { + const result: NonNullable = []; menus.forEach((menu) => { - // 如果只有一个子菜单,直接提升子菜单到当前层级 if (menu.children && menu.children.length === 1) { - const onlyChild = menu.children[0] - const childRouteName = getRouteNameFromPath(onlyChild.path, onlyChild.id, true) + const onlyChild = menu.children[0]; + const childRouteName = getRouteNameFromPath(onlyChild.path, onlyChild.id); - const item: any = { + const item: Record = { key: childRouteName, label: onlyChild.name, title: onlyChild.name, - } + }; - // 优先使用父菜单的图标,如果没有则使用子菜单的图标 - const iconName = menu.icon || onlyChild.icon + const iconName = menu.icon || onlyChild.icon; if (iconName) { - const IconComponent = getIconComponent(iconName) + const IconComponent = getIconComponent(iconName); if (IconComponent) { - item.icon = IconComponent + item.icon = IconComponent; } } - // 如果这个唯一的子菜单还有子菜单,继续递归处理 if (onlyChild.children && onlyChild.children.length > 0) { - item.children = convertMenusToMenuItems(onlyChild.children, true) + item.children = convertMenusToMenuItems(onlyChild.children); } - result.push(item) - return + result.push(item as unknown as (typeof result)[number]); + return; } - // 正常处理:使用路由名称作为 key - const routeName = getRouteNameFromPath(menu.path, menu.id, isChild) + const routeName = getRouteNameFromPath(menu.path, menu.id); - const item: any = { + const item: Record = { key: routeName, label: menu.name, title: menu.name, - } + }; - // 添加图标 if (menu.icon) { - const IconComponent = getIconComponent(menu.icon) + const IconComponent = getIconComponent(menu.icon); if (IconComponent) { - item.icon = IconComponent + item.icon = IconComponent; } } - // 如果有多个子菜单,递归处理 if (menu.children && menu.children.length > 1) { - item.children = convertMenusToMenuItems(menu.children, true) + item.children = convertMenusToMenuItems(menu.children); } - result.push(item) - }) + result.push(item as unknown as (typeof result)[number]); + }); - return result -} - -/** - * 将数据库菜单转换为 Vue Router 的路由配置 - * 注意:这些路由会被添加到 /:tenantCode 父路由下,所以不需要再添加 tenantCode 前缀 - */ -/** - * 移除路径中与父路径重合的部分 - */ -function removeParentPathFromRoutePath( - routePath: string, - parentPath: string -): string { - if (!parentPath) { - return routePath - } - - // 标准化路径:移除开头的斜杠 - const normalizedRoutePath = routePath.startsWith("/") - ? routePath.slice(1) - : routePath - const normalizedParentPath = parentPath.startsWith("/") - ? parentPath.slice(1) - : parentPath - - // 如果子路径以父路径开头,移除父路径部分 - if (normalizedRoutePath.startsWith(normalizedParentPath + "/")) { - return normalizedRoutePath.slice(normalizedParentPath.length + 1) - } else if (normalizedRoutePath === normalizedParentPath) { - // 如果路径完全相同,返回空字符串(表示当前路由) - return "" - } - - return normalizedRoutePath + return result; } +/** 后端菜单树 → 挂到 `/:tenantCode`(Main)下的子路由 */ export function convertMenusToRoutes( menus: Menu[], parentPath: string = "", - isChild: boolean = false ): RouteRecordRaw[] { - const routes: RouteRecordRaw[] = [] + const routes: RouteRecordRaw[] = []; menus.forEach((menu) => { - // 构建路由路径 - // 注意:这些路由会被添加到 /:tenantCode 父路由下,所以路径应该是相对路径 let routePath = menu.path ? menu.path.startsWith("/") - ? menu.path.slice(1) // 移除开头的斜杠,因为这是相对路径 + ? menu.path.slice(1) : menu.path - : `menu-${menu.id}` + : `menu-${menu.id}`; - // 如果有父路径,移除与父路径重合的部分 if (parentPath) { - routePath = removeParentPathFromRoutePath(routePath, parentPath) + routePath = removeParentPathFromRoutePath(routePath, parentPath); } - // 构建路由名称(与 convertMenusToMenuItems 中的逻辑一致) - const routeName = getRouteNameFromPath(menu.path, menu.id, isChild) + const routeName = getRouteNameFromPath(menu.path, menu.id); - // 确定组件加载器 - let componentLoader: (() => Promise) | undefined + let componentLoader: (() => Promise) | undefined; if (menu.component) { - // 从组件映射中获取导入函数 - // 如果组件路径以 @/ 开头,说明是完整路径,需要去掉 @/views/ 前缀和 .vue 后缀来匹配 - let componentKey = menu.component + let componentKey = menu.component; if (componentKey.startsWith("@/views/")) { - componentKey = componentKey.replace("@/views/", "").replace(".vue", "") + componentKey = componentKey + .replace("@/views/", "") + .replace(".vue", ""); } else if (componentKey.endsWith(".vue")) { - componentKey = componentKey.replace(".vue", "") + componentKey = componentKey.replace(".vue", ""); } - // 从映射中获取组件导入函数 - const mappedLoader = componentMap[componentKey] + const mappedLoader = componentMap[componentKey]; if (mappedLoader) { - componentLoader = mappedLoader + componentLoader = mappedLoader; } else { - const componentPath = menu.component - console.warn( - `组件路径 "${componentPath}" (key: "${componentKey}") 未在 componentMap 中定义,请添加到 menu.ts 的 componentMap 中` - ) - // 如果找不到映射,使用 import.meta.glob 的模块映射进行兜底加载(可被 Vite 分析) - let normalizedPath = componentPath.startsWith("@/") - ? componentPath - : `@/views/${componentPath}` + let normalizedPath = menu.component.startsWith("@/") + ? menu.component + : `@/views/${menu.component}`; if (!normalizedPath.endsWith(".vue")) { - normalizedPath = `${normalizedPath}.vue` + normalizedPath = `${normalizedPath}.vue`; } const candidatePaths = [ normalizedPath, - // 兼容部分构建环境下 glob key 可能为 /src/xxx 形式 normalizedPath.startsWith("@/views/") ? normalizedPath.replace("@/views/", "/src/views/") : normalizedPath.startsWith("@/") ? normalizedPath.replace("@/", "/src/") : normalizedPath, - ] + ]; - const fallbackLoader = - candidatePaths.map((p) => viewComponentModules[p]).find(Boolean) || - undefined + const fallbackLoader = candidatePaths + .map((p) => viewComponentModules[p]) + .find(Boolean); if (fallbackLoader) { - componentLoader = fallbackLoader + componentLoader = fallbackLoader; } else { console.warn( - `组件路径 "${normalizedPath}" 未找到对应的视图文件(尝试:${candidatePaths.join( - ", " - )}),已跳过渲染该菜单` - ) - componentLoader = undefined + `组件未找到,已跳过菜单「${menu.name}」:尝试路径 ${candidatePaths.join(", ")}`, + ); + componentLoader = undefined; } } } else if (menu.children && menu.children.length > 0) { - // 如果没有 component 但有子菜单,使用空布局组件来渲染子路由 - componentLoader = EmptyLayout + componentLoader = EmptyLayout; } - // 如果有子菜单,先处理子菜单 - let childrenRoutes: RouteRecordRaw[] | undefined - let redirectToDefaultChild: string | undefined + let childrenRoutes: RouteRecordRaw[] | undefined; + let redirectToDefaultChild: string | undefined; if (menu.children && menu.children.length > 0) { - childrenRoutes = convertMenusToRoutes( - menu.children, - menu.path - ? menu.path.startsWith("/") - ? menu.path.slice(1) - : menu.path - : parentPath, - true // 标记为子菜单 - ) + const nextParent = menu.path + ? menu.path.startsWith("/") + ? menu.path.slice(1) + : menu.path + : parentPath; + + childrenRoutes = convertMenusToRoutes(menu.children, nextParent); - // 如果父菜单没有 component,但子菜单中有路径为空字符串的路由(默认子路由) - // 应该让父路由重定向到该子路由 if (!menu.component && childrenRoutes.length > 0) { - const defaultChild = childrenRoutes.find((child) => child.path === "") + const defaultChild = childrenRoutes.find((child) => child.path === ""); if (defaultChild && defaultChild.name) { - // 重定向到默认子路由(使用路由名称) - redirectToDefaultChild = defaultChild.name as string + redirectToDefaultChild = defaultChild.name as string; } } } - // 如果既没有组件也没有子路由,跳过这个菜单(无法渲染) if (!componentLoader && (!childrenRoutes || childrenRoutes.length === 0)) { - return + return; } - const route: RouteRecordRaw = { + const route = { path: routePath, name: routeName, meta: { title: menu.name, requiresAuth: true, - // 如果菜单有权限要求,添加到路由meta中 ...(menu.permission && { permissions: [menu.permission] }), }, - ...(componentLoader && { component: componentLoader }), - // 如果有重定向,添加重定向 + ...(componentLoader && { + component: componentLoader as () => Promise, + }), ...(redirectToDefaultChild && { redirect: { name: redirectToDefaultChild }, }), - // 如果有子菜单,添加子路由 ...(childrenRoutes && - childrenRoutes.length > 0 && { - children: childrenRoutes, - }), - } as RouteRecordRaw + childrenRoutes.length > 0 && { children: childrenRoutes }), + } as RouteRecordRaw; - routes.push(route) - }) + routes.push(route); + }); - return routes + return routes; } -/** - * 扁平化菜单树,用于查找特定路径的菜单 - */ export function flattenMenus(menus: Menu[]): Menu[] { - const result: Menu[] = [] - + const result: Menu[] = []; menus.forEach((menu) => { - result.push(menu) + result.push(menu); if (menu.children && menu.children.length > 0) { - result.push(...flattenMenus(menu.children)) + result.push(...flattenMenus(menu.children)); } - }) - - return result + }); + return result; } diff --git a/java-frontend/src/views/contests/RegisterIndividual.vue b/java-frontend/src/views/contests/RegisterIndividual.vue index e60600e..1f55951 100644 --- a/java-frontend/src/views/contests/RegisterIndividual.vue +++ b/java-frontend/src/views/contests/RegisterIndividual.vue @@ -157,9 +157,9 @@ import { registrationsApi, type Contest, type ContestRegistration, + type RegistrationCandidateUser, } from "@/api/contests" import { useListRequest } from "@/composables/useListRequest" -import { type Student } from "@/api/students" import AddParticipantDrawer from "./components/AddParticipantDrawer.vue" import AddTeacherDrawer from "./components/AddTeacherDrawer.vue" @@ -175,7 +175,7 @@ const currentRegistrationId = ref(null) const contest = ref(null) // 选中的参赛人列表 -const selectedParticipants = ref([]) +const selectedParticipants = ref([]) // 使用列表请求组合函数 const { @@ -245,7 +245,7 @@ const columns: TableColumnsType = [ ] // 获取机构信息 -const getOrganizationInfo = (record: ContestRegistration | Student): string => { +const getOrganizationInfo = (record: ContestRegistration | RegistrationCandidateUser): string => { // 优先从 user.student.class 获取(已报名状态) if ("user" in record && record.user) { const user = record.user as any @@ -255,9 +255,8 @@ const getOrganizationInfo = (record: ContestRegistration | Student): string => { }` } } - // 从 record.class 获取(待报名状态) - if ("class" in record && record.class) { - return `${record.class.grade?.name || ""} - ${record.class.name || ""}` + if ("roleNames" in record && record.roleNames?.length) { + return record.roleNames.join("、") } return "-" } @@ -280,14 +279,18 @@ const selectedTeacherUserIds = computed(() => { // 合并显示数据源(已报名的 + 待报名的) const displayDataSource = computed(() => { // 将选中的参赛人转换为表格显示格式 - const pendingParticipants = selectedParticipants.value.map((student) => ({ - id: student.id, - userId: student.userId, - user: student.user, - gender: student.gender, - phone: student.phone, - class: student.class, - registrationState: undefined, // 待报名状态 + const pendingParticipants = selectedParticipants.value.map((u) => ({ + id: u.id, + userId: u.id, + user: { + nickname: u.nickname, + username: u.username, + phone: u.phone, + gender: u.gender, + }, + gender: u.gender === "male" ? 1 : u.gender === "female" ? 2 : undefined, + phone: u.phone, + registrationState: undefined, })) // 合并已报名和待报名的数据 @@ -326,11 +329,6 @@ const getStatusText = (status?: string) => { } } -// 添加参赛人表单验证规则 -const addParticipantRules = { - userId: [{ required: true, message: "请选择用户", trigger: "change" }], -} - // 加载活动详情 const fetchContestDetail = async () => { try { @@ -346,7 +344,7 @@ const handleAddParticipant = () => { } // 添加参赛人确认(从组件接收选中的学生) -const handleAddParticipantConfirm = (students: Student[]) => { +const handleAddParticipantConfirm = (students: RegistrationCandidateUser[]) => { // 合并新选中的参赛人到列表(去重) const existingIds = new Set(selectedParticipants.value.map((p) => p.id)) const newStudents = students.filter((s) => !existingIds.has(s.id)) @@ -387,7 +385,7 @@ const handleAddTeacherConfirm = async (teachers: any[]) => { try { // 批量添加选中的教师 const promises = teachers.map((teacher) => - registrationsApi.addTeacher(currentRegistrationId.value!, teacher.userId) + registrationsApi.addTeacher(currentRegistrationId.value!, teacher.id) ) await Promise.all(promises) @@ -462,7 +460,7 @@ const handleSubmit = async () => { registrationsApi.create({ contestId, registrationType: "individual", - userId: student.userId, + userId: student.id, }) ) diff --git a/java-frontend/src/views/contests/RegisterTeam.vue b/java-frontend/src/views/contests/RegisterTeam.vue index d7bc495..5a32344 100644 --- a/java-frontend/src/views/contests/RegisterTeam.vue +++ b/java-frontend/src/views/contests/RegisterTeam.vue @@ -107,19 +107,19 @@ >