Compare commits

...

No commits in common. 'main' and 'master' have entirely different histories.
main ... master

@ -1,2 +0,0 @@
# RollCall
**代码在master分支**

@ -0,0 +1,88 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>com.wbq</groupId>
<artifactId>Software_Engineering</artifactId>
<version>0.0.1-SNAPSHOT</version>
</parent>
<artifactId>RollCallSystem</artifactId>
<dependencies>
<!-- https://mvnrepository.com/artifact/com.github.pagehelper/pagehelper-spring-boot-starter -->
<dependency>
<groupId>com.github.pagehelper</groupId>
<artifactId>pagehelper-spring-boot-starter</artifactId>
<version>2.1.0</version>
</dependency>
<!--展示API文档-->
<dependency>
<groupId>com.github.xiaoymin</groupId>
<artifactId>knife4j-openapi3-jakarta-spring-boot-starter</artifactId>
<version>4.4.0</version>
</dependency>
<!--负责自动生成API文档-->
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger2</artifactId>
<version>3.0.0</version>
</dependency>
<!--展示API文档本应该搭配swagger2使用
但是由于SpringBoot3.xjavax->jakarta)不支持,
所以展示API文档部分改成knife4j-->
<!--<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger-ui</artifactId>
<version>3.0.0</version>
</dependency>-->
<!-- https://mvnrepository.com/artifact/io.jsonwebtoken/jjwt -->
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt</artifactId>
<version>0.9.1</version>
</dependency>
<!--与上面的绑定使用-->
<dependency>
<groupId>javax.xml.bind</groupId>
<artifactId>jaxb-api</artifactId>
<version>2.3.1</version>
</dependency>
<!--QQ邮箱发送验证码服务-->
<dependency>
<groupId>com.sun.mail</groupId>
<artifactId>jakarta.mail</artifactId>
<version>2.0.1</version>
</dependency>
<!--账号密码加密-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
<!--excel导入-->
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi-ooxml</artifactId>
<version>5.2.3</version>
</dependency>
</dependencies>
<properties>
<maven.compiler.source>21</maven.compiler.source>
<maven.compiler.target>21</maven.compiler.target>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
</project>

@ -0,0 +1,16 @@
package com.wbq;
import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.transaction.annotation.EnableTransactionManagement;
// 项目启动类
@SpringBootApplication
@EnableTransactionManagement
@Slf4j
public class RollCallApplication {
public static void main(String[] args) {
SpringApplication.run(RollCallApplication.class, args);
log.info("server started");
}
}

@ -0,0 +1,23 @@
/*package com.wbq.config;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.csrf().disable() // 禁用 CSRF 保护(如果不需要的话)
.authorizeRequests()
.antMatchers("/doc.html", "/swagger-ui/**", "/v2/api-docs/**", "/webjars/**").permitAll() // 允许访问 Swagger 文档
.anyRequest().authenticated() // 其他请求需要认证
.and()
.formLogin().disable(); // 禁用默认的登录页面
}
}*/

@ -0,0 +1,32 @@
/*
package com.wbq.config;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import springfox.documentation.builders.ApiInfoBuilder;
import springfox.documentation.builders.PathSelectors;
import springfox.documentation.builders.RequestHandlerSelectors;
import springfox.documentation.spi.DocumentationType;
import springfox.documentation.spring.web.plugins.Docket;
import springfox.documentation.swagger2.annotations.EnableSwagger2;
@Configuration
@EnableSwagger2
public class SwaggerConfig {
@Bean
public Docket api() {
return new Docket(DocumentationType.OAS_30) // 使用 OpenAPI 3
.select()
.apis(RequestHandlerSelectors.basePackage("com.wbq.controller")) // 替换为你的包路径
.paths(PathSelectors.any())
.build()
.apiInfo(new ApiInfoBuilder()
.title("API 文档标题")
.description("API 文档描述")
.version("1.0")
.build());
}
}
*/

@ -0,0 +1,94 @@
package com.wbq.config;
import com.wbq.interceptor.JwtTokenAdminInterceptor;
import com.wbq.interceptor.JwtTokenStudentInterceptor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurationSupport;
import springfox.documentation.builders.ApiInfoBuilder;
import springfox.documentation.builders.PathSelectors;
import springfox.documentation.builders.RequestHandlerSelectors;
import springfox.documentation.service.ApiInfo;
import springfox.documentation.service.Contact;
import springfox.documentation.spi.DocumentationType;
import springfox.documentation.spring.web.plugins.Docket;
@Slf4j
@Configuration
// MVC配置
public class WebMvcConfiguration extends WebMvcConfigurationSupport {
@Autowired
private JwtTokenAdminInterceptor jwtTokenAdminInterceptor;
@Autowired
private JwtTokenStudentInterceptor jwtTokenStudentInterceptor;
/**
*
* @param registry
*/
protected void addInterceptors(InterceptorRegistry registry) {
log.info("开始注册自定义拦截器...");
registry.addInterceptor(jwtTokenStudentInterceptor)
.addPathPatterns("/student/**")
.excludePathPatterns("/student/login");
registry.addInterceptor(jwtTokenAdminInterceptor)
.addPathPatterns("/admin/**")
.excludePathPatterns("/admin/login")
.excludePathPatterns("/admin/registry");
}
@Bean
public Docket docketAdmin() {
log.info("准备生成接口文档...");
ApiInfo apiInfo = new ApiInfoBuilder()
.title("课堂随机点名项目接口文档")
.version("1.0")
.description("课堂随机点名项目接口文档")
.contact(new Contact("王碧强", "https://www.bilibili.com/", "2108095381@qq.com"))
.build();
Docket docket = new Docket(DocumentationType.SWAGGER_2)
.groupName("管理端接口")
.apiInfo(apiInfo)
.select()
.apis(RequestHandlerSelectors.basePackage("com.wbq.controller.admin"))
.paths(PathSelectors.any())
.build();
return docket;
}
@Bean
public Docket docketStudent() {
log.info("准备生成接口文档...");
ApiInfo apiInfo = new ApiInfoBuilder()
.title("课堂随机点名项目接口文档")
.version("1.0")
.description("课堂随机点名项目接口文档")
.contact(new Contact("王碧强", "https://www.bilibili.com/", "2108095381@qq.com"))
.build();
Docket docket = new Docket(DocumentationType.SWAGGER_2)
.groupName("学生端接口")
.apiInfo(apiInfo)
.select()
.apis(RequestHandlerSelectors.basePackage("com.wbq.controller.student"))
.paths(PathSelectors.any())
.build();
return docket;
}
/**
*
* @param registry
*/
protected void addResourceHandlers(ResourceHandlerRegistry registry) {
log.info("开始设置静态资源映射...");
registry.addResourceHandler("/doc.html").addResourceLocations("classpath:/META-INF/resources/");
registry.addResourceHandler("/webjars/**").addResourceLocations("classpath:/META-INF/resources/webjars/");
}
}

@ -0,0 +1,7 @@
package com.wbq.constant;
// 常量配置
public class EmailConstant {
public static final String SMTP_HOST = "smtp.qq.com";
public static final String SMTP_PORT = "465";
}

@ -0,0 +1,8 @@
package com.wbq.constant;
public class JwtClaimsConstant {
public static final String ADMIN_ID = "adminId";
public static final String STUDENT_ID = "studentId";
public static final String PHONE = "phone";
public static final String USERNAME = "username";
}

@ -0,0 +1,8 @@
package com.wbq.constant;
/**
*
*/
public class PasswordConstant {
public static final String DEFAULT_PASSWORD = "1234";
}

@ -0,0 +1,20 @@
package com.wbq.context;
// 线程变量记录当前id
public class BaseContext {
public static ThreadLocal<Integer> threadLocal = new ThreadLocal<>();
public static void setCurrentId(Integer id) {
threadLocal.set(id);
}
public static Integer getCurrentId() {
return threadLocal.get();
}
public static void removeCurrentId() {
threadLocal.remove();
}
}

