Compare commits

...

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

8
.idea/.gitignore vendored

@ -0,0 +1,8 @@
# 默认忽略的文件
/shelf/
/workspace.xml
# 基于编辑器的 HTTP 客户端请求
/httpRequests/
# Datasource local storage ignored files
/dataSources/
/dataSources.local.xml

@ -0,0 +1,9 @@
<?xml version="1.0" encoding="UTF-8"?>
<module type="JAVA_MODULE" version="4">
<component name="NewModuleRootManager" inherit-compiler-output="true">
<exclude-output />
<content url="file://$MODULE_DIR$" />
<orderEntry type="inheritedJdk" />
<orderEntry type="sourceFolder" forTests="false" />
</component>
</module>

@ -0,0 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="ProjectRootManager" version="2" languageLevel="JDK_20" default="true" project-jdk-name="20" project-jdk-type="JavaSDK">
<output url="file://$PROJECT_DIR$/out" />
</component>
</project>

@ -0,0 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="ProjectModuleManager">
<modules>
<module fileurl="file://$PROJECT_DIR$/.idea/ExamSphere.iml" filepath="$PROJECT_DIR$/.idea/ExamSphere.iml" />
</modules>
</component>
</project>

@ -0,0 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="VcsDirectoryMappings">
<mapping directory="" vcs="Git" />
</component>
</project>

Binary file not shown.

@ -1,33 +0,0 @@
HELP.md
target/
!.mvn/wrapper/maven-wrapper.jar
!**/src/main/**/target/
!**/src/test/**/target/
### STS ###
.apt_generated
.classpath
.factorypath
.project
.settings
.springBeans
.sts4-cache
### IntelliJ IDEA ###
.idea
*.iws
*.iml
*.ipr
### NetBeans ###
/nbproject/private/
/nbbuild/
/dist/
/nbdist/
/.nb-gradle/
build/
!**/src/main/**/build/
!**/src/test/**/build/
### VS Code ###
.vscode/

