【新增】班级管理功能相关

This commit is contained in:
任维炳
2025-04-23 17:21:06 +08:00
parent cca2ec1925
commit 8f99ff4d47
14 changed files with 610 additions and 0 deletions

View File

@@ -0,0 +1,118 @@
package pc.exam.pp.module.exam.controller.admin.classs;
import org.springframework.web.bind.annotation.*;
import jakarta.annotation.Resource;
import org.springframework.validation.annotation.Validated;
import org.springframework.security.access.prepost.PreAuthorize;
import io.swagger.v3.oas.annotations.tags.Tag;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.Operation;
import jakarta.validation.constraints.*;
import jakarta.validation.*;
import jakarta.servlet.http.*;
import java.util.*;
import java.io.IOException;
import pc.exam.pp.framework.common.pojo.PageParam;
import pc.exam.pp.framework.common.pojo.PageResult;
import pc.exam.pp.framework.common.pojo.CommonResult;
import pc.exam.pp.framework.common.util.object.BeanUtils;
import static pc.exam.pp.framework.common.pojo.CommonResult.success;
import pc.exam.pp.framework.excel.core.util.ExcelUtils;
import pc.exam.pp.framework.apilog.core.annotation.ApiAccessLog;
import static pc.exam.pp.framework.apilog.core.enums.OperateTypeEnum.*;
import pc.exam.pp.module.exam.controller.admin.classs.vo.*;
import pc.exam.pp.module.exam.dal.dataobject.classs.ClassDO;
import pc.exam.pp.module.exam.service.classs.ClassService;
@Tag(name = "管理后台 - 学生班级")
@RestController
@RequestMapping("/exam/class")
@Validated
public class ClassController {
@Resource
private ClassService classService;
@PostMapping("/create")
@Operation(summary = "创建学生班级")
@PreAuthorize("@ss.hasPermission('exam:class:create')")
public CommonResult<Long> createClass(@Valid @RequestBody ClassSaveReqVO createReqVO) {
return success(classService.createClass(createReqVO));
}
@PutMapping("/update")
@Operation(summary = "更新学生班级")
@PreAuthorize("@ss.hasPermission('exam:class:update')")
public CommonResult<Boolean> updateClass(@Valid @RequestBody ClassSaveReqVO updateReqVO) {
classService.updateClass(updateReqVO);
return success(true);
}
@DeleteMapping("/delete")
@Operation(summary = "删除学生班级")
@Parameter(name = "id", description = "编号", required = true)
@PreAuthorize("@ss.hasPermission('exam:class:delete')")
public CommonResult<Boolean> deleteClass(@RequestParam("id") Long id) {
classService.deleteClass(id);
return success(true);
}
@GetMapping("/get")
@Operation(summary = "获得学生班级")
@Parameter(name = "id", description = "编号", required = true, example = "1024")
@PreAuthorize("@ss.hasPermission('exam:class:query')")
public CommonResult<ClassRespVO> getClass(@RequestParam("id") Long id) {
ClassDO classs = classService.getClass(id);
return success(BeanUtils.toBean(classs, ClassRespVO.class));
}
@GetMapping("/getClassName")
@Operation(summary = "获得班级名称列表")
@Parameter(name = "id", description = "编号", required = true, example = "1024")
public CommonResult<List<ClassNameReturnVO>> getClassName() {
List<ClassNameReturnVO> className = classService.getClassName();
return success(BeanUtils.toBean(className, ClassNameReturnVO.class));
}
@GetMapping("/getClassIdName")
@Operation(summary = "获得班级名称ID列表")
@Parameter(name = "id", description = "编号", required = true, example = "1024")
public CommonResult<List<ClassDoReturnVO>> getClassIdName() {
List<ClassDoReturnVO> classDo = classService.getClassIdName();
return success(BeanUtils.toBean(classDo, ClassDoReturnVO.class));
}
@GetMapping("/page")
@Operation(summary = "获得学生班级分页")
@PreAuthorize("@ss.hasPermission('exam:class:query')")
public CommonResult<PageResult<ClassRespVO>> getClassPage(@Valid ClassPageReqVO pageReqVO) {
PageResult<ClassDO> pageResult = classService.getClassPage(pageReqVO);
return success(BeanUtils.toBean(pageResult, ClassRespVO.class));
}
@PostMapping("/binding")
@Operation(summary = "班级绑定学生列表")
public CommonResult<Boolean> getClassPage(@RequestBody ClassStudentSaveReqVO reqVO) {
classService.createClassStudent(reqVO);
return success(true);
}
@GetMapping("/export-excel")
@Operation(summary = "导出学生班级 Excel")
@PreAuthorize("@ss.hasPermission('exam:class:export')")
@ApiAccessLog(operateType = EXPORT)
public void exportClassExcel(@Valid ClassPageReqVO pageReqVO,
HttpServletResponse response) throws IOException {
pageReqVO.setPageSize(PageParam.PAGE_SIZE_NONE);
List<ClassDO> list = classService.getClassPage(pageReqVO).getList();
// 导出 Excel
ExcelUtils.write(response, "学生班级.xls", "数据", ClassRespVO.class,
BeanUtils.toBean(list, ClassRespVO.class));
}
}