@ -0,0 +1,375 @@
package com.wbq.controller.admin;
import com.wbq.constant.JwtClaimsConstant;
import com.wbq.context.BaseContext;
import com.wbq.dto.*;
import com.wbq.entity.Admin;
import com.wbq.entity.Course;
import com.wbq.entity.EnrollRequest;
import com.wbq.entity.Student;
import com.wbq.mapper.AdminCourseMapper;
import com.wbq.properties.MailProperties;
import com.wbq.result.PageResult;
import com.wbq.result.Result;
import com.wbq.service.AdminService;
import com.wbq.service.CourseService;
import com.wbq.service.StudentService;
import com.wbq.utils.JwtUtils;
import com.wbq.utils.MailUtils;
import com.wbq.vo.AdminLoginVO;
import com.wbq.vo.AdminRegistryVO;
import com.wbq.vo.CourseVO;
import com.wbq.vo.StudentCourseInfoVO;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.security.core.parameters.P;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import java.sql.ResultSet;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Random;
@RestController
@Slf4j
@RequestMapping("/admin")
// controller 控制层代码
@Api(tags = "管理端相关接口")
public class AdminController {
@Autowired
private StudentService studentService;
@Autowired
private AdminService adminService;
@Autowired
private CourseService courseService;
@Autowired
private AdminCourseMapper adminCourseMapper;
@Autowired
private JwtUtils jwtUtils;
/*@Autowired
private MailUtils mailUtils;
@Autowired
private MailProperties mailProperties;*/
// 模拟存储已发送的验证码,通常应存储在 Redis 等缓存中
// private Map<String, String> verificationCodeStore = new HashMap<>();
/**
*
* @param studentPageQueryDTO
* @param courseId
* @return
*/
@PostMapping("/pageQuery4Course")
@ApiOperation("分页查询学生(按课程积分排名)")
public Result<PageResult> pageQuery4Course(@RequestBody StudentPageQueryDTO studentPageQueryDTO,
int courseId) {
log.info("课程{}的学生查询: {}", courseId, studentPageQueryDTO);
PageResult pageResult = studentService.pageQuery(studentPageQueryDTO, courseId);
return Result.success(pageResult);
}
/**
*
* @param courseId
* @return
*/
@PostMapping("/randomRollCall")
@ApiOperation("随机点名")
public Result<StudentCourseInfoVO> randomRollCall(int courseId) {
log.info("随机点名");
return Result.success(studentService.callStudent(courseId));
}
/**
*
* @param courseId
* @param firstname
* @return
*/
@PostMapping("/callByFirstname")
@ApiOperation("根据姓氏点名")
public Result<StudentCourseInfoVO> callByFirstname(int courseId, String firstname) {
log.info("根据姓氏点名");
return Result.success(studentService.callStudentByFirstname(courseId, firstname));
}
/**
*
* @param courseId
* @param lastNum
* @return
*/
@PostMapping("/callByLastNum")
@ApiOperation("根据学号尾数点名")
public Result<StudentCourseInfoVO> callByLastNum(int courseId, int lastNum) {
log.info("根据学号尾数点名");
return Result.success(studentService.callStudentByLastNum(courseId, lastNum));
}
/**
*
* @param score
* @param enrollRequest
* @return
*/
@PutMapping("/addScore")
@ApiOperation("给学生加分")
public Result<StudentCourseInfoVO> addScore(@RequestBody EnrollRequest enrollRequest, double score) {
log.info("给课程{}的学生加分: {}, {}", enrollRequest.getCourse(),
enrollRequest.getStudent(), score);
StudentCourseInfoVO studentCourseInfoVO = studentService.addScore(enrollRequest.getCourse(),
enrollRequest.getStudent(), score);
return Result.success(studentCourseInfoVO);
}
/**
*
* @param studentDTO
* @param courseDTO
*/
/*@PostMapping("/updateStudentCourseInfo")
@ApiOperation("修改学生信息")
public Result update(@RequestBody StudentDTO studentDTO, @RequestBody CourseDTO courseDTO) {
log.info("修改学生信息: {}", studentDTO);
studentService.update(studentDTO);
return Result.success();
}*/
/**
*
* @param userName
* @return
*/
/*@PostMapping("/sendCode")
@ApiOperation("发送验证码")
public Result<String> sendVerificationCode(@RequestParam String userName) {
// 产生随机6位的验证码
String code = String.valueOf(new Random().nextInt(899999) + 100000);
verificationCodeStore.put(userName, code);
// 模拟发送短信逻辑(实际项目中需要接入短信发送服务)
System.out.println("发送验证码:" + code + " 到QQ邮箱: " + userName);
String subject = "验证码邮件";
String text = "您好,您的验证码是:" + code + "请在5分钟内使用。";
mailUtils.sendEmail(mailProperties.getEmailCount(), userName,
mailProperties.getEmailAuthorizationCode(),
subject, text);
return Result.success("Verification code sent to " + userName);
}*/
/**
*
* @param
* @param adminRegistryDTO
* @return
*/
@PostMapping("/registry")
@ApiOperation("管理员注册")
public Result<AdminRegistryVO> registry(@RequestBody AdminRegistryDTO adminRegistryDTO) {
// String storedCode = verificationCodeStore.get(adminRegistryDTO.getUserName());
/*if(storedCode != null && storedCode.equals(adminRegistryDTO.getVerificationCode())) {
// 验证码正确,完成注册逻辑
// 在此可以进行密码加密、保存数据库等操作
adminRegistryVO.setRegistrationStatus("Registration Successful");
// 将管理员数据保存到数据库
AdminDTO adminDTO = new AdminDTO();
BeanUtils.copyProperties(adminRegistryDTO, adminDTO);
adminService.add(adminDTO);
// 注册成功后删除验证码
verificationCodeStore.remove(adminRegistryDTO.getUserName());
} else {
adminRegistryVO.setRegistrationStatus("Invalid Verification Code");
}*/
AdminRegistryVO adminRegistryVO = new AdminRegistryVO();
adminRegistryVO.setRegistrationStatus("Registration Successful");
// 将管理员数据保存到数据库
AdminDTO adminDTO = new AdminDTO();
BeanUtils.copyProperties(adminRegistryDTO, adminDTO);
adminService.addAdmin(adminDTO);
return Result.success(adminRegistryVO);
}
/**
*
* @param adminLoginDTO
* @return
*/
@PostMapping("/login")
@ApiOperation("管理员登录")
public Result<AdminLoginVO> login(@RequestBody AdminLoginDTO adminLoginDTO) {
log.info("管理员登录: {}", adminLoginDTO);
Admin admin = adminService.login(adminLoginDTO);
// 调试部分
// System.out.println(admin);
// 生成jwt
Map<String, Object> claims = new HashMap<>();
claims.put(JwtClaimsConstant.ADMIN_ID, admin.getId());
// 调试部分
// System.out.println(claims);
String token = jwtUtils.createJWT(claims);
// 调试部分
// System.out.println(claims);
// System.out.println(token);
AdminLoginVO adminLoginVO = AdminLoginVO.builder()
.adminId(admin.getAdminId())
.name(admin.getName())
.token(token)
.build();
return Result.success(adminLoginVO);
}
/**
* 退
* @return
*/
@PostMapping("/logout")
@ApiOperation("退出登录")
public Result<String> logout() {
return Result.success();
}
/**
*
* @param enrollRequest
*/
@PutMapping("/addStudent2Course")
@ApiOperation("将学生加入课程")
public Result<String> addStudent2Course(@RequestBody EnrollRequest enrollRequest) {
log.info("将学生{}加入课程{}", enrollRequest.getStudent(), enrollRequest.getCourse());
studentService.joinCourse(enrollRequest.getStudent(), enrollRequest.getCourse());
return Result.success();
}
/**
* 退
* @param enrollRequest
*/
@PutMapping("/dropStudentOutCourse")
@ApiOperation("将学生退出课程")
public Result<String> dropStudentOutCourse(@RequestBody EnrollRequest enrollRequest) {
log.info("将学生{}退出课程{}", enrollRequest.getStudent(), enrollRequest.getCourse());
studentService.dropCourse(enrollRequest.getCourse(), enrollRequest.getStudent());
return Result.success();
}
/**
*
* @param courseDTO
*/
@PutMapping("/addAdmin2Course")
@ApiOperation("加入管理课程")
public Result<String> addAdmin2Course(@RequestBody CourseDTO courseDTO) {
log.info("加入管理课程: {}", courseDTO);
Admin admin = adminService.getById(BaseContext.getCurrentId());
AdminDTO adminDTO = new AdminDTO();
BeanUtils.copyProperties(admin, adminDTO);
adminService.addCourse(adminDTO, courseDTO);
return Result.success();
}
/**
* 退
* @param courseDTO
*/
@PutMapping("dropAdminOutCourse")
@ApiOperation("退出管理课程")
public Result<String> dropAdminOutCourse(@RequestBody CourseDTO courseDTO) {
log.info("退出管理课程: {}", courseDTO);
Admin admin = adminService.getById(BaseContext.getCurrentId());
AdminDTO adminDTO = new AdminDTO();
BeanUtils.copyProperties(admin, adminDTO);
adminService.dropCourse(adminDTO, courseDTO);
return Result.success();
}
/**
*
* @return
*/
@GetMapping("/courseList")
@ApiOperation("查询所有的班级")
public Result<List<CourseVO>> courseList() {
log.info("查询所有班级");
return Result.success(courseService.courseList());
}
/**
*
* @preturn
*/
@GetMapping("/ownCourseList")
@ApiOperation("查询自己加入管理的班级")
public Result<List<CourseVO>> ownCourseList() {
log.info("查询自己加入管理的班级");
return Result.success(adminService.courseList());
}
/**
*
* @param file
* @param courseId
*/
@PostMapping("/batchAddStudents")
public Result<String> batchAddStudents(@RequestParam("file")MultipartFile file, int courseId) {
log.info("批量增加学生到课程{}: {}", courseId, file);
try {
List<StudentDTO> studentDTOS = studentService.parseExcel(file);
studentService.batchAddStudents(studentDTOS, courseId);
return Result.success("Students upload and save successfully");
}
catch (Exception e) {
e.printStackTrace();
return Result.error("Failed to upload students");
}
}
/**
*
* @param courseDescription
*/
@PostMapping("/createCourse")
public Result<Integer> createCourse(String courseDescription) {
log.info("创建新的课程:{}", courseDescription);
int courseId = courseService.addCourse(courseDescription);
int adminId = adminService.getById(BaseContext.getCurrentId()).getAdminId();
adminCourseMapper.insert(adminId, courseId);
return Result.success(courseId);
}
/**
*
* @param adminDTO
*/
@PutMapping("/changePassword")
public Result<String> changePassword(@RequestBody AdminDTO adminDTO) {
log.info("修改密码: {}", adminDTO);
adminService.changePassword(adminDTO);
return Result.success();
}
}