@ -1,167 +0,0 @@
<?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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.exam</groupId>
<artifactId>ExamSphere</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>ExamSphere</name>
<description>ExamSphere</description>
<properties>
<java.version>1.8</java.version>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<spring-boot.version>2.6.13</spring-boot.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<scope>runtime</scope>
<optional>true</optional>
</dependency>
<dependency>
<groupId>com.mysql</groupId>
<artifactId>mysql-connector-j</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<version>3.5.4.1</version>
</dependency>
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger2</artifactId>
<version>2.9.2</version>
</dependency>
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger-ui</artifactId>
<version>2.9.2</version>
</dependency>
<dependency>
<groupId>com.github.xiaoymin</groupId>
<artifactId>swagger-bootstrap-ui</artifactId>
<version>1.9.6</version>
</dependency>
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-generator</artifactId>
<version>3.5.1</version>
</dependency>
<dependency>
<groupId>org.apache.velocity</groupId>
<artifactId>velocity</artifactId>
<version>1.7</version>
</dependency>
<dependency>
<groupId>org.freemarker</groupId>
<artifactId>freemarker</artifactId>
<version>2.3.30</version>
</dependency>
<!-- <dependency>-->
<!-- <groupId>io.jsonwebtoken</groupId>-->
<!-- <artifactId>jjwt</artifactId>-->
<!-- <version>0.9.1</version>-->
<!-- </dependency>-->
<dependency>
<groupId>com.auth0</groupId>
<artifactId>java-jwt</artifactId>
<version>3.10.3</version>
</dependency>
<dependency>
<groupId>cn.hutool</groupId>
<artifactId>hutool-all</artifactId>
<version>5.7.20</version>
</dependency>
<dependency>
<groupId>com.github.whvcse</groupId>
<artifactId>easy-captcha</artifactId>
<version>1.6.2</version>
</dependency>
<dependency>
<groupId>org.mindrot</groupId>
<artifactId>jbcrypt</artifactId>
<version>0.4</version>
</dependency>
<dependency>
<groupId>com.exam</groupId>
<artifactId>ExamSphere</artifactId>
<version>0.0.1-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus</artifactId>
<version>3.5.4.1</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-autoconfigure</artifactId>
<version>2.6.13</version>
</dependency>
</dependencies>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-dependencies</artifactId>
<version>${spring-boot.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.6.1</version>
<configuration>
<source>1.8</source>
<target>1.8</target>
<encoding>UTF-8</encoding>
</configuration>
</plugin>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<version>${spring-boot.version}</version>
<configuration>
<mainClass>com.exam.examsphere.ExamSphereApplication</mainClass>
<skip>true</skip>
</configuration>
<executions>
<execution>
<id>repackage</id>
<goals>
<goal>repackage</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>

@ -1,13 +0,0 @@
package com.exam.examsphere;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class ExamSphereApplication {
public static void main(String[] args) {
SpringApplication.run(ExamSphereApplication.class, args);
}
}

@ -1,29 +0,0 @@
package com.exam.examsphere.common;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
@Data
@NoArgsConstructor
@AllArgsConstructor
public class Result<T> {
private Integer code;
private String msg;
private Object data;
public static Result success() {
return new Result(200,"操作成功",null);
}
public static Result success(Object data) {
return new Result(200,"操作成功",data);
}
public static Result error(String msg) {
return new Result(500,msg,null);
}
public static Result error(Integer code, String msg) {
return new Result(code,msg,null);
}
public static Result error() {
return new Result(500,"系统错误,请联系管理员",null);
}
}

@ -1,12 +0,0 @@
package com.exam.examsphere.config;
import org.springframework.stereotype.Component;
import java.util.HashMap;
import java.util.Map;
@Component
public class CaptureConfig {
public static Map<String,String> CAPTURE_MAP = new HashMap<String,String>();
}

@ -1,25 +0,0 @@
package com.exam.examsphere.config;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.cors.CorsConfiguration;
import org.springframework.web.cors.UrlBasedCorsConfigurationSource;
import org.springframework.web.filter.CorsFilter;
@Configuration
public class CorsConfig {
// 当前跨域请求最大有效时长。默认1天
private static final long MAX_AGE = 24 * 60 * 60;
@Bean
public CorsFilter corsFilter() {
UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
CorsConfiguration corsConfiguration = new CorsConfiguration();
corsConfiguration.addAllowedOrigin("http://localhost:5173/"); // 1 设置访问源地址
corsConfiguration.addAllowedHeader("*"); // 2 设置访问源请求头
corsConfiguration.addAllowedMethod("*"); // 3 设置访问源请求方法
corsConfiguration.setMaxAge(MAX_AGE);
source.registerCorsConfiguration("/**", corsConfiguration); // 4 对接口配置跨域设置
return new CorsFilter(source);
}
}

@ -1,22 +0,0 @@
package com.exam.examsphere.config;
import com.exam.examsphere.config.interceptor.JwtInterceptor;
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.WebMvcConfigurer;
@Configuration
public class InterceptorConfig implements WebMvcConfigurer {
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(jwtInterceptor())
.addPathPatterns("/**")//拦截所有请求通过判断token是否合法决定是否需要登录
.excludePathPatterns("/user/login","/user/register","/doc.html","/swagger-resources/**","/captcha","/file/upload","/file/download");
}
@Bean
public JwtInterceptor jwtInterceptor() {
return new JwtInterceptor();
}
}

@ -1,28 +0,0 @@
package com.exam.examsphere.config;
import com.baomidou.mybatisplus.annotation.DbType;
import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor;
import com.baomidou.mybatisplus.extension.plugins.inner.BlockAttackInnerInterceptor;
import com.baomidou.mybatisplus.extension.plugins.inner.PaginationInnerInterceptor;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
/**
*
*/
@Configuration
public class MybatisPlusConfig {
@Bean
public MybatisPlusInterceptor mybatisPlusInterceptor() {
MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
interceptor.addInnerInterceptor(new BlockAttackInnerInterceptor());
return interceptor;
}
@Bean
public MybatisPlusInterceptor mybatisPlusInterceptor2() {
MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL));
return interceptor;
}
}

