Update docs: 将类,api方法使用文档注释规范化开发

develop
王奕辉 2 days ago
parent f36eed33fd
commit c9c6dc27ee

@ -12,12 +12,21 @@ import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry; import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
/**
*
*/
@Configuration @Configuration
public class IntercepterConfig implements WebMvcConfigurer { public class IntercepterConfig implements WebMvcConfigurer {
/**
* LoginInterceptor
*/
@Autowired @Autowired
private LoginInterceptor loginInterceptor; private LoginInterceptor loginInterceptor;
/**
*
*/
@Override @Override
public void addInterceptors(InterceptorRegistry registry) { public void addInterceptors(InterceptorRegistry registry) {
// 拦截user下的api // 拦截user下的api

@ -7,12 +7,22 @@ import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Configuration;
import org.springframework.http.HttpStatus; import org.springframework.http.HttpStatus;
/**
* Servlet
*/
@Configuration @Configuration
public class ServletConfig { public class ServletConfig {
/**
* WebServerFactoryCustomizer beanWeb
* @return WebServerFactoryCustomizer<ConfigurableWebServerFactory>
*/
@Bean @Bean
public WebServerFactoryCustomizer<ConfigurableWebServerFactory> webServerFactoryCustomizer() { public WebServerFactoryCustomizer<ConfigurableWebServerFactory> webServerFactoryCustomizer() {
// 返回一个lambda表达式用于自定义Web服务器的工厂
return factory -> { return factory -> {
// 创建一个ErrorPage对象用于处理404错误
ErrorPage error404Page = new ErrorPage(HttpStatus.NOT_FOUND, "/"); ErrorPage error404Page = new ErrorPage(HttpStatus.NOT_FOUND, "/");
// 将ErrorPage对象添加到Web服务器的工厂中
factory.addErrorPages(error404Page); factory.addErrorPages(error404Page);
}; };
} }

@ -23,12 +23,18 @@ import springfox.documentation.swagger2.annotations.EnableSwagger2;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
/**
* Swagger2
*/
@Configuration @Configuration
@EnableSwagger2 @EnableSwagger2
public class Swagger2Config { public class Swagger2Config {
/**
* Docket bean
* @return Docket
*/
@Bean @Bean
public Docket api() { public Docket api() {
ParameterBuilder ticketPar = new ParameterBuilder(); ParameterBuilder ticketPar = new ParameterBuilder();
List<Parameter> pars = new ArrayList<>(); List<Parameter> pars = new ArrayList<>();
ticketPar.name("Access-Token").description("Rest接口权限认证token,无需鉴权可为空") ticketPar.name("Access-Token").description("Rest接口权限认证token,无需鉴权可为空")
@ -48,6 +54,10 @@ public class Swagger2Config {
.globalOperationParameters(pars); .globalOperationParameters(pars);
} }
/**
* ApiInfo
* @return ApiInfo
*/
private ApiInfo apiInfo() { private ApiInfo apiInfo() {
return new ApiInfoBuilder() return new ApiInfoBuilder()
.title("online exam by springboot") .title("online exam by springboot")
@ -57,4 +67,4 @@ public class Swagger2Config {
.contact(new Contact("liangshanguang", "https://github.com/lsgwr/spring-boot-online-exam", "liangshanguang2@gmail.com")) .contact(new Contact("liangshanguang", "https://github.com/lsgwr/spring-boot-online-exam", "liangshanguang2@gmail.com"))
.build(); .build();
} }
} }

@ -40,51 +40,79 @@ public class UploadDownloadController {
// return FileTransUtil.uploadFile(uploadfile, "/root/" + File.separator + uploadfile.getOriginalFilename()); // return FileTransUtil.uploadFile(uploadfile, "/root/" + File.separator + uploadfile.getOriginalFilename());
// } // }
/**
*
*
* @param dir
* @param uploadfile
* @return String
*/
@ApiOperation("单文件上传,支持同时传入参数") @ApiOperation("单文件上传,支持同时传入参数")
@PostMapping("/api/upload/singleAndparas") @PostMapping("/api/upload/singleAndparas")
// 单文件上传。 public String uploadFileSingle(@RequestParam("dir") String dir, @RequestParam("file") MultipartFile uploadfile) {
public String uploadFileSingle(@RequestParam("dir") String dir, @RequestParam("file") MultipartFile uploadfile) {
// 调用FileTransUtil工具类中的uploadFile方法将上传的文件和目录作为参数传入。
return FileTransUtil.uploadFile(uploadfile, dir); return FileTransUtil.uploadFile(uploadfile, dir);
} }
// 单文件上传支持同时传入参数Model。 /**
* Model
*
* @param model UploadModel2
* @return String
*/
@ApiOperation("单文件上传,支持同时传入参数,Model") @ApiOperation("单文件上传,支持同时传入参数,Model")
@PostMapping("/upload/single/model") @PostMapping("/upload/single/model")
public String singleUploadFileModel(@ModelAttribute("model") UploadModel2 model) { public String singleUploadFileModel(@ModelAttribute("model") UploadModel2 model) {
// 调用FileTransUtil工具类中的uploadFile方法将上传的文件和目录作为参数传入。
return FileTransUtil.uploadFile(model.getFile(), model.getDir()); return FileTransUtil.uploadFile(model.getFile(), model.getDir());
} }
// 多文件上传,支持同时传入参数。 /**
*
*
* @param dir
* @param uploadfiles
* @return String
*/
@ApiOperation("多文件上传,支持同时传入参数") @ApiOperation("多文件上传,支持同时传入参数")
@PostMapping("upload/multiAndparas") @PostMapping("upload/multiAndparas")
public String uploadFileMulti(@RequestParam("dir") String dir, @RequestParam("files") MultipartFile[] uploadfiles) { public String uploadFileMulti(@RequestParam("dir") String dir, @RequestParam("files") MultipartFile[] uploadfiles) {
// 调用FileTransUtil工具类中的uploadFiles方法将上传的文件数组和目录作为参数传入。
return FileTransUtil.uploadFiles(uploadfiles, dir); return FileTransUtil.uploadFiles(uploadfiles, dir);
} }
// 多文件上传,支持同时传入参数。 /**
*
*
* @param model UploadModel
* @return String
*/
@ApiOperation("多文件上传,支持同时传入参数") @ApiOperation("多文件上传,支持同时传入参数")
@PostMapping(value = "/upload/multi/model") @PostMapping(value = "/upload/multi/model")
public String multiUploadFileModel(@ModelAttribute(("model")) UploadModel model) { public String multiUploadFileModel(@ModelAttribute(("model")) UploadModel model) {
// 调用FileTransUtil工具类中的uploadFiles方法将上传的文件数组和目录作为参数传入。
return FileTransUtil.uploadFiles(model.getFiles(), model.getDir()); return FileTransUtil.uploadFiles(model.getFiles(), model.getDir());
} }
// Get下载文件 /**
* Get
*
* @param filePath
* @return ResponseEntity<InputStreamResource>
* @throws IOException
*/
@ApiOperation("Get下载文件") @ApiOperation("Get下载文件")
@GetMapping(value = "/download/get") @GetMapping(value = "/download/get")
public ResponseEntity<InputStreamResource> downloadFileGet(@RequestParam String filePath) throws IOException { public ResponseEntity<InputStreamResource> downloadFileGet(@RequestParam String filePath) throws IOException {
// 调用FileTransUtil工具类中的downloadFile方法将文件路径作为参数传入。
return FileTransUtil.downloadFile(filePath); return FileTransUtil.downloadFile(filePath);
} }
// Post下载文件 /**
* Post
*
* @param downloadQo DownloadQo
* @return ResponseEntity<InputStreamResource>
* @throws IOException
*/
@ApiOperation("Post下载文件") @ApiOperation("Post下载文件")
@PostMapping(value = "/download/post") @PostMapping(value = "/download/post")
public ResponseEntity<InputStreamResource> downloadFilePost(@RequestBody DownloadQo downloadQo) throws IOException { public ResponseEntity<InputStreamResource> downloadFilePost(@RequestBody DownloadQo downloadQo) throws IOException {
// 调用FileTransUtil工具类中的downloadFile方法将文件路径作为参数传入。
return FileTransUtil.downloadFile(downloadQo.getPath()); return FileTransUtil.downloadFile(downloadQo.getPath());
} }
} }

@ -29,6 +29,12 @@ public class UserController {
@Autowired @Autowired
private UserService userService; private UserService userService;
/**
*
*
* @param registerDTO RegisterDTO
* @return ResultVO<User>
*/
@PostMapping("/register") @PostMapping("/register")
@ApiOperation("注册") @ApiOperation("注册")
ResultVO<User> register(@RequestBody RegisterDTO registerDTO) { ResultVO<User> register(@RequestBody RegisterDTO registerDTO) {
@ -44,6 +50,12 @@ public class UserController {
return resultVO; return resultVO;
} }
/**
* ,token
*
* @param loginQo LoginQo
* @return ResultVO<String>
*/
@PostMapping("/login") @PostMapping("/login")
@ApiOperation("根据用户名或邮箱登录,登录成功返回token") @ApiOperation("根据用户名或邮箱登录,登录成功返回token")
ResultVO<String> login(@RequestBody LoginQo loginQo) { // 这里不用手机号是因为手机号和用户名难以进行格式区分,而用户名和 ResultVO<String> login(@RequestBody LoginQo loginQo) { // 这里不用手机号是因为手机号和用户名难以进行格式区分,而用户名和
@ -60,6 +72,12 @@ public class UserController {
return resultVO; return resultVO;
} }
/**
*
*
* @param request HttpServletRequest
* @return ResultVO<UserVo>
*/
@GetMapping("/user-info") @GetMapping("/user-info")
@ApiOperation("获取用户信息") @ApiOperation("获取用户信息")
// 根据请求获取用户信息 // 根据请求获取用户信息
@ -72,6 +90,12 @@ public class UserController {
return new ResultVO<>(ResultEnum.GET_INFO_SUCCESS.getCode(), ResultEnum.GET_INFO_SUCCESS.getMessage(), userVo); return new ResultVO<>(ResultEnum.GET_INFO_SUCCESS.getCode(), ResultEnum.GET_INFO_SUCCESS.getMessage(), userVo);
} }
/**
*
*
* @param request HttpServletRequest
* @return ResultVO<UserInfoVo>
*/
@GetMapping("/info") @GetMapping("/info")
@ApiOperation("获取用户的详细信息,包括个人信息页面和操作权限") @ApiOperation("获取用户的详细信息,包括个人信息页面和操作权限")
// 获取用户信息的接口 // 获取用户信息的接口
@ -86,6 +110,12 @@ public class UserController {
return new ResultVO<>(ResultEnum.GET_INFO_SUCCESS.getCode(), ResultEnum.GET_INFO_SUCCESS.getMessage(), userInfoVo); return new ResultVO<>(ResultEnum.GET_INFO_SUCCESS.getCode(), ResultEnum.GET_INFO_SUCCESS.getMessage(), userInfoVo);
} }
/**
*
*
* @param request HttpServletRequest
* @return String
*/
@GetMapping("/test") @GetMapping("/test")
@ApiOperation("测试接口") @ApiOperation("测试接口")
String test(HttpServletRequest request) { String test(HttpServletRequest request) {

@ -8,11 +8,26 @@ package lsgwr.exam.dto;
import lombok.Data; import lombok.Data;
/**
*
*/
@Data @Data
public class RegisterDTO { public class RegisterDTO {
/**
*
*/
private String email; private String email;
/**
*
*/
private String password; private String password;
/**
*
*/
private String password2; private String password2;
/**
*
*/
private String mobile; private String mobile;
/** /**
* *

@ -23,37 +23,85 @@ import java.util.Date;
@Entity @Entity
@Data @Data
@DynamicUpdate @DynamicUpdate
/**
*
*/
public class Exam { public class Exam {
// 使用JPA的@Id注解声明该字段为主键 // 使用JPA的@Id注解声明该字段为主键
/**
* ID
*/
@Id @Id
private String examId;// 考试ID唯一标识一场考试 private String examId;
private String examName;// 考试名称 /**
private String examAvatar; // 考试头像或图标 *
private String examDescription;// 考试描述或简介 */
private String examQuestionIds;// 存储所有问题ID的字符串可能是逗号分隔的ID列表 private String examName;
private String examQuestionIdsRadio;// 存储所有单选题ID的字符串 /**
private String examQuestionIdsCheck;// 存储所有多选题ID的字符串 *
private String examQuestionIdsJudge;// 存储所有判断题ID的字符串 */
private Integer examScore;// 考试总分 private String examAvatar;
private Integer examScoreRadio;// 单选题总分 /**
private Integer examScoreCheck;// 多选题总分 *
private Integer examScoreJudge;// 判断题总分 */
private String examCreatorId;// 创建者ID标识谁创建了这场考试 private String examDescription;
private Integer examTimeLimit;// 考试时间限制,单位可能是分钟 /**
// 考试开始时间使用Jackson的@JsonFormat注解自定义日期格式 * IDID
*/
private String examQuestionIds;
/**
* ID
*/
private String examQuestionIdsRadio;
/**
* ID
*/
private String examQuestionIdsCheck;
/**
* ID
*/
private String examQuestionIdsJudge;
/**
*
*/
private Integer examScore;
/**
*
*/
private Integer examScoreRadio;
/**
*
*/
private Integer examScoreCheck;
/**
*
*/
private Integer examScoreJudge;
/**
* ID
*/
private String examCreatorId;
/**
*
*/
private Integer examTimeLimit;
/**
* 使Jackson@JsonFormat
*/
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8") @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
private Date examStartDate; private Date examStartDate;
// 考试结束时间 /**
*
*/
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8") @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
private Date examEndDate; private Date examEndDate;
/** /**
* Java * Java
* 使Jackson@JsonFormat便 * 使Jackson@JsonFormat便
*/ */
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8") @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
private Date createTime; private Date createTime;
/** /**
* Java * Java
* 使Hibernate@DynamicUpdate * 使Hibernate@DynamicUpdate

@ -16,13 +16,22 @@ import javax.persistence.Id;// 引入JPA中的@Id注解标识实体类的主
@Data @Data
// 使用@Entity注解标识这是一个JPA实体类 // 使用@Entity注解标识这是一个JPA实体类
@Entity @Entity
public class ExamRecordLevel { /**
// 考试记录等级的ID是主键通过@Id注解标识并通过@GeneratedValue注解指定主键生成策略 *
*/
public class ExamRecordLevel {
/**
* ID@Id@GeneratedValue
*/
@Id @Id
@GeneratedValue @GeneratedValue
private Integer examRecordLevelId; private Integer examRecordLevelId;
// 考试记录等级的名称,用于标识等级,如“优秀”、“良好”等 /**
*
*/
private String examRecordLevelName; private String examRecordLevelName;
// 考试记录等级的描述,用于对等级进行更详细的说明 /**
*
*/
private String examRecordLevelDescription; private String examRecordLevelDescription;
} }

@ -12,16 +12,28 @@ import javax.persistence.Entity;
import javax.persistence.GeneratedValue; import javax.persistence.GeneratedValue;
import javax.persistence.Id; import javax.persistence.Id;
/**
*
*/
@Data @Data
@Entity @Entity
public class Page { public class Page {
/**
* ID@Id@GeneratedValue
*/
@Id @Id
@GeneratedValue @GeneratedValue
private Integer pageId; private Integer pageId;
/**
*
*/
private String pageName; private String pageName;
/**
*
*/
private String pageDescription; private String pageDescription;
/**
* ID
*/
private String actionIds; private String actionIds;
} }

@ -9,20 +9,34 @@ package lsgwr.exam.exception;
import lsgwr.exam.enums.ResultEnum; import lsgwr.exam.enums.ResultEnum;
import lombok.Getter; import lombok.Getter;
/**
*
*/
@Getter @Getter
public class ExamException extends RuntimeException { public class ExamException extends RuntimeException {
// 定义异常码 /**
*
*/
private Integer code; private Integer code;
// 构造函数,传入枚举类型 /**
*
*
* @param resultEnum ResultEnum
*/
public ExamException(ResultEnum resultEnum) { public ExamException(ResultEnum resultEnum) {
super(resultEnum.getMessage()); super(resultEnum.getMessage());
this.code = resultEnum.getCode(); this.code = resultEnum.getCode();
} }
// 构造函数,传入异常码和异常信息 /**
*
*
* @param code
* @param message
*/
public ExamException( Integer code, String message) { public ExamException( Integer code, String message) {
super(message); super(message);
this.code = code; this.code = code;
} }
} }

@ -23,6 +23,10 @@ import java.io.PrintWriter;
* *
* @author liangshanguang * @author liangshanguang
*/ */
/**
* Token
*/
@Component @Component
public class LoginInterceptor implements HandlerInterceptor { public class LoginInterceptor implements HandlerInterceptor {
@ -84,9 +88,9 @@ public class LoginInterceptor implements HandlerInterceptor {
/** /**
* *
* *
* @param response * @param response
* @param obj * @param obj
* @throws Exception * @throws Exception
*/ */
public static void sendJsonMessage(HttpServletResponse response, Object obj) throws Exception { public static void sendJsonMessage(HttpServletResponse response, Object obj) throws Exception {
Gson g = new Gson(); Gson g = new Gson();

@ -10,6 +10,9 @@ import lombok.AllArgsConstructor;
import lombok.Data; import lombok.Data;
import lombok.NoArgsConstructor; import lombok.NoArgsConstructor;
/**
*
*/
@Data @Data
@AllArgsConstructor @AllArgsConstructor
@NoArgsConstructor @NoArgsConstructor

@ -11,7 +11,10 @@ import lombok.AllArgsConstructor;
import lombok.Data; import lombok.Data;
import lombok.NoArgsConstructor; import lombok.NoArgsConstructor;
import org.springframework.web.multipart.MultipartFile; import org.springframework.web.multipart.MultipartFile;
/**
*
*/
@Data @Data
@AllArgsConstructor @AllArgsConstructor
@NoArgsConstructor @NoArgsConstructor

@ -12,6 +12,9 @@ import lombok.Data;
import lombok.NoArgsConstructor; import lombok.NoArgsConstructor;
import org.springframework.web.multipart.MultipartFile; import org.springframework.web.multipart.MultipartFile;
/**
*
*/
@Data @Data
@AllArgsConstructor @AllArgsConstructor
@NoArgsConstructor @NoArgsConstructor

@ -9,6 +9,8 @@ package lsgwr.exam.repository;
import lsgwr.exam.entity.ExamRecordLevel; import lsgwr.exam.entity.ExamRecordLevel;
import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.data.jpa.repository.JpaRepository;
// ExamRecordLevelRepository接口继承JpaRepository接口用于操作ExamRecordLevel实体类 /**
* ExamRecordLevelRepositoryJpaRepositoryExamRecordLevel
*/
public interface ExamRecordLevelRepository extends JpaRepository<ExamRecordLevel, Integer> { public interface ExamRecordLevelRepository extends JpaRepository<ExamRecordLevel, Integer> {
} }

@ -5,6 +5,9 @@ import org.springframework.data.jpa.repository.JpaRepository;
import java.util.List; import java.util.List;
/**
*
*/
public interface ExamRecordRepository extends JpaRepository<ExamRecord, String> { public interface ExamRecordRepository extends JpaRepository<ExamRecord, String> {
/** /**
* *

@ -12,7 +12,9 @@ import org.springframework.data.jpa.repository.Query;
import java.util.List; import java.util.List;
// ExamRepository接口继承JpaRepository接口用于操作Exam实体类 /**
* ExamRepositoryJpaRepositoryExam
*/
public interface ExamRepository extends JpaRepository<Exam, String> { public interface ExamRepository extends JpaRepository<Exam, String> {
// 使用JPQL查询语句查询Exam实体类按照updateTime降序排列 // 使用JPQL查询语句查询Exam实体类按照updateTime降序排列
@Query("select e from Exam e order by e.updateTime desc") @Query("select e from Exam e order by e.updateTime desc")

@ -15,7 +15,18 @@ import java.util.List;
* *
*/ */
public interface QuestionRepository extends JpaRepository<Question, String> { public interface QuestionRepository extends JpaRepository<Question, String> {
/**
* ID
*
* @param id ID
* @return
*/
List<Question> findByQuestionTypeId(Integer id); List<Question> findByQuestionTypeId(Integer id);
/**
*
*
* @return
*/
@Query("select q from Question q order by q.updateTime desc") @Query("select q from Question q order by q.updateTime desc")
List<Question> findAll(); List<Question> findAll();
} }

@ -19,6 +19,9 @@ import org.springframework.stereotype.Service;
import javax.transaction.Transactional; import javax.transaction.Transactional;
import java.util.*; import java.util.*;
/**
*
*/
@Service @Service
@Transactional @Transactional
public class ExamServiceImpl implements ExamService { public class ExamServiceImpl implements ExamService {
@ -39,10 +42,21 @@ public class ExamServiceImpl implements ExamService {
private final QuestionOptionRepository questionOptionRepository; private final QuestionOptionRepository questionOptionRepository;
/**
*
* @param questionRepository
* @param userRepository
* @param questionLevelRepository
* @param questionTypeRepository
* @param questionCategoryRepository
* @param questionOptionRepository
* @param examRepository
* @param examRecordRepository
*/
public ExamServiceImpl(QuestionRepository questionRepository, UserRepository userRepository, QuestionLevelRepository questionLevelRepository, QuestionTypeRepository questionTypeRepository, QuestionCategoryRepository questionCategoryRepository, QuestionOptionRepository questionOptionRepository, ExamRepository examRepository, ExamRecordRepository examRecordRepository) { public ExamServiceImpl(QuestionRepository questionRepository, UserRepository userRepository, QuestionLevelRepository questionLevelRepository, QuestionTypeRepository questionTypeRepository, QuestionCategoryRepository questionCategoryRepository, QuestionOptionRepository questionOptionRepository, ExamRepository examRepository, ExamRecordRepository examRecordRepository) {
this.questionRepository = questionRepository;// this.questionRepository = questionRepository;
this.userRepository = userRepository;// this.userRepository = userRepository;
this.questionLevelRepository = questionLevelRepository;// this.questionLevelRepository = questionLevelRepository;
this.questionTypeRepository = questionTypeRepository; this.questionTypeRepository = questionTypeRepository;
this.questionCategoryRepository = questionCategoryRepository; this.questionCategoryRepository = questionCategoryRepository;
this.questionOptionRepository = questionOptionRepository; this.questionOptionRepository = questionOptionRepository;
@ -50,12 +64,22 @@ public class ExamServiceImpl implements ExamService {
this.examRecordRepository = examRecordRepository; this.examRecordRepository = examRecordRepository;
} }
/**
* @decription :
* return List<QuestionVo>
*/
@Override @Override
public List<QuestionVo> getQuestionAll() { public List<QuestionVo> getQuestionAll() {
List<Question> questionList = questionRepository.findAll(); List<Question> questionList = questionRepository.findAll();
return getQuestionVos(questionList); return getQuestionVos(questionList);
} }
/**
* Vo
*
* @param questionList
* @return Vo
*/
private List<QuestionVo> getQuestionVos(List<Question> questionList) { private List<QuestionVo> getQuestionVos(List<Question> questionList) {
// 需要自定义的question列表 // 需要自定义的question列表
List<QuestionVo> questionVoList = new ArrayList<>(); List<QuestionVo> questionVoList = new ArrayList<>();

@ -86,6 +86,12 @@ public class UserServiceImpl implements UserService {
} }
} }
/**
*
*
* @param loginQo
* @return tokennull
*/
@Override @Override
public String login(LoginQo loginQo) { public String login(LoginQo loginQo) {
User user; User user;

@ -5,7 +5,7 @@ spring:
driver-class-name: com.mysql.cj.jdbc.Driver driver-class-name: com.mysql.cj.jdbc.Driver
username: root username: root
password: aA111111 password: aA111111
url: jdbc:mysql://localhost:3306/exam?characterEncoding=utf-8&useSSL=false&serverTimezone=Asia/Shanghai url: jdbc:mysql://localhost:3306/exam?characterEncoding=utf-8&useSSL=false&serverTimezone=Asia/Shanghai&&allowPublicKeyRetrieval=true
jpa: jpa:
# 调试的时候用用于打印完成SQL语句(但是不打印参数),联合下面的logging.level一同打印最完整的SQL信息(语句+参数) # 调试的时候用用于打印完成SQL语句(但是不打印参数),联合下面的logging.level一同打印最完整的SQL信息(语句+参数)
show-sql: false show-sql: false

File diff suppressed because one or more lines are too long

@ -1,12 +1,15 @@
import enquireJs from 'enquire.js' import enquireJs from 'enquire.js'
// 定义设备类型的常量
export const DEVICE_TYPE = { export const DEVICE_TYPE = {
DESKTOP: 'desktop', DESKTOP: 'desktop',
TABLET: 'tablet', TABLET: 'tablet',
MOBILE: 'mobile' MOBILE: 'mobile'
} }
// 检测设备类型的函数
export const deviceEnquire = function (callback) { export const deviceEnquire = function (callback) {
// 定义每个设备类型的匹配函数
const matchDesktop = { const matchDesktop = {
match: () => { match: () => {
callback && callback(DEVICE_TYPE.DESKTOP) callback && callback(DEVICE_TYPE.DESKTOP)
@ -25,6 +28,7 @@ export const deviceEnquire = function (callback) {
} }
} }
// 为每个设备类型注册媒体查询
// screen and (max-width: 1087.99px) // screen and (max-width: 1087.99px)
enquireJs enquireJs
.register('screen and (max-width: 576px)', matchMobile) .register('screen and (max-width: 576px)', matchMobile)

@ -1,8 +1,8 @@
import Vue from 'vue' import Vue from 'vue' // 引入Vue
import moment from 'moment' import moment from 'moment' // 引入moment库
import 'moment/locale/zh-cn' import 'moment/locale/zh-cn' // 引入moment的中文语言包
import $ from 'jquery' import $ from 'jquery' // 引入jQuery
moment.locale('zh-cn') moment.locale('zh-cn') // 设置moment的语言为中文
Vue.filter('NumberFormat', function (value) { Vue.filter('NumberFormat', function (value) {
if (!value) { if (!value) {

@ -1,3 +1,4 @@
// 定义权限枚举
const PERMISSION_ENUM = { const PERMISSION_ENUM = {
'add': { key: 'add', label: '新增' }, 'add': { key: 'add', label: '新增' },
'delete': { key: 'delete', label: '删除' }, 'delete': { key: 'delete', label: '删除' },
@ -10,21 +11,30 @@ const PERMISSION_ENUM = {
'export': { key: 'export', label: '导出' } 'export': { key: 'export', label: '导出' }
} }
// 定义插件
function plugin (Vue) { function plugin (Vue) {
// 如果插件已经安装,则返回
if (plugin.installed) { if (plugin.installed) {
return return
} }
// 如果Vue实例中没有$auth属性则定义$auth属性
!Vue.prototype.$auth && Object.defineProperties(Vue.prototype, { !Vue.prototype.$auth && Object.defineProperties(Vue.prototype, {
$auth: { $auth: {
get () { get () {
// 获取当前实例
const _this = this const _this = this
// 返回一个函数,用于判断权限
return (permissions) => { return (permissions) => {
// 将权限字符串分割成permission和action
const [permission, action] = permissions.split('.') const [permission, action] = permissions.split('.')
// 获取当前用户的权限列表
const permissionList = _this.$store.getters.roles.permissions const permissionList = _this.$store.getters.roles.permissions
// 在权限列表中查找对应的permission
return permissionList.find((val) => { return permissionList.find((val) => {
return val.permissionId === permission return val.permissionId === permission
}).actionList.findIndex((val) => { }).actionList.findIndex((val) => {
// 在actionList中查找对应的action
return val === action return val === action
}) > -1 }) > -1
} }
@ -32,15 +42,21 @@ function plugin (Vue) {
} }
}) })
// 如果Vue实例中没有$enum属性则定义$enum属性
!Vue.prototype.$enum && Object.defineProperties(Vue.prototype, { !Vue.prototype.$enum && Object.defineProperties(Vue.prototype, {
$enum: { $enum: {
get () { get () {
// const _this = this; // const _this = this;
// 返回一个函数,用于获取枚举值
return (val) => { return (val) => {
// 初始化result为PERMISSION_ENUM
let result = PERMISSION_ENUM let result = PERMISSION_ENUM
// 如果val存在则将val按'.'分割成数组
val && val.split('.').forEach(v => { val && val.split('.').forEach(v => {
// 在result中查找对应的值
result = result && result[v] || null result = result && result[v] || null
}) })
// 返回result
return result return result
} }
} }
@ -48,4 +64,5 @@ function plugin (Vue) {
}) })
} }
// 导出插件
export default plugin export default plugin

@ -1,9 +1,13 @@
// import Vue from 'vue' // import Vue from 'vue'
// 引入Vue
import { deviceEnquire, DEVICE_TYPE } from '../utils/device' import { deviceEnquire, DEVICE_TYPE } from '../utils/device'
// 引入设备检测工具和设备类型
import { mapState } from 'vuex' import { mapState } from 'vuex'
// 引入Vuex的mapState方法
// const mixinsComputed = Vue.config.optionMergeStrategies.computed // const mixinsComputed = Vue.config.optionMergeStrategies.computed
// const mixinsMethods = Vue.config.optionMergeStrategies.methods // const mixinsMethods = Vue.config.optionMergeStrategies.methods
// 定义Vue的computed和methods的合并策略
const mixin = { const mixin = {
computed: { computed: {
@ -72,5 +76,5 @@ const AppDeviceEnquire = {
}) })
} }
} }
// 导出mixin、AppDeviceEnquire、mixinDevice
export { mixin, AppDeviceEnquire, mixinDevice } export { mixin, AppDeviceEnquire, mixinDevice }

@ -1,8 +1,12 @@
// 导出一个函数将json字符串转换为对象
export function actionToObject (json) { export function actionToObject (json) {
try { try {
// 尝试将json字符串转换为对象
return JSON.parse(json) return JSON.parse(json)
} catch (e) { } catch (e) {
// 如果转换失败,打印错误信息
console.log('err', e.message) console.log('err', e.message)
} }
// 返回一个空数组
return [] return []
} }

@ -15,6 +15,7 @@ const service = axios.create({
timeout: 6000 // 请求超时时间 timeout: 6000 // 请求超时时间
}) })
// 错误处理函数
const err = (error) => { const err = (error) => {
if (error.response) { if (error.response) {
const data = error.response.data const data = error.response.data

@ -6,17 +6,22 @@
* @param maxAge * @param maxAge
*/ */
export const setStore = (name, content, maxAge = null) => { export const setStore = (name, content, maxAge = null) => {
// 如果没有全局window对象或者没有传入name则返回
if (!global.window || !name) { if (!global.window || !name) {
return return
} }
// 如果content不是字符串则将其转换为字符串
if (typeof content !== 'string') { if (typeof content !== 'string') {
content = JSON.stringify(content) content = JSON.stringify(content)
} }
// 获取localStorage对象
const storage = global.window.localStorage const storage = global.window.localStorage
// 将content存储到localStorage中
storage.setItem(name, content) storage.setItem(name, content)
// 如果maxAge存在且为数字则将过期时间存储到localStorage中
if (maxAge && !isNaN(parseInt(maxAge))) { if (maxAge && !isNaN(parseInt(maxAge))) {
const timeout = parseInt(new Date().getTime() / 1000) const timeout = parseInt(new Date().getTime() / 1000)
storage.setItem(`${name}_expire`, timeout + maxAge) storage.setItem(`${name}_expire`, timeout + maxAge)
@ -30,13 +35,17 @@ export const setStore = (name, content, maxAge = null) => {
* @returns {*} * @returns {*}
*/ */
export const getStore = name => { export const getStore = name => {
// 如果没有全局window对象或者没有传入name则返回
if (!global.window || !name) { if (!global.window || !name) {
return return
} }
// 获取localStorage中存储的content
const content = window.localStorage.getItem(name) const content = window.localStorage.getItem(name)
// 获取localStorage中存储的过期时间
const _expire = window.localStorage.getItem(`${name}_expire`) const _expire = window.localStorage.getItem(`${name}_expire`)
// 如果过期时间存在,则判断当前时间是否超过过期时间
if (_expire) { if (_expire) {
const now = parseInt(new Date().getTime() / 1000) const now = parseInt(new Date().getTime() / 1000)
if (now > _expire) { if (now > _expire) {
@ -44,9 +53,11 @@ export const getStore = name => {
} }
} }
// 尝试将content解析为JSON对象
try { try {
return JSON.parse(content) return JSON.parse(content)
} catch (e) { } catch (e) {
// 如果解析失败则返回content
return content return content
} }
} }
@ -57,11 +68,14 @@ export const getStore = name => {
* @param name * @param name
*/ */
export const clearStore = name => { export const clearStore = name => {
// 如果没有全局window对象或者没有传入name则返回
if (!global.window || !name) { if (!global.window || !name) {
return return
} }
// 从localStorage中移除content
window.localStorage.removeItem(name) window.localStorage.removeItem(name)
// 从localStorage中移除过期时间
window.localStorage.removeItem(`${name}_expire`) window.localStorage.removeItem(`${name}_expire`)
} }
@ -69,9 +83,11 @@ export const clearStore = name => {
* Clear all storage * Clear all storage
*/ */
export const clearAll = () => { export const clearAll = () => {
// 如果没有全局window对象或者没有传入name则返回
if (!global.window || !name) { if (!global.window || !name) {
return return
} }
// 清空localStorage
window.localStorage.clear() window.localStorage.clear()
} }

@ -1,9 +1,11 @@
// 导出一个函数,用于获取当前时间并返回相应的问候语
export function timeFix () { export function timeFix () {
const time = new Date() const time = new Date()
const hour = time.getHours() const hour = time.getHours()
return hour < 9 ? '早上好' : hour <= 11 ? '上午好' : hour <= 13 ? '中午好' : hour < 20 ? '下午好' : '晚上好' return hour < 9 ? '早上好' : hour <= 11 ? '上午好' : hour <= 13 ? '中午好' : hour < 20 ? '下午好' : '晚上好'
} }
// 导出一个函数,用于随机返回一个问候语
export function welcome () { export function welcome () {
const arr = ['休息一会儿吧', '准备吃什么呢?', '要不要打一把 DOTA', '我猜你可能累了'] const arr = ['休息一会儿吧', '准备吃什么呢?', '要不要打一把 DOTA', '我猜你可能累了']
const index = Math.floor(Math.random() * arr.length) const index = Math.floor(Math.random() * arr.length)
@ -13,6 +15,7 @@ export function welcome () {
/** /**
* 触发 window.resize * 触发 window.resize
*/ */
// 导出一个函数,用于触发 window.resize 事件
export function triggerWindowResizeEvent () { export function triggerWindowResizeEvent () {
const event = document.createEvent('HTMLEvents') const event = document.createEvent('HTMLEvents')
event.initEvent('resize', true, true) event.initEvent('resize', true, true)
@ -20,6 +23,7 @@ export function triggerWindowResizeEvent () {
window.dispatchEvent(event) window.dispatchEvent(event)
} }
// 导出一个函数,用于监听页面滚动事件
export function handleScrollHeader (callback) { export function handleScrollHeader (callback) {
let timer = 0 let timer = 0
@ -50,6 +54,7 @@ export function handleScrollHeader (callback) {
* @param id parent element id or class * @param id parent element id or class
* @param timeout * @param timeout
*/ */
// 导出一个函数,用于移除加载动画
export function removeLoadingAnimate (id = '', timeout = 1500) { export function removeLoadingAnimate (id = '', timeout = 1500) {
if (id === '') { if (id === '') {
return return

@ -1,11 +1,14 @@
<template> <template>
<!-- 这是 Vue 组件的模板部分 -->
<exception-page type="403" /> <exception-page type="403" />
</template> </template>
<script> <script>
// components ExceptionPage
import { ExceptionPage } from '../../components' import { ExceptionPage } from '../../components'
export default { export default {
// ExceptionPage
components: { components: {
ExceptionPage ExceptionPage
} }

@ -1,18 +1,28 @@
<template> <template>
<div class="card-list" ref="content"> <div class="card-list" ref="content">
<!-- 使用a-list组件设置grid属性gutter为24lg为3md为2sm为1xs为1 -->
<a-list <a-list
:grid="{gutter: 24, lg: 3, md: 2, sm: 1, xs: 1}" :grid="{gutter: 24, lg: 3, md: 2, sm: 1, xs: 1}"
:dataSource="dataSource" :dataSource="dataSource"
> >
<!-- 使用a-list-item组件设置slot为renderItemslot-scope为item -->
<a-list-item slot="renderItem" slot-scope="item"> <a-list-item slot="renderItem" slot-scope="item">
<!-- 使用a-card组件设置hoverable为true点击事件为joinExam -->
<a-card :hoverable="true" @click="joinExam(item.id)"> <a-card :hoverable="true" @click="joinExam(item.id)">
<!-- 使用a-card-meta组件设置slot为titleavatardescription -->
<a-card-meta> <a-card-meta>
<!-- 设置title为item.title -->
<div style="margin-bottom: 3px" slot="title">{{ item.title }}</div> <div style="margin-bottom: 3px" slot="title">{{ item.title }}</div>
<!-- 设置avatar为item.avatar使用imgSrcFilter过滤器 -->
<a-avatar class="card-avatar" slot="avatar" :src="item.avatar | imgSrcFilter" size="large" /> <a-avatar class="card-avatar" slot="avatar" :src="item.avatar | imgSrcFilter" size="large" />
<!-- 设置description为item.content -->
<div class="meta-content" slot="description">{{ item.content }}</div> <div class="meta-content" slot="description">{{ item.content }}</div>
</a-card-meta> </a-card-meta>
<!-- 使用template组件设置slot为actions -->
<template class="ant-card-actions" slot="actions"> <template class="ant-card-actions" slot="actions">
<!-- 设置a为满分item.score分 -->
<a>满分{{ item.score }}</a> <a>满分{{ item.score }}</a>
<!-- 设置a为限时item.elapse分钟 -->
<a>限时{{ item.elapse }}分钟</a> <a>限时{{ item.elapse }}分钟</a>
</template> </template>
</a-card> </a-card>
@ -34,6 +44,7 @@ export default {
} }
}, },
methods: { methods: {
//
joinExam (id) { joinExam (id) {
const routeUrl = this.$router.resolve({ const routeUrl = this.$router.resolve({
path: `/exam/${id}` path: `/exam/${id}`

@ -85,15 +85,15 @@ export default {
}, },
data () { data () {
return { return {
// //
examDetail: {}, examDetail: {},
// id, currentQuestion(answersidids), // id, currentQuestion(answersidids),
answersMap: {}, answersMap: {},
// //
currentQuestion: '', currentQuestion: '',
// answersMap // answersMap
radioValue: '', radioValue: '',
// answersMap // answersMap
checkValues: [], checkValues: [],
optionStyle: { optionStyle: {
display: 'block', display: 'block',
@ -106,7 +106,7 @@ export default {
mounted () { mounted () {
this.answersMap = new Map() this.answersMap = new Map()
const that = this const that = this
// //
getExamDetail(this.$route.params.id) getExamDetail(this.$route.params.id)
.then(res => { .then(res => {
if (res.code === 0) { if (res.code === 0) {
@ -122,26 +122,26 @@ export default {
}) })
}, },
methods: { methods: {
// , //
...mapGetters(['nickname', 'avatar']), ...mapGetters(['nickname', 'avatar']),
getQuestionDetail (questionId) { getQuestionDetail (questionId) {
// content // content
const that = this const that = this
// //
this.radioValue = '' this.radioValue = ''
this.checkValues = [] this.checkValues = []
getQuestionDetail(questionId) getQuestionDetail(questionId)
.then(res => { .then(res => {
if (res.code === 0) { if (res.code === 0) {
// //
that.currentQuestion = res.data that.currentQuestion = res.data
// answersMapid // answersMapid
if (that.answersMap.get(that.currentQuestion.id)) { if (that.answersMap.get(that.currentQuestion.id)) {
// //
if (that.currentQuestion.type === '单选题' || that.currentQuestion.type === '判断题') { if (that.currentQuestion.type === '单选题' || that.currentQuestion.type === '判断题') {
that.radioValue = that.answersMap.get(that.currentQuestion.id)[0] that.radioValue = that.answersMap.get(that.currentQuestion.id)[0]
} else if (that.currentQuestion.type === '多选题') { } else if (that.currentQuestion.type === '多选题') {
// //
Object.assign(that.checkValues, that.answersMap.get(that.currentQuestion.id)) Object.assign(that.checkValues, that.answersMap.get(that.currentQuestion.id))
} }
} }

Loading…
Cancel
Save