@ -0,0 +1,264 @@
package com.wbq.controller.student;
import com.wbq.constant.JwtClaimsConstant;
import com.wbq.context.BaseContext;
import com.wbq.dto.*;
import com.wbq.entity.Student;
import com.wbq.exception.LoginFailedException;
import com.wbq.mapper.StudentCourseMapper;
import com.wbq.mapper.StudentMapper;
import com.wbq.result.PageResult;
import com.wbq.result.Result;
import com.wbq.service.CourseService;
import com.wbq.service.StudentService;
import com.wbq.utils.JwtUtils;
import com.wbq.vo.CourseCallVO;
import com.wbq.vo.CourseVO;
import com.wbq.vo.StudentCourseInfoVO;
import com.wbq.vo.StudentLoginVO;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
// 一定是RestController不是Controller否则API文档不行
@RestController
@RequestMapping("/student")
@Slf4j
@Api(tags = "学生端相关接口")
public class StudentController {
@Autowired
private StudentService studentService;
@Autowired
private JwtUtils jwtUtils;
@Autowired
private CourseService courseService;
@Autowired
private StudentMapper studentMapper;
/* @Autowired
private MailUtils mailUtils;
@Autowired
private MailProperties mailProperties;*/
// 模拟存储已发送的验证码,通常应存储在 Redis 等缓存中
// private Map<String, String> verificationCodeStore = new HashMap<>();
/**
*
* @param userName QQ
* @return
*/
/* @PostMapping("/sendCode")
@ApiOperation("发送验证码")
public Result<String> sendVerificationCode(@RequestParam String userName) {
// 产生随机6位的验证码
String code = String.valueOf(new Random().nextInt(899999) + 100000);
verificationCodeStore.put(userName, code);
// 模拟发送短信逻辑(实际项目中需要接入短信发送服务)
System.out.println("发送验证码:" + code + " 到QQ邮箱: " + userName);
String subject = "验证码邮件";
String text = "您好,您的验证码是:" + code + "请在5分钟内使用。";
mailUtils.sendEmail(mailProperties.getEmailCount(), userName,
mailProperties.getEmailAuthorizationCode(),
subject, text);
return Result.success("Verification code sent to " + userName);
}*/
/**
*
* @param
* @param studentRegistryDTO
* @return
*/
/* @PostMapping("/registry")
@ApiOperation("学生注册")
public Result<StudentRegistryVO> registry(@RequestBody StudentRegistryDTO studentRegistryDTO) {
String storedCode = verificationCodeStore.get(studentRegistryDTO.getUserName());
StudentRegistryVO studentRegistryVO = new StudentRegistryVO();
// debug
// System.out.println(studentRegistryDTO.getName());
if(storedCode != null && storedCode.equals(studentRegistryDTO.getVerificationCode())) {
// 验证码正确,完成注册逻辑
// 在此可以进行密码加密、保存数据库等操作
studentRegistryVO.setRegistrationStatus("Registration Successful");
// 将账号密码等信息存入数据库
StudentDTO studentDTO = new StudentDTO();
BeanUtils.copyProperties(studentRegistryDTO, studentDTO);
// debug
// System.out.println(studentDTO.getName());
studentService.addStudent(studentDTO);
// 注册成功后删除验证码
verificationCodeStore.remove(studentRegistryDTO.getUserName());
} else {
studentRegistryVO.setRegistrationStatus("Invalid Verification Code");
}
return Result.success(studentRegistryVO);
}*/
/**
*
* @param studentLoginDTO
* @return
*/
@PostMapping("/login")
@ApiOperation("学生登录")
public Result<StudentLoginVO> login(@RequestBody StudentLoginDTO studentLoginDTO) {
log.info("学生登录: {}", studentLoginDTO);
Student student = studentService.login(studentLoginDTO);
if (student == null) throw new LoginFailedException("账号或密码错误!");
// 调试部分
// System.out.println(admin);
// 生成jwt
Map<String, Object> claims = new HashMap<>();
claims.put(JwtClaimsConstant.STUDENT_ID, student.getId());
// 调试部分
// System.out.println(claims);
String token = jwtUtils.createJWT(claims);
// 调试部分
// System.out.println(claims);
// System.out.println(token);
StudentLoginVO studentLoginVO = StudentLoginVO.builder()
.name(student.getName())
.studentId(student.getStudentId())
.token(token)
.build();
return Result.success(studentLoginVO);
}
/**
* 退
* @return
*/
@PostMapping("/logout")
@ApiOperation("退出登录")
public Result<String> logout() {
return Result.success();
}
/**
*
* @param courseDTO
*/
@PostMapping("/joinCourse")
@ApiOperation("加入班级")
public Result joinCourse(@RequestBody CourseDTO courseDTO) {
log.info("加入课程: {}", courseDTO);
StudentDTO studentDTO = new StudentDTO();
Student student = studentMapper.getById(BaseContext.getCurrentId());
BeanUtils.copyProperties(student, studentDTO);
studentService.joinCourse(studentDTO, courseDTO);
return Result.success();
}
/**
* 退
* @param courseDTO
*/
@PostMapping("/dropCourse")
@ApiOperation("退出班级")
public Result dropCourse(@RequestBody CourseDTO courseDTO) {
log.info("退出课程: {}", courseDTO);
Student student = studentMapper.getById(BaseContext.getCurrentId());
StudentDTO studentDTO = new StudentDTO();
BeanUtils.copyProperties(student, studentDTO);
studentService.dropCourse(courseDTO, studentDTO);
return Result.success();
}
/**
*
* @return
*/
@GetMapping("/courseList")
@ApiOperation("查询所有的班级")
public Result<List<CourseVO>> courseList() {
log.info("查询所有班级");
return Result.success(courseService.courseList());
}
/**
*
* @param
*/
@GetMapping("/ownCourseList")
@ApiOperation("查询自己加入的班级")
public Result<List<CourseVO>> ownCourseList() {
log.info("查询自己加入的班级");
return Result.success(studentService.courseList());
}
/**
*
* @param courseId
* @return
*/
@GetMapping("/courseInfo")
@ApiOperation("查询自己的课程信息")
public Result<StudentCourseInfoVO> courseInfo(int courseId) {
log.info("查询自己的某门课程信息: {}", courseId);
int studentId = studentService.getById(BaseContext.getCurrentId()).getStudentId();
return Result.success(studentService.getStudentCourseInfo(studentId, courseId));
}
/**
*
* @param courseId
* @param studentPageQueryDTO
* @return
*/
@PostMapping("/callRecord")
@ApiOperation("查询自己某门课程的历次点名记录")
public Result<PageResult> callRecord(@RequestBody StudentPageQueryDTO studentPageQueryDTO,
int courseId) {
log.info("查询自己某门课程{}的历次点名记录: {}", courseId, studentPageQueryDTO);
PageResult pageResult = studentService.getCallRecord(studentPageQueryDTO, courseId);
return Result.success(pageResult);
}
/**
*
* @param studentPageQueryDTO
* @param courseId
* @return
*/
@PostMapping("/pageQuery4Course")
@ApiOperation("分页查询学生(按课程积分排名)")
public Result<PageResult> pageQuery4Course(@RequestBody StudentPageQueryDTO studentPageQueryDTO,
int courseId) {
log.info("课程{}的学生查询: {}", courseId, studentPageQueryDTO);
PageResult pageResult = studentService.pageQuery(studentPageQueryDTO, courseId);
return Result.success(pageResult);
}
/**
*
* @param studentDTO
*/
@PutMapping("/changePassword")
public Result<String> changePassword(@RequestBody StudentDTO studentDTO) {
log.info("修改密码: {}", studentDTO);
studentService.changePassword(studentDTO);
return Result.success();
}
}

@ -0,0 +1,20 @@
package com.wbq.dto;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
// 管理前端传递的参数
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class AdminDTO {
// 姓名
String name;
// 账号
int adminId;
// 密码
String password;
}

@ -0,0 +1,15 @@
package com.wbq.dto;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
@Data
@ApiModel(description = "管理员登录时传递的数据模型")
public class AdminLoginDTO {
@ApiModelProperty("账号")
private int adminId;
@ApiModelProperty("密码")
private String password;
}

@ -0,0 +1,19 @@
package com.wbq.dto;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class AdminRegistryDTO {
// 管理员账号
private int adminId;
// 姓名
private String name;
// 密码
private String password;
}

@ -0,0 +1,15 @@
package com.wbq.dto;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class CourseDTO {
int courseId;
String description;
}

@ -0,0 +1,19 @@
package com.wbq.dto;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class StudentDTO {
// 学号暨账号
int studentId;
// 姓名
String name;
// 密码
String password;
}

@ -0,0 +1,15 @@
package com.wbq.dto;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
@Data
@ApiModel(description = "学生登录时传递的数据模型")
public class StudentLoginDTO {
@ApiModelProperty("账号")
private int studentId;
@ApiModelProperty("密码")
private String password;
}

@ -0,0 +1,15 @@
package com.wbq.dto;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class StudentPageQueryDTO {
int page;
int pageSize;
}

@ -0,0 +1,23 @@
package com.wbq.dto;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class StudentRegistryDTO {
// 学号
private int studentId;
// 真实姓名
private String name;
// qq邮箱
private String userName;
// 密码
private String password;
// 验证码
private String verificationCode;
}

@ -0,0 +1,27 @@
package com.wbq.entity;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.io.Serializable;
import java.util.List;
// 整个项目所用到的实体参数数据
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class Admin implements Serializable {
private static final long serialVersionUID = 1L;
private int id;
//账号名暨管理员id
private int adminId;
//密码
private String password;
// 姓名
private String name;
// 管理的课程
private List<Course> courseList;
}

@ -0,0 +1,32 @@
package com.wbq.entity;
import com.fasterxml.jackson.annotation.JsonFormat;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.io.Serializable;
import java.time.LocalDateTime;
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class CallRecord implements Serializable {
private static final long serialVersionUID = 1L;
// id
private int id;
// 时间
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
private LocalDateTime callTime;
// 课程
private String courseDescription;
// 管理员
private String adminName;
// 加分
private double score;
// 学号
private int studentId;
}