@ -1,33 +0,0 @@
package com.exam.examsphere.config;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
import springfox.documentation.builders.ApiInfoBuilder;
import springfox.documentation.builders.PathSelectors;
import springfox.documentation.builders.RequestHandlerSelectors;
import springfox.documentation.service.ApiInfo;
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 docket() {
return new Docket(DocumentationType.SWAGGER_2)
.select()
.apis(RequestHandlerSelectors.basePackage("com.exam.examsphere.controller"))
.paths(PathSelectors.any())
.build().apiInfo(apiInfo());
}
private ApiInfo apiInfo() {
return new ApiInfoBuilder()
.title("ExamSphere在线考试系统")
.version("1.0")
.build();
}
}

@ -1,61 +0,0 @@
package com.exam.examsphere.config.interceptor;
import cn.hutool.core.util.StrUtil;
import com.auth0.jwt.JWT;
import com.auth0.jwt.JWTVerifier;
import com.auth0.jwt.algorithms.Algorithm;
import com.auth0.jwt.exceptions.JWTVerificationException;
import com.exam.examsphere.entity.User;
import com.exam.examsphere.exception.ServiceException;
import com.exam.examsphere.service.IUserService;
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;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
@Slf4j
@Component
public class JwtInterceptor implements HandlerInterceptor {
@Autowired
private IUserService userService;
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) {
String token = request.getHeader("token");
if(!(handler instanceof HandlerMethod)){
return true;
}
// 执行认证
if (StrUtil.isBlank(token)) {
throw new ServiceException("无token请重新登录");
}
// 获取 token 中的 userId
String userId;
try {
userId = JWT.decode(token).getAudience().get(0);
} catch (Exception e) {
throw new ServiceException("token验证失败请重新登录");
}
// 根据token中的userid查询数据库
User user =userService.getById(userId);
if (user == null) {
throw new ServiceException("用户不存在,请重新登录");
}
try {
// 用户密码加签验证 token
JWTVerifier jwtVerifier = JWT.require(Algorithm.HMAC256(user.getPassword())).build();
jwtVerifier.verify(token); // 验证token
} catch (JWTVerificationException e) {
throw new ServiceException("token验证失败请重新登录");
}
return true;
}
}