View File

@@ -0,0 +1,14 @@
package pc.exam.pp.module.exam.controller.admin.classs.vo;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import lombok.ToString;
@Schema(description = "管理后台 - 学生班级分页 Request VO")
@Data
@ToString(callSuper = true)
public class ClassDoReturnVO {
private Long id;
private String name;
}

View File

@@ -0,0 +1,13 @@
package pc.exam.pp.module.exam.controller.admin.classs.vo;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.ToString;
@Schema(description = "管理后台 - 学生班级分页 Request VO")
@Data
@ToString(callSuper = true)
public class ClassNameReturnVO {
private String className;
}

View File

@@ -0,0 +1,24 @@
package pc.exam.pp.module.exam.controller.admin.classs.vo;
import lombok.*;
import java.util.*;
import io.swagger.v3.oas.annotations.media.Schema;
import pc.exam.pp.framework.common.pojo.PageParam;
import org.springframework.format.annotation.DateTimeFormat;
import java.time.LocalDateTime;
import static pc.exam.pp.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND;
@Schema(description = "管理后台 - 学生班级分页 Request VO")
@Data
@EqualsAndHashCode(callSuper = true)
@ToString(callSuper = true)
public class ClassPageReqVO extends PageParam {
@Schema(description = "名字", example = "芋艿")
private String name;
@Schema(description = "状态", example = "1")
private Integer status;
}

View File

@@ -0,0 +1,35 @@
package pc.exam.pp.module.exam.controller.admin.classs.vo;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.*;
import java.util.*;
import org.springframework.format.annotation.DateTimeFormat;
import java.time.LocalDateTime;
import com.alibaba.excel.annotation.*;
@Schema(description = "管理后台 - 学生班级 Response VO")
@Data
@ExcelIgnoreUnannotated
public class ClassRespVO {
@Schema(description = "班级编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "26824")
@ExcelProperty("班级编号")
private Long id;
@Schema(description = "名字", example = "芋艿")
@ExcelProperty("名字")
private String name;
@Schema(description = "状态", example = "1")
@ExcelProperty("状态")
private Integer status;
@Schema(description = "备注", example = "你说的对")
@ExcelProperty("备注")
private String remark;
@Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED)
@ExcelProperty("创建时间")
private LocalDateTime createTime;
}

View File