@ -0,0 +1,25 @@
package com.wbq.entity;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.io.Serializable;
import java.util.List;
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class Course implements Serializable {
private static final long serialVersionUID = 1L;
// 课程id
private int courseId;
// 课程描述
private String description;
// 课程学生
private List<Student> studentList;
// 课程管理员
private List<Admin> adminList;
}

@ -0,0 +1,18 @@
package com.wbq.entity;
import com.wbq.dto.CourseDTO;
import com.wbq.dto.StudentDTO;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class EnrollRequest {
private StudentDTO student;
private CourseDTO course;
}

@ -0,0 +1,27 @@
package com.wbq.entity;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.io.Serializable;
import java.util.List;
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class Student implements Serializable {
private static final long serialVersionUID = 1L;
private int id;
// 学号暨学生登录账号
private int studentId;
// 姓名
private String name;
// 密码
private String password;
// 参与的课程
private List<Course> courseList;
}

@ -0,0 +1,10 @@
package com.wbq.exception;
// 管理项目中出现的异常
public class AccountNotFoundException extends BaseException{
public AccountNotFoundException() {
}
public AccountNotFoundException(String msg) {
super(msg);
}
}

@ -0,0 +1,11 @@
package com.wbq.exception;
/**
*
*/
public class BaseException extends RuntimeException{
public BaseException(){}
public BaseException(String msg) {
super(msg);
}
}

@ -0,0 +1,10 @@
package com.wbq.exception;
public class LoginFailedException extends BaseException{
public LoginFailedException() {
}
public LoginFailedException(String msg) {
super(msg);
}
}

@ -0,0 +1,10 @@
package com.wbq.exception;
public class PasswordEditFailedException extends BaseException{
public PasswordEditFailedException() {
}
public PasswordEditFailedException(String msg) {
super(msg);
}
}

@ -0,0 +1,10 @@
package com.wbq.exception;
public class PasswordErrorException extends BaseException{
public PasswordErrorException() {
}
public PasswordErrorException(String msg) {
super(msg);
}
}

@ -0,0 +1,10 @@
package com.wbq.exception;
public class StudentNotLoginException extends BaseException{
public StudentNotLoginException() {
}
public StudentNotLoginException(String msg) {
super(msg);
}
}

@ -0,0 +1,59 @@
package com.wbq.interceptor;
import com.wbq.constant.JwtClaimsConstant;
import com.wbq.context.BaseContext;
import com.wbq.properties.JwtProperties;
import com.wbq.utils.JwtUtils;
import io.jsonwebtoken.Claims;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.HandlerInterceptor;
// token拦截器
@Component
@Slf4j
public class JwtTokenAdminInterceptor implements HandlerInterceptor {
@Autowired
private JwtProperties jwtProperties;
@Autowired
private JwtUtils jwtUtils;
/**
* jwt
*
* @param request
* @param response
* @param handler
* @return
* @throws Exception
*/
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
// 判断是否需要拦截,如果请求静态资源就不需要拦截
if (!(handler instanceof HandlerMethod))
return true;
// 从请求头获取令牌
String token = request.getHeader(jwtProperties.getAdminTokenName());
// 校验令牌
try{
Claims claims = jwtUtils.parseJWT(token);
Integer adminId = Integer.valueOf(claims.get(JwtClaimsConstant.ADMIN_ID).toString());
log.info("当前管理员id: {}", adminId);
BaseContext.setCurrentId(adminId);
// 放行
return true;
} catch (Exception ex) {
response.setStatus(401);
return false;
}
}
}

@ -0,0 +1,59 @@
package com.wbq.interceptor;
import com.wbq.constant.JwtClaimsConstant;
import com.wbq.context.BaseContext;
import com.wbq.properties.JwtProperties;
import com.wbq.utils.JwtUtils;
import io.jsonwebtoken.Claims;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.HandlerInterceptor;
@Component
@Slf4j
public class JwtTokenStudentInterceptor implements HandlerInterceptor {
@Autowired
private JwtProperties jwtProperties;
@Autowired
private JwtUtils jwtUtils;
/**
* jwt
*
* @param request
* @param response
* @param handler
* @return
* @throws Exception
*/
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
// 判断是否需要拦截,如果请求静态资源就不需要拦截
if (!(handler instanceof HandlerMethod))
return true;
// 从请求头获取令牌
String token = request.getHeader(jwtProperties.getStudentTokenName());
// 校验令牌
try{
Claims claims = jwtUtils.parseJWT(token);
Integer studentId = Integer.valueOf(claims.get(JwtClaimsConstant.STUDENT_ID).toString());
log.info("当前学生id: {}", studentId);
BaseContext.setCurrentId(studentId);
// 放行
return true;
} catch (Exception ex) {
response.setStatus(401);
return false;
}
}
}

@ -0,0 +1,24 @@
package com.wbq.mapper;
import org.apache.ibatis.annotations.Delete;
import org.apache.ibatis.annotations.Insert;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Select;
import java.util.List;
// mapper层操作数据库
@Mapper
public interface AdminCourseMapper {
@Insert("insert into rollcall.admincourse (admin_id, course_id) " +
"values (#{adminId}, #{courseId})")
void insert(int adminId, int courseId);
@Delete("delete from rollcall.admincourse " +
"where admin_id = #{adminId} and course_id = #{courseId}")
void delete(int adminId, int courseId);
@Select("select course_id from rollcall.admincourse " +
"where admin_id = #{adminId}")
List<Integer> getByAdminId(int adminId);
}

@ -0,0 +1,56 @@
package com.wbq.mapper;
import com.wbq.dto.AdminDTO;
import com.wbq.dto.AdminLoginDTO;
import com.wbq.entity.Admin;
import org.apache.ibatis.annotations.Insert;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Select;
@Mapper
public interface AdminMapper {
/**
*
* @param adminDTO
*/
void update(AdminDTO adminDTO);
/**
*
* @param adminLoginDTO
* @return
*/
Admin getByAdminLoginDTO(AdminLoginDTO adminLoginDTO);
/**
* id
* @param id
*/
@Select("select * from rollcall.admin " +
"where id = #{id}")
Admin getById(int id);
/**
*
* @param adminDTO
*/
@Insert("insert into rollcall.admin " +
"(admin_id, name, password) " +
"values " +
"(#{adminId}, #{name}, #{password})")
void insert(AdminDTO adminDTO);
/**
*
* @param adminId
* @return
*/
String getPasswordByAdminId(int adminId);
/**
*
* @param adminId
* @return
*/
Admin getByAdminId(int adminId);
}

@ -0,0 +1,32 @@
package com.wbq.mapper;
import com.github.pagehelper.Page;
import com.wbq.dto.StudentPageQueryDTO;
import com.wbq.entity.CallRecord;
import org.apache.ibatis.annotations.Insert;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Select;
import java.util.List;
@Mapper
public interface CallRecordMapper {
@Select("select * from rollcall.callrecord " +
"where student_id = #{studentId} and " +
"callrecord.course_description = #{courseDescription} " +
"order by call_time desc")
Page<CallRecord> pageQuery(StudentPageQueryDTO studentPageQueryDTO, int studentId, String courseDescription);
@Insert("insert into rollcall.callrecord " +
"(call_time, course_description, admin_name, score, student_id) " +
"values " +
"(#{callTime}, #{courseDescription}, #{adminName}, #{score}, #{studentId})")
void insert(CallRecord CallRecord);
void update(CallRecord callRecord);
@Select("select * from rollcall.callrecord " +
"where student_id = #{studentId} " +
"order by call_time desc")
List<CallRecord> getByStudentId(int studentId);
}

@ -0,0 +1,29 @@
package com.wbq.mapper;
import com.wbq.dto.CourseDTO;
import com.wbq.entity.Course;
import io.swagger.models.auth.In;
import org.apache.ibatis.annotations.Insert;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Select;
import java.util.List;
@Mapper
public interface CourseMapper {
@Select("select * from rollcall.course")
List<Course> getCourses();
List<Course> getByCourseIdList(List<Integer> courseIdList);
@Insert("insert into rollcall.course " +
"(course_id, description) " +
"values (#{courseId}, #{description})")
void insert(CourseDTO courseDTO);
@Select("select * from rollcall.course " +
"where course_id = #{courseId}")
Course getByCourseId(int courseId);
Boolean existsByCourseId(int courseId);
}

@ -0,0 +1,61 @@
package com.wbq.mapper;
import com.github.pagehelper.Page;
import com.wbq.dto.StudentDTO;
import com.wbq.vo.StudentCourseInfoVO;
import org.apache.ibatis.annotations.*;
import java.util.List;
@Mapper
public interface StudentCourseMapper {
@Insert("insert into studentcourse (student_id, course_id) " +
"values (#{studentId}, #{courseId})")
void insert(int studentId, int courseId);
@Select("select course_id from rollcall.studentcourse " +
"where student_id = #{studentId}")
List<Integer> getByStudentId(int studentId);
@Select("select student_id from rollcall.studentcourse " +
"where course_id = #{courseId} " +
"order by score desc")
List<Integer> getByCourseId(int courseId);
@Select("select s.student_id, s.name, sc.call_count, sc.score " +
"from rollcall.students s " +
"join rollcall.studentcourse sc on s.student_id = sc.student_id " +
"where sc.student_id = #{studentId} and sc.course_id = #{courseId}")
StudentCourseInfoVO getCourseInfo(int studentId, int courseId);
@Select("select s.student_id, s.name, sc.call_count, sc.score " +
"from rollcall.students s " +
"join rollcall.studentcourse sc on s.student_id = sc.student_id " +
"where sc.course_id = #{courseId} " +
"order by sc.score desc")
Page<StudentCourseInfoVO> pageQuery4CourseInfo(int courseId);
@Delete("delete from rollcall.studentcourse " +
"where student_id = #{studentId} and course_id = #{courseId}")
void delete(int studentId, int courseId);
@Update("update rollcall.studentcourse " +
"set call_count = #{callCount} " +
"where student_id = #{studentId} and course_id = #{courseId}")
void updateCallCountByStudentIdAndCourseId(int callCount, int studentId, int courseId);
@Update("update rollcall.studentcourse " +
"set score = #{score} " +
"where student_id = #{studentId} and course_id = #{courseId}")
void updateScoreByStudentIdAndCourseId(double score, int studentId, int courseId);
/**
*
* @param courseId
* @param studentDTOs
*/
void batchInsert(@Param("list") List<StudentDTO> studentDTOs, int courseId);
}