@ -1,136 +0,0 @@
package com.exam.examsphere.controller;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.exam.examsphere.common.Result;
import com.exam.examsphere.dto.AnswerDTO;
import com.exam.examsphere.entity.Exam;
import com.exam.examsphere.entity.Question;
import com.exam.examsphere.mapper.ExamMapper;
import com.exam.examsphere.mapper.QuestionMapper;
import com.exam.examsphere.service.IExamService;
import com.exam.examsphere.service.IQuestionService;
import com.exam.examsphere.utils.TokenUtils;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.*;
import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.List;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.exam.examsphere.service.IAnswerService;
import com.exam.examsphere.entity.Answer;
import org.springframework.web.bind.annotation.RestController;
/**
*
* @author chx
*
*/
@RestController
@RequestMapping("/answer")
public class AnswerController {
@Resource
private IAnswerService answerService;
@Resource
private ExamMapper examMapper;
@Resource
private QuestionMapper questionMapper;
// 新增或者更新
@PostMapping
public Result save(@RequestBody Answer answer) {
return Result.success(answerService.saveOrUpdate(answer));
}
//删除
@DeleteMapping("/{id}")
public Result delete(@PathVariable Integer id) {
return Result.success(answerService.removeById(id));
}
//多项删除
@PostMapping("/del/batch")
public Result deleteBatch(@RequestBody List<Integer> ids) {
return Result.success(answerService.removeByIds(ids));
}
//查询所有数据
@GetMapping
public Result findAll() {
return Result.success(answerService.markListWithName());
}
@GetMapping("/findByUserId")
public Result findByUserId() {
QueryWrapper<Answer> queryWrapper = new QueryWrapper<>();
Long id = TokenUtils.getCurrentUser().getId();
queryWrapper.eq("user_id", id);
queryWrapper.orderByDesc("submit_time");
return Result.success(answerService.list(queryWrapper));
}
//根据id查询
@GetMapping("/{id}")
public Result findOne(@PathVariable Integer id) {
return Result.success(answerService.getById(id));
}
//分页查询
@GetMapping("/page")
public Result findPage(@RequestParam Integer pageNum,
@RequestParam Integer pageSize) {
QueryWrapper<Answer> queryWrapper = new QueryWrapper<>();
queryWrapper.orderByDesc("id");
return Result.success(answerService.page(new Page<>(pageNum, pageSize),queryWrapper));
}
// 获取考试详情,包括答题详情
@GetMapping("/details/{examId}")
public Result getExamDetails(@PathVariable Long examId) {
// 获取考试的基本信息
Exam exam = examMapper.selectById(examId);
Long userId = TokenUtils.getCurrentUser().getId();
// 获取该考试的答题详情
List<AnswerDTO> answerDetails = answerService.getAnswerDetailsByExamId(examId, userId);
for (AnswerDTO answerDTO : answerDetails) {
// 根据题目ID获取每道题目的信息
Question question = questionMapper.selectById(answerDTO.getId());
if (question != null) {
// 设置每道题目的正确答案
answerDTO.setCorrectAnswer(question.getAnswer());
if(question.getAnswer().equals(String.join("", answerDTO.getUserAnswers()).trim())){
answerDTO.setUserScore(question.getScore());
}
} else {
answerDTO.setCorrectAnswer(null);
answerDTO.setUserScore(0);
}
}
return Result.success(answerDetails);
}
@GetMapping("/{examId}/student/{studentId}")
public Result getExamDetails(@PathVariable Long examId, @PathVariable Long studentId) {
// 获取考试的基本信息
Exam exam = examMapper.selectById(examId);
// 获取该考试的答题详情
List<AnswerDTO> answerDetails = answerService.getAnswerDetailsByExamId(examId,studentId);
for (AnswerDTO answerDTO : answerDetails) {
// 根据题目ID获取每道题目的信息
Question question = questionMapper.selectById(answerDTO.getId());
if (question != null) {
// 设置每道题目的正确答案
answerDTO.setCorrectAnswer(question.getAnswer());
if(question.getAnswer().equals(String.join("", answerDTO.getUserAnswers()).trim())){
answerDTO.setUserScore(question.getScore());
}
} else {
answerDTO.setCorrectAnswer(null);
answerDTO.setUserScore(0);
}
}
return Result.success(answerDetails);
}
}

@ -1,32 +0,0 @@
package com.exam.examsphere.controller;
import com.exam.examsphere.config.CaptureConfig;
import com.wf.captcha.ArithmeticCaptcha;
import com.wf.captcha.SpecCaptcha;
import com.wf.captcha.utils.CaptchaUtil;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
@RestController
@RequestMapping
public class CaptchaController {
@RequestMapping("/captcha")
public void captcha(@RequestParam String key,HttpServletRequest request, HttpServletResponse response) throws IOException {
// SpecCaptcha captcha = new SpecCaptcha(100, 30,4);
// captcha.setCharType(SpecCaptcha.TYPE_ONLY_NUMBER);
// CaptureConfig.CAPTURE_MAP.put(key,captcha.text().toLowerCase());
// CaptchaUtil.out(captcha,request,response);
ArithmeticCaptcha captcha = new ArithmeticCaptcha();
captcha.setLen(4);
captcha.getArithmeticString();
captcha.text();
CaptureConfig.CAPTURE_MAP.put(key, captcha.text().toLowerCase());
CaptchaUtil.out(captcha, request, response);
}
}