@@ -0,0 +1,24 @@
package pc.exam.pp.module.exam.controller.admin.classs.vo;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.*;
import java.util.*;
import jakarta.validation.constraints.*;
@Schema(description = "管理后台 - 学生班级新增/修改 Request VO")
@Data
public class ClassSaveReqVO {
@Schema(description = "班级编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "26824")
private Long id;
@Schema(description = "名字", example = "芋艿")
private String name;
@Schema(description = "状态", example = "1")
private Integer status;
@Schema(description = "备注", example = "你说的对")
private String remark;
}

View File

@@ -0,0 +1,16 @@
package pc.exam.pp.module.exam.controller.admin.classs.vo;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import pc.exam.pp.module.exam.dal.dataobject.student.StudentClassDO;
import java.util.List;
@Schema(description = "管理后台 - 学生班级绑定新增/修改 Request VO")
@Data
public class ClassStudentSaveReqVO {
@Schema(description = "学生表")
private List<StudentClassDO> studentClassDOS;
}

View File

@@ -0,0 +1,43 @@
package pc.exam.pp.module.exam.dal.dataobject.classs;
import lombok.*;
import java.util.*;
import java.time.LocalDateTime;
import java.time.LocalDateTime;
import com.baomidou.mybatisplus.annotation.*;
import pc.exam.pp.framework.mybatis.core.dataobject.BaseDO;
/**
* 学生班级 DO
*
* @author rwb
*/
@TableName("exam_class")
@KeySequence("exam_class_seq") // 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 MySQL 等数据库,可不写。
@Data
@EqualsAndHashCode(callSuper = true)
@ToString(callSuper = true)
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class ClassDO extends BaseDO {
/**
* 班级编号
*/
@TableId
private Long id;
/**
* 名字
*/
private String name;
/**
* 状态
*/
private Integer status;
/**
* 备注
*/
private String remark;
}

View File

@@ -0,0 +1,35 @@
package pc.exam.pp.module.exam.dal.dataobject.classs;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.*;
import pc.exam.pp.framework.mybatis.core.dataobject.BaseDO;
import pc.exam.pp.framework.tenant.core.db.TenantBaseDO;
/**
* 班级老师 DO
*
* @author rwb
*/
@TableName("exam_class_teacher")
@Data
@ToString(callSuper = true)
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class ClassTeacherDO extends TenantBaseDO {
/**
* Id
*/
@TableId
private Long id;
/**
* 班级编号
*/
private Long classId;
/**
* 老师编号
*/
private Long teacherId;
}

View File

@@ -0,0 +1,34 @@
package pc.exam.pp.module.exam.dal.mysql.classs;
import java.util.*;
import org.apache.ibatis.annotations.Param;
import pc.exam.pp.framework.common.pojo.PageResult;
import pc.exam.pp.framework.mybatis.core.query.LambdaQueryWrapperX;
import pc.exam.pp.framework.mybatis.core.mapper.BaseMapperX;
import pc.exam.pp.module.exam.dal.dataobject.classs.ClassDO;
import org.apache.ibatis.annotations.Mapper;
import pc.exam.pp.module.exam.controller.admin.classs.vo.*;
/**
* 学生班级 Mapper
*
* @author rwb
*/
@Mapper
public interface ClassMapper extends BaseMapperX<ClassDO> {
default PageResult<ClassDO> selectPage(ClassPageReqVO reqVO) {
return selectPage(reqVO, new LambdaQueryWrapperX<ClassDO>()
.likeIfPresent(ClassDO::getName, reqVO.getName())
.eqIfPresent(ClassDO::getStatus, reqVO.getStatus())
.orderByDesc(ClassDO::getId));
}
List<ClassNameReturnVO> getClassName();
List<ClassDoReturnVO> getClassIdName();
ClassDO getClassNameOne(@Param("className") String className);
}

View File

@@ -0,0 +1,10 @@
package pc.exam.pp.module.exam.dal.mysql.classs;
import org.apache.ibatis.annotations.Mapper;
import pc.exam.pp.framework.mybatis.core.mapper.BaseMapperX;
import pc.exam.pp.module.exam.dal.dataobject.classs.ClassTeacherDO;
@Mapper
public interface ClassTeacherMapper extends BaseMapperX<ClassTeacherDO> {
}

View File

@@ -0,0 +1,102 @@
package pc.exam.pp.module.exam.service.classs;
import java.util.*;
import jakarta.validation.*;
import pc.exam.pp.framework.common.util.collection.CollectionUtils;
import pc.exam.pp.module.exam.controller.admin.classs.vo.*;
import pc.exam.pp.module.exam.dal.dataobject.classs.ClassDO;
import pc.exam.pp.framework.common.pojo.PageResult;
import pc.exam.pp.framework.common.pojo.PageParam;
/**
* 学生班级 Service 接口
*
* @author rwb
*/
public interface ClassService {
/**
* 创建学生班级
*
* @param createReqVO 创建信息
* @return 编号
*/
Long createClass(@Valid ClassSaveReqVO createReqVO);
/**
* 创建学生班级绑定关系
*
* @param reqVO 创建信息
*/
void createClassStudent(ClassStudentSaveReqVO reqVO);
/**
* 解除学生班级绑定关系
*
* @param reqVO 解除信息
*/
void deleteClassStudent(ClassStudentSaveReqVO reqVO);
/**
* 更新学生班级
*
* @param updateReqVO 更新信息
*/
void updateClass(@Valid ClassSaveReqVO updateReqVO);
/**
* 删除学生班级
*
* @param id 编号
*/
void deleteClass(Long id);
/**
* 获得学生班级
*
* @param id 编号
* @return 学生班级
*/
ClassDO getClass(Long id);
/**
* 获得班级名称
*
* @return 班级名称
*/
List<ClassNameReturnVO> getClassName();
/**
* 获得班级名称和ID
*
* @return 班级名称和ID
*/
List<ClassDoReturnVO> getClassIdName();
/**
* 获得学生班级分页
*
* @param pageReqVO 分页查询
* @return 学生班级分页
*/
PageResult<ClassDO> getClassPage(ClassPageReqVO pageReqVO);
/**
* 获得指定编号的班级 Map
*
* @param ids 班级编号数组
* @return 班级 Map
*/
default Map<Long, ClassDO> getClassMap(Collection<Long> ids) {
List<ClassDO> list = getClassList(ids);
return CollectionUtils.convertMap(list, ClassDO::getId);
}
/**
* 获得班级信息数组
*
* @param ids 班级编号数组
* @return 班级信息数组
*/
List<ClassDO> getClassList(Collection<Long> ids);
}

View File

@@ -0,0 +1,119 @@
package pc.exam.pp.module.exam.service.classs;
import cn.hutool.core.collection.CollUtil;
import org.springframework.stereotype.Service;
import jakarta.annotation.Resource;
import org.springframework.validation.annotation.Validated;
import org.springframework.transaction.annotation.Transactional;
import java.util.*;
import pc.exam.pp.framework.common.enums.CommonStatusEnum;
import pc.exam.pp.module.exam.controller.admin.classs.vo.*;
import pc.exam.pp.module.exam.dal.dataobject.classs.ClassDO;
import pc.exam.pp.framework.common.pojo.PageResult;
import pc.exam.pp.framework.common.pojo.PageParam;
import pc.exam.pp.framework.common.util.object.BeanUtils;
import pc.exam.pp.module.exam.dal.dataobject.student.StudentClassDO;
import pc.exam.pp.module.exam.dal.dataobject.student.StudentDO;
import pc.exam.pp.module.exam.dal.mysql.classs.ClassMapper;
import pc.exam.pp.module.exam.dal.mysql.student.StudentClassMapper;
import static pc.exam.pp.framework.common.exception.util.ServiceExceptionUtil.exception;
import static pc.exam.pp.module.system.enums.ErrorCodeConstants.CLASS_NOT_EXISTS;
/**
* 学生班级 Service 实现类
*
* @author rwb
*/
@Service
@Validated
public class ClassServiceImpl implements ClassService {
@Resource
private ClassMapper classMapper;
@Resource
private StudentClassMapper studentClassMapper;
@Override
public Long createClass(ClassSaveReqVO createReqVO) {
// 插入
createReqVO.setStatus(CommonStatusEnum.ENABLE.getStatus()); // 默认开启
ClassDO classs = BeanUtils.toBean(createReqVO, ClassDO.class);
classMapper.insert(classs);
// 返回
return classs.getId();
}
@Override
public void createClassStudent(ClassStudentSaveReqVO reqVO) {
// 循环插入或者更新数据
for (StudentClassDO studentClassDO : reqVO.getStudentClassDOS()){
studentClassMapper.insert(studentClassDO);
}
}
@Override
public void deleteClassStudent(ClassStudentSaveReqVO reqVO) {
// 循环插入或者更新数据
// for (Long longs : reqVO.getStudentClassDOS()){
// StudentClassDO studentClassDO = new StudentClassDO();
// studentClassDO.setStudentId(longs);
// studentClassMapper.deleteById(studentClassDO);
// }
}
@Override
public void updateClass(ClassSaveReqVO updateReqVO) {
// 校验存在
validateClassExists(updateReqVO.getId());
// 更新
ClassDO updateObj = BeanUtils.toBean(updateReqVO, ClassDO.class);
classMapper.updateById(updateObj);
}
@Override
public void deleteClass(Long id) {
// 校验存在
validateClassExists(id);
// 删除
classMapper.deleteById(id);
}
private void validateClassExists(Long id) {
if (classMapper.selectById(id) == null) {
throw exception(CLASS_NOT_EXISTS);
}
}
@Override
public ClassDO getClass(Long id) {
return classMapper.selectById(id);
}
@Override
public List<ClassNameReturnVO> getClassName() {
return classMapper.getClassName();
}
@Override
public List<ClassDoReturnVO> getClassIdName() {
return classMapper.getClassIdName();
}
@Override
public PageResult<ClassDO> getClassPage(ClassPageReqVO pageReqVO) {
return classMapper.selectPage(pageReqVO);
}
@Override
public List<ClassDO> getClassList(Collection<Long> ids) {
if (CollUtil.isEmpty(ids)) {
return Collections.emptyList();
}
return classMapper.selectBatchIds(ids);
}
}

View File

@@ -0,0 +1,23 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="pc.exam.pp.module.exam.dal.mysql.classs.ClassMapper">
<!--
一般情况下,尽可能使用 Mapper 进行 CRUD 增删改查即可。
无法满足的场景,例如说多表关联查询,才使用 XML 编写 SQL。
代码生成器暂时只生成 Mapper XML 文件本身,更多推荐 MybatisX 快速开发插件来生成查询。
文档可见https://www.iocoder.cn/MyBatis/x-plugins/
-->
<select id="getClassName" resultType="pc.exam.pp.module.exam.controller.admin.classs.vo.ClassNameReturnVO">
select name as className from exam_class
</select>
<select id="getClassIdName" resultType="pc.exam.pp.module.exam.controller.admin.classs.vo.ClassDoReturnVO">
select id, name from exam_class
</select>
<select id="getClassNameOne" resultType="pc.exam.pp.module.exam.dal.dataobject.classs.ClassDO">
select * from exam_class where name = #{className}
</select>
</mapper>