@ -0,0 +1,109 @@
package com.wbq.mapper;
import com.github.pagehelper.Page;
import com.wbq.dto.AdminLoginDTO;
import com.wbq.dto.StudentDTO;
import com.wbq.dto.StudentLoginDTO;
import com.wbq.dto.StudentPageQueryDTO;
import com.wbq.entity.Admin;
import com.wbq.entity.Student;
import org.apache.ibatis.annotations.*;
import org.springframework.aop.target.SingletonTargetSource;
import java.util.List;
@Mapper
public interface StudentMapper {
/**
*
* @return
*/
@Select("select * from rollcall.students")
List<Student> getAllStudent();
/**
* id
* @param id
* @return
*/
@Select("select * from rollcall.students where id = #{id}")
Student getById(int id);
/**
*
* @param studentId
* @return
*/
@Select("select * from rollcall.students where student_id = #{studentId}")
Student getByStudentId(int studentId);
/**
*
* @param studentPageQueryDTO
* @return
*/
Page<Student> pageQuery(StudentPageQueryDTO studentPageQueryDTO, List<Integer> studentIds);
/**
*
* @param minCount
* @param maxCount
* @return
*/
/*List<Student> getByCallCount(int minCount, int maxCount);*/
/**
*
* @param studentDTO
*/
/*void update(StudentDTO studentDTO);*/
/**
*
* @param studentDTO
*/
/* @Insert("insert into students (student_id, name, password)" +
"values(#{studentId}, #{name}, #{password})")
void insert (StudentDTO studentDTO);*/
/**
* studentId
* @param studentId
*/
/* @Delete("delete from rollcall.students where student_id = #{studentId}")
void deleteByStudentId(int studentId);*/
/**
*
* @param studentLoginDTO
* @return
*/
Student getByStudentLoginDTO(StudentLoginDTO studentLoginDTO);
/**
* ids
* @param ids
* @return
*/
List<Student> getByStudentIds (List<Integer> ids);
/**
*
* @param studentId
* @return
*/
String getPasswordByStudentId(int studentId);
/**
*
* @param studentDTO
* @return
*/
void update(StudentDTO studentDTO);
/**
*
* @param studentDTOs
*/
void batchInsert(@Param("list") List<StudentDTO> studentDTOs);
}

@ -0,0 +1,20 @@
package com.wbq.properties;
import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;
// 配置参数
@Data
@ConfigurationProperties(prefix = "wbq.jwt")
@Component
public class JwtProperties {
// 管理员端
private String adminSecretKey;
private String adminTokenName;
private long adminTtl;
// 学生端
private String studentSecretKey;
private String studentTokenName;
private long studentTtl;
}

@ -0,0 +1,13 @@
package com.wbq.properties;
import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;
@Data
@ConfigurationProperties(prefix = "wbq.qq")
@Component
public class MailProperties {
private String emailCount;
private String emailAuthorizationCode;
}

@ -0,0 +1,17 @@
package com.wbq.result;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.io.Serializable;
import java.util.List;
// 管理返回前端的数据
@Data
@AllArgsConstructor
@NoArgsConstructor
public class PageResult implements Serializable {
private long total; //总记录数
private List records; //当前页数据集合
}

@ -0,0 +1,36 @@
package com.wbq.result;
import lombok.Data;
import java.io.Serializable;
/**
*
* @param <T>
*/
@Data
public class Result<T> implements Serializable {
private Integer code; // 编码1成功0和其他数字为失败
private String msg; // 错误信息
private T data; // 数据
public static <T> Result<T> success() {
Result<T> result = new Result<>();
result.code = 1;
return result;
}
public static <T> Result<T> success(T object) {
Result<T> result = new Result<>();
result.code = 1;
result.data = object;
return result;
}
public static <T> Result<T> error(String msg) {
Result<T> result = new Result<>();
result.code = 0;
result.msg = msg;
return result;
}
}

@ -0,0 +1,61 @@
package com.wbq.service;
import com.wbq.dto.*;
import com.wbq.entity.Admin;
import com.wbq.vo.CourseVO;
import java.util.List;
public interface AdminService {
/**
*
* @param adminDTO
*/
void update(AdminDTO adminDTO);
/**
*
* @param adminLoginDTO
* @return
*/
Admin login(AdminLoginDTO adminLoginDTO);
/**
* id
* @param id
* @return
*/
Admin getById(int id);
/**
*
* @param adminDTO
* @param courseDTO
*/
void addCourse(AdminDTO adminDTO, CourseDTO courseDTO);
/**
* 退
* @param adminDTO
* @param courseDTO
*/
void dropCourse(AdminDTO adminDTO, CourseDTO courseDTO);
/**
*
* @return
*/
List<CourseVO> courseList();
/**
*
* @param adminDTO
*/
void addAdmin(AdminDTO adminDTO);
/**
*
* @param adminDTO
*/
void changePassword(AdminDTO adminDTO);
}

@ -0,0 +1,22 @@
package com.wbq.service;
import com.wbq.dto.CourseDTO;
import com.wbq.vo.CourseVO;
import java.util.List;
public interface CourseService {
/**
*
* @return
*/
List<CourseVO> courseList();
/**
*
* @param courseDescription
*/
int addCourse(String courseDescription);
}

@ -0,0 +1,142 @@
package com.wbq.service;
import com.wbq.dto.CourseDTO;
import com.wbq.dto.StudentDTO;
import com.wbq.dto.StudentLoginDTO;
import com.wbq.dto.StudentPageQueryDTO;
import com.wbq.entity.Student;
import com.wbq.result.PageResult;
import com.wbq.vo.CourseCallVO;
import com.wbq.vo.CourseVO;
import com.wbq.vo.StudentCourseInfoVO;
import org.springframework.web.multipart.MultipartFile;
import java.util.List;
public interface StudentService {
/**
* id
* @param id
* @return
*/
Student getById(int id);
/**
*
* @param studentDTO
*/
void update(StudentDTO studentDTO);
/**
*
* @param studentPageQueryDTO
* @param courseId
* @return
*/
PageResult pageQuery(StudentPageQueryDTO studentPageQueryDTO, int courseId);
/**
*
* @param courseId
* @param studentIds
* @return
*/
Student coreCall(int courseId, List<Integer> studentIds);
/**
*
* @param courseId
* @return
*/
StudentCourseInfoVO callStudent(int courseId);
/**
*
* @param courseId
* @param firstname
* @return
*/
StudentCourseInfoVO callStudentByFirstname(int courseId, String firstname);
/**
*
* @param courseId
* @param lastNum
* @return
*/
StudentCourseInfoVO callStudentByLastNum(int courseId, int lastNum);
/**
*
* @param courseDTO
* @param studentDTO
* @param score
* @return
*/
StudentCourseInfoVO addScore(CourseDTO courseDTO, StudentDTO studentDTO, double score);
/**
*
* @param studentLoginDTO
* @return
*/
Student login(StudentLoginDTO studentLoginDTO);
/**
*
* @param studentDTO
* @param courseDTO
*/
void joinCourse(StudentDTO studentDTO, CourseDTO courseDTO);
/**
* 退
* @param courseDTO
* @param studentDTO
*/
void dropCourse(CourseDTO courseDTO, StudentDTO studentDTO);
/**
*
* @return
*/
List<CourseVO> courseList();
/**
*
* @param studentId
* @param courseId
* @return
*/
StudentCourseInfoVO getStudentCourseInfo(int studentId, int courseId);
/**
*
* @param courseId
* @param studentDTOs
*/
void batchAddStudents(List<StudentDTO> studentDTOs, int courseId);
/**
* Excel
* @param file
* @return
* @throws Exception
*/
List<StudentDTO> parseExcel(MultipartFile file) throws Exception;
/**
*
* @param courseId
* @param studentPageQueryDTO
* @return
*/
PageResult getCallRecord(StudentPageQueryDTO studentPageQueryDTO, int courseId);
/**
*
* @param studentDTO
*/
void changePassword(StudentDTO studentDTO);
}