@ -1,63 +0,0 @@
package com.exam.examsphere.controller;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.exam.examsphere.common.Result;
import org.springframework.web.bind.annotation.*;
import javax.annotation.Resource;
import java.util.List;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.exam.examsphere.service.ICommentService;
import com.exam.examsphere.entity.Comment;
import org.springframework.web.bind.annotation.RestController;
/**
*
* @author chx
*
*/
@RestController
@RequestMapping("/comment")
public class CommentController {
@Resource
private ICommentService commentService;
// 新增或者更新
@PostMapping
public Result save(@RequestBody Comment comment) {
return Result.success(commentService.saveOrUpdate(comment));
}
//删除
@DeleteMapping("/{id}")
public Result delete(@PathVariable Integer id) {
return Result.success(commentService.removeById(id));
}
//多项删除
@PostMapping("/del/batch")
public Result deleteBatch(@RequestBody List<Integer> ids) {
return Result.success(commentService.removeByIds(ids));
}
//查询所有数据
@GetMapping
public Result findAll() {
return Result.success(commentService.getComments());
}
//根据id查询
@GetMapping("/{id}")
public Result findOne(@PathVariable Integer id) {
return Result.success(commentService.getById(id));
}
//分页查询
@GetMapping("/page")
public Result findPage(@RequestParam Integer pageNum,
@RequestParam Integer pageSize) {
QueryWrapper<Comment> queryWrapper = new QueryWrapper<>();
queryWrapper.orderByDesc("id");
return Result.success(commentService.page(new Page<>(pageNum, pageSize),queryWrapper));
}
}

@ -1,196 +0,0 @@
package com.exam.examsphere.controller;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.exam.examsphere.common.Result;
import com.exam.examsphere.dto.*;
import com.exam.examsphere.entity.Answer;
import com.exam.examsphere.entity.Question;
import com.exam.examsphere.mapper.ExamMapper;
import com.exam.examsphere.mapper.QuestionMapper;
import com.exam.examsphere.service.IAnswerService;
import com.exam.examsphere.service.IQuestionService;
import com.exam.examsphere.utils.TokenUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.CacheControl;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
import javax.annotation.Resource;
import java.time.LocalDateTime;
import java.util.*;
import java.util.stream.Collectors;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.exam.examsphere.service.IExamService;
import com.exam.examsphere.entity.Exam;
import org.springframework.web.bind.annotation.RestController;
/**
*
* @author chx
*
*/
@RestController
@RequestMapping("/exam")
public class ExamController {
@Resource
private IExamService examService;
@Resource
private ExamMapper examMapper;
@Resource
private IQuestionService questionService;
@Resource
private QuestionMapper questionMapper;
// 新增或者更新
@PostMapping
public Result save(@RequestBody Exam exam) {
return Result.success(examService.saveOrUpdate(exam));
}
//删除
@DeleteMapping("/{id}")
public Result delete(@PathVariable Integer id) {
return Result.success(examService.removeById(id));
}
//多项删除
@PostMapping("/del/batch")
public Result deleteBatch(@RequestBody List<Integer> ids) {
return Result.success(examService.removeByIds(ids));
}
//查询所有数据
@GetMapping
public Result findAll() {
return Result.success(examService.findAllWithTeacherName());
}
//根据id查询
@GetMapping("/{id}")
public Result findOne(@PathVariable Integer id) {
return Result.success(examService.getByIdWithTeacherName(id));
}
//分页查询
@GetMapping("/page")
public Result findPage(@RequestParam Integer pageNum,
@RequestParam Integer pageSize) {
QueryWrapper<Exam> queryWrapper = new QueryWrapper<>();
queryWrapper.orderByDesc("id");
return Result.success(examService.page(new Page<>(pageNum, pageSize),queryWrapper));
}
// 根据 question_ids 获取多道题目
@GetMapping("/{examId}/question")
public Result getQuestionsByExam(@PathVariable Long examId, @RequestParam(defaultValue = "1") int page) {
// 假设每次只加载一道题目
int pageSize = 1;
// 根据 examId 获取 question_ids
Exam exam = examMapper.selectById(examId);
if (exam == null) {
return Result.error();
}
// 将 question_ids 转换为 List<Long>
List<Long> questionIds = Arrays.stream(exam.getQuestionIds().split(","))
.map(Long::valueOf)
.collect(Collectors.toList());
int totalQuestions = questionIds.size();
// 分页获取题目 ID
int fromIndex = Math.min((page - 1) * pageSize, questionIds.size());
int toIndex = Math.min(fromIndex + pageSize, questionIds.size());
List<Long> pagedQuestionIds = questionIds.subList(fromIndex, toIndex);
// 查询题目表
List<Question> questions = questionService.getQuestionsByIds(pagedQuestionIds);
Map<String, Object> response = new HashMap<>();
response.put("data", questions);
response.put("total", totalQuestions);
return Result.success(response);
}
// 提交答案
@PostMapping("/submit")
public Result submitExam(@RequestBody SubmitExamDTO submitExamDTO) {
try {
examService.submitExam(submitExamDTO);
return Result.success("试卷提交成功");
} catch (Exception e) {
return Result.error("试卷提交失败:" + e.getMessage());
}
}
//提交评分
@PostMapping("/submit-scores")
public Result submitScores(@RequestBody SubmitScoreDTO submitScoreDTO) {
try {
examService.submitScores(submitScoreDTO);
return Result.success("试卷提交成功");
} catch (Exception e) {
return Result.error("试卷提交失败:" + e.getMessage());
}
}
@PostMapping("/manual")
public Result createManualExam(@RequestBody Exam exam) {
boolean success = examService.createManualExam(exam);
return success ? Result.success("手动组卷成功") : Result.error("手动组卷失败");
}
@PostMapping("/random")
public Result randomExam(@RequestBody RandomExamDTO randomExamDTO) {
String title = randomExamDTO.getTitle();
Map<String, Integer> typeCounts = randomExamDTO.getTypeCounts();
LocalDateTime startTime=randomExamDTO.getStartTime();
LocalDateTime endTime=randomExamDTO.getEndTime();
String img=randomExamDTO.getImg();
if (StrUtil.isBlank(title)) {
return Result.error("试卷标题不能为空");
}
List<Question> selectedQuestions = new ArrayList<>();
for (Map.Entry<String, Integer> entry : typeCounts.entrySet()) {
String type = entry.getKey();
Integer count = entry.getValue();
if (count > 0) {
List<Question> questions = questionMapper.findRandomQuestionsByType(type, count);
selectedQuestions.addAll(questions);
}
}
if (selectedQuestions.isEmpty()) {
return Result.error("未找到符合条件的题目");
}
int totalScore = selectedQuestions.stream().mapToInt(Question::getScore).sum();
String questionIds = selectedQuestions.stream()
.map(q -> String.valueOf(q.getId()))
.collect(Collectors.joining(","));
Exam exam = new Exam();
exam.setTitle(title);
exam.setTotal(totalScore);
exam.setQuestionIds(questionIds);
exam.setUserId(Math.toIntExact(TokenUtils.getCurrentUser().getId()));
exam.setStartTime(startTime);
exam.setEndTime(endTime);
exam.setImg(img);
examMapper.insert(exam);
Map<String, Object> response = new HashMap<>();
response.put("examId", exam.getId());
return Result.success(response);
}
}

@ -1,70 +0,0 @@
package com.exam.examsphere.controller;
import com.exam.examsphere.common.Result;
import org.springframework.core.io.Resource;
import org.springframework.core.io.UrlResource;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import java.io.File;
import java.net.MalformedURLException;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.UUID;
@RestController
@RequestMapping("/file")
public class FileController {
private static final String UPLOAD_DIR = System.getProperty("user.dir")+"/static/img";
@PostMapping("/upload")
public Result uploadFile(@RequestParam("file") MultipartFile file) {
if (file.isEmpty()) {
return Result.error("文件不能为空");
}
try {
// 确保目录存在
File uploadDir = new File(UPLOAD_DIR);
if (!uploadDir.exists()) {
uploadDir.mkdirs();
}
// 生成唯一文件名
String fileName = UUID.randomUUID().toString() + "_" + file.getOriginalFilename();
File dest = new File(UPLOAD_DIR, fileName);
// 保存文件
file.transferTo(dest);
// 返回文件访问路径
String fileUrl = "http://localhost:8080/file/download?name=" + fileName;
return Result.success(fileUrl);
} catch (Exception e) {
e.printStackTrace();
return Result.error("上传失败");
}
}
@GetMapping("/download")
public ResponseEntity<Resource> downloadFile(@RequestParam String name) {
try {
// 文件完整路径
Path filePath = Paths.get(UPLOAD_DIR, name);
Resource resource = new UrlResource(filePath.toUri());
if (resource.exists() && resource.isReadable()) {
return ResponseEntity.ok()
.header("Content-Disposition", "inline; filename=\"" + name + "\"")
.body(resource);
} else {
throw new RuntimeException("文件不存在");
}
} catch (Exception e) {
throw new RuntimeException("下载失败", e);
}
}
}