@ -0,0 +1,134 @@
package com.wbq.service.impl;
import com.wbq.context.BaseContext;
import com.wbq.dto.AdminDTO;
import com.wbq.dto.AdminLoginDTO;
import com.wbq.dto.CourseDTO;
import com.wbq.dto.StudentDTO;
import com.wbq.entity.Admin;
import com.wbq.entity.Course;
import com.wbq.entity.Student;
import com.wbq.mapper.AdminCourseMapper;
import com.wbq.mapper.AdminMapper;
import com.wbq.mapper.CourseMapper;
import com.wbq.service.AdminService;
import com.wbq.vo.CourseVO;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.crypto.bcrypt.BCrypt;
import org.springframework.stereotype.Service;
import java.util.ArrayList;
import java.util.List;
// service服务层业务代码
@Service
public class AdminServiceImpl implements AdminService {
@Autowired
private AdminMapper adminMapper;
@Autowired
private AdminCourseMapper adminCourseMapper;
@Autowired
private CourseMapper courseMapper;
/**
*
* @param adminDTO
*/
@Override
public void update(AdminDTO adminDTO) {
adminMapper.update(adminDTO);
}
/**
*
* @param adminLoginDTO
* @return
*/
@Override
public Admin login(AdminLoginDTO adminLoginDTO) {
Admin admin = null;
String hashedPassword = adminMapper.getPasswordByAdminId(adminLoginDTO.getAdminId());
// 使用BCrypt的checkpw方法来验证密码
boolean isPasswordCorrect = BCrypt.checkpw(adminLoginDTO.getPassword(), hashedPassword);
// 验证成功
if (isPasswordCorrect)
admin = adminMapper.getByAdminId(adminLoginDTO.getAdminId());
return admin;
}
/**
* id
* @param id
* @return
*/
@Override
public Admin getById(int id) {
return adminMapper.getById(id);
}
/**
*
* @param adminDTO
* @param courseDTO
*/
@Override
public void addCourse(AdminDTO adminDTO, CourseDTO courseDTO) {
adminCourseMapper.insert(adminDTO.getAdminId(), courseDTO.getCourseId());
}
/**
* 退
* @param adminDTO
* @param courseDTO
*/
@Override
public void dropCourse(AdminDTO adminDTO, CourseDTO courseDTO) {
adminCourseMapper.delete(adminDTO.getAdminId(), courseDTO.getCourseId());
}
/**
*
* @return
*/
@Override
public List<CourseVO> courseList() {
Admin admin = adminMapper.getById(BaseContext.getCurrentId());
int adminId = admin.getAdminId();
List<Integer> courseIds = adminCourseMapper.getByAdminId(adminId);
List<Course> courseList = courseMapper.getByCourseIdList(courseIds);
List<CourseVO> courseVOList = new ArrayList<>();
for (Course course : courseList) {
CourseVO courseVO = new CourseVO();
BeanUtils.copyProperties(course, courseVO);
courseVOList.add(courseVO);
}
return courseVOList;
}
/**
*
* @param adminDTO
*/
@Override
public void addAdmin(AdminDTO adminDTO) {
String hashPassword = BCrypt.hashpw(adminDTO.getPassword(), BCrypt.gensalt());
adminDTO.setPassword(hashPassword);
adminMapper.insert(adminDTO);
}
/**
*
* @param adminDTO
*/
@Override
public void changePassword(AdminDTO adminDTO) {
String password = adminDTO.getPassword();
String hashedPassword = BCrypt.hashpw(password, BCrypt.gensalt());
adminDTO.setPassword(hashedPassword);
adminMapper.update(adminDTO);
}
}

@ -0,0 +1,59 @@
package com.wbq.service.impl;
import com.fasterxml.jackson.databind.util.BeanUtil;
import com.wbq.dto.CourseDTO;
import com.wbq.entity.Course;
import com.wbq.mapper.CourseMapper;
import com.wbq.service.CourseService;
import com.wbq.vo.CourseVO;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.ArrayList;
import java.util.List;
import java.util.Random;
@Service
public class CourseServiceImpl implements CourseService {
@Autowired
private CourseMapper courseMapper;
/**
*
* @return
*/
@Override
public List<CourseVO> courseList() {
List<Course> courseList = courseMapper.getCourses();
List<CourseVO> courseVOList = new ArrayList<>();
for (Course course : courseList) {
CourseVO courseVO = new CourseVO();
BeanUtils.copyProperties(course, courseVO);
courseVOList.add(courseVO);
}
return courseVOList;
}
/**
*
* @param courseDescription
*/
@Override
public int addCourse(String courseDescription) {
Random random = new Random();
int courseId = 10000 + random.nextInt(90000);
while (courseMapper.existsByCourseId(courseId)) {
courseId = 10000 + random.nextInt(90000);
}
CourseDTO courseDTO = CourseDTO.builder()
.courseId(courseId)
.description(courseDescription)
.build();
courseMapper.insert(courseDTO);
return courseId;
}
}

@ -0,0 +1,393 @@
package com.wbq.service.impl;
import com.github.pagehelper.Page;
import com.github.pagehelper.PageHelper;
import com.wbq.context.BaseContext;
import com.wbq.dto.CourseDTO;
import com.wbq.dto.StudentDTO;
import com.wbq.dto.StudentLoginDTO;
import com.wbq.dto.StudentPageQueryDTO;
import com.wbq.entity.CallRecord;
import com.wbq.entity.Course;
import com.wbq.entity.Student;
import com.wbq.mapper.*;
import com.wbq.result.PageResult;
import com.wbq.service.StudentService;
import com.wbq.vo.CourseCallVO;
import com.wbq.vo.CourseVO;
import com.wbq.vo.StudentCourseInfoVO;
import org.apache.poi.ss.usermodel.*;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.crypto.bcrypt.BCrypt;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;
import javax.print.attribute.IntegerSyntax;
import java.io.InputStream;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Random;
@Service
public class StudentServiceImpl implements StudentService {
@Autowired
private StudentMapper studentMapper;
@Autowired
private StudentCourseMapper studentCourseMapper;
@Autowired
private CourseMapper courseMapper;
@Autowired
private CallRecordMapper callRecordMapper;
@Autowired
private AdminMapper adminMapper;
@Override
public Student getById(int id) {
return studentMapper.getById(id);
}
/**
*
* @param studentDTO
*/
@Override
public void update(StudentDTO studentDTO) {
studentMapper.update(studentDTO);
}
/**
*
* @param studentPageQueryDTO
* @param courseId
* @return
*/
@Override
public PageResult pageQuery(StudentPageQueryDTO studentPageQueryDTO, int courseId) {
PageHelper.startPage(studentPageQueryDTO.getPage(), studentPageQueryDTO.getPageSize());
Page<StudentCourseInfoVO> page = studentCourseMapper.pageQuery4CourseInfo(courseId);
return new PageResult(page.getTotal(), page.getResult());
}
/**
*
* @param courseId
* @param studentIds
* @return
*/
@Override
public Student coreCall(int courseId, List<Integer> studentIds) {
// 生成权重
double totalWeight = 0;
for (int studentId : studentIds) {
StudentCourseInfoVO studentCourseInfoVO = studentCourseMapper.getCourseInfo(studentId, courseId);
double studentScore = studentCourseInfoVO.getScore();
totalWeight += 1.0/(studentScore + 1);
}
double cumulativeWeight = 0;
Random random = new Random();
double rand = random.nextDouble();
int selectedStudentId = 0;
// 轮盘赌算法
for (int studentId : studentIds) {
StudentCourseInfoVO studentCourseInfoVO = studentCourseMapper.getCourseInfo(studentId, courseId);
double studentScore = studentCourseInfoVO.getScore();
cumulativeWeight += 1.0/(studentScore + 1);
if (cumulativeWeight >= rand*totalWeight) {
selectedStudentId = studentId;
break;
}
}
// 增加被叫次数
int oldCallCount = studentCourseMapper.getCourseInfo(selectedStudentId, courseId).getCallCount();
int newCallCount = oldCallCount + 1;
studentCourseMapper.updateCallCountByStudentIdAndCourseId(newCallCount, selectedStudentId, courseId);
Student selectedStudent = studentMapper.getByStudentId(selectedStudentId);
// 生成点名记录
CallRecord callRecord = CallRecord.builder()
.callTime(LocalDateTime.now())
.courseDescription(courseMapper.getByCourseId(courseId).getDescription())
.adminName(adminMapper.getById(BaseContext.getCurrentId()).getName())
.studentId(selectedStudentId)
.build();
callRecordMapper.insert(callRecord);
return selectedStudent;
}
/**
*
* @param courseId
* @return
*/
@Override
public StudentCourseInfoVO callStudent(int courseId) {
List<Integer> studentIds = studentCourseMapper.getByCourseId(courseId);
Student selectedStudent = coreCall(courseId, studentIds);
StudentCourseInfoVO studentCourseInfoVO = studentCourseMapper.getCourseInfo(selectedStudent.getStudentId(), courseId);
return studentCourseInfoVO;
}
/**
*
* @param courseId
* @param firstname
* @return
*/
@Override
public StudentCourseInfoVO callStudentByFirstname(int courseId, String firstname) {
List<Integer> studentIds = studentCourseMapper.getByCourseId(courseId);
// 筛选方式
Iterator<Integer> iterator = studentIds.iterator();
while (iterator.hasNext()) {
Integer studentId = iterator.next();
Student student = studentMapper.getByStudentId(studentId);
String studentName = student.getName();
if (!firstname.equals(Character.toString(studentName.charAt(0)))) {
iterator.remove(); // 使用 iterator.remove() 安全地移除元素
}
}
Student selectedStudent = coreCall(courseId, studentIds);
StudentCourseInfoVO studentCourseInfoVO = studentCourseMapper.getCourseInfo(selectedStudent.getStudentId(), courseId);
return studentCourseInfoVO;
}
/**
*
* @param courseId
* @param lastNum
* @return
*/
@Override
public StudentCourseInfoVO callStudentByLastNum(int courseId, int lastNum) {
List<Integer> studentIds = studentCourseMapper.getByCourseId(courseId);
// 筛选方式
Iterator<Integer> iterator = studentIds.iterator();
while (iterator.hasNext()) {
Integer studentId = iterator.next();
if (studentId % 10 != lastNum) {
iterator.remove(); // 使用 iterator.remove() 安全地移除元素
}
}
Student selectedStudent = coreCall(courseId, studentIds);
StudentCourseInfoVO studentCourseInfoVO = studentCourseMapper.getCourseInfo(selectedStudent.getStudentId(), courseId);
return studentCourseInfoVO;
}
/**
*
* @param courseDTO
* @param studentDTO
* @param score
* @return
*/
@Override
public StudentCourseInfoVO addScore(CourseDTO courseDTO, StudentDTO studentDTO, double score) {
double oldScore = studentCourseMapper.getCourseInfo(studentDTO.getStudentId(), courseDTO.getCourseId()).getScore();
studentCourseMapper.updateScoreByStudentIdAndCourseId(oldScore + score,
studentDTO.getStudentId(),
courseDTO.getCourseId());
// 返回更新值
StudentCourseInfoVO studentCourseInfoVO = studentCourseMapper.getCourseInfo(studentDTO.getStudentId(), courseDTO.getCourseId());
// 更新记录
List<CallRecord> callRecordList = callRecordMapper.getByStudentId(studentDTO.getStudentId());
CallRecord newCallRecord = callRecordList.getFirst();
newCallRecord.setScore(score);
callRecordMapper.update(newCallRecord);
return studentCourseInfoVO;
}
/**
*
* @param studentLoginDTO
* @return
*/
@Override
public Student login(StudentLoginDTO studentLoginDTO) {
Student student = null;
String hashedPassword = studentMapper.getPasswordByStudentId(studentLoginDTO.getStudentId());
// 使用BCrypt的checkpw方法来验证密码
boolean isPasswordCorrect = BCrypt.checkpw(studentLoginDTO.getPassword(), hashedPassword);
// 验证成功
if (isPasswordCorrect)
student = studentMapper.getByStudentId(studentLoginDTO.getStudentId());
return student;
}
/**
*
* @param courseDTO
*/
@Override
public void joinCourse(StudentDTO studentDTO, CourseDTO courseDTO) {
studentCourseMapper.insert(studentDTO.getStudentId(), courseDTO.getCourseId());
}
/**
* 退
* @param courseDTO
* @param studentDTO
*/
@Override
public void dropCourse(CourseDTO courseDTO, StudentDTO studentDTO) {
studentCourseMapper.delete(studentDTO.getStudentId(), courseDTO.getCourseId());
}
/**
*
* @return
*/
@Override
public List<CourseVO> courseList() {
int studentId = studentMapper.getById(BaseContext.getCurrentId()).getStudentId();
List<CourseVO> courseVOList = new ArrayList<>();
List<Integer> courseIdList = studentCourseMapper.getByStudentId(studentId);
List<Course> courseList = courseMapper.getByCourseIdList(courseIdList);
for (Course course : courseList) {
CourseVO courseVO = new CourseVO();
BeanUtils.copyProperties(course, courseVO);
courseVOList.add(courseVO);
}
return courseVOList;
}
/**
*
* @param studentId
* @param courseId
* @return
*/
@Override
public StudentCourseInfoVO getStudentCourseInfo(int studentId, int courseId) {
return studentCourseMapper.getCourseInfo(studentId, courseId);
}
/**
*
* @param courseId
* @param studentDTOs
*/
@Override
public void batchAddStudents(List<StudentDTO> studentDTOs, int courseId) {
if (studentDTOs != null && !studentDTOs.isEmpty()) {
for (StudentDTO studentDTO : studentDTOs) {
String initPassword = "1234";
String hashedPassword = BCrypt.hashpw(initPassword, BCrypt.gensalt());
studentDTO.setPassword(hashedPassword);
}
studentCourseMapper.batchInsert(studentDTOs, courseId);
}
}
/**
* Excel
* @param file
* @return
* @throws Exception
*/
@Override
public List<StudentDTO> parseExcel(MultipartFile file) throws Exception {
List<StudentDTO> studentDTOs = new ArrayList<>();
// 获取 Excel 文件的输入流
InputStream inputStream = file.getInputStream();
Workbook workbook = WorkbookFactory.create(inputStream);
// 学生信息在第一张表
Sheet sheet = workbook.getSheetAt(0);
for (Row row : sheet) {
// 跳过表头
/*if (row.getRowNum() == 0) {
continue;
}*/
StudentDTO studentDTO = new StudentDTO();
if(row.getRowNum() == 103) break;
//debug
System.out.println("第" + row.getRowNum() + "行");
System.out.println(row.getCell(0).getCellType() + " " +
row.getCell(1).getCellType() + " " +
row.getCell(2).getCellType());
if(row.getCell(0).getCellType() == CellType.STRING)
studentDTO.setStudentId(Integer.parseInt(row.getCell(0).getStringCellValue()));
else
studentDTO.setStudentId((int)row.getCell(0).getNumericCellValue()); // 学号
studentDTO.setName(row.getCell(1).getStringCellValue()); // 姓名
studentDTO.setPassword(row.getCell(2).getStringCellValue()); // 密码
studentDTOs.add(studentDTO);
}
workbook.close();
return studentDTOs;
}
/**
*
* @param courseId
* @param studentPageQueryDTO
* @return
*/
@Override
public PageResult getCallRecord(StudentPageQueryDTO studentPageQueryDTO, int courseId) {
int studentId = studentMapper.getById(BaseContext.getCurrentId()).getStudentId();
String courseDescription = courseMapper.getByCourseId(courseId).getDescription();
PageHelper.startPage(studentPageQueryDTO.getPage(), studentPageQueryDTO.getPageSize());
Page<CallRecord> page = callRecordMapper.pageQuery(studentPageQueryDTO, studentId, courseDescription);
List<CallRecord> callRecordList = page.getResult();
List<CourseCallVO> courseCallVOList = new ArrayList<>();
for (CallRecord callRecord : callRecordList) {
CourseCallVO courseCallVO = new CourseCallVO();
BeanUtils.copyProperties(callRecord, courseCallVO);
courseCallVOList.add(courseCallVO);
}
return new PageResult(page.getTotal(), courseCallVOList);
}
/**
*
* @param studentDTO
*/
@Override
public void changePassword(StudentDTO studentDTO) {
String password = studentDTO.getPassword();
String hashPassword = BCrypt.hashpw(password, BCrypt.gensalt());
studentDTO.setPassword(hashPassword);
studentMapper.update(studentDTO);
}
}

@ -0,0 +1,64 @@
package com.wbq.utils;
import com.wbq.properties.JwtProperties;
import io.jsonwebtoken.Claims;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import java.nio.charset.StandardCharsets;
import java.util.Date;
import java.util.Map;
// 实用工具集合
@Component
public class JwtUtils {
@Autowired
private JwtProperties jwtProperties;
/**
* jwt
* 使Hs256, 使
*
* @param claims
* @return
*/
public String createJWT(Map<String, Object> claims) {
// 设置签名算法
SignatureAlgorithm signatureAlgorithm = SignatureAlgorithm.HS256;
// 设置截止时间
long expMillis = System.currentTimeMillis() + jwtProperties.getAdminTtl();
Date exp = new Date(expMillis);
// debug
// System.out.println(claims);
// System.out.println(jwtProperties.getAdminSecretKey());
// 生成JWT
String JWT = Jwts.builder()
.setClaims(claims)
.signWith(signatureAlgorithm, jwtProperties.getAdminSecretKey().getBytes(StandardCharsets.UTF_8))
.setExpiration(exp)
.compact();
// debug
// System.out.println(claims);
return JWT;
}
/**
* Token
*
* @param token token
* @return
*/
public Claims parseJWT(String token) {
// 得到DefaultJwtParser
Claims claims = Jwts.parser()
.setSigningKey(jwtProperties.getAdminSecretKey().getBytes(StandardCharsets.UTF_8))
.parseClaimsJws(token)
.getBody();
return claims;
}
}

@ -0,0 +1,59 @@
package com.wbq.utils;
import com.wbq.constant.EmailConstant;
import jakarta.mail.Message;
import jakarta.mail.MessagingException;
import jakarta.mail.Session;
import jakarta.mail.Transport;
import jakarta.mail.internet.InternetAddress;
import jakarta.mail.internet.MimeMessage;
import org.springframework.stereotype.Component;
import java.util.Properties;
@Component
public class MailUtils {
/**
*
*
* @param fromEmail
* @param toEmail
* @param emailAuthorizationCode
* @param subject
* @param text
*/
public static void sendEmail(String fromEmail, String toEmail,
String emailAuthorizationCode,
String subject, String text) {
// 配置SMTP服务器的属性
Properties props = new Properties();
props.put("mail.smtp.host", EmailConstant.SMTP_HOST);
props.put("mail.smtp.port", EmailConstant.SMTP_HOST);
props.put("mail.smtp.auth", "true");
props.put("mail.smtp.ssl.enable", "true");
props.put("mail.smtp.socketFactory.class", "javax.net.ssl.SSLSocketFactory");
Session session = Session.getInstance(props, new jakarta.mail.Authenticator() {
protected jakarta.mail.PasswordAuthentication getPasswordAuthentication() {
return new jakarta.mail.PasswordAuthentication(fromEmail, emailAuthorizationCode);
}
});
try {
Message message = new MimeMessage(session);
message.setFrom(new InternetAddress(fromEmail));
message.setRecipients(Message.RecipientType.TO, InternetAddress.parse(toEmail));
message.setSubject(subject);
message.setText(text);
Transport.send(message);
System.out.println("邮件已发送成功!");
} catch (MessagingException e) {
e.printStackTrace();
}
}
}

@ -0,0 +1,24 @@
package com.wbq.vo;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
// 返回前端的可视化数据
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
@ApiModel(description = "管理员登录返回的数据格式")
public class AdminLoginVO {
@ApiModelProperty("账号")
private int adminId;
@ApiModelProperty("姓名")
private String name;
@ApiModelProperty("jwt令牌")
private String token;
}

@ -0,0 +1,14 @@
package com.wbq.vo;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class AdminRegistryVO {
private String registrationStatus;
}

@ -0,0 +1,28 @@
package com.wbq.vo;
import com.fasterxml.jackson.annotation.JsonFormat;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.io.Serializable;
import java.time.LocalDateTime;
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class CourseCallVO implements Serializable {
private static final long serialVersionUID = 1L;
// 时间
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
private LocalDateTime callTime;
// 课程
private String courseDescription;
// 管理员
private String adminName;
// 加分
private double score;
}