@ -1,85 +0,0 @@
package com.exam.examsphere.controller;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.exam.examsphere.common.Result;
import com.exam.examsphere.dto.QuestionDTO;
import com.exam.examsphere.mapper.QuestionMapper;
import org.springframework.web.bind.annotation.*;
import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.List;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.exam.examsphere.service.IQuestionService;
import com.exam.examsphere.entity.Question;
import org.springframework.web.bind.annotation.RestController;
/**
*
* @author chx
*
*/
@RestController
@RequestMapping("/question")
public class QuestionController {
@Resource
private IQuestionService questionService;
// 新增或者更新
@PostMapping
public Result save(@RequestBody Question question) {
return Result.success(questionService.saveOrUpdate(question));
}
//删除
@DeleteMapping("/{id}")
public Result delete(@PathVariable Integer id) {
return Result.success(questionService.removeById(id));
}
//多项删除
@PostMapping("/del/batch")
public Result deleteBatch(@RequestBody List<Integer> ids) {
return Result.success(questionService.removeByIds(ids));
}
//查询所有数据
@GetMapping
public Result findAll() {
return Result.success(questionService.list());
}
@GetMapping("/getQuestion")
public Result getQuestion(@RequestParam("ids") Integer[] ids) {
List<Question> list = new ArrayList<>();
for (Integer id : ids) {
Question byId = questionService.getById(id);
list.add(byId);
}
return Result.success(list);
}
@GetMapping("/getQuestionsByIds")
public Result getQuestionsByIds(@RequestParam("ids") Integer[] ids) {
List<Question> list = new ArrayList<>();
for (Integer id : ids) {
Question byId = questionService.getById(id);
}
return Result.success(ids);
}
//根据id查询
@GetMapping("/{id}")
public Result findOne(@PathVariable Integer id) {
return Result.success(questionService.getById(id));
}
//分页查询
@GetMapping("/page")
public Result findPage(@RequestParam Integer pageNum,
@RequestParam Integer pageSize,
@RequestParam(required = false) String keyword) {
return Result.success(questionService.findQuestionsWithTeacher(new Page<>(pageNum, pageSize),keyword));
}
}