@ -0,0 +1,15 @@
package com.wbq.vo;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class CourseVO {
private int courseId;
private String description;
}

@ -0,0 +1,21 @@
package com.wbq.vo;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class StudentCourseInfoVO {
// 学号
private int studentId;
// 姓名
private String name;
// 被叫次数
private int callCount;
// 课程积分
private double score;
}

@ -0,0 +1,24 @@
package com.wbq.vo;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
@ApiModel(description = "学生登录返回的数据格式")
public class StudentLoginVO {
@ApiModelProperty("账号")
private int studentId;
@ApiModelProperty("姓名")
private String name;
@ApiModelProperty("jwt令牌")
private String token;
}

@ -0,0 +1,15 @@
package com.wbq.vo;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class StudentRegistryVO {
private String registrationStatus;
}

@ -0,0 +1,6 @@
spring:
datasource:
driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://localhost:3306/rollcall?serverTimezone=Asia/Shanghai&useUnicode=true&characterEncoding=utf-8&zeroDateTimeBehavior=convertToNull&useSSL=false&allowPublicKeyRetrieval=true
username: root
password: 1234

@ -0,0 +1,48 @@
server:
port: 8888
spring:
application:
name: RollCallSystem
profiles:
active: dev
main:
allow-circular-references: true
autoconfigure:
exclude: org.springframework.boot.autoconfigure.security.servlet.SecurityAutoConfiguration
jackson:
date-format: yyyy-MM-dd HH:mm:ss
time-zone: GMT+8
mybatis:
#mapper配置文件
mapper-locations: classpath:mapper/*.xml
configuration:
map-underscore-to-camel-case: true
logging:
level:
com:
wbq:
mapper: debug
service: info
controller: info
wbq:
jwt:
admin-secret-key: bugaoshuni
admin-token-name: admin_token
admin-ttl: 7200000
student-secret-key: yebugaoshuni
student-token-name: student_token
student-ttl: 7200000
qq:
email-count: 2108095381@qq.com
email-authorization-code: alwlqedbpbpfdgfc
knife4j:
enable: true
base-path: /doc

@ -0,0 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTO Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.wbq.mapper.AdminCourseMapper">
</mapper>

@ -0,0 +1,32 @@
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTO Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.wbq.mapper.AdminMapper">
<update id="update" parameterType="com.wbq.dto.AdminDTO">
update admin
<set>
<if test="name != null">
name = #{name},
</if>
<if test="password != null">
password = #{password}
</if>
</set>
where admin_id = #{adminId}
</update>
<select id="getByAdminLoginDTO" parameterType="com.wbq.dto.AdminLoginDTO" resultType="com.wbq.entity.Admin">
select * from admin
where admin_id = #{adminId} and password = #{password}
</select>
<select id="getPasswordByAdminId" resultType="java.lang.String" parameterType="java.lang.Integer">
select password from admin
where admin_id = #{adminId}
</select>
<select id="getByAdminId" resultType="com.wbq.entity.Admin" parameterType="java.lang.Integer">
select * from admin
where admin_id = #{adminId}
</select>
</mapper>

@ -0,0 +1,23 @@
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTO Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.wbq.mapper.CallRecordMapper">
<update id="update" parameterType="com.wbq.entity.CallRecord">
update callrecord
<set>
<if test="callTime != null">
call_time = #{callTime},
</if>
<if test="courseDescription != null">
course_description = #{courseDescription},
</if>
<if test="adminName != null">
admin_name = #{adminName},
</if>
<if test="score != null">
score = #{score}
</if>
where id = #{id}
</set>
</update>
</mapper>

@ -0,0 +1,18 @@
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTO Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.wbq.mapper.CourseMapper">
<select id="getByCourseIdList" resultType="com.wbq.entity.Course">
select * from course
where course_id in
<foreach collection="courseIdList" item="id" open="(" separator="," close=")">
#{id}
</foreach>
</select>
<select id="existsByCourseId" resultType="boolean">
select exists (select 1 from course where course_id = #{courseId})
</select>
</mapper>

@ -0,0 +1,11 @@
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTO Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.wbq.mapper.StudentCourseMapper">
<insert id="batchInsert">
insert into rollcall.studentcourse (student_id, course_id) values
<foreach collection="list" item="studentDTO" separator=",">
(#{studentDTO.studentId}, #{courseId})
</foreach>
</insert>
</mapper>

@ -0,0 +1,84 @@
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTO Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.wbq.mapper.StudentMapper">
<select id="pageQuery" parameterType="com.wbq.dto.StudentPageQueryDTO"
resultType="com.wbq.entity.Student">
select * from students
where student_id in
<foreach collection="studentIds" item="id" open="(" separator="," close=")">
#{id}
</foreach>
order by FIELD(student_id,
<foreach collection="studentIds" item="id" separator=",">
#{id}
</foreach>
)
</select>
<!--<select id="getByCallCount" resultType="com.wbq.entity.Student">
select * from students
<where>
<if test="minCount != null">
and call_count &gt;= #{minCount}
</if>
<if test="maxCount != null">
and call_count &lt;= #{maxCount}
</if>
</where>
order by score desc
</select>-->
<!--<update id="update" parameterType="com.wbq.dto.StudentDTO">
update students
<set>
<if test="score != null">
score = #{score},
</if>
<if test="callCount != null">
call_count = #{callCount},
</if>
</set>
where student_id = #{studentId}
</update>-->
<select id="getByStudentLoginDTO" parameterType="com.wbq.dto.StudentLoginDTO" resultType="com.wbq.entity.Student">
select * from students
where student_id = #{studentId} and password = #{password}
</select>
<select id="getByStudentIds" resultType="com.wbq.entity.Student">
select * from students
where student_id in
<foreach collection="studentIds" item="id" open="(" separator="," close=")">
#{id}
</foreach>
</select>
<select id="getPasswordByStudentId" resultType="java.lang.String">
select password from students
where student_id = #{studentId}
</select>
<update id="update" parameterType="com.wbq.dto.StudentDTO">
update students
<set>
<if test="name != null">
name = #{name},
</if>
<if test="password != null">
password = #{password}
</if>
</set>
where student_id = #{studentId}
</update>
<insert id="batchInsert">
insert into rollcall.students (student_id, name, password) values
<foreach collection="list" item="studentDTO" separator=",">
(#{studentDTO.studentId}, #{studentDTO.name}, #{studentDTO.password})
</foreach>
</insert>
</mapper>

@ -0,0 +1,64 @@
/*
package com.wbq.test;
import com.wbq.dto.StudentDTO;
import com.wbq.entity.Student;
import com.wbq.mapper.StudentCourseMapper;
import com.wbq.mapper.StudentMapper;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import java.util.ArrayList;
import java.util.List;
@SpringBootTest
public class StudentMapperTest {
// 依赖注入
@Autowired
private StudentMapper studentMapper;
@Autowired
private StudentCourseMapper studentCourseMapper;
// 函数功能测试StudentMapper的getById接口是否可以根据id值返回相应的学生实体
// 测试数据构造一个普通的存在的id值如1
@Test
public void demo01() {
System.out.println(studentMapper.getById(1));
}
// 函数功能测试StudentMapper的update接口是否可以正确的更新学生的数据
// 测试数据构造一个普通的存在的studentId以及合适的password如“1022012041125”
@Test
public void demo02() {
StudentDTO studentDTO = StudentDTO.builder()
.studentId(102201204)
.password("1125")
.build();
studentMapper.update(studentDTO);
}
// 函数功能测试StudentMapper的batchInsert接口是否可以批量增加学生
// 测试数据构造一个特殊的测试值如只有一个实体的List测试该接口的通用性及正确性
@Test
public void demo03() {
StudentDTO studentDTO = StudentDTO.builder()
.studentId(123456789)
.name("妞子郡")
.build();
List<StudentDTO> studentDTOList = new ArrayList<>();
studentDTOList.add(studentDTO);
studentMapper.batchInsert(studentDTOList);
}
// 函数功能测试StudentMapper的getAllStudent接口是否可以返回所有学生实体
// 测试数据:无
@Test
public void demo04() {
List<Student> studentList = studentMapper.getAllStudent();
System.out.println(studentList);
}
}
*/

@ -0,0 +1,6 @@
spring:
datasource:
driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://localhost:3306/rollcall?serverTimezone=Asia/Shanghai&useUnicode=true&characterEncoding=utf-8&zeroDateTimeBehavior=convertToNull&useSSL=false&allowPublicKeyRetrieval=true
username: root
password: 1234

@ -0,0 +1,48 @@
server:
port: 8888
spring:
application:
name: RollCallSystem
profiles:
active: dev
main:
allow-circular-references: true
autoconfigure:
exclude: org.springframework.boot.autoconfigure.security.servlet.SecurityAutoConfiguration
jackson:
date-format: yyyy-MM-dd HH:mm:ss
time-zone: GMT+8
mybatis:
#mapper配置文件
mapper-locations: classpath:mapper/*.xml
configuration:
map-underscore-to-camel-case: true
logging:
level:
com:
wbq:
mapper: debug
service: info
controller: info
wbq:
jwt:
admin-secret-key: bugaoshuni
admin-token-name: admin_token
admin-ttl: 7200000
student-secret-key: yebugaoshuni
student-token-name: student_token
student-ttl: 7200000
qq:
email-count: 2108095381@qq.com
email-authorization-code: alwlqedbpbpfdgfc
knife4j:
enable: true
base-path: /doc

Some files were not shown because too many files have changed in this diff Show More

Loading…
Cancel
Save