@ -1,159 +0,0 @@
package com.exam.examsphere.controller;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.exam.examsphere.common.Result;
import com.exam.examsphere.config.CaptureConfig;
import com.exam.examsphere.dto.UserDTO;
import com.exam.examsphere.utils.TokenUtils;
import com.wf.captcha.utils.CaptchaUtil;
import org.springframework.web.bind.annotation.*;
import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.util.List;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.exam.examsphere.service.IUserService;
import com.exam.examsphere.entity.User;
import org.springframework.web.bind.annotation.RestController;
/**
*
* @author chx
*
*/
@RestController
@RequestMapping("/user")
public class UserController {
@Resource
private IUserService userService;
@PostMapping("/login")
public Result login(@RequestBody UserDTO userDTO, @RequestParam String key, HttpServletRequest request) {
if(!userDTO.getVerificationCode().equalsIgnoreCase(CaptureConfig.CAPTURE_MAP.get(key))){
CaptchaUtil.clear(request);
return Result.error("验证码错误");
}
String username = userDTO.getUsername();
String password = userDTO.getPassword();
if(StrUtil.isBlank(username) || StrUtil.isBlank(password)){
return Result.error("用户名或密码不能为空");
}
CaptureConfig.CAPTURE_MAP.remove(key);
return Result.success(userService.login(userDTO));
}
@PostMapping("/register")
public Result register(@RequestBody UserDTO userDTO) {
String username = userDTO.getUsername();
String password = userDTO.getPassword();
if(StrUtil.isBlank(username) || StrUtil.isBlank(password)){
return Result.error("用户名或密码不能为空");
}
return Result.success(userService.register(userDTO));
}
// 新增或者更新
@PostMapping
public Result save(@RequestBody User user) {
User existingUser = null;
if (StrUtil.isNotBlank(user.getUsername())) {
existingUser = userService.getOne(new QueryWrapper<User>().eq("username", user.getUsername()));
}
if (existingUser != null) {
if (StrUtil.isBlank(user.getPassword())) {
user.setPassword(existingUser.getPassword());
}
user.setId(existingUser.getId());
}
return Result.success(userService.saveOrUpdate(user));
}
//删除
@DeleteMapping("/{id}")
public Result delete(@PathVariable Integer id) {
return Result.success(userService.removeById(id));
}
//多项删除
@PostMapping("/del/batch")
public Result deleteBatch(@RequestBody List<Integer> ids) {
return Result.success(userService.removeByIds(ids));
}
//查询所有数据
@GetMapping
public Result findAll() {
return Result.success(userService.list());
}
//获取当前用户信息
@GetMapping("/info")
public Result findOne() {
Long id= TokenUtils.getCurrentUser().getId();
return Result.success(userService.getById(id));
}
@GetMapping("/{id}")
public Result findById(@PathVariable Integer id) {
return Result.success(userService.getById(id));
}
//分页查询
@GetMapping("/page")
public Result findPage(@RequestParam Integer pageNum,
@RequestParam Integer pageSize,
@RequestParam(required = false) String keyword) {
QueryWrapper<User> queryWrapper = new QueryWrapper<>();
queryWrapper.orderByAsc("id");
if (keyword != null && !keyword.isEmpty()) {
queryWrapper.like("id", keyword)
.or().like("username", keyword)
.or().like("mobile", keyword)
.or().like("email", keyword)
.or().like("gender", keyword)
.or().like("address", keyword)
.or().like("role", keyword);
}
return Result.success(userService.page(new Page<>(pageNum, pageSize),queryWrapper));
}
@GetMapping("/student")
public Result findStudents(@RequestParam Integer pageNum,
@RequestParam Integer pageSize,
@RequestParam(required = false) String keyword) {
QueryWrapper<User> queryWrapper = new QueryWrapper<>();
queryWrapper.orderByAsc("id");
queryWrapper.like("role", "student");
if (keyword != null && !keyword.isEmpty()) {
queryWrapper.like("id", keyword)
.or().like("username", keyword)
.or().like("mobile", keyword)
.or().like("email", keyword)
.or().like("gender", keyword)
.or().like("address", keyword)
.or().like("role", keyword);
}
return Result.success(userService.page(new Page<>(pageNum, pageSize),queryWrapper));
}
@GetMapping("/teacher")
public Result findTeachers(@RequestParam Integer pageNum,
@RequestParam Integer pageSize,
@RequestParam(required = false) String keyword) {
QueryWrapper<User> queryWrapper = new QueryWrapper<>();
queryWrapper.orderByAsc("id");
queryWrapper.like("role", "teacher");
if (keyword != null && !keyword.isEmpty()) {
queryWrapper.like("id", keyword)
.or().like("username", keyword)
.or().like("mobile", keyword)
.or().like("email", keyword)
.or().like("gender", keyword)
.or().like("address", keyword)
.or().like("role", keyword);
}
return Result.success(userService.page(new Page<>(pageNum, pageSize),queryWrapper));
}
}

@ -1,37 +0,0 @@
package com.exam.examsphere.dto;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import com.fasterxml.jackson.annotation.JsonIgnore;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.DeserializationContext;
import com.fasterxml.jackson.databind.JsonDeserializer;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
import lombok.Data;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
@Data
@JsonIgnoreProperties(ignoreUnknown = true) // 忽略未定义字段
public class AnswerDTO {
private Long id; // 题目ID
private String name; // 题目名称
private String type; // 题目类型
private List<String> options; // 选项
private String answer; // 用户答案
private Integer score; // 分数
private String user; // 用户信息
private List<String> userAnswers; // 用户多选题答案
private Integer userScore; // 用户得分
private String correctAnswer;
}

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

Loading…
Cancel
Save