Initial commit

Signed-off-by: shl <1577537067@qq.com>
pzk6utiap 2 years ago committed by shl
parent 009f41dbc2
commit 3099d7c4a1

@ -1,117 +1,113 @@
package com.yf.exam.modules.repo.controller;
package com.yf.exam.modules.repo.controller; // 包名:表示该类属于 repo.controller 包
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.yf.exam.core.api.ApiRest;
import com.yf.exam.core.api.controller.BaseController;
import com.yf.exam.core.api.dto.BaseIdReqDTO;
import com.yf.exam.core.api.dto.BaseIdsReqDTO;
import com.yf.exam.core.api.dto.PagingReqDTO;
import com.yf.exam.modules.qu.dto.request.QuRepoBatchReqDTO;
import com.yf.exam.modules.qu.service.QuRepoService;
import com.yf.exam.modules.repo.dto.RepoDTO;
import com.yf.exam.modules.repo.dto.request.RepoReqDTO;
import com.yf.exam.modules.repo.dto.response.RepoRespDTO;
import com.yf.exam.modules.repo.entity.Repo;
import com.yf.exam.modules.repo.service.RepoService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.apache.shiro.authz.annotation.RequiresRoles;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;
// 导入所需的类和包
import com.baomidou.mybatisplus.core.metadata.IPage; // 分页元数据接口
import com.yf.exam.core.api.ApiRest; // 统一 API 响应类
import com.yf.exam.core.api.controller.BaseController; // 控制器基类,提供通用控制功能
import com.yf.exam.core.api.dto.BaseIdReqDTO; // 数据传输对象,用于封装单个 ID 请求
import com.yf.exam.core.api.dto.BaseIdsReqDTO; // 数据传输对象,用于封装多个 ID 请求
import com.yf.exam.core.api.dto.PagingReqDTO; // 数据传输对象,用于分页请求
import com.yf.exam.modules.qu.dto.request.QuRepoBatchReqDTO; // 数据传输对象,用于题库批量操作请求
import com.yf.exam.modules.qu.service.QuRepoService; // 服务接口,用于题库的批量操作
import com.yf.exam.modules.repo.dto.RepoDTO; // 数据传输对象,封装题库信息
import com.yf.exam.modules.repo.dto.request.RepoReqDTO; // 数据传输对象,用于题库分页查询请求
import com.yf.exam.modules.repo.dto.response.RepoRespDTO; // 数据传输对象,用于题库分页查询响应
import com.yf.exam.modules.repo.entity.Repo; // 题库实体类
import com.yf.exam.modules.repo.service.RepoService; // 服务接口,用于题库操作
import io.swagger.annotations.Api; // Swagger 注解,用于 API 文档生成
import io.swagger.annotations.ApiOperation; // Swagger 注解,用于定义接口操作说明
import org.apache.shiro.authz.annotation.RequiresRoles; // Shiro 注解,用于权限控制
import org.springframework.beans.BeanUtils; // 工具类,用于对象属性拷贝
import org.springframework.beans.factory.annotation.Autowired; // Spring 注解,用于依赖注入
import org.springframework.web.bind.annotation.RequestBody; // 注解,用于绑定请求体
import org.springframework.web.bind.annotation.RequestMapping; // 注解,用于定义请求路径
import org.springframework.web.bind.annotation.RequestMethod; // 注解,用于指定 HTTP 请求方法
import org.springframework.web.bind.annotation.RestController; // 注解,标识为 REST 控制器
/**
* <p>
*
* </p>
*
* @author
* @since 2020-05-25 13:25
*/
@Api(tags={"题库"})
@RestController
@RequestMapping("/exam/api/repo")
public class RepoController extends BaseController {
* <p>
*
* </p>
*
*
* @
* @ 2020-05-25 13:25
*/
@Api(tags = {"题库"}) // Swagger 注解:定义 API 文档中该控制器的标签为“题库”
@RestController // Spring 注解:标识该类为 REST 控制器
@RequestMapping("/exam/api/repo") // 定义请求路径前缀为 /exam/api/repo
public class RepoController extends BaseController { // 题库控制器类,继承基础控制器
@Autowired
@Autowired // 自动注入题库服务
private RepoService baseService;
@Autowired
@Autowired // 自动注入题库批量操作服务
private QuRepoService quRepoService;
/**
*
* @param reqDTO
* @return
*/
@RequiresRoles("sa")
@ApiOperation(value = "添加或修改")
@RequestMapping(value = "/save", method = { RequestMethod.POST})
public ApiRest save(@RequestBody RepoDTO reqDTO) {
baseService.save(reqDTO);
return super.success();
*
* @param reqDTO
* @return
*/
@RequiresRoles("sa") // 权限控制:要求用户具有 "sa" 角色
@ApiOperation(value = "添加或修改") // Swagger 注解:定义接口操作说明为“添加或修改”
@RequestMapping(value = "/save", method = {RequestMethod.POST}) // 定义请求路径为 /save请求方法为 POST
public ApiRest save(@RequestBody RepoDTO reqDTO) { // 添加或修改题库的方法
baseService.save(reqDTO); // 调用服务保存题库信息
return super.success(); // 返回成功结果
}
/**
*
* @param reqDTO
* @return
*/
@RequiresRoles("sa")
@ApiOperation(value = "批量删除")
@RequestMapping(value = "/delete", method = { RequestMethod.POST})
public ApiRest edit(@RequestBody BaseIdsReqDTO reqDTO) {
//根据ID删除
baseService.removeByIds(reqDTO.getIds());
return super.success();
*
* @param reqDTO ID
* @return
*/
@RequiresRoles("sa") // 权限控制:要求用户具有 "sa" 角色
@ApiOperation(value = "批量删除") // Swagger 注解:定义接口操作说明为“批量删除”
@RequestMapping(value = "/delete", method = {RequestMethod.POST}) // 定义请求路径为 /delete请求方法为 POST
public ApiRest edit(@RequestBody BaseIdsReqDTO reqDTO) { // 批量删除题库的方法
baseService.removeByIds(reqDTO.getIds()); // 根据 ID 列表删除题库
return super.success(); // 返回成功结果
}
/**
*
* @param reqDTO
* @return
*/
@RequiresRoles("sa")
@ApiOperation(value = "查找详情")
@RequestMapping(value = "/detail", method = { RequestMethod.POST})
public ApiRest<RepoDTO> find(@RequestBody BaseIdReqDTO reqDTO) {
Repo entity = baseService.getById(reqDTO.getId());
RepoDTO dto = new RepoDTO();
BeanUtils.copyProperties(entity, dto);
return super.success(dto);
*
* @param reqDTO ID
* @return
*/
@RequiresRoles("sa") // 权限控制:要求用户具有 "sa" 角色
@ApiOperation(value = "查找详情") // Swagger 注解:定义接口操作说明为“查找详情”
@RequestMapping(value = "/detail", method = {RequestMethod.POST}) // 定义请求路径为 /detail请求方法为 POST
public ApiRest<RepoDTO> find(@RequestBody BaseIdReqDTO reqDTO) { // 查找题库详情的方法
Repo entity = baseService.getById(reqDTO.getId()); // 根据 ID 查找题库实体
RepoDTO dto = new RepoDTO(); // 创建题库数据传输对象
BeanUtils.copyProperties(entity, dto); // 将实体属性拷贝到 DTO 中
return super.success(dto); // 返回成功结果,包含题库详情
}
/**
*
* @param reqDTO
* @return
*/
@RequiresRoles("sa")
@ApiOperation(value = "分页查找")
@RequestMapping(value = "/paging", method = { RequestMethod.POST})
public ApiRest<IPage<RepoRespDTO>> paging(@RequestBody PagingReqDTO<RepoReqDTO> reqDTO) {
//分页查询并转换
IPage<RepoRespDTO> page = baseService.paging(reqDTO);
return super.success(page);
*
* @param reqDTO
* @return
*/
@RequiresRoles("sa") // 权限控制:要求用户具有 "sa" 角色
@ApiOperation(value = "分页查找") // Swagger 注解:定义接口操作说明为“分页查找”
@RequestMapping(value = "/paging", method = {RequestMethod.POST}) // 定义请求路径为 /paging请求方法为 POST
public ApiRest<IPage<RepoRespDTO>> paging(@RequestBody PagingReqDTO<RepoReqDTO> reqDTO) { // 分页查找题库的方法
IPage<RepoRespDTO> page = baseService.paging(reqDTO); // 调用服务进行分页查询
return super.success(page); // 返回成功结果,包含分页数据
}
/**
*
* @param reqDTO
* @return
*
* @param reqDTO
* @return
*/
@RequiresRoles("sa")
@ApiOperation(value = "批量操作", notes = "批量加入或从题库移除")
@RequestMapping(value = "/batch-action", method = { RequestMethod.POST})
public ApiRest batchAction(@RequestBody QuRepoBatchReqDTO reqDTO) {
//分页查询并转换
quRepoService.batchAction(reqDTO);
return super.success();
@RequiresRoles("sa") // 权限控制:要求用户具有 "sa" 角色
@ApiOperation(value = "批量操作", notes = "批量加入或从题库移除") // Swagger 注解:定义接口操作说明为“批量操作”,并提供备注
@RequestMapping(value = "/batch-action", method = {RequestMethod.POST}) // 定义请求路径为 /batch-action请求方法为 POST
public ApiRest batchAction(@RequestBody QuRepoBatchReqDTO reqDTO) { // 批量操作题库的方法
quRepoService.batchAction(reqDTO); // 调用服务执行批量操作
return super.success(); // 返回成功结果
}
}

@ -1,43 +1,42 @@
package com.yf.exam.modules.repo.dto;
package com.yf.exam.modules.repo.dto; // 包名:表示该类属于 repo.dto 包
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import io.swagger.annotations.ApiModel; // 导入 Swagger 注解,用于定义 API 模型
import io.swagger.annotations.ApiModelProperty; // 导入 Swagger 注解,用于描述 API 模型的属性
import lombok.Data; // 导入 Lombok 注解,用于自动生成 Getter、Setter、toString 等方法
import java.io.Serializable;
import java.util.Date;
import java.io.Serializable; // 导入 Serializable 接口,用于支持序列化
import java.util.Date; // 导入 Date 类,用于处理日期和时间
/**
* <p>
*
* </p>
*
* @author
* @since 2020-05-25 13:23
*/
@Data
@ApiModel(value="题库", description="题库")
public class RepoDTO implements Serializable {
* <p>
*
* </p>
*
*
* @
* @ 2020-05-25 13:23
*/
@Data // Lombok 注解,自动生成 Getter、Setter 和其他方法
@ApiModel(value = "题库", description = "题库") // Swagger 注解,定义该类的 API 模型名称及描述
public class RepoDTO implements Serializable { // 定义类 RepoDTO实现 Serializable 接口以支持序列化
private static final long serialVersionUID = 1L;
private static final long serialVersionUID = 1L; // 序列化版本号,用于序列化和反序列化的一致性检查
@ApiModelProperty(value = "题库ID", required = true) // Swagger 注解,描述该属性为“题库 ID”
private String id; // 定义属性:题库的唯一标识符
@ApiModelProperty(value = "题库ID", required=true)
private String id;
@ApiModelProperty(value = "题库编号", required = true) // Swagger 注解,描述该属性为“题库编号”
private String code; // 定义属性:题库编号
@ApiModelProperty(value = "题库编号", required=true)
private String code;
@ApiModelProperty(value = "题库名称", required = true) // Swagger 注解,描述该属性为“题库名称”
private String title; // 定义属性:题库名称
@ApiModelProperty(value = "题库名称", required=true)
private String title;
@ApiModelProperty(value = "题库备注", required = true) // Swagger 注解,描述该属性为“题库备注”
private String remark; // 定义属性:题库备注信息
@ApiModelProperty(value = "题库备注", required=true)
private String remark;
@ApiModelProperty(value = "创建时间", required = true) // Swagger 注解,描述该属性为“创建时间”
private Date createTime; // 定义属性:题库的创建时间
@ApiModelProperty(value = "创建时间", required=true)
private Date createTime;
@ApiModelProperty(value = "更新时间", required=true)
private Date updateTime;
@ApiModelProperty(value = "更新时间", required = true) // Swagger 注解,描述该属性为“更新时间”
private Date updateTime; // 定义属性:题库的最后更新时间
}

@ -1,30 +1,30 @@
package com.yf.exam.modules.repo.dto.request;
package com.yf.exam.modules.repo.dto.request; // 包名:表示该类属于 repo.dto.request 包
import com.yf.exam.modules.repo.dto.RepoDTO;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import com.yf.exam.modules.repo.dto.RepoDTO; // 导入 RepoDTO 类,题库数据传输对象
import io.swagger.annotations.ApiModel; // 导入 Swagger 注解,用于定义 API 模型
import io.swagger.annotations.ApiModelProperty; // 导入 Swagger 注解,用于描述 API 模型的属性
import lombok.Data; // 导入 Lombok 注解,用于自动生成 Getter、Setter、toString 等方法
import java.util.List;
import java.util.List; // 导入 Java 的 List 接口,用于存储排除的题库 ID 列表
/**
* <p>
*
* </p>
*
* @author
* @since 2020-05-25 13:23
*/
@Data
@ApiModel(value="题库分页请求类", description="题库分页请求类")
public class RepoReqDTO extends RepoDTO {
* <p>
*
* </p>
*
*
* @
* @ 2020-05-25 13:23
*/
@Data // Lombok 注解,自动生成 Getter、Setter 和其他方法
@ApiModel(value = "题库分页请求类", description = "题库分页请求类") // Swagger 注解,定义该类的 API 模型名称及描述
public class RepoReqDTO extends RepoDTO { // 定义类 RepoReqDTO继承自 RepoDTO
private static final long serialVersionUID = 1L;
private static final long serialVersionUID = 1L; // 序列化版本号,用于序列化和反序列化的一致性检查
@ApiModelProperty(value = "排除题库ID", required=true)
private List<String> excludes;
@ApiModelProperty(value = "单选题数量", required=true)
private String title;
@ApiModelProperty(value = "排除题库ID", required = true) // Swagger 注解,描述该属性为“需要排除的题库 ID 列表”
private List<String> excludes; // 定义属性:排除的题库 ID 列表
@ApiModelProperty(value = "单选题数量", required = true) // Swagger 注解,描述该属性为“单选题数量”
private String title; // 定义属性:单选题数量(注意:变量名可能存在歧义,建议确认或重命名)
}

@ -1,31 +1,31 @@
package com.yf.exam.modules.repo.dto.response;
package com.yf.exam.modules.repo.dto.response; // 包名:表示该类属于 repo.dto.response 包
import com.yf.exam.modules.repo.dto.RepoDTO;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import com.yf.exam.modules.repo.dto.RepoDTO; // 导入 RepoDTO 类,题库通用数据传输对象
import io.swagger.annotations.ApiModel; // 导入 Swagger 注解,用于定义 API 模型
import io.swagger.annotations.ApiModelProperty; // 导入 Swagger 注解,用于描述 API 模型的属性
import lombok.Data; // 导入 Lombok 注解,用于自动生成 Getter、Setter、toString 等方法
/**
* <p>
*
* </p>
*
* @author
* @since 2020-05-25 13:23
*/
@Data
@ApiModel(value="题库分页响应类", description="题库分页响应类")
public class RepoRespDTO extends RepoDTO {
* <p>
*
* </p>
*
*
* @
* @ 2020-05-25 13:23
*/
@Data // Lombok 注解,自动生成 Getter、Setter 和其他方法
@ApiModel(value = "题库分页响应类", description = "题库分页响应类") // Swagger 注解,定义该类的 API 模型名称及描述
public class RepoRespDTO extends RepoDTO { // 定义类 RepoRespDTO继承自 RepoDTO
private static final long serialVersionUID = 1L;
private static final long serialVersionUID = 1L; // 序列化版本号,用于序列化和反序列化的一致性检查
@ApiModelProperty(value = "多选题数量", required=true)
private Integer multiCount;
@ApiModelProperty(value = "多选题数量", required = true) // Swagger 注解,描述该属性为“多选题数量”
private Integer multiCount; // 定义属性:多选题的数量
@ApiModelProperty(value = "单选题数量", required=true)
private Integer radioCount;
@ApiModelProperty(value = "判断题数量", required=true)
private Integer judgeCount;
@ApiModelProperty(value = "单选题数量", required = true) // Swagger 注解,描述该属性为“单选题数量”
private Integer radioCount; // 定义属性:单选题的数量
@ApiModelProperty(value = "判断题数量", required = true) // Swagger 注解,描述该属性为“判断题数量”
private Integer judgeCount; // 定义属性:判断题的数量
}

@ -1,59 +1,59 @@
package com.yf.exam.modules.repo.entity;
package com.yf.exam.modules.repo.entity; // 包名:表示该类属于 repo.entity 包
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import com.baomidou.mybatisplus.extension.activerecord.Model;
import lombok.Data;
import com.baomidou.mybatisplus.annotation.IdType; // 导入 MyBatis-Plus 注解,用于定义主键类型
import com.baomidou.mybatisplus.annotation.TableField; // 导入 MyBatis-Plus 注解,用于映射数据库字段
import com.baomidou.mybatisplus.annotation.TableId; // 导入 MyBatis-Plus 注解,用于标识主键字段
import com.baomidou.mybatisplus.annotation.TableName; // 导入 MyBatis-Plus 注解,用于映射数据库表名
import com.baomidou.mybatisplus.extension.activerecord.Model; // 导入 MyBatis-Plus ActiveRecord 模式基类
import lombok.Data; // 导入 Lombok 注解,用于自动生成 Getter、Setter、toString 等方法
import java.util.Date;
import java.util.Date; // 导入 Java 的 Date 类,用于表示日期和时间
/**
* <p>
*
* </p>
*
* @author
* @since 2020-05-25 13:23
*/
@Data
@TableName("el_repo")
public class Repo extends Model<Repo> {
private static final long serialVersionUID = 1L;
* <p>
*
* </p>
*
*
* @
* @ 2020-05-25 13:23
*/
@Data // Lombok 注解,自动生成 Getter、Setter 和其他方法
@TableName("el_repo") // MyBatis-Plus 注解,指定该实体类映射的数据库表名为 "el_repo"
public class Repo extends Model<Repo> { // 定义类 Repo继承 MyBatis-Plus 的 Model 类以支持 ActiveRecord 模式
private static final long serialVersionUID = 1L; // 序列化版本号,用于序列化和反序列化的一致性检查
/**
* ID
*/
@TableId(value = "id", type = IdType.ASSIGN_ID)
private String id;
@TableId(value = "id", type = IdType.ASSIGN_ID) // MyBatis-Plus 注解,标识主键字段,并指定主键生成策略为分配 ID
private String id; // 定义字段:题库的唯一标识符
/**
*
*/
private String code;
private String code; // 定义字段:题库编号
/**
*
*/
private String title;
private String title; // 定义字段:题库名称
/**
*
*/
private String remark;
private String remark; // 定义字段:题库备注信息
/**
*
*/
@TableField("create_time")
private Date createTime;
@TableField("create_time") // MyBatis-Plus 注解,指定该字段映射数据库中的 "create_time" 列
private Date createTime; // 定义字段:题库的创建时间
/**
*
*/
@TableField("update_time")
private Date updateTime;
@TableField("update_time") // MyBatis-Plus 注解,指定该字段映射数据库中的 "update_time" 列
private Date updateTime; // 定义字段:题库的最后更新时间
}

@ -1,29 +1,29 @@
package com.yf.exam.modules.repo.mapper;
package com.yf.exam.modules.repo.mapper; // 包名:表示该类属于 repo.mapper 包
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.yf.exam.modules.repo.dto.request.RepoReqDTO;
import com.yf.exam.modules.repo.dto.response.RepoRespDTO;
import com.yf.exam.modules.repo.entity.Repo;
import org.apache.ibatis.annotations.Param;
import com.baomidou.mybatisplus.core.mapper.BaseMapper; // 导入 MyBatis-Plus 的 BaseMapper 接口,用于基本的数据库操作
import com.baomidou.mybatisplus.core.metadata.IPage; // 导入 MyBatis-Plus 分页接口
import com.baomidou.mybatisplus.extension.plugins.pagination.Page; // 导入 MyBatis-Plus 分页插件中的 Page 类
import com.yf.exam.modules.repo.dto.request.RepoReqDTO; // 导入用于分页查询的请求数据传输对象 RepoReqDTO
import com.yf.exam.modules.repo.dto.response.RepoRespDTO; // 导入用于分页查询的响应数据传输对象 RepoRespDTO
import com.yf.exam.modules.repo.entity.Repo; // 导入题库实体类 Repo
import org.apache.ibatis.annotations.Param; // 导入 MyBatis 注解,用于标注参数
/**
* <p>
* Mapper
* </p>
*
* @author
* @since 2020-05-25 13:23
*/
public interface RepoMapper extends BaseMapper<Repo> {
* <p>
* Mapper
* </p>
* Mapper
*
* @
* @ 2020-05-25 13:23
*/
public interface RepoMapper extends BaseMapper<Repo> { // RepoMapper 接口,继承自 MyBatis-Plus 的 BaseMapper提供常见的数据库操作
/**
*
* @param page
* @param query
* @return
* @param page
* @param query
* @return
*/
IPage<RepoRespDTO> paging(Page page, @Param("query") RepoReqDTO query);
IPage<RepoRespDTO> paging(Page page, @Param("query") RepoReqDTO query); // 自定义分页查询方法,返回题库分页响应数据
}

@ -1,34 +1,34 @@
package com.yf.exam.modules.repo.service;
package com.yf.exam.modules.repo.service; // 包名:表示该类属于 repo.service 包
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.service.IService;
import com.yf.exam.core.api.dto.PagingReqDTO;
import com.yf.exam.modules.repo.dto.RepoDTO;
import com.yf.exam.modules.repo.dto.request.RepoReqDTO;
import com.yf.exam.modules.repo.dto.response.RepoRespDTO;
import com.yf.exam.modules.repo.entity.Repo;
import com.baomidou.mybatisplus.core.metadata.IPage; // 导入 MyBatis-Plus 分页接口
import com.baomidou.mybatisplus.extension.service.IService; // 导入 MyBatis-Plus 服务接口,提供通用的数据库操作
import com.yf.exam.core.api.dto.PagingReqDTO; // 导入分页请求数据传输对象
import com.yf.exam.modules.repo.dto.RepoDTO; // 导入 RepoDTO 类,题库数据传输对象
import com.yf.exam.modules.repo.dto.request.RepoReqDTO; // 导入 RepoReqDTO 类,用于封装分页查询条件
import com.yf.exam.modules.repo.dto.response.RepoRespDTO; // 导入 RepoRespDTO 类,题库分页响应数据传输对象
import com.yf.exam.modules.repo.entity.Repo; // 导入 Repo 实体类,表示题库
/**
* <p>
*
* </p>
*
* @author
* @since 2020-05-25 13:23
*/
public interface RepoService extends IService<Repo> {
* <p>
*
* </p>
* MyBatis-Plus IService
*
* @
* @ 2020-05-25 13:23
*/
public interface RepoService extends IService<Repo> { // RepoService 接口,继承 MyBatis-Plus 的 IService提供常见数据库操作
/**
*
* @param reqDTO
* @return
*/
IPage<RepoRespDTO> paging(PagingReqDTO<RepoReqDTO> reqDTO);
*
* @param reqDTO
* @return
*/
IPage<RepoRespDTO> paging(PagingReqDTO<RepoReqDTO> reqDTO); // 分页查询方法,接收分页请求数据对象,并返回分页结果
/**
*
* @param reqDTO
*
* @param reqDTO
*/
void save(RepoDTO reqDTO);
void save(RepoDTO reqDTO); // 保存题库方法,用于保存或更新题库信息
}

@ -1,39 +1,49 @@
package com.yf.exam.modules.repo.service.impl;
package com.yf.exam.modules.repo.service.impl; // 包名:表示该类属于 repo.service.impl 包
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.yf.exam.core.api.dto.PagingReqDTO;
import com.yf.exam.core.utils.BeanMapper;
import com.yf.exam.modules.repo.dto.RepoDTO;
import com.yf.exam.modules.repo.dto.request.RepoReqDTO;
import com.yf.exam.modules.repo.dto.response.RepoRespDTO;
import com.yf.exam.modules.repo.entity.Repo;
import com.yf.exam.modules.repo.mapper.RepoMapper;
import com.yf.exam.modules.repo.service.RepoService;
import org.springframework.stereotype.Service;
import com.baomidou.mybatisplus.core.metadata.IPage; // 导入 MyBatis-Plus 分页接口
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; // 导入 MyBatis-Plus 服务实现类,用于提供通用的数据库操作
import com.yf.exam.core.api.dto.PagingReqDTO; // 导入分页请求数据传输对象
import com.yf.exam.core.utils.BeanMapper; // 导入 BeanMapper 工具类,用于对象属性拷贝
import com.yf.exam.modules.repo.dto.RepoDTO; // 导入 RepoDTO题库数据传输对象
import com.yf.exam.modules.repo.dto.request.RepoReqDTO; // 导入 RepoReqDTO封装分页查询条件的请求数据传输对象
import com.yf.exam.modules.repo.dto.response.RepoRespDTO; // 导入 RepoRespDTO题库分页响应数据传输对象
import com.yf.exam.modules.repo.entity.Repo; // 导入 Repo 实体类,表示题库实体
import com.yf.exam.modules.repo.mapper.RepoMapper; // 导入 RepoMapper数据访问层接口
import com.yf.exam.modules.repo.service.RepoService; // 导入 RepoService题库服务接口
import org.springframework.stereotype.Service; // 导入 Spring 的 Service 注解,标识该类为服务层组件
/**
* <p>
*
* </p>
*
* @author
* @since 2020-05-25 13:23
*/
@Service
public class RepoServiceImpl extends ServiceImpl<RepoMapper, Repo> implements RepoService {
* <p>
*
* </p>
* RepoService
*
* @
* @ 2020-05-25 13:23
*/
@Service // Spring 注解,标识该类为服务层组件
public class RepoServiceImpl extends ServiceImpl<RepoMapper, Repo> implements RepoService { // 继承 MyBatis-Plus 提供的 ServiceImpl简化数据库操作
/**
*
* @param reqDTO
* @return
*/
@Override
public IPage<RepoRespDTO> paging(PagingReqDTO<RepoReqDTO> reqDTO) {
return baseMapper.paging(reqDTO.toPage(), reqDTO.getParams());
return baseMapper.paging(reqDTO.toPage(), reqDTO.getParams()); // 调用 Mapper 的分页查询方法,传入分页信息和查询条件
}
/**
*
* @param reqDTO
*/
@Override
public void save(RepoDTO reqDTO) {
//复制参数
Repo entity = new Repo();
BeanMapper.copy(reqDTO, entity);
this.saveOrUpdate(entity);
// 复制参数,将请求数据传输对象的属性复制到实体类中
Repo entity = new Repo(); // 创建 Repo 实体对象
BeanMapper.copy(reqDTO, entity); // 使用 BeanMapper 工具类复制属性
this.saveOrUpdate(entity); // 调用 MyBatis-Plus 提供的 saveOrUpdate 方法,保存或更新实体
}
}

@ -1,70 +1,71 @@
package com.yf.exam.modules.sys.config.controller;
package com.yf.exam.modules.sys.config.controller; // 包名:表示该类属于 sys.config.controller 包
import com.yf.exam.core.api.ApiRest;
import com.yf.exam.core.api.controller.BaseController;
import com.yf.exam.core.api.dto.BaseIdRespDTO;
import com.yf.exam.core.utils.BeanMapper;
import com.yf.exam.modules.qu.utils.ImageCheckUtils;
import com.yf.exam.modules.sys.config.dto.SysConfigDTO;
import com.yf.exam.modules.sys.config.entity.SysConfig;
import com.yf.exam.modules.sys.config.service.SysConfigService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.apache.shiro.authz.annotation.RequiresRoles;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;
import com.yf.exam.core.api.ApiRest; // 导入统一的 API 响应类
import com.yf.exam.core.api.controller.BaseController; // 导入控制器基类,提供通用的控制器功能
import com.yf.exam.core.api.dto.BaseIdRespDTO; // 导入基础响应 DTO用于返回 ID 响应
import com.yf.exam.core.utils.BeanMapper; // 导入 BeanMapper 工具类,用于对象属性拷贝
import com.yf.exam.modules.qu.utils.ImageCheckUtils; // 导入图片检查工具类,用于校验图片地址
import com.yf.exam.modules.sys.config.dto.SysConfigDTO; // 导入 SysConfigDTO 类,用于封装系统配置的数据传输对象
import com.yf.exam.modules.sys.config.entity.SysConfig; // 导入 SysConfig 实体类,表示系统配置
import com.yf.exam.modules.sys.config.service.SysConfigService; // 导入 SysConfigService 服务接口
import io.swagger.annotations.Api; // 导入 Swagger 注解,用于 API 文档生成
import io.swagger.annotations.ApiOperation; // 导入 Swagger 注解,用于定义接口操作说明
import org.apache.shiro.authz.annotation.RequiresRoles; // 导入 Shiro 权限控制注解,限制角色访问
import org.springframework.beans.factory.annotation.Autowired; // 导入 Spring 注解,用于依赖注入
import org.springframework.web.bind.annotation.RequestBody; // 导入注解,用于绑定请求体
import org.springframework.web.bind.annotation.RequestMapping; // 导入注解,用于定义请求路径
import org.springframework.web.bind.annotation.RequestMethod; // 导入注解,用于指定请求方法
import org.springframework.web.bind.annotation.RestController; // 导入注解,标识该类为 REST 控制器
/**
* <p>
*
* </p>
*
* @author
* @since 2020-04-17 09:12
*/
@Api(tags={"通用配置"})
@RestController
@RequestMapping("/exam/api/sys/config")
public class SysConfigController extends BaseController {
* <p>
*
* </p>
*
*
* @
* @ 2020-04-17 09:12
*/
@Api(tags = {"通用配置"}) // Swagger 注解:定义该类的 API 文档标签为“通用配置”
@RestController // Spring 注解:标识该类为 REST 控制器
@RequestMapping("/exam/api/sys/config") // 定义请求路径前缀为 /exam/api/sys/config
public class SysConfigController extends BaseController { // SysConfigController 类,继承自 BaseController提供通用功能
@Autowired
@Autowired // 自动注入 SysConfigService 服务
private SysConfigService baseService;
@Autowired
@Autowired // 自动注入 ImageCheckUtils 工具类
private ImageCheckUtils imageCheckUtils;
/**
*
* @param reqDTO
* @return
*/
@RequiresRoles("sa")
@ApiOperation(value = "添加或修改")
@RequestMapping(value = "/save", method = { RequestMethod.POST})
public ApiRest<BaseIdRespDTO> save(@RequestBody SysConfigDTO reqDTO) {
*
* @param reqDTO
* @return ID
*/
@RequiresRoles("sa") // 权限控制:要求用户具有 "sa" 角色
@ApiOperation(value = "添加或修改") // Swagger 注解:定义接口操作说明为“添加或修改”
@RequestMapping(value = "/save", method = { RequestMethod.POST}) // 定义请求路径为 /save方法为 POST
public ApiRest<BaseIdRespDTO> save(@RequestBody SysConfigDTO reqDTO) { // 定义保存或修改系统配置的方法
//复制参数
SysConfig entity = new SysConfig();
BeanMapper.copy(reqDTO, entity);
// 复制请求参数到实体对象
SysConfig entity = new SysConfig(); // 创建 SysConfig 实体对象
BeanMapper.copy(reqDTO, entity); // 使用 BeanMapper 工具类将 DTO 的属性拷贝到实体对象
// 校验图片地址
imageCheckUtils.checkImage(entity.getBackLogo(), "系统LOGO地址错误");
// 校验图片地址是否有效
imageCheckUtils.checkImage(entity.getBackLogo(), "系统LOGO地址错误"); // 检查系统LOGO地址是否有效
baseService.saveOrUpdate(entity);
return super.success(new BaseIdRespDTO(entity.getId()));
baseService.saveOrUpdate(entity); // 调用服务的保存或更新方法
return super.success(new BaseIdRespDTO(entity.getId())); // 返回成功响应,并包含系统配置 ID
}
/**
*
* @return
*/
@ApiOperation(value = "查找详情")
@RequestMapping(value = "/detail", method = { RequestMethod.POST})
public ApiRest<SysConfigDTO> find() {
SysConfigDTO dto = baseService.find();
return super.success(dto);
*
* @return
*/
@ApiOperation(value = "查找详情") // Swagger 注解:定义接口操作说明为“查找详情”
@RequestMapping(value = "/detail", method = { RequestMethod.POST}) // 定义请求路径为 /detail方法为 POST
public ApiRest<SysConfigDTO> find() { // 定义查找系统配置详情的方法
SysConfigDTO dto = baseService.find(); // 调用服务查找系统配置详情
return super.success(dto); // 返回成功响应,包含系统配置详情
}
}

@ -1,39 +1,38 @@
package com.yf.exam.modules.sys.config.dto;
package com.yf.exam.modules.sys.config.dto; // 包名:表示该类属于 sys.config.dto 包
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import io.swagger.annotations.ApiModel; // 导入 Swagger 注解,用于定义 API 模型
import io.swagger.annotations.ApiModelProperty; // 导入 Swagger 注解,用于描述 API 模型的属性
import lombok.Data; // 导入 Lombok 注解,用于自动生成 Getter、Setter、toString 等方法
import java.io.Serializable;
import java.io.Serializable; // 导入 Serializable 接口,用于对象序列化
/**
* <p>
*
* </p>
*
* @author
* @since 2020-04-17 09:12
*/
@Data
@ApiModel(value="通用配置", description="通用配置")
public class SysConfigDTO implements Serializable {
private static final long serialVersionUID = 1L;
@ApiModelProperty(value = "ID", required=true)
private String id;
@ApiModelProperty(value = "系统名称")
private String siteName;
@ApiModelProperty(value = "前端LOGO")
private String frontLogo;
@ApiModelProperty(value = "后台LOGO")
private String backLogo;
@ApiModelProperty(value = "版权信息")
private String copyRight;
* <p>
*
* </p>
* API
*
* @
* @ 2020-04-17 09:12
*/
@Data // Lombok 注解,自动生成 Getter、Setter 和其他方法
@ApiModel(value = "通用配置", description = "通用配置") // Swagger 注解:定义该类的 API 模型名称和描述
public class SysConfigDTO implements Serializable { // 定义 SysConfigDTO 类,实现 Serializable 接口以支持序列化
private static final long serialVersionUID = 1L; // 序列化版本号,用于序列化和反序列化的一致性检查
@ApiModelProperty(value = "ID", required = true) // Swagger 注解描述该属性为“ID”并标记为必填
private String id; // 定义字段:系统配置的唯一标识符
@ApiModelProperty(value = "系统名称") // Swagger 注解:描述该属性为“系统名称”
private String siteName; // 定义字段:系统名称
@ApiModelProperty(value = "前端LOGO") // Swagger 注解描述该属性为“前端LOGO”
private String frontLogo; // 定义字段:前端展示用的 LOGO 图片地址
@ApiModelProperty(value = "后台LOGO") // Swagger 注解描述该属性为“后台LOGO”
private String backLogo; // 定义字段:后台管理用的 LOGO 图片地址
@ApiModelProperty(value = "版权信息") // Swagger 注解:描述该属性为“版权信息”
private String copyRight; // 定义字段:版权信息
}

@ -1,53 +1,54 @@
package com.yf.exam.modules.sys.config.entity;
package com.yf.exam.modules.sys.config.entity; // 包名:表示该类属于 sys.config.entity 包
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import com.baomidou.mybatisplus.extension.activerecord.Model;
import lombok.Data;
import com.baomidou.mybatisplus.annotation.IdType; // 导入 MyBatis-Plus 注解,用于定义主键类型
import com.baomidou.mybatisplus.annotation.TableField; // 导入 MyBatis-Plus 注解,用于映射数据库字段
import com.baomidou.mybatisplus.annotation.TableId; // 导入 MyBatis-Plus 注解,用于标识主键字段
import com.baomidou.mybatisplus.annotation.TableName; // 导入 MyBatis-Plus 注解,用于映射数据库表名
import com.baomidou.mybatisplus.extension.activerecord.Model; // 导入 MyBatis-Plus ActiveRecord 模式基类
import lombok.Data; // 导入 Lombok 注解,用于自动生成 Getter、Setter、toString 等方法
/**
* <p>
*
* </p>
*
* @author
* @since 2020-04-17 09:12
*/
@Data
@TableName("sys_config")
public class SysConfig extends Model<SysConfig> {
private static final long serialVersionUID = 1L;
* <p>
*
* </p>
* `sys_config`
*
* @
* @ 2020-04-17 09:12
*/
@Data // Lombok 注解,自动生成 Getter、Setter 和其他方法
@TableName("sys_config") // MyBatis-Plus 注解,指定该实体类映射数据库表名为 `sys_config`
public class SysConfig extends Model<SysConfig> { // SysConfig 类继承自 MyBatis-Plus 的 Model 类,启用 ActiveRecord 模式
private static final long serialVersionUID = 1L; // 序列化版本号,用于序列化和反序列化的一致性检查
/**
* ID
*/
@TableId(value = "id", type = IdType.ASSIGN_ID)
private String id;
@TableId(value = "id", type = IdType.ASSIGN_ID) // MyBatis-Plus 注解,标识主键字段,并指定主键生成策略为分配 ID
private String id; // 定义字段:系统配置的唯一标识符
/**
*
*/
@TableField("site_name")
private String siteName;
@TableField("site_name") // MyBatis-Plus 注解,指定该字段映射数据库中的 "site_name" 列
private String siteName; // 定义字段:系统名称
/**
* LOGO
*/
@TableField("front_logo")
private String frontLogo;
@TableField("front_logo") // MyBatis-Plus 注解,指定该字段映射数据库中的 "front_logo" 列
private String frontLogo; // 定义字段:前端展示的 LOGO 图片地址
/**
* LOGO
*/
@TableField("back_logo")
private String backLogo;
@TableField("back_logo") // MyBatis-Plus 注解,指定该字段映射数据库中的 "back_logo" 列
private String backLogo; // 定义字段:后台管理系统的 LOGO 图片地址
/**
*
*/
@TableField("copy_right")
private String copyRight;
@TableField("copy_right") // MyBatis-Plus 注解,指定该字段映射数据库中的 "copy_right" 列
private String copyRight; // 定义字段:版权信息
}

@ -1,16 +1,18 @@
package com.yf.exam.modules.sys.config.mapper;
package com.yf.exam.modules.sys.config.mapper; // 包名:表示该类属于 sys.config.mapper 包
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.yf.exam.modules.sys.config.entity.SysConfig;
import com.baomidou.mybatisplus.core.mapper.BaseMapper; // 导入 MyBatis-Plus 的 BaseMapper 接口,用于基本的数据库操作
import com.yf.exam.modules.sys.config.entity.SysConfig; // 导入 SysConfig 实体类,表示系统配置
/**
* <p>
* Mapper
* </p>
*
* @author
* @since 2020-04-17 09:12
*/
public interface SysConfigMapper extends BaseMapper<SysConfig> {
* <p>
* Mapper
* </p>
* MyBatis-Plus BaseMapper
*
* @
* @ 2020-04-17 09:12
*/
public interface SysConfigMapper extends BaseMapper<SysConfig> { // SysConfigMapper 接口,继承自 MyBatis-Plus 的 BaseMapper
// 该接口继承了 BaseMapper<SysConfig>,因此自动具备了 CRUD 方法,无需手动实现
}

@ -1,22 +1,23 @@
package com.yf.exam.modules.sys.config.service;
package com.yf.exam.modules.sys.config.service; // 包名:表示该类属于 sys.config.service 包
import com.baomidou.mybatisplus.extension.service.IService;
import com.yf.exam.modules.sys.config.dto.SysConfigDTO;
import com.yf.exam.modules.sys.config.entity.SysConfig;
import com.baomidou.mybatisplus.extension.service.IService; // 导入 MyBatis-Plus 提供的 IService 接口,提供通用的数据库操作
import com.yf.exam.modules.sys.config.dto.SysConfigDTO; // 导入 SysConfigDTO 类,封装系统配置的数据传输对象
import com.yf.exam.modules.sys.config.entity.SysConfig; // 导入 SysConfig 实体类,表示系统配置
/**
* <p>
*
* </p>
*
* @author
* @since 2020-04-17 09:12
*/
public interface SysConfigService extends IService<SysConfig> {
* <p>
*
* </p>
*
*
* @
* @ 2020-04-17 09:12
*/
public interface SysConfigService extends IService<SysConfig> { // SysConfigService 接口继承 MyBatis-Plus 的 IService 接口,提供 CRUD 操作
/**
*
* @return
* @return DTO
*/
SysConfigDTO find();
SysConfigDTO find(); // 定义查找系统配置信息的方法,返回一个 SysConfigDTO 对象
}

@ -1,34 +1,44 @@
package com.yf.exam.modules.sys.config.service.impl;
package com.yf.exam.modules.sys.config.service.impl; // 包名:表示该类属于 sys.config.service.impl 包
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.yf.exam.core.utils.BeanMapper;
import com.yf.exam.modules.sys.config.dto.SysConfigDTO;
import com.yf.exam.modules.sys.config.entity.SysConfig;
import com.yf.exam.modules.sys.config.mapper.SysConfigMapper;
import com.yf.exam.modules.sys.config.service.SysConfigService;
import org.springframework.stereotype.Service;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; // 导入 MyBatis-Plus 的 QueryWrapper用于构建查询条件
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; // 导入 MyBatis-Plus 的 ServiceImpl 类,用于提供常见的数据库操作
import com.yf.exam.core.utils.BeanMapper; // 导入 BeanMapper 工具类,用于对象属性拷贝
import com.yf.exam.modules.sys.config.dto.SysConfigDTO; // 导入 SysConfigDTO 类,封装系统配置的数据传输对象
import com.yf.exam.modules.sys.config.entity.SysConfig; // 导入 SysConfig 实体类,表示系统配置
import com.yf.exam.modules.sys.config.mapper.SysConfigMapper; // 导入 SysConfigMapper数据访问层接口
import com.yf.exam.modules.sys.config.service.SysConfigService; // 导入 SysConfigService系统配置服务接口
import org.springframework.stereotype.Service; // 导入 Spring 注解,用于标识该类为服务层组件
/**
* <p>
*
* </p>
*
* @author
* @since 2020-04-17 09:12
*/
@Service
public class SysConfigServiceImpl extends ServiceImpl<SysConfigMapper, SysConfig> implements SysConfigService {
* <p>
*
* </p>
* SysConfigService
*
* @
* @ 2020-04-17 09:12
*/
@Service // Spring 注解,标识该类为服务层组件
public class SysConfigServiceImpl extends ServiceImpl<SysConfigMapper, SysConfig> implements SysConfigService { // 继承 MyBatis-Plus 的 ServiceImpl 类,简化数据库操作
/**
*
* @return DTO
*/
@Override
public SysConfigDTO find() {
// 创建 QueryWrapper 对象,用于构建查询条件
QueryWrapper<SysConfig> wrapper = new QueryWrapper<>();
wrapper.last(" LIMIT 1");
wrapper.last(" LIMIT 1"); // 限制查询结果为一条记录
SysConfig entity = this.getOne(wrapper, false);
SysConfigDTO dto = new SysConfigDTO();
BeanMapper.copy(entity, dto);
return dto;
// 使用 getOne 方法查询系统配置的第一条记录
SysConfig entity = this.getOne(wrapper, false); // false 表示不抛出异常,如果没有结果会返回 null
// 将查询到的实体对象复制到 DTO 对象
SysConfigDTO dto = new SysConfigDTO(); // 创建 SysConfigDTO 对象
BeanMapper.copy(entity, dto); // 使用 BeanMapper 工具类将 SysConfig 实体对象的属性复制到 DTO 中
return dto; // 返回系统配置 DTO
}
}

@ -1,150 +1,136 @@
package com.yf.exam.modules.sys.depart.controller;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.yf.exam.core.api.ApiRest;
import com.yf.exam.core.api.controller.BaseController;
import com.yf.exam.core.api.dto.BaseIdReqDTO;
import com.yf.exam.core.api.dto.BaseIdsReqDTO;
import com.yf.exam.core.api.dto.PagingReqDTO;
import com.yf.exam.core.utils.BeanMapper;
import com.yf.exam.modules.sys.depart.dto.SysDepartDTO;
import com.yf.exam.modules.sys.depart.dto.request.DepartSortReqDTO;
import com.yf.exam.modules.sys.depart.dto.response.SysDepartTreeDTO;
import com.yf.exam.modules.sys.depart.entity.SysDepart;
import com.yf.exam.modules.sys.depart.service.SysDepartService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.apache.shiro.authz.annotation.RequiresRoles;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;
import java.util.List;
package com.yf.exam.modules.sys.depart.controller; // 包名:表示该类属于 sys.depart.controller 包
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; // 导入 MyBatis-Plus 的 QueryWrapper用于构建查询条件
import com.baomidou.mybatisplus.core.metadata.IPage; // 导入 MyBatis-Plus 分页接口
import com.yf.exam.core.api.ApiRest; // 导入统一的 API 响应类
import com.yf.exam.core.api.controller.BaseController; // 导入控制器基类,提供通用的控制器功能
import com.yf.exam.core.api.dto.BaseIdReqDTO; // 导入基本请求 DTO用于单个 ID 请求
import com.yf.exam.core.api.dto.BaseIdsReqDTO; // 导入基本请求 DTO用于多个 ID 请求
import com.yf.exam.core.api.dto.PagingReqDTO; // 导入分页请求 DTO
import com.yf.exam.core.utils.BeanMapper; // 导入 BeanMapper 工具类,用于对象属性拷贝
import com.yf.exam.modules.sys.depart.dto.SysDepartDTO; // 导入 SysDepartDTO 数据传输对象
import com.yf.exam.modules.sys.depart.dto.request.DepartSortReqDTO; // 导入部门排序请求 DTO
import com.yf.exam.modules.sys.depart.dto.response.SysDepartTreeDTO; // 导入部门树状结构响应 DTO
import com.yf.exam.modules.sys.depart.entity.SysDepart; // 导入 SysDepart 实体类,表示部门
import com.yf.exam.modules.sys.depart.service.SysDepartService; // 导入部门服务接口
import io.swagger.annotations.Api; // 导入 Swagger 注解,用于 API 文档生成
import io.swagger.annotations.ApiOperation; // 导入 Swagger 注解,用于定义接口操作说明
import org.apache.shiro.authz.annotation.RequiresRoles; // 导入 Shiro 权限控制注解,限制角色访问
import org.springframework.beans.BeanUtils; // 导入 Spring 的 BeanUtils用于对象属性拷贝
import org.springframework.beans.factory.annotation.Autowired; // 导入 Spring 注解,用于依赖注入
import org.springframework.web.bind.annotation.RequestBody; // 导入注解,用于绑定请求体
import org.springframework.web.bind.annotation.RequestMapping; // 导入注解,用于定义请求路径
import org.springframework.web.bind.annotation.RequestMethod; // 导入注解,用于指定请求方法
import org.springframework.web.bind.annotation.RestController; // 导入注解,标识该类为 REST 控制器
/**
* <p>
*
* </p>
*
* @author
* @since 2020-09-02 17:25
*/
@Api(tags={"部门信息"})
@RestController
@RequestMapping("/exam/api/sys/depart")
public class SysDepartController extends BaseController {
@Autowired
* <p>
*
* </p>
*
*
* @
* @ 2020-09-02 17:25
*/
@Api(tags = {"部门信息"}) // Swagger 注解:定义该类的 API 文档标签为“部门信息”
@RestController // Spring 注解:标识该类为 REST 控制器
@RequestMapping("/exam/api/sys/depart") // 定义请求路径前缀为 /exam/api/sys/depart
public class SysDepartController extends BaseController { // SysDepartController 类,继承自 BaseController提供通用功能
@Autowired // 自动注入 SysDepartService 服务
private SysDepartService baseService;
/**
*
* @param reqDTO
* @return
*/
@RequiresRoles("sa")
@ApiOperation(value = "添加或修改")
@RequestMapping(value = "/save", method = { RequestMethod.POST})
public ApiRest save(@RequestBody SysDepartDTO reqDTO) {
baseService.save(reqDTO);
return super.success();
*
* @param reqDTO
* @return
*/
@RequiresRoles("sa") // 权限控制:要求用户具有 "sa" 角色
@ApiOperation(value = "添加或修改") // Swagger 注解:定义接口操作说明为“添加或修改”
@RequestMapping(value = "/save", method = {RequestMethod.POST}) // 定义请求路径为 /save方法为 POST
public ApiRest save(@RequestBody SysDepartDTO reqDTO) { // 添加或修改部门的方法
baseService.save(reqDTO); // 调用服务保存或更新部门信息
return super.success(); // 返回成功响应
}
/**
*
* @param reqDTO
* @return
*/
@RequiresRoles("sa")
@ApiOperation(value = "批量删除")
@RequestMapping(value = "/delete", method = { RequestMethod.POST})
public ApiRest edit(@RequestBody BaseIdsReqDTO reqDTO) {
//根据ID删除
baseService.removeByIds(reqDTO.getIds());
return super.success();
*
* @param reqDTO ID
* @return
*/
@RequiresRoles("sa") // 权限控制:要求用户具有 "sa" 角色
@ApiOperation(value = "批量删除") // Swagger 注解:定义接口操作说明为“批量删除”
@RequestMapping(value = "/delete", method = {RequestMethod.POST}) // 定义请求路径为 /delete方法为 POST
public ApiRest edit(@RequestBody BaseIdsReqDTO reqDTO) { // 批量删除部门的方法
baseService.removeByIds(reqDTO.getIds()); // 根据 ID 列表删除部门
return super.success(); // 返回成功响应
}
/**
*
* @param reqDTO
* @return
*/
@RequiresRoles("sa")
@ApiOperation(value = "查找详情")
@RequestMapping(value = "/detail", method = { RequestMethod.POST})
public ApiRest<SysDepartDTO> find(@RequestBody BaseIdReqDTO reqDTO) {
SysDepart entity = baseService.getById(reqDTO.getId());
SysDepartDTO dto = new SysDepartDTO();
BeanUtils.copyProperties(entity, dto);
return super.success(dto);
*
* @param reqDTO ID
* @return
*/
@RequiresRoles("sa") // 权限控制:要求用户具有 "sa" 角色
@ApiOperation(value = "查找详情") // Swagger 注解:定义接口操作说明为“查找详情”
@RequestMapping(value = "/detail", method = {RequestMethod.POST}) // 定义请求路径为 /detail方法为 POST
public ApiRest<SysDepartDTO> find(@RequestBody BaseIdReqDTO reqDTO) { // 查找部门详情的方法
SysDepart entity = baseService.getById(reqDTO.getId()); // 根据 ID 查找部门实体
SysDepartDTO dto = new SysDepartDTO(); // 创建部门数据传输对象
BeanUtils.copyProperties(entity, dto); // 将实体对象属性拷贝到 DTO 对象
return super.success(dto); // 返回成功响应,包含部门详情
}
/**
*
* @param reqDTO
* @return
*/
@RequiresRoles("sa")
@ApiOperation(value = "分页查找")
@RequestMapping(value = "/paging", method = { RequestMethod.POST})
public ApiRest<IPage<SysDepartTreeDTO>> paging(@RequestBody PagingReqDTO<SysDepartDTO> reqDTO) {
//分页查询并转换
IPage<SysDepartTreeDTO> page = baseService.paging(reqDTO);
return super.success(page);
*
* @param reqDTO
* @return
*/
@RequiresRoles("sa") // 权限控制:要求用户具有 "sa" 角色
@ApiOperation(value = "分页查找") // Swagger 注解:定义接口操作说明为“分页查找”
@RequestMapping(value = "/paging", method = {RequestMethod.POST}) // 定义请求路径为 /paging方法为 POST
public ApiRest<IPage<SysDepartTreeDTO>> paging(@RequestBody PagingReqDTO<SysDepartDTO> reqDTO) { // 分页查找部门的方法
IPage<SysDepartTreeDTO> page = baseService.paging(reqDTO); // 调用服务进行分页查询
return super.success(page); // 返回成功响应,包含分页数据
}
/**
* 200
* @param reqDTO
* @return
* 200
* @param reqDTO
* @return
*/
@RequiresRoles("sa")
@ApiOperation(value = "查找列表")
@RequestMapping(value = "/list", method = { RequestMethod.POST})
public ApiRest<List<SysDepartDTO>> list(@RequestBody SysDepartDTO reqDTO) {
//分页查询并转换
QueryWrapper<SysDepart> wrapper = new QueryWrapper<>();
//转换并返回
List<SysDepart> list = baseService.list(wrapper);
//转换数据
List<SysDepartDTO> dtoList = BeanMapper.mapList(list, SysDepartDTO.class);
return super.success(dtoList);
@RequiresRoles("sa") // 权限控制:要求用户具有 "sa" 角色
@ApiOperation(value = "查找列表") // Swagger 注解:定义接口操作说明为“查找列表”
@RequestMapping(value = "/list", method = {RequestMethod.POST}) // 定义请求路径为 /list方法为 POST
public ApiRest<List<SysDepartDTO>> list(@RequestBody SysDepartDTO reqDTO) { // 查找部门列表的方法
QueryWrapper<SysDepart> wrapper = new QueryWrapper<>(); // 创建查询条件
List<SysDepart> list = baseService.list(wrapper); // 获取部门列表
List<SysDepartDTO> dtoList = BeanMapper.mapList(list, SysDepartDTO.class); // 将部门实体列表转换为 DTO 列表
return super.success(dtoList); // 返回成功响应,包含部门列表
}
/**
*
* @return
*
* @return
*/
@RequiresRoles("sa")
@ApiOperation(value = "树列表")
@RequestMapping(value = "/tree", method = { RequestMethod.POST})
public ApiRest<List<SysDepartTreeDTO>> tree() {
List<SysDepartTreeDTO> dtoList = baseService.findTree();
return super.success(dtoList);
@RequiresRoles("sa") // 权限控制:要求用户具有 "sa" 角色
@ApiOperation(value = "树列表") // Swagger 注解:定义接口操作说明为“树列表”
@RequestMapping(value = "/tree", method = {RequestMethod.POST}) // 定义请求路径为 /tree方法为 POST
public ApiRest<List<SysDepartTreeDTO>> tree() { // 查找部门树状结构的方法
List<SysDepartTreeDTO> dtoList = baseService.findTree(); // 获取部门树状结构
return super.success(dtoList); // 返回成功响应,包含部门树状结构
}
/**
*
* @param reqDTO
* @return
*
* @param reqDTO
* @return
*/
@RequiresRoles("sa")
@ApiOperation(value = "分类排序")
@RequestMapping(value = "/sort", method = { RequestMethod.POST})
public ApiRest sort(@RequestBody DepartSortReqDTO reqDTO) {
baseService.sort(reqDTO.getId(), reqDTO.getSort());
return super.success();
@RequiresRoles("sa") // 权限控制:要求用户具有 "sa" 角色
@ApiOperation(value = "分类排序") // Swagger 注解:定义接口操作说明为“分类排序”
@RequestMapping(value = "/sort", method = {RequestMethod.POST}) // 定义请求路径为 /sort方法为 POST
public ApiRest sort(@RequestBody DepartSortReqDTO reqDTO) { // 部门排序的方法
baseService.sort(reqDTO.getId(), reqDTO.getSort()); // 调用服务进行排序
return super.success(); // 返回成功响应
}
}

@ -1,42 +1,41 @@
package com.yf.exam.modules.sys.depart.dto;
package com.yf.exam.modules.sys.depart.dto; // 包名:表示该类属于 sys.depart.dto 包
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import io.swagger.annotations.ApiModel; // 导入 Swagger 注解,用于定义 API 模型
import io.swagger.annotations.ApiModelProperty; // 导入 Swagger 注解,用于描述 API 模型的属性
import lombok.Data; // 导入 Lombok 注解,用于自动生成 Getter、Setter、toString 等方法
import java.io.Serializable;
import java.io.Serializable; // 导入 Serializable 接口,用于支持对象序列化
/**
* <p>
*
* </p>
*
* @author
* @since 2020-09-02 17:25
*/
@Data
@ApiModel(value="部门信息", description="部门信息")
public class SysDepartDTO implements Serializable {
* <p>
*
* </p>
*
*
* @
* @ 2020-09-02 17:25
*/
@Data // Lombok 注解,自动生成 Getter、Setter 和其他方法
@ApiModel(value = "部门信息", description = "部门信息") // Swagger 注解:定义该类的 API 模型名称和描述
public class SysDepartDTO implements Serializable { // 实现 Serializable 接口以支持序列化
private static final long serialVersionUID = 1L;
private static final long serialVersionUID = 1L; // 序列化版本号,用于序列化和反序列化的一致性检查
@ApiModelProperty(value = "ID", required = true) // Swagger 注解描述该属性为“ID”并标记为必填
private String id; // 定义字段:部门的唯一标识符
@ApiModelProperty(value = "ID", required=true)
private String id;
@ApiModelProperty(value = "1公司2部门", required = true) // Swagger 注解描述该属性为“1公司2部门”并标记为必填
private Integer deptType; // 定义字段部门类型1 表示公司2 表示部门
@ApiModelProperty(value = "1公司2部门", required=true)
private Integer deptType;
@ApiModelProperty(value = "所属上级", required = true) // Swagger 注解:描述该属性为“所属上级”,并标记为必填
private String parentId; // 定义字段:上级部门的 ID
@ApiModelProperty(value = "所属上级", required=true)
private String parentId;
@ApiModelProperty(value = "部门名称", required = true) // Swagger 注解:描述该属性为“部门名称”,并标记为必填
private String deptName; // 定义字段:部门名称
@ApiModelProperty(value = "部门名称", required=true)
private String deptName;
@ApiModelProperty(value = "部门编码", required=true)
private String deptCode;
@ApiModelProperty(value = "排序", required=true)
private Integer sort;
@ApiModelProperty(value = "部门编码", required = true) // Swagger 注解:描述该属性为“部门编码”,并标记为必填
private String deptCode; // 定义字段:部门的唯一编码,用于标识部门
@ApiModelProperty(value = "排序", required = true) // Swagger 注解:描述该属性为“排序”,并标记为必填
private Integer sort; // 定义字段:部门排序序号,用于定义显示顺序
}

@ -1,28 +1,29 @@
package com.yf.exam.modules.sys.depart.dto.request;
package com.yf.exam.modules.sys.depart.dto.request; // 包名:表示该类属于 sys.depart.dto.request 包
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import io.swagger.annotations.ApiModel; // 导入 Swagger 注解,用于定义 API 模型
import io.swagger.annotations.ApiModelProperty; // 导入 Swagger 注解,用于描述 API 模型的属性
import lombok.Data; // 导入 Lombok 注解,用于自动生成 Getter、Setter、toString 等方法
import java.io.Serializable;
import java.io.Serializable; // 导入 Serializable 接口,用于对象序列化
/**
* <p>
*
* </p>
*
* @author
* @since 2020-03-14 10:37
*/
@Data
@ApiModel(value="部门排序请求类", description="部门排序请求类")
public class DepartSortReqDTO implements Serializable {
* <p>
*
* </p>
*
*
* @
* @ 2020-03-14 10:37
*/
@Data // Lombok 注解,自动生成 Getter、Setter 和其他方法
@ApiModel(value = "部门排序请求类", description = "部门排序请求类") // Swagger 注解:定义该类的 API 模型名称和描述
public class DepartSortReqDTO implements Serializable { // 实现 Serializable 接口以支持序列化
private static final long serialVersionUID = 1L;
private static final long serialVersionUID = 1L; // 序列化版本号,用于序列化和反序列化的一致性检查
@ApiModelProperty(value = "分类ID")
private String id;
@ApiModelProperty(value = "分类ID") // Swagger 注解描述该属性为“分类ID”
private String id; // 定义字段:分类的唯一标识符
@ApiModelProperty(value = "排序0下降1上升")
private Integer sort;
@ApiModelProperty(value = "排序0下降1上升") // Swagger 注解描述该属性为“排序”0 表示下降1 表示上升
private Integer sort; // 定义字段排序方式0 为下降排序1 为上升排序
}

@ -1,28 +1,27 @@
package com.yf.exam.modules.sys.depart.dto.response;
package com.yf.exam.modules.sys.depart.dto.response; // 包名:表示该类属于 sys.depart.dto.response 包
import com.yf.exam.modules.sys.depart.dto.SysDepartDTO;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import com.yf.exam.modules.sys.depart.dto.SysDepartDTO; // 导入 SysDepartDTO 类,表示部门的基本信息
import io.swagger.annotations.ApiModel; // 导入 Swagger 注解,用于定义 API 模型
import io.swagger.annotations.ApiModelProperty; // 导入 Swagger 注解,用于描述 API 模型的属性
import lombok.Data; // 导入 Lombok 注解,用于自动生成 Getter、Setter、toString 等方法
import java.util.List;
import java.util.List; // 导入 List 接口,用于存储子部门列表
/**
* <p>
*
* </p>
*
* @author
* @since 2020-09-02 17:25
*/
@Data
@ApiModel(value="部门树结构响应类", description="部门树结构响应类")
public class SysDepartTreeDTO extends SysDepartDTO {
* <p>
*
* </p>
*
*
* @
* @ 2020-09-02 17:25
*/
@Data // Lombok 注解,自动生成 Getter、Setter 和其他方法
@ApiModel(value = "部门树结构响应类", description = "部门树结构响应类") // Swagger 注解:定义该类的 API 模型名称和描述
public class SysDepartTreeDTO extends SysDepartDTO { // 继承 SysDepartDTO扩展支持树形结构
private static final long serialVersionUID = 1L;
private static final long serialVersionUID = 1L; // 序列化版本号,用于序列化和反序列化的一致性检查
@ApiModelProperty(value = "子列表", required=true)
private List<SysDepartTreeDTO> children;
@ApiModelProperty(value = "子列表", required = true) // Swagger 注解:描述该属性为“子列表”,标记为必填
private List<SysDepartTreeDTO> children; // 定义字段:子部门列表,支持递归嵌套表示树形结构
}

@ -1,59 +1,59 @@
package com.yf.exam.modules.sys.depart.entity;
package com.yf.exam.modules.sys.depart.entity; // 包名:表示该类属于 sys.depart.entity 包
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import com.baomidou.mybatisplus.extension.activerecord.Model;
import lombok.Data;
import com.baomidou.mybatisplus.annotation.IdType; // 导入 MyBatis-Plus 注解,用于定义主键类型
import com.baomidou.mybatisplus.annotation.TableField; // 导入 MyBatis-Plus 注解,用于映射数据库字段
import com.baomidou.mybatisplus.annotation.TableId; // 导入 MyBatis-Plus 注解,用于标识主键字段
import com.baomidou.mybatisplus.annotation.TableName; // 导入 MyBatis-Plus 注解,用于映射数据库表名
import com.baomidou.mybatisplus.extension.activerecord.Model; // 导入 MyBatis-Plus 的 Model 基类,用于支持 ActiveRecord 模式
import lombok.Data; // 导入 Lombok 注解,用于自动生成 Getter、Setter、toString 等方法
/**
* <p>
*
* </p>
*
* @author
* @since 2020-09-02 17:25
*/
@Data
@TableName("sys_depart")
public class SysDepart extends Model<SysDepart> {
* <p>
*
* </p>
* `sys_depart`
*
* @
* @ 2020-09-02 17:25
*/
@Data // Lombok 注解,自动生成 Getter、Setter 和其他方法
@TableName("sys_depart") // MyBatis-Plus 注解,指定该类映射的数据库表名为 `sys_depart`
public class SysDepart extends Model<SysDepart> { // 继承 MyBatis-Plus 的 Model 类,支持 ActiveRecord 模式
private static final long serialVersionUID = 1L;
private static final long serialVersionUID = 1L; // 序列化版本号,用于序列化和反序列化的一致性检查
/**
* ID
*/
@TableId(value = "id", type = IdType.ASSIGN_ID)
private String id;
* ID
*/
@TableId(value = "id", type = IdType.ASSIGN_ID) // MyBatis-Plus 注解,指定主键字段及其生成策略为 ASSIGN_ID
private String id; // 部门的唯一标识符
/**
* 12
*/
@TableField("dept_type")
private Integer deptType;
* 12
*/
@TableField("dept_type") // MyBatis-Plus 注解,指定该字段映射数据库中的 `dept_type` 列
private Integer deptType; // 部门类型1 表示公司2 表示部门
/**
*
*/
@TableField("parent_id")
private String parentId;
*
*/
@TableField("parent_id") // MyBatis-Plus 注解,指定该字段映射数据库中的 `parent_id` 列
private String parentId; // 上级部门的 ID用于定义层级关系
/**
*
*/
@TableField("dept_name")
private String deptName;
*
*/
@TableField("dept_name") // MyBatis-Plus 注解,指定该字段映射数据库中的 `dept_name` 列
private String deptName; // 部门的名称,用于显示和标识部门
/**
*
*/
@TableField("dept_code")
private String deptCode;
*
*/
@TableField("dept_code") // MyBatis-Plus 注解,指定该字段映射数据库中的 `dept_code` 列
private String deptCode; // 部门的唯一编码,用于标识部门
/**
*
*/
private Integer sort;
*
*/
private Integer sort; // 排序字段,用于定义部门显示的顺序
}

@ -1,28 +1,29 @@
package com.yf.exam.modules.sys.depart.mapper;
package com.yf.exam.modules.sys.depart.mapper; // 包名:表示该类属于 sys.depart.mapper 包
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.yf.exam.modules.sys.depart.dto.SysDepartDTO;
import com.yf.exam.modules.sys.depart.dto.response.SysDepartTreeDTO;
import com.yf.exam.modules.sys.depart.entity.SysDepart;
import org.apache.ibatis.annotations.Param;
import com.baomidou.mybatisplus.core.mapper.BaseMapper; // 导入 MyBatis-Plus 的 BaseMapper 接口,用于提供基础的数据库操作
import com.baomidou.mybatisplus.core.metadata.IPage; // 导入 MyBatis-Plus 的分页接口
import com.baomidou.mybatisplus.extension.plugins.pagination.Page; // 导入 MyBatis-Plus 的分页插件中的 Page 类
import com.yf.exam.modules.sys.depart.dto.SysDepartDTO; // 导入部门数据传输对象,用于封装查询条件
import com.yf.exam.modules.sys.depart.dto.response.SysDepartTreeDTO; // 导入部门树形结构响应对象
import com.yf.exam.modules.sys.depart.entity.SysDepart; // 导入部门实体类
import org.apache.ibatis.annotations.Param; // 导入 MyBatis 注解,用于标注参数
/**
* <p>
* Mapper
* </p>
*
* @author
* @since 2020-09-02 17:25
*/
public interface SysDepartMapper extends BaseMapper<SysDepart> {
* <p>
* Mapper
* </p>
*
*
* @
* @ 2020-09-02 17:25
*/
public interface SysDepartMapper extends BaseMapper<SysDepart> { // SysDepartMapper 接口,继承 MyBatis-Plus 的 BaseMapper
/**
*
* @param page
* @param query
* @return
* @param page
* @param query
* @return
*/
IPage<SysDepartTreeDTO> paging(Page page, @Param("query") SysDepartDTO query);
IPage<SysDepartTreeDTO> paging(Page page, @Param("query") SysDepartDTO query); // 自定义分页查询方法,返回部门树形结构的分页数据
}

@ -1,62 +1,62 @@
package com.yf.exam.modules.sys.depart.service;
package com.yf.exam.modules.sys.depart.service; // 包名:表示该接口属于 sys.depart.service 包
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.service.IService;
import com.yf.exam.core.api.dto.PagingReqDTO;
import com.yf.exam.modules.sys.depart.dto.SysDepartDTO;
import com.yf.exam.modules.sys.depart.dto.response.SysDepartTreeDTO;
import com.yf.exam.modules.sys.depart.entity.SysDepart;
import com.baomidou.mybatisplus.core.metadata.IPage; // 导入 MyBatis-Plus 的分页接口,用于返回分页查询结果
import com.baomidou.mybatisplus.extension.service.IService; // 导入 MyBatis-Plus 的 IService 接口,用于提供通用的数据库操作
import com.yf.exam.core.api.dto.PagingReqDTO; // 导入分页请求数据传输对象
import com.yf.exam.modules.sys.depart.dto.SysDepartDTO; // 导入 SysDepartDTO 数据传输对象,用于封装部门数据
import com.yf.exam.modules.sys.depart.dto.response.SysDepartTreeDTO; // 导入 SysDepartTreeDTO 类,用于表示部门树形结构
import com.yf.exam.modules.sys.depart.entity.SysDepart; // 导入 SysDepart 实体类,表示部门
import java.util.List;
import java.util.List; // 导入 List 接口,用于存储部门 ID 或部门列表
/**
* <p>
*
* </p>
*
* @author
* @since 2020-09-02 17:25
*/
public interface SysDepartService extends IService<SysDepart> {
* <p>
*
* </p>
*
*
* @
* @ 2020-09-02 17:25
*/
public interface SysDepartService extends IService<SysDepart> { // SysDepartService 接口继承 MyBatis-Plus 的 IService 接口,提供 CRUD 操作
/**
*
* @param reqDTO
*
* @param reqDTO
*/
void save(SysDepartDTO reqDTO);
void save(SysDepartDTO reqDTO); // 保存部门信息方法,接收部门数据传输对象
/**
*
* @param reqDTO
* @return
*/
IPage<SysDepartTreeDTO> paging(PagingReqDTO<SysDepartDTO> reqDTO);
*
* @param reqDTO
* @return
*/
IPage<SysDepartTreeDTO> paging(PagingReqDTO<SysDepartDTO> reqDTO); // 分页查询部门树的方法
/**
*
* @return
*
* @return
*/
List<SysDepartTreeDTO> findTree();
List<SysDepartTreeDTO> findTree(); // 查找所有部门树的方法,返回树形结构数据
/**
*
* @param ids
* @return
* ID
* @param ids ID
* @return
*/
List<SysDepartTreeDTO> findTree(List<String> ids);
List<SysDepartTreeDTO> findTree(List<String> ids); // 查找指定部门ID列表下的部门树的方法
/**
*
* @param id
* @param sort
*
* @param id ID
* @param sort 01
*/
void sort(String id, Integer sort);
void sort(String id, Integer sort); // 排序部门的方法,支持上升和下降排序
/**
* IDID
* @param id
* @return
* @param id ID
* @return ID
*/
List<String> listAllSubIds( String id);
List<String> listAllSubIds(String id); // 获取某个部门下所有子部门ID的方法
}

@ -1,227 +1,233 @@
package com.yf.exam.modules.sys.depart.service.impl;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.yf.exam.core.api.dto.PagingReqDTO;
import com.yf.exam.core.utils.BeanMapper;
import com.yf.exam.modules.sys.depart.dto.SysDepartDTO;
import com.yf.exam.modules.sys.depart.dto.response.SysDepartTreeDTO;
import com.yf.exam.modules.sys.depart.entity.SysDepart;
import com.yf.exam.modules.sys.depart.mapper.SysDepartMapper;
import com.yf.exam.modules.sys.depart.service.SysDepartService;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
package com.yf.exam.modules.sys.depart.service.impl; // 包名:表示该类属于 sys.depart.service.impl 包
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; // 导入 MyBatis-Plus 的 QueryWrapper用于构建查询条件
import com.baomidou.mybatisplus.core.metadata.IPage; // 导入 MyBatis-Plus 分页接口
import com.baomidou.mybatisplus.extension.plugins.pagination.Page; // 导入 MyBatis-Plus 分页插件中的 Page 类
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; // 导入 MyBatis-Plus 的 ServiceImpl 类,用于提供通用的数据库操作
import com.yf.exam.core.api.dto.PagingReqDTO; // 导入分页请求数据传输对象
import com.yf.exam.core.utils.BeanMapper; // 导入 BeanMapper 工具类,用于对象属性拷贝
import com.yf.exam.modules.sys.depart.dto.SysDepartDTO; // 导入 SysDepartDTO 类,封装部门数据传输对象
import com.yf.exam.modules.sys.depart.dto.response.SysDepartTreeDTO; // 导入 SysDepartTreeDTO 类,用于部门树形结构
import com.yf.exam.modules.sys.depart.entity.SysDepart; // 导入 SysDepart 实体类,表示部门
import com.yf.exam.modules.sys.depart.mapper.SysDepartMapper; // 导入部门的 Mapper 接口,用于数据库交互
import com.yf.exam.modules.sys.depart.service.SysDepartService; // 导入部门服务接口
import org.apache.commons.lang3.StringUtils; // 导入 Apache Commons Lang3 库中的 StringUtils用于字符串操作
import org.springframework.stereotype.Service; // 导入 Spring 注解,用于标识该类为服务层组件
import org.springframework.util.CollectionUtils; // 导入 Spring 的 CollectionUtils 工具类,用于集合操作
import java.util.ArrayList; // 导入 ArrayList 类,用于列表数据存储
import java.util.HashMap; // 导入 HashMap 类,用于映射键值对
import java.util.List; // 导入 List 接口,用于存储列表数据
import java.util.Map; // 导入 Map 接口,用于映射键值对
/**
* <p>
*
* </p>
*
* @author
* @since 2020-09-02 17:25
*/
@Service
public class SysDepartServiceImpl extends ServiceImpl<SysDepartMapper, SysDepart> implements SysDepartService {
* <p>
*
* </p>
* SysDepartService
*
* @
* @ 2020-09-02 17:25
*/
@Service // Spring 注解,标识该类为服务层组件
public class SysDepartServiceImpl extends ServiceImpl<SysDepartMapper, SysDepart> implements SysDepartService { // 继承 MyBatis-Plus 的 ServiceImpl 类,简化数据库操作
/**
* 0
*/
private static final String ROOT_TAG = "0";
private static final String ROOT_TAG = "0"; // 顶级部门标识符
/**
*
* @param reqDTO
*/
@Override
public void save(SysDepartDTO reqDTO) {
// 如果部门ID为空生成部门编码
if(StringUtils.isBlank(reqDTO.getId())) {
this.fillCode(reqDTO);
}else{
reqDTO.setSort(null);
reqDTO.setDeptCode(null);
this.fillCode(reqDTO); // 填充部门编码
} else {
reqDTO.setSort(null); // 如果有ID则清空排序字段
reqDTO.setDeptCode(null); // 清空部门编码
}
SysDepart entity = new SysDepart();
BeanMapper.copy(reqDTO, entity);
this.saveOrUpdate(entity);
SysDepart entity = new SysDepart(); // 创建部门实体对象
BeanMapper.copy(reqDTO, entity); // 将 DTO 数据拷贝到实体对象
this.saveOrUpdate(entity); // 保存或更新部门信息
}
/**
*
* @param reqDTO
* @return
*/
@Override
public IPage<SysDepartTreeDTO> paging(PagingReqDTO<SysDepartDTO> reqDTO) {
// 创建分页对象
Page query = new Page(reqDTO.getCurrent(), reqDTO.getSize());
// 请求参数
// 获取查询条件
SysDepartDTO params = reqDTO.getParams();
//转换结果
// 执行分页查询
IPage<SysDepartTreeDTO> pageData = baseMapper.paging(query, params);
return pageData;
}
return pageData; // 返回分页结果
}
/**
*
* @return
*/
@Override
public List<SysDepartTreeDTO> findTree() {
return this.findTree(null);
return this.findTree(null); // 默认查找所有部门
}
/**
* ID
* @param ids ID
* @return
*/
@Override
public List<SysDepartTreeDTO> findTree(List<String> ids) {
QueryWrapper<SysDepart> wrapper = new QueryWrapper<>(); // 创建查询条件
wrapper.lambda().orderByAsc(SysDepart::getSort); // 按照排序字段升序排列
QueryWrapper<SysDepart> wrapper = new QueryWrapper();
wrapper.lambda().orderByAsc(SysDepart::getSort);
// 如果传入了部门ID列表递归获取所有父级部门
if(!CollectionUtils.isEmpty(ids)){
List<String> fullIds = new ArrayList<>();
List<String> fullIds = new ArrayList<>(); // 用于存储所有父部门ID
for(String id: ids){
this.cycleAllParent(fullIds, id);
this.cycleAllParent(fullIds, id); // 递归获取所有父部门ID
}
if(!CollectionUtils.isEmpty(fullIds)){
wrapper.lambda().in(SysDepart::getId, fullIds);
wrapper.lambda().in(SysDepart::getId, fullIds); // 根据部门ID列表查询
}
}
//全部列表
List<SysDepart> list = this.list(wrapper);
List<SysDepartTreeDTO> dtoList = BeanMapper.mapList(list, SysDepartTreeDTO.class);
//子结构的列表
Map<String,List<SysDepartTreeDTO>> map = new HashMap<>(16);
// 获取所有部门数据
List<SysDepart> list = this.list(wrapper);
List<SysDepartTreeDTO> dtoList = BeanMapper.mapList(list, SysDepartTreeDTO.class); // 将部门实体列表转换为部门树形结构DTO列表
// 构建子部门的映射关系
Map<String, List<SysDepartTreeDTO>> map = new HashMap<>(16);
for(SysDepartTreeDTO item: dtoList){
//如果存在
// 如果当前部门已经有子部门,直接添加
if(map.containsKey(item.getParentId())){
map.get(item.getParentId()).add(item);
continue;
}
//增加新的结构
// 如果没有子部门,则新建一个子部门列表
List<SysDepartTreeDTO> a = new ArrayList<>();
a.add(item);
map.put(item.getParentId(), a);
}
//注意第0级为顶级的
// 获取顶级部门parentId 为 ROOT_TAG
List<SysDepartTreeDTO> topList = map.get(ROOT_TAG);
if(!CollectionUtils.isEmpty(topList)){
for(SysDepartTreeDTO item: topList){
this.fillChildren(map, item);
this.fillChildren(map, item); // 填充子部门
}
}
return topList;
return topList; // 返回顶级部门及其子部门树
}
/**
*
* @param id ID
* @param sort 01
*/
@Override
public void sort(String id, Integer sort) {
SysDepart depart = this.getById(id);
SysDepart depart = this.getById(id); // 获取部门实体
SysDepart exchange = null;
QueryWrapper<SysDepart> wrapper = new QueryWrapper<>();
// 同级排序
wrapper.lambda()
.eq(SysDepart::getParentId, depart.getParentId());
QueryWrapper<SysDepart> wrapper = new QueryWrapper<>(); // 创建查询条件
// 根据部门的父ID查询同级别的部门
wrapper.lambda().eq(SysDepart::getParentId, depart.getParentId());
wrapper.last("LIMIT 1");
// 上升
// 上升排序
if(sort == 0){
// 同级排序
wrapper.lambda()
.lt(SysDepart::getSort, depart.getSort())
.orderByDesc(SysDepart::getSort);
exchange = this.getOne(wrapper, false);
wrapper.lambda().lt(SysDepart::getSort, depart.getSort()).orderByDesc(SysDepart::getSort); // 查找排序小于当前部门的部门
exchange = this.getOne(wrapper, false); // 获取交换部门
}
// 下降
// 下降排序
if(sort == 1){
// 同级排序
wrapper.lambda()
.gt(SysDepart::getSort, depart.getSort())
.orderByAsc(SysDepart::getSort);
exchange = this.getOne(wrapper, false);
wrapper.lambda().gt(SysDepart::getSort, depart.getSort()).orderByAsc(SysDepart::getSort); // 查找排序大于当前部门的部门
exchange = this.getOne(wrapper, false); // 获取交换部门
}
if(exchange!=null) {
// 如果找到了交换的部门,进行交换排序
if(exchange != null) {
SysDepart a = new SysDepart();
a.setId(id);
a.setSort(exchange.getSort());
SysDepart b = new SysDepart();
b.setId(exchange.getId());
b.setSort(depart.getSort());
this.updateById(a);
this.updateById(b);
this.updateById(a); // 更新部门a的排序
this.updateById(b); // 更新部门b的排序
}
}
/**
*
* @param reqDTO
* @return
*
* @param reqDTO
*/
private void fillCode(SysDepartDTO reqDTO){
// 前缀
String code = "";
if(StringUtils.isNotBlank(reqDTO.getParentId())
&& !ROOT_TAG.equals(reqDTO.getParentId())){
// 获取上级部门编码
if(StringUtils.isNotBlank(reqDTO.getParentId()) && !ROOT_TAG.equals(reqDTO.getParentId())){
SysDepart parent = this.getById(reqDTO.getParentId());
code = parent.getDeptCode();
code = parent.getDeptCode(); // 获取上级部门的编码
}
QueryWrapper<SysDepart> wrapper = new QueryWrapper<>();
wrapper.lambda().eq(SysDepart::getParentId, reqDTO.getParentId()).orderByDesc(SysDepart::getSort); // 查询同级部门
// 同级排序
wrapper.lambda()
.eq(SysDepart::getParentId, reqDTO.getParentId())
.orderByDesc(SysDepart::getSort);
wrapper.last("LIMIT 1");
SysDepart depart = this.getOne(wrapper, false);
if(depart !=null){
code += this.formatCode(depart.getSort()+1);
reqDTO.setSort(depart.getSort()+1);
}else{
code += this.formatCode(1);
reqDTO.setSort(1);
if(depart != null){
code += this.formatCode(depart.getSort() + 1); // 根据排序生成部门编码
reqDTO.setSort(depart.getSort() + 1); // 设置部门的排序
} else {
code += this.formatCode(1); // 如果没有同级部门则从1开始
reqDTO.setSort(1); // 设置部门的排序为1
}
reqDTO.setDeptCode(code);
reqDTO.setDeptCode(code); // 设置部门编码
}
/**
* 0
* @param sort
* @return
*
* @param sort
* @return
*/
private String formatCode(Integer sort){
if(sort < 10){
return "A0"+sort;
return "A0" + sort; // 排序小于10时返回带前导零的编码
}
return "A"+sort;
return "A" + sort; // 排序大于或等于10时返回正常编码
}
/**
*
* @param map
* @param item
*
* @param map
* @param item
*/
private void fillChildren(Map<String,List<SysDepartTreeDTO>> map, SysDepartTreeDTO item){
private void fillChildren(Map<String, List<SysDepartTreeDTO>> map, SysDepartTreeDTO item){
//设置子类
if(map.containsKey(item.getId())){
@ -229,60 +235,61 @@ public class SysDepartServiceImpl extends ServiceImpl<SysDepartMapper, SysDepart
List<SysDepartTreeDTO> children = map.get(item.getId());
if(!CollectionUtils.isEmpty(children)){
for(SysDepartTreeDTO sub: children){
this.fillChildren(map, sub);
this.fillChildren(map, sub); // 递归填充子部门
}
}
item.setChildren(children);
item.setChildren(children); // 设置子部门列表
}
}
/**
* ID
* @param id ID
* @return ID
*/
@Override
public List<String> listAllSubIds( String id){
public List<String> listAllSubIds(String id){
List<String> ids = new ArrayList<>();
this.cycleAllSubs(ids, id);
this.cycleAllSubs(ids, id); // 递归获取所有子部门的ID
return ids;
}
/**
* ID
* @param list
* @param id
* ID
* @param list ID
* @param id ID
*/
private void cycleAllSubs(List<String> list, String id){
// 添加ID
// 添加当前部门ID
list.add(id);
QueryWrapper<SysDepart> wrapper = new QueryWrapper<>();
wrapper.lambda()
.eq(SysDepart::getParentId, id)
.orderByDesc(SysDepart::getSort);
.orderByDesc(SysDepart::getSort); // 查询当前部门的所有子部门
List<SysDepart> subList = this.list(wrapper);
if(!CollectionUtils.isEmpty(subList)){
for(SysDepart item: subList){
this.cycleAllSubs(list, item.getId());
this.cycleAllSubs(list, item.getId()); // 递归查询子部门
}
}
}
/**
* ID
* @param list
* @param id
* ID
* @param list ID
* @param id ID
*/
private void cycleAllParent(List<String> list, String id){
// 往上递归获得父类
// 往上递归获取父部门
list.add(id);
SysDepart depart = this.getById(id);
if(StringUtils.isNotBlank(depart.getParentId())
&& !ROOT_TAG.equals(depart.getParentId())){
this.cycleAllParent(list, depart.getParentId());
if(StringUtils.isNotBlank(depart.getParentId()) && !ROOT_TAG.equals(depart.getParentId())){
this.cycleAllParent(list, depart.getParentId()); // 递归查询父部门
}
}
}

@ -1,29 +1,30 @@
package com.yf.exam.modules.sys.system.mapper;
package com.yf.exam.modules.sys.system.mapper; // 包名:表示该接口属于 sys.system.mapper 包
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;
import org.apache.ibatis.annotations.Mapper; // 导入 MyBatis 的 @Mapper 注解,表示这是一个 Mapper 接口
import org.apache.ibatis.annotations.Param; // 导入 MyBatis 的 @Param 注解,用于指定参数名称
/**
* <p>
* Mapper
* </p>
*
* @author
* @since 2020-08-22 13:46
*/
@Mapper
* <p>
* Mapper
* </p>
*
*
* @
* @ 2020-08-22 13:46
*/
@Mapper // MyBatis 注解,表示该接口为 Mapper 接口MyBatis 会自动生成相应的实现
public interface SysDictMapper {
/**
*
* @param table
* @param text
* @param key
* @param value
* @return
* @param table
* @param text
* @param key
* @param value
* @return
*/
String findDict(@Param("table") String table,
@Param("text") String text,
@Param("key") String key,
@Param("value") String value);
String findDict(@Param("table") String table, // 使用 @Param 注解绑定 SQL 参数名
@Param("text") String text, // 绑定 SQL 参数 text
@Param("key") String key, // 绑定 SQL 参数 key
@Param("value") String value); // 绑定 SQL 参数 value
}

@ -1,21 +1,25 @@
package com.yf.exam.modules.sys.system.service;
package com.yf.exam.modules.sys.system.service; // 包名:表示该接口属于 sys.system.service 包
/**
*
* @author bool
*
*
* @ bool
*/
public interface SysDictService {
public interface SysDictService { // 定义 SysDictService 接口,提供数据字典的服务
/**
*
* @param table
* @param text
* @param key
* @param value
* @return
*
*
* @param table
* @param text
* @param key
* @param value
* @return
*/
String findDict(String table,
String text,
String key,
String value);
String findDict(String table, // 表示字典数据的表名
String text, // 字段文本,用于描述字段
String key, // 字段的键
String value); // 字段的值,查询条件之一
}

@ -1,21 +1,30 @@
package com.yf.exam.modules.sys.system.service.impl;
package com.yf.exam.modules.sys.system.service.impl; // 包名:表示该类属于 sys.system.service.impl 包
import com.yf.exam.modules.sys.system.mapper.SysDictMapper;
import com.yf.exam.modules.sys.system.service.SysDictService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.yf.exam.modules.sys.system.mapper.SysDictMapper; // 导入 SysDictMapper 接口,用于操作数据字典
import com.yf.exam.modules.sys.system.service.SysDictService; // 导入 SysDictService 接口,定义数据字典的业务逻辑
import org.springframework.beans.factory.annotation.Autowired; // 导入 Spring 的 @Autowired 注解,用于自动注入依赖
import org.springframework.stereotype.Service; // 导入 Spring 的 @Service 注解,用于标识该类为服务层组件
/**
* SysDictServiceImpl
* @author bool
*/
@Service
public class SysDictServiceImpl implements SysDictService {
@Service // Spring 注解,标识该类为服务层组件
public class SysDictServiceImpl implements SysDictService { // 实现 SysDictService 接口
@Autowired
@Autowired // 自动注入 SysDictMapper
private SysDictMapper sysDictMapper;
/**
*
* @param table
* @param text
* @param key
* @param value
* @return
*/
@Override
public String findDict(String table, String text, String key, String value) {
return sysDictMapper.findDict(table, text, key, value);
return sysDictMapper.findDict(table, text, key, value); // 调用 Mapper 层的方法查找字典数据
}
}

@ -1,77 +1,75 @@
package com.yf.exam.modules.sys.user.controller;
package com.yf.exam.modules.sys.user.controller; // 包名:表示该类属于 sys.user.controller 包
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.yf.exam.core.api.ApiRest;
import com.yf.exam.core.api.controller.BaseController;
import com.yf.exam.core.api.dto.PagingReqDTO;
import com.yf.exam.core.utils.BeanMapper;
import com.yf.exam.modules.sys.user.dto.SysRoleDTO;
import com.yf.exam.modules.sys.user.entity.SysRole;
import com.yf.exam.modules.sys.user.service.SysRoleService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.apache.shiro.authz.annotation.RequiresRoles;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; // 导入 MyBatis-Plus 的 QueryWrapper用于构建查询条件
import com.baomidou.mybatisplus.core.metadata.IPage; // 导入 MyBatis-Plus 分页接口
import com.yf.exam.core.api.ApiRest; // 导入统一的 API 响应类
import com.yf.exam.core.api.controller.BaseController; // 导入基类控制器,提供通用功能
import com.yf.exam.core.api.dto.PagingReqDTO; // 导入分页请求数据传输对象
import com.yf.exam.core.utils.BeanMapper; // 导入 BeanMapper 工具类,用于对象属性拷贝
import com.yf.exam.modules.sys.user.dto.SysRoleDTO; // 导入 SysRoleDTO 数据传输对象
import com.yf.exam.modules.sys.user.entity.SysRole; // 导入 SysRole 实体类,表示角色
import com.yf.exam.modules.sys.user.service.SysRoleService; // 导入 SysRoleService 服务接口
import io.swagger.annotations.Api; // 导入 Swagger 注解,用于定义 API 文档
import io.swagger.annotations.ApiOperation; // 导入 Swagger 注解,用于描述接口操作
import org.apache.shiro.authz.annotation.RequiresRoles; // 导入 Shiro 注解,用于权限控制,限制访问角色
import org.springframework.beans.factory.annotation.Autowired; // 导入 Spring 注解,用于自动注入依赖
import org.springframework.web.bind.annotation.RequestBody; // 导入注解,用于绑定请求体
import org.springframework.web.bind.annotation.RequestMapping; // 导入注解,用于定义请求路径
import org.springframework.web.bind.annotation.RequestMethod; // 导入注解,用于指定请求方法
import org.springframework.web.bind.annotation.RestController; // 导入注解,标识该类为 REST 控制器
import java.util.List;
import java.util.List; // 导入 List 接口,用于存储角色列表
/**
* <p>
*
* </p>
*
* @author
* @since 2020-04-13 16:57
*
*
* @
* @ 2020-04-13 16:57
*/
@Api(tags = {"管理用户"})
@RestController
@RequestMapping("/exam/api/sys/role")
public class SysRoleController extends BaseController {
@Api(tags = {"管理用户"}) // Swagger 注解:定义该类的 API 文档标签为“管理用户”
@RestController // Spring 注解:标识该类为 REST 控制器,处理 HTTP 请求
@RequestMapping("/exam/api/sys/role") // 定义请求路径前缀为 /exam/api/sys/role
public class SysRoleController extends BaseController { // SysRoleController 继承自 BaseController提供通用功能
@Autowired
@Autowired // 自动注入 SysRoleService 服务
private SysRoleService baseService;
/**
*
* @param reqDTO
* @return
*
* @param reqDTO
* @return
*/
@RequiresRoles("sa")
@ApiOperation(value = "分页查找")
@RequestMapping(value = "/paging", method = { RequestMethod.POST})
@RequiresRoles("sa") // 权限控制:要求用户具有 "sa" 角色
@ApiOperation(value = "分页查找") // Swagger 注解:描述接口操作为“分页查找”
@RequestMapping(value = "/paging", method = { RequestMethod.POST}) // 请求路径为 /paging方法为 POST
public ApiRest<IPage<SysRoleDTO>> paging(@RequestBody PagingReqDTO<SysRoleDTO> reqDTO) {
//分页查询并转换
IPage<SysRoleDTO> page = baseService.paging(reqDTO);
return super.success(page);
// 调用服务层进行分页查询,并返回角色数据
IPage<SysRoleDTO> page = baseService.paging(reqDTO);
return super.success(page); // 返回成功响应,包含分页数据
}
/**
* 200
* @return
* 200
* @return
*/
@RequiresRoles("sa")
@ApiOperation(value = "查找列表")
@RequestMapping(value = "/list", method = { RequestMethod.POST})
@RequiresRoles("sa") // 权限控制:要求用户具有 "sa" 角色
@ApiOperation(value = "查找列表") // Swagger 注解:描述接口操作为“查找列表”
@RequestMapping(value = "/list", method = { RequestMethod.POST}) // 请求路径为 /list方法为 POST
public ApiRest<List<SysRoleDTO>> list() {
//分页查询并转换
QueryWrapper<SysRole> wrapper = new QueryWrapper<>();
// 创建查询条件
QueryWrapper<SysRole> wrapper = new QueryWrapper<>();
//转换并返回
List<SysRole> list = baseService.list(wrapper);
// 获取所有角色数据
List<SysRole> list = baseService.list(wrapper);
//转换数据
// 将角色实体数据转换为角色数据传输对象
List<SysRoleDTO> dtoList = BeanMapper.mapList(list, SysRoleDTO.class);
return super.success(dtoList);
return super.success(dtoList); // 返回成功响应,包含角色列表
}
}

@ -1,182 +1,185 @@
package com.yf.exam.modules.sys.user.controller;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.yf.exam.core.api.ApiRest;
import com.yf.exam.core.api.controller.BaseController;
import com.yf.exam.core.api.dto.BaseIdsReqDTO;
import com.yf.exam.core.api.dto.BaseStateReqDTO;
import com.yf.exam.core.api.dto.PagingReqDTO;
import com.yf.exam.modules.sys.user.dto.SysUserDTO;
import com.yf.exam.modules.sys.user.dto.request.SysUserLoginReqDTO;
import com.yf.exam.modules.sys.user.dto.request.SysUserSaveReqDTO;
import com.yf.exam.modules.sys.user.dto.response.SysUserLoginDTO;
import com.yf.exam.modules.sys.user.entity.SysUser;
import com.yf.exam.modules.sys.user.service.SysUserService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.apache.shiro.authz.annotation.RequiresRoles;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.CrossOrigin;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import javax.servlet.http.HttpServletRequest;
package com.yf.exam.modules.sys.user.controller; // 包名:表示该类属于 sys.user.controller 包
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; // 导入 MyBatis-Plus 的 QueryWrapper用于构建查询条件
import com.baomidou.mybatisplus.core.metadata.IPage; // 导入 MyBatis-Plus 分页接口
import com.yf.exam.core.api.ApiRest; // 导入统一的 API 响应类
import com.yf.exam.core.api.controller.BaseController; // 导入基类控制器,提供通用功能
import com.yf.exam.core.api.dto.BaseIdsReqDTO; // 导入基本请求 DTO用于处理多个 ID 请求
import com.yf.exam.core.api.dto.BaseStateReqDTO; // 导入基本状态请求 DTO用于更新状态
import com.yf.exam.core.api.dto.PagingReqDTO; // 导入分页请求 DTO
import com.yf.exam.modules.sys.user.dto.SysUserDTO; // 导入 SysUserDTO 数据传输对象
import com.yf.exam.modules.sys.user.dto.request.SysUserLoginReqDTO; // 导入 SysUserLoginReqDTO 登录请求 DTO
import com.yf.exam.modules.sys.user.dto.request.SysUserSaveReqDTO; // 导入 SysUserSaveReqDTO 保存请求 DTO
import com.yf.exam.modules.sys.user.dto.response.SysUserLoginDTO; // 导入 SysUserLoginDTO 登录响应 DTO
import com.yf.exam.modules.sys.user.entity.SysUser; // 导入 SysUser 实体类,表示系统用户
import com.yf.exam.modules.sys.user.service.SysUserService; // 导入 SysUserService 服务接口
import io.swagger.annotations.Api; // 导入 Swagger 注解,用于定义 API 文档
import io.swagger.annotations.ApiOperation; // 导入 Swagger 注解,用于描述接口操作
import org.apache.shiro.authz.annotation.RequiresRoles; // 导入 Shiro 注解,用于角色权限控制
import org.springframework.beans.factory.annotation.Autowired; // 导入 Spring 注解,用于自动注入依赖
import org.springframework.web.bind.annotation.CrossOrigin; // 导入 Spring 注解,用于启用跨域请求
import org.springframework.web.bind.annotation.RequestBody; // 导入 Spring 注解,用于请求体绑定
import org.springframework.web.bind.annotation.RequestMapping; // 导入 Spring 注解,用于指定请求路径
import org.springframework.web.bind.annotation.RequestMethod; // 导入 Spring 注解,用于指定请求方法
import org.springframework.web.bind.annotation.RequestParam; // 导入 Spring 注解,用于请求参数绑定
import org.springframework.web.bind.annotation.RestController; // 导入 Spring 注解,标识该类为 REST 控制器
import javax.servlet.http.HttpServletRequest; // 导入 HttpServletRequest 类,用于获取 HTTP 请求
/**
* <p>
*
* </p>
*
* @author
* @since 2020-04-13 16:57
*
*
* @
* @ 2020-04-13 16:57
*/
@Api(tags = {"管理用户"})
@RestController
@RequestMapping("/exam/api/sys/user")
public class SysUserController extends BaseController {
@Api(tags = {"管理用户"}) // Swagger 注解:定义该类的 API 文档标签为“管理用户”
@RestController // Spring 注解:标识该类为 REST 控制器,处理 HTTP 请求
@RequestMapping("/exam/api/sys/user") // 定义请求路径前缀为 /exam/api/sys/user
public class SysUserController extends BaseController { // SysUserController 类继承 BaseController提供通用功能
@Autowired
@Autowired // 自动注入 SysUserService 服务
private SysUserService baseService;
/**
*
* @return
* @param reqDTO DTO
* @return
*/
@CrossOrigin
@ApiOperation(value = "用户登录")
@RequestMapping(value = "/login", method = {RequestMethod.POST})
@CrossOrigin // 允许跨域请求
@ApiOperation(value = "用户登录") // Swagger 注解:描述接口操作为“用户登录”
@RequestMapping(value = "/login", method = {RequestMethod.POST}) // 请求路径为 /login方法为 POST
public ApiRest<SysUserLoginDTO> login(@RequestBody SysUserLoginReqDTO reqDTO) {
SysUserLoginDTO respDTO = baseService.login(reqDTO.getUsername(), reqDTO.getPassword());
return super.success(respDTO);
SysUserLoginDTO respDTO = baseService.login(reqDTO.getUsername(), reqDTO.getPassword()); // 调用服务层的登录方法
return super.success(respDTO); // 返回成功响应,包含用户登录信息
}
/**
*
* @return
*
* @param request HTTP token
* @return
*/
@CrossOrigin
@ApiOperation(value = "用户登录")
@RequestMapping(value = "/logout", method = {RequestMethod.POST})
@CrossOrigin // 允许跨域请求
@ApiOperation(value = "用户登出") // Swagger 注解:描述接口操作为“用户登出”
@RequestMapping(value = "/logout", method = {RequestMethod.POST}) // 请求路径为 /logout方法为 POST
public ApiRest logout(HttpServletRequest request) {
String token = request.getHeader("token");
System.out.println("+++++当前会话为:"+token);
baseService.logout(token);
return super.success();
String token = request.getHeader("token"); // 获取请求头中的 token
System.out.println("+++++当前会话为:" + token); // 打印当前会话的 token
baseService.logout(token); // 调用服务层的登出方法
return super.success(); // 返回成功响应
}
/**
*
* @return
*
* @param token token
* @return
*/
@ApiOperation(value = "获取会话")
@RequestMapping(value = "/info", method = {RequestMethod.POST})
@ApiOperation(value = "获取会话") // Swagger 注解:描述接口操作为“获取会话”
@RequestMapping(value = "/info", method = {RequestMethod.POST}) // 请求路径为 /info方法为 POST
public ApiRest info(@RequestParam("token") String token) {
SysUserLoginDTO respDTO = baseService.token(token);
return success(respDTO);
SysUserLoginDTO respDTO = baseService.token(token); // 根据 token 获取当前会话信息
return success(respDTO); // 返回会话信息
}
/**
*
* @return
* @param reqDTO DTO
* @return
*/
@ApiOperation(value = "修改用户资料")
@RequestMapping(value = "/update", method = {RequestMethod.POST})
@ApiOperation(value = "修改用户资料") // Swagger 注解:描述接口操作为“修改用户资料”
@RequestMapping(value = "/update", method = {RequestMethod.POST}) // 请求路径为 /update方法为 POST
public ApiRest update(@RequestBody SysUserDTO reqDTO) {
baseService.update(reqDTO);
return success();
baseService.update(reqDTO); // 调用服务层的更新方法
return success(); // 返回成功响应
}
/**
*
* @return
* @param reqDTO DTO
* @return
*/
@RequiresRoles("sa")
@ApiOperation(value = "保存或修改")
@RequestMapping(value = "/save", method = {RequestMethod.POST})
@RequiresRoles("sa") // 权限控制:要求用户具有 "sa" 角色
@ApiOperation(value = "保存或修改") // Swagger 注解:描述接口操作为“保存或修改”
@RequestMapping(value = "/save", method = {RequestMethod.POST}) // 请求路径为 /save方法为 POST
public ApiRest save(@RequestBody SysUserSaveReqDTO reqDTO) {
baseService.save(reqDTO);
return success();
baseService.save(reqDTO); // 调用服务层的保存方法
return success(); // 返回成功响应
}
/**
*
* @param reqDTO
* @return
*
* @param reqDTO DTO ID
* @return
*/
@RequiresRoles("sa")
@ApiOperation(value = "批量删除")
@RequestMapping(value = "/delete", method = { RequestMethod.POST})
@RequiresRoles("sa") // 权限控制:要求用户具有 "sa" 角色
@ApiOperation(value = "批量删除") // Swagger 注解:描述接口操作为“批量删除”
@RequestMapping(value = "/delete", method = {RequestMethod.POST}) // 请求路径为 /delete方法为 POST
public ApiRest edit(@RequestBody BaseIdsReqDTO reqDTO) {
//根据ID删除
baseService.removeByIds(reqDTO.getIds());
return super.success();
baseService.removeByIds(reqDTO.getIds()); // 根据 ID 列表删除用户
return super.success(); // 返回成功响应
}
/**
*
* @param reqDTO
* @return
*
* @param reqDTO DTO
* @return
*/
@RequiresRoles("sa")
@ApiOperation(value = "分页查找")
@RequestMapping(value = "/paging", method = { RequestMethod.POST})
@RequiresRoles("sa") // 权限控制:要求用户具有 "sa" 角色
@ApiOperation(value = "分页查找") // Swagger 注解:描述接口操作为“分页查找”
@RequestMapping(value = "/paging", method = {RequestMethod.POST}) // 请求路径为 /paging方法为 POST
public ApiRest<IPage<SysUserDTO>> paging(@RequestBody PagingReqDTO<SysUserDTO> reqDTO) {
//分页查询并转换
// 调用服务层的分页查询方法
IPage<SysUserDTO> page = baseService.paging(reqDTO);
return super.success(page);
return super.success(page); // 返回成功响应,包含分页数据
}
/**
*
* @param reqDTO
* @return
*
* @param reqDTO DTO ID
* @return
*/
@RequiresRoles("sa")
@ApiOperation(value = "修改状态")
@RequestMapping(value = "/state", method = { RequestMethod.POST})
@RequiresRoles("sa") // 权限控制:要求用户具有 "sa" 角色
@ApiOperation(value = "修改状态") // Swagger 注解:描述接口操作为“修改状态”
@RequestMapping(value = "/state", method = {RequestMethod.POST}) // 请求路径为 /state方法为 POST
public ApiRest state(@RequestBody BaseStateReqDTO reqDTO) {
// 条件
// 构建查询条件:排除 admin 用户
QueryWrapper<SysUser> wrapper = new QueryWrapper<>();
wrapper.lambda()
.in(SysUser::getId, reqDTO.getIds())
.ne(SysUser::getUserName, "admin");
.in(SysUser::getId, reqDTO.getIds()) // 根据 ID 列表查询
.ne(SysUser::getUserName, "admin"); // 排除用户名为 admin 的用户
SysUser record = new SysUser();
record.setState(reqDTO.getState());
baseService.update(record, wrapper);
record.setState(reqDTO.getState()); // 设置用户状态
baseService.update(record, wrapper); // 更新状态
return super.success();
return super.success(); // 返回成功响应
}
/**
*
* @return
*
* @param reqDTO DTO
* @return
*/
@ApiOperation(value = "学员注册")
@RequestMapping(value = "/reg", method = {RequestMethod.POST})
@ApiOperation(value = "学员注册") // Swagger 注解:描述接口操作为“学员注册”
@RequestMapping(value = "/reg", method = {RequestMethod.POST}) // 请求路径为 /reg方法为 POST
public ApiRest<SysUserLoginDTO> reg(@RequestBody SysUserDTO reqDTO) {
SysUserLoginDTO respDTO = baseService.reg(reqDTO);
return success(respDTO);
SysUserLoginDTO respDTO = baseService.reg(reqDTO); // 调用服务层的注册方法
return success(respDTO); // 返回注册后的用户登录信息
}
/**
*
* @return
*
* @param reqDTO DTO
* @return
*/
@ApiOperation(value = "快速注册")
@RequestMapping(value = "/quick-reg", method = {RequestMethod.POST})
@ApiOperation(value = "快速注册") // Swagger 注解:描述接口操作为“快速注册”
@RequestMapping(value = "/quick-reg", method = {RequestMethod.POST}) // 请求路径为 /quick-reg方法为 POST
public ApiRest<SysUserLoginDTO> quick(@RequestBody SysUserDTO reqDTO) {
SysUserLoginDTO respDTO = baseService.quickReg(reqDTO);
return success(respDTO);
SysUserLoginDTO respDTO = baseService.quickReg(reqDTO); // 调用服务层的快速注册方法
return success(respDTO); // 返回快速注册后的用户登录信息
}
}

@ -1,30 +1,29 @@
package com.yf.exam.modules.sys.user.dto;
package com.yf.exam.modules.sys.user.dto; // 包名:表示该类属于 sys.user.dto 包
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import io.swagger.annotations.ApiModel; // 导入 Swagger 注解,用于定义 API 模型
import io.swagger.annotations.ApiModelProperty; // 导入 Swagger 注解,用于描述 API 模型的属性
import lombok.Data; // 导入 Lombok 注解,用于自动生成 Getter、Setter、toString 等方法
import java.io.Serializable;
import java.io.Serializable; // 导入 Serializable 接口,用于支持对象的序列化
/**
* <p>
*
* </p>
*
* @author
* @since 2020-04-13 16:57
*/
@Data
@ApiModel(value="角色", description="角色")
public class SysRoleDTO implements Serializable {
* <p>
*
* </p>
* ID
*
* @
* @ 2020-04-13 16:57
*/
@Data // Lombok 注解,自动生成 Getter、Setter 和其他方法
@ApiModel(value = "角色", description = "角色") // Swagger 注解:定义该类的 API 模型名称和描述
public class SysRoleDTO implements Serializable { // 实现 Serializable 接口,以支持序列化
private static final long serialVersionUID = 1L;
@ApiModelProperty(value = "角色ID", required=true)
private String id;
@ApiModelProperty(value = "角色名称", required=true)
private String roleName;
private static final long serialVersionUID = 1L; // 序列化版本号,用于序列化和反序列化的一致性检查
@ApiModelProperty(value = "角色ID", required = true) // Swagger 注解描述该属性为“角色ID”并标记为必填
private String id; // 定义字段:角色的唯一标识符
@ApiModelProperty(value = "角色名称", required = true) // Swagger 注解:描述该属性为“角色名称”,并标记为必填
private String roleName; // 定义字段:角色的名称
}

@ -1,55 +1,54 @@
package com.yf.exam.modules.sys.user.dto;
package com.yf.exam.modules.sys.user.dto; // 包名:表示该类属于 sys.user.dto 包
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import io.swagger.annotations.ApiModel; // 导入 Swagger 注解,用于定义 API 模型
import io.swagger.annotations.ApiModelProperty; // 导入 Swagger 注解,用于描述 API 模型的属性
import lombok.Data; // 导入 Lombok 注解,用于自动生成 Getter、Setter、toString 等方法
import java.io.Serializable;
import java.util.Date;
import java.io.Serializable; // 导入 Serializable 接口,用于支持对象的序列化
import java.util.Date; // 导入 Date 类,用于表示日期和时间
/**
* <p>
*
* </p>
*
* @author
* @since 2020-04-13 16:57
*/
@Data
@ApiModel(value="管理用户", description="管理用户")
public class SysUserDTO implements Serializable {
* <p>
*
* </p>
*
*
* @
* @ 2020-04-13 16:57
*/
@Data // Lombok 注解,自动生成 Getter、Setter 和其他方法
@ApiModel(value = "管理用户", description = "管理用户") // Swagger 注解:定义该类的 API 模型名称和描述
public class SysUserDTO implements Serializable { // 实现 Serializable 接口,以支持序列化
private static final long serialVersionUID = 1L;
private static final long serialVersionUID = 1L; // 序列化版本号,用于序列化和反序列化的一致性检查
@ApiModelProperty(value = "ID", required = true) // Swagger 注解描述该属性为“ID”并标记为必填
private String id; // 定义字段:用户的唯一标识符
@ApiModelProperty(value = "ID", required=true)
private String id;
@ApiModelProperty(value = "用户名", required = true) // Swagger 注解:描述该属性为“用户名”,并标记为必填
private String userName; // 定义字段:管理员的用户名,用于登录和身份验证
@ApiModelProperty(value = "用户名", required=true)
private String userName;
@ApiModelProperty(value = "真实姓名", required = true) // Swagger 注解:描述该属性为“真实姓名”,并标记为必填
private String realName; // 定义字段:管理员的真实姓名
@ApiModelProperty(value = "真实姓名", required=true)
private String realName;
@ApiModelProperty(value = "密码", required = true) // Swagger 注解:描述该属性为“密码”,并标记为必填
private String password; // 定义字段:管理员的密码
@ApiModelProperty(value = "密码", required=true)
private String password;
@ApiModelProperty(value = "密码", required = true) // Swagger 注解:描述该属性为“密码盐”,并标记为必填
private String salt; // 定义字段:用于加密密码的盐值
@ApiModelProperty(value = "密码盐", required=true)
private String salt;
@ApiModelProperty(value = "角色列表", required = true) // Swagger 注解:描述该属性为“角色列表”,并标记为必填
private String roleIds; // 定义字段用户的角色ID列表用于权限控制
@ApiModelProperty(value = "角色列表", required=true)
private String roleIds;
@ApiModelProperty(value = "部门ID", required = true) // Swagger 注解描述该属性为“部门ID”并标记为必填
private String departId; // 定义字段用户所属的部门ID
@ApiModelProperty(value = "部门ID", required=true)
private String departId;
@ApiModelProperty(value = "创建时间", required = true) // Swagger 注解:描述该属性为“创建时间”,并标记为必填
private Date createTime; // 定义字段:管理员账号的创建时间
@ApiModelProperty(value = "创建时间", required=true)
private Date createTime;
@ApiModelProperty(value = "更新时间", required = true) // Swagger 注解:描述该属性为“更新时间”,并标记为必填
private Date updateTime; // 定义字段:管理员账号的最后更新时间
@ApiModelProperty(value = "更新时间", required=true)
private Date updateTime;
@ApiModelProperty(value = "状态", required=true)
private Integer state;
@ApiModelProperty(value = "状态", required = true) // Swagger 注解:描述该属性为“状态”,并标记为必填
private Integer state; // 定义字段:管理员账号的状态,如启用或禁用
}

@ -1,33 +1,32 @@
package com.yf.exam.modules.sys.user.dto;
package com.yf.exam.modules.sys.user.dto; // 包名:表示该类属于 sys.user.dto 包
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import io.swagger.annotations.ApiModel; // 导入 Swagger 注解,用于定义 API 模型
import io.swagger.annotations.ApiModelProperty; // 导入 Swagger 注解,用于描述 API 模型的属性
import lombok.Data; // 导入 Lombok 注解,用于自动生成 Getter、Setter、toString 等方法
import java.io.Serializable;
import java.io.Serializable; // 导入 Serializable 接口,用于支持对象的序列化
/**
* <p>
*
* </p>
*
* @author
* @since 2020-04-13 16:57
*/
@Data
@ApiModel(value="用户角色", description="用户角色")
public class SysUserRoleDTO implements Serializable {
* <p>
*
* </p>
*
*
* @
* @ 2020-04-13 16:57
*/
@Data // Lombok 注解,自动生成 Getter、Setter 和其他方法
@ApiModel(value = "用户角色", description = "用户角色") // Swagger 注解:定义该类的 API 模型名称和描述
public class SysUserRoleDTO implements Serializable { // 实现 Serializable 接口,以支持序列化
private static final long serialVersionUID = 1L;
@ApiModelProperty(value = "ID", required=true)
private String id;
@ApiModelProperty(value = "用户ID", required=true)
private String userId;
@ApiModelProperty(value = "角色ID", required=true)
private String roleId;
private static final long serialVersionUID = 1L; // 序列化版本号,用于序列化和反序列化的一致性检查
@ApiModelProperty(value = "ID", required = true) // Swagger 注解描述该属性为“ID”并标记为必填
private String id; // 定义字段:用户角色关系的唯一标识符
@ApiModelProperty(value = "用户ID", required = true) // Swagger 注解描述该属性为“用户ID”并标记为必填
private String userId; // 定义字段:用户的唯一标识符,关联到特定的用户
@ApiModelProperty(value = "角色ID", required = true) // Swagger 注解描述该属性为“角色ID”并标记为必填
private String roleId; // 定义字段:角色的唯一标识符,关联到特定的角色
}

@ -1,29 +1,29 @@
package com.yf.exam.modules.sys.user.dto.request;
package com.yf.exam.modules.sys.user.dto.request; // 包名:表示该类属于 sys.user.dto.request 包
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import io.swagger.annotations.ApiModel; // 导入 Swagger 注解,用于定义 API 模型
import io.swagger.annotations.ApiModelProperty; // 导入 Swagger 注解,用于描述 API 模型的属性
import lombok.Data; // 导入 Lombok 注解,用于自动生成 Getter、Setter、toString 等方法
import java.io.Serializable;
import java.io.Serializable; // 导入 Serializable 接口,用于支持对象的序列化
/**
* <p>
*
* </p>
*
* @author
* @since 2020-04-13 16:57
*/
@Data
@ApiModel(value="管理员登录请求类", description="管理员登录请求类")
public class SysUserLoginReqDTO implements Serializable {
* <p>
*
* </p>
*
*
* @
* @ 2020-04-13 16:57
*/
@Data // Lombok 注解,自动生成 Getter、Setter 和其他方法
@ApiModel(value = "管理员登录请求类", description = "管理员登录请求类") // Swagger 注解:定义该类的 API 模型名称和描述
public class SysUserLoginReqDTO implements Serializable { // 实现 Serializable 接口,以支持序列化
private static final long serialVersionUID = 1L;
private static final long serialVersionUID = 1L; // 序列化版本号,用于序列化和反序列化的一致性检查
@ApiModelProperty(value = "用户名", required=true)
private String username;
@ApiModelProperty(value = "用户名", required = true) // Swagger 注解:描述该属性为“用户名”,并标记为必填
private String username; // 定义字段:用户名,登录时使用
@ApiModelProperty(value = "密码", required=true)
private String password;
@ApiModelProperty(value = "密码", required = true) // Swagger 注解:描述该属性为“密码”,并标记为必填
private String password; // 定义字段:密码,登录时使用
}

@ -1,43 +1,43 @@
package com.yf.exam.modules.sys.user.dto.request;
package com.yf.exam.modules.sys.user.dto.request; // 包名:表示该类属于 sys.user.dto.request 包
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import io.swagger.annotations.ApiModel; // 导入 Swagger 注解,用于定义 API 模型
import io.swagger.annotations.ApiModelProperty; // 导入 Swagger 注解,用于描述 API 模型的属性
import lombok.Data; // 导入 Lombok 注解,用于自动生成 Getter、Setter、toString 等方法
import java.io.Serializable;
import java.util.List;
import java.io.Serializable; // 导入 Serializable 接口,用于支持对象的序列化
import java.util.List; // 导入 List 接口,用于存储角色列表
/**
* <p>
*
* </p>
*
* @author
* @since 2020-04-13 16:57
*/
@Data
@ApiModel(value="管理员保存请求类", description="管理员保存请求类")
public class SysUserSaveReqDTO implements Serializable {
@ApiModelProperty(value = "ID", required=true)
private String id;
@ApiModelProperty(value = "用户名", required=true)
private String userName;
@ApiModelProperty(value = "头像", required=true)
private String avatar;
@ApiModelProperty(value = "真实姓名", required=true)
private String realName;
@ApiModelProperty(value = "密码", required=true)
private String password;
@ApiModelProperty(value = "部门", required=true)
private String departId;
@ApiModelProperty(value = "角色列表", required=true)
private List<String> roles;
* <p>
*
* </p>
*
*
* @
* @ 2020-04-13 16:57
*/
@Data // Lombok 注解,自动生成 Getter、Setter 和其他方法
@ApiModel(value = "管理员保存请求类", description = "管理员保存请求类") // Swagger 注解:定义该类的 API 模型名称和描述
public class SysUserSaveReqDTO implements Serializable { // 实现 Serializable 接口,以支持序列化
@ApiModelProperty(value = "ID", required = true) // Swagger 注解描述该属性为“ID”并标记为必填
private String id; // 定义字段:管理员的唯一标识符,通常用于更新操作
@ApiModelProperty(value = "用户名", required = true) // Swagger 注解:描述该属性为“用户名”,并标记为必填
private String userName; // 定义字段:管理员的用户名,用于登录
@ApiModelProperty(value = "头像", required = true) // Swagger 注解:描述该属性为“头像”,并标记为必填
private String avatar; // 定义字段:管理员的头像 URL
@ApiModelProperty(value = "真实姓名", required = true) // Swagger 注解:描述该属性为“真实姓名”,并标记为必填
private String realName; // 定义字段:管理员的真实姓名
@ApiModelProperty(value = "密码", required = true) // Swagger 注解:描述该属性为“密码”,并标记为必填
private String password; // 定义字段:管理员的登录密码
@ApiModelProperty(value = "部门", required = true) // Swagger 注解:描述该属性为“部门”,并标记为必填
private String departId; // 定义字段管理员所属的部门ID
@ApiModelProperty(value = "角色列表", required = true) // Swagger 注解:描述该属性为“角色列表”,并标记为必填
private List<String> roles; // 定义字段:管理员的角色列表,每个角色的 ID 组成的列表
}

@ -1,26 +1,26 @@
package com.yf.exam.modules.sys.user.dto.request;
package com.yf.exam.modules.sys.user.dto.request; // 包名:表示该类属于 sys.user.dto.request 包
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import io.swagger.annotations.ApiModel; // 导入 Swagger 注解,用于定义 API 模型
import io.swagger.annotations.ApiModelProperty; // 导入 Swagger 注解,用于描述 API 模型的属性
import lombok.Data; // 导入 Lombok 注解,用于自动生成 Getter、Setter、toString 等方法
import java.io.Serializable;
import java.io.Serializable; // 导入 Serializable 接口,用于支持对象的序列化
/**
* <p>
*
* </p>
*
* @author
* @since 2020-04-13 16:57
*/
@Data
@ApiModel(value="会话检查请求类", description="会话检查请求类")
public class SysUserTokenReqDTO implements Serializable {
* <p>
*
* </p>
* token
*
* @
* @ 2020-04-13 16:57
*/
@Data // Lombok 注解,自动生成 Getter、Setter 和其他方法
@ApiModel(value = "会话检查请求类", description = "会话检查请求类") // Swagger 注解:定义该类的 API 模型名称和描述
public class SysUserTokenReqDTO implements Serializable { // 实现 Serializable 接口,以支持序列化
private static final long serialVersionUID = 1L;
private static final long serialVersionUID = 1L; // 序列化版本号,用于序列化和反序列化的一致性检查
@ApiModelProperty(value = "用户名", required=true)
private String token;
@ApiModelProperty(value = "用户名", required = true) // Swagger 注解:描述该属性为“用户名”,并标记为必填
private String token; // 定义字段:会话的 token用于标识当前会话
}

@ -1,55 +1,55 @@
package com.yf.exam.modules.sys.user.dto.response;
package com.yf.exam.modules.sys.user.dto.response; // 包名:表示该类属于 sys.user.dto.response 包
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import io.swagger.annotations.ApiModel; // 导入 Swagger 注解,用于定义 API 模型
import io.swagger.annotations.ApiModelProperty; // 导入 Swagger 注解,用于描述 API 模型的属性
import lombok.Data; // 导入 Lombok 注解,用于自动生成 Getter、Setter、toString 等方法
import java.io.Serializable;
import java.util.Date;
import java.util.List;
import java.io.Serializable; // 导入 Serializable 接口,用于支持对象的序列化
import java.util.Date; // 导入 Date 类,用于表示日期和时间
import java.util.List; // 导入 List 接口,用于存储角色列表
/**
* <p>
*
* </p>
*
* @author
* @since 2020-04-13 16:57
*/
@Data
@ApiModel(value="管理用户登录响应类", description="管理用户登录响应类")
public class SysUserLoginDTO implements Serializable {
* <p>
*
* </p>
*
*
* @
* @ 2020-04-13 16:57
*/
@Data // Lombok 注解,自动生成 Getter、Setter 和其他方法
@ApiModel(value = "管理用户登录响应类", description = "管理用户登录响应类") // Swagger 注解:定义该类的 API 模型名称和描述
public class SysUserLoginDTO implements Serializable { // 实现 Serializable 接口,以支持序列化
private static final long serialVersionUID = 1L;
private static final long serialVersionUID = 1L; // 序列化版本号,用于序列化和反序列化的一致性检查
@ApiModelProperty(value = "ID", required=true)
private String id;
@ApiModelProperty(value = "ID", required = true) // Swagger 注解描述该属性为“ID”并标记为必填
private String id; // 定义字段:管理员的唯一标识符
@ApiModelProperty(value = "用户名", required=true)
private String userName;
@ApiModelProperty(value = "用户名", required = true) // Swagger 注解:描述该属性为“用户名”,并标记为必填
private String userName; // 定义字段:管理员的用户名
@ApiModelProperty(value = "真实姓名", required=true)
private String realName;
@ApiModelProperty(value = "真实姓名", required = true) // Swagger 注解:描述该属性为“真实姓名”,并标记为必填
private String realName; // 定义字段:管理员的真实姓名
@ApiModelProperty(value = "角色列表", required=true)
private String roleIds;
@ApiModelProperty(value = "角色列表", required = true) // Swagger 注解:描述该属性为“角色列表”,并标记为必填
private String roleIds; // 定义字段管理员的角色ID列表用于权限控制
@ApiModelProperty(value = "部门ID", required=true)
private String departId;
@ApiModelProperty(value = "部门ID", required = true) // Swagger 注解描述该属性为“部门ID”并标记为必填
private String departId; // 定义字段管理员所属部门的ID
@ApiModelProperty(value = "创建时间", required=true)
private Date createTime;
@ApiModelProperty(value = "创建时间", required = true) // Swagger 注解:描述该属性为“创建时间”,并标记为必填
private Date createTime; // 定义字段:管理员账号的创建时间
@ApiModelProperty(value = "更新时间", required=true)
private Date updateTime;
@ApiModelProperty(value = "更新时间", required = true) // Swagger 注解:描述该属性为“更新时间”,并标记为必填
private Date updateTime; // 定义字段:管理员账号的最后更新时间
@ApiModelProperty(value = "状态", required=true)
private Integer state;
@ApiModelProperty(value = "状态", required = true) // Swagger 注解:描述该属性为“状态”,并标记为必填
private Integer state; // 定义字段:管理员账号的状态,如启用或禁用
@ApiModelProperty(value = "角色列表", required=true)
private List<String> roles;
@ApiModelProperty(value = "角色列表", required = true) // Swagger 注解:描述该属性为“角色列表”,并标记为必填
private List<String> roles; // 定义字段管理员角色的列表每个角色的名称或ID
@ApiModelProperty(value = "登录令牌", required=true)
private String token;
@ApiModelProperty(value = "登录令牌", required = true) // Swagger 注解:描述该属性为“登录令牌”,并标记为必填
private String token; // 定义字段:管理员登录后的令牌,用于身份验证
}

@ -1,36 +1,38 @@
package com.yf.exam.modules.sys.user.entity;
package com.yf.exam.modules.sys.user.entity; // 包名:表示该类属于 sys.user.entity 包
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import com.baomidou.mybatisplus.extension.activerecord.Model;
import lombok.Data;
import com.baomidou.mybatisplus.annotation.IdType; // 导入 MyBatis-Plus 注解,用于指定主键生成策略
import com.baomidou.mybatisplus.annotation.TableField; // 导入 MyBatis-Plus 注解,用于指定表字段
import com.baomidou.mybatisplus.annotation.TableId; // 导入 MyBatis-Plus 注解,用于指定表主键字段
import com.baomidou.mybatisplus.annotation.TableName; // 导入 MyBatis-Plus 注解,用于指定表名
import com.baomidou.mybatisplus.extension.activerecord.Model; // 导入 MyBatis-Plus 扩展的 Model 类,支持 ActiveRecord 模式
import lombok.Data; // 导入 Lombok 注解,用于自动生成 Getter、Setter、toString 等方法
/**
* <p>
*
* </p>
*
* @author
* @since 2020-04-13 16:57
*/
@Data
@TableName("sys_role")
public class SysRole extends Model<SysRole> {
* <p>
*
* </p>
* `sys_role`
*
* @
* @ 2020-04-13 16:57
*/
@Data // Lombok 注解,自动生成 Getter、Setter 和其他方法
@TableName("sys_role") // MyBatis-Plus 注解,指定该实体类对应数据库表名为 "sys_role"
public class SysRole extends Model<SysRole> { // SysRole 类继承自 Model 类,支持 ActiveRecord 模式
private static final long serialVersionUID = 1L; // 序列化版本号,用于序列化和反序列化的一致性检查
private static final long serialVersionUID = 1L;
/**
* ID
*/
@TableId(value = "id", type = IdType.ASSIGN_ID)
private String id;
* ID
* 使 MyBatis-Plus
*/
@TableId(value = "id", type = IdType.ASSIGN_ID) // MyBatis-Plus 注解,指定主键字段及生成策略
private String id; // 定义字段:角色的唯一标识符
/**
*
*/
@TableField("role_name")
private String roleName;
*
* "role_name"
*/
@TableField("role_name") // MyBatis-Plus 注解,指定该字段对应数据库中的 "role_name" 字段
private String roleName; // 定义字段:角色的名称
}

@ -1,83 +1,93 @@
package com.yf.exam.modules.sys.user.entity;
package com.yf.exam.modules.sys.user.entity; // 包名:表示该类属于 sys.user.entity 包
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import com.baomidou.mybatisplus.extension.activerecord.Model;
import lombok.Data;
import com.baomidou.mybatisplus.annotation.IdType; // 导入 MyBatis-Plus 注解,用于指定主键生成策略
import com.baomidou.mybatisplus.annotation.TableField; // 导入 MyBatis-Plus 注解,用于指定表字段
import com.baomidou.mybatisplus.annotation.TableId; // 导入 MyBatis-Plus 注解,用于指定表主键字段
import com.baomidou.mybatisplus.annotation.TableName; // 导入 MyBatis-Plus 注解,用于指定表名
import com.baomidou.mybatisplus.extension.activerecord.Model; // 导入 MyBatis-Plus 扩展的 Model 类,支持 ActiveRecord 模式
import lombok.Data; // 导入 Lombok 注解,用于自动生成 Getter、Setter、toString 等方法
import java.util.Date;
import java.util.Date; // 导入 Date 类,用于表示日期和时间
/**
* <p>
*
* </p>
*
* @author
* @since 2020-04-13 16:57
*/
@Data
@TableName("sys_user")
public class SysUser extends Model<SysUser> {
* <p>
*
* </p>
* `sys_user`
*
* @
* @ 2020-04-13 16:57
*/
@Data // Lombok 注解,自动生成 Getter、Setter 和其他方法
@TableName("sys_user") // MyBatis-Plus 注解,指定该实体类对应数据库表名为 "sys_user"
public class SysUser extends Model<SysUser> { // SysUser 类继承自 Model 类,支持 ActiveRecord 模式
private static final long serialVersionUID = 1L;
private static final long serialVersionUID = 1L; // 序列化版本号,用于序列化和反序列化的一致性检查
/**
* ID
* 使 MyBatis-Plus
*/
@TableId(value = "id", type = IdType.ASSIGN_ID)
private String id;
@TableId(value = "id", type = IdType.ASSIGN_ID) // MyBatis-Plus 注解,指定主键字段及生成策略
private String id; // 定义字段:用户的唯一标识符
/**
*
* "user_name"
*/
@TableField("user_name")
private String userName;
@TableField("user_name") // MyBatis-Plus 注解,指定该字段对应数据库中的 "user_name" 字段
private String userName; // 定义字段:管理员的用户名,用于登录和身份验证
/**
*
* "real_name"
*/
@TableField("real_name")
private String realName;
@TableField("real_name") // MyBatis-Plus 注解,指定该字段对应数据库中的 "real_name" 字段
private String realName; // 定义字段:管理员的真实姓名
/**
*
*
*/
private String password;
private String password; // 定义字段:管理员的登录密码
/**
*
*
*/
private String salt;
private String salt; // 定义字段:用于加密密码的盐值
/**
*
* "role_ids" ID
*/
@TableField("role_ids")
private String roleIds;
@TableField("role_ids") // MyBatis-Plus 注解,指定该字段对应数据库中的 "role_ids" 字段
private String roleIds; // 定义字段用户的角色ID列表用于权限控制
/**
* ID
* "depart_id"
*/
@TableField("depart_id")
private String departId;
@TableField("depart_id") // MyBatis-Plus 注解,指定该字段对应数据库中的 "depart_id" 字段
private String departId; // 定义字段管理员所属的部门ID
/**
*
* "create_time"
*/
@TableField("create_time")
private Date createTime;
@TableField("create_time") // MyBatis-Plus 注解,指定该字段对应数据库中的 "create_time" 字段
private Date createTime; // 定义字段:管理员账号的创建时间
/**
*
* "update_time"
*/
@TableField("update_time")
private Date updateTime;
@TableField("update_time") // MyBatis-Plus 注解,指定该字段对应数据库中的 "update_time" 字段
private Date updateTime; // 定义字段:管理员账号的最后更新时间
/**
*
*
*/
private Integer state;
private Integer state; // 定义字段:管理员账号的状态(如启用或禁用)
}

@ -1,42 +1,45 @@
package com.yf.exam.modules.sys.user.entity;
package com.yf.exam.modules.sys.user.entity; // 包名:表示该类属于 sys.user.entity 包
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import com.baomidou.mybatisplus.extension.activerecord.Model;
import lombok.Data;
import com.baomidou.mybatisplus.annotation.IdType; // 导入 MyBatis-Plus 注解,用于指定主键生成策略
import com.baomidou.mybatisplus.annotation.TableField; // 导入 MyBatis-Plus 注解,用于指定表字段
import com.baomidou.mybatisplus.annotation.TableId; // 导入 MyBatis-Plus 注解,用于指定表主键字段
import com.baomidou.mybatisplus.annotation.TableName; // 导入 MyBatis-Plus 注解,用于指定表名
import com.baomidou.mybatisplus.extension.activerecord.Model; // 导入 MyBatis-Plus 扩展的 Model 类,支持 ActiveRecord 模式
import lombok.Data; // 导入 Lombok 注解,用于自动生成 Getter、Setter、toString 等方法
/**
* <p>
*
* </p>
*
* @author
* @since 2020-04-13 16:57
*/
@Data
@TableName("sys_user_role")
public class SysUserRole extends Model<SysUserRole> {
* <p>
*
* </p>
* `sys_user_role`
*
* @
* @ 2020-04-13 16:57
*/
@Data // Lombok 注解,自动生成 Getter、Setter 和其他方法
@TableName("sys_user_role") // MyBatis-Plus 注解,指定该实体类对应数据库表名为 "sys_user_role"
public class SysUserRole extends Model<SysUserRole> { // SysUserRole 类继承自 Model 类,支持 ActiveRecord 模式
private static final long serialVersionUID = 1L; // 序列化版本号,用于序列化和反序列化的一致性检查
private static final long serialVersionUID = 1L;
/**
* ID
*/
@TableId(value = "id", type = IdType.ASSIGN_ID)
private String id;
* ID
* 使 MyBatis-Plus
*/
@TableId(value = "id", type = IdType.ASSIGN_ID) // MyBatis-Plus 注解,指定主键字段及生成策略
private String id; // 定义字段:用户角色关系的唯一标识符
/**
* ID
*/
@TableField("user_id")
private String userId;
* ID
* "user_id"
*/
@TableField("user_id") // MyBatis-Plus 注解,指定该字段对应数据库中的 "user_id" 字段
private String userId; // 定义字段:用户的唯一标识符,关联到特定的用户
/**
* ID
*/
@TableField("role_id")
private String roleId;
* ID
* "role_id"
*/
@TableField("role_id") // MyBatis-Plus 注解,指定该字段对应数据库中的 "role_id" 字段
private String roleId; // 定义字段:角色的唯一标识符,关联到特定的角色
}

@ -1,15 +1,17 @@
package com.yf.exam.modules.sys.user.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.yf.exam.modules.sys.user.entity.SysRole;
package com.yf.exam.modules.sys.user.mapper; // 包名:表示该类属于 sys.user.mapper 包
import com.baomidou.mybatisplus.core.mapper.BaseMapper; // 导入 MyBatis-Plus 的 BaseMapper 接口,提供基本的数据库操作方法
import com.yf.exam.modules.sys.user.entity.SysRole; // 导入 SysRole 实体类,表示角色实体
/**
* <p>
* Mapper
* </p>
*
* @author
* @since 2020-04-13 16:57
*/
public interface SysRoleMapper extends BaseMapper<SysRole> {
* <p>
* Mapper
* </p>
* MyBatis-Plus BaseMapper `SysRole`
*
* @
* @ 2020-04-13 16:57
*/
public interface SysRoleMapper extends BaseMapper<SysRole> { // 继承 MyBatis-Plus 的 BaseMapper自动提供对 SysRole 实体的 CRUD 操作
}

@ -1,16 +1,17 @@
package com.yf.exam.modules.sys.user.mapper;
package com.yf.exam.modules.sys.user.mapper; // 包名:表示该类属于 sys.user.mapper 包
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.yf.exam.modules.sys.user.entity.SysUser;
import com.baomidou.mybatisplus.core.mapper.BaseMapper; // 导入 MyBatis-Plus 的 BaseMapper 接口,提供基本的数据库操作方法
import com.yf.exam.modules.sys.user.entity.SysUser; // 导入 SysUser 实体类,表示管理员用户实体
/**
* <p>
* Mapper
* </p>
*
* @author
* @since 2020-04-13 16:57
*/
public interface SysUserMapper extends BaseMapper<SysUser> {
* <p>
* Mapper
* </p>
* MyBatis-Plus BaseMapper `SysUser`
*
* @
* @ 2020-04-13 16:57
*/
public interface SysUserMapper extends BaseMapper<SysUser> { // 继承 MyBatis-Plus 的 BaseMapper自动提供对 SysUser 实体的 CRUD 操作
}

@ -1,16 +1,17 @@
package com.yf.exam.modules.sys.user.mapper;
package com.yf.exam.modules.sys.user.mapper; // 包名:表示该类属于 sys.user.mapper 包
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.yf.exam.modules.sys.user.entity.SysUserRole;
import com.baomidou.mybatisplus.core.mapper.BaseMapper; // 导入 MyBatis-Plus 的 BaseMapper 接口,提供基本的数据库操作方法
import com.yf.exam.modules.sys.user.entity.SysUserRole; // 导入 SysUserRole 实体类,表示用户角色实体
/**
* <p>
* Mapper
* </p>
*
* @author
* @since 2020-04-13 16:57
*/
public interface SysUserRoleMapper extends BaseMapper<SysUserRole> {
* <p>
* Mapper
* </p>
* MyBatis-Plus BaseMapper `SysUserRole`
*
* @
* @ 2020-04-13 16:57
*/
public interface SysUserRoleMapper extends BaseMapper<SysUserRole> { // 继承 MyBatis-Plus 的 BaseMapper自动提供对 SysUserRole 实体的 CRUD 操作
}

@ -1,25 +1,26 @@
package com.yf.exam.modules.sys.user.service;
package com.yf.exam.modules.sys.user.service; // 包名:表示该类属于 sys.user.service 包
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.service.IService;
import com.yf.exam.modules.sys.user.dto.SysRoleDTO;
import com.yf.exam.modules.sys.user.entity.SysRole;
import com.yf.exam.core.api.dto.PagingReqDTO;
import com.baomidou.mybatisplus.core.metadata.IPage; // 导入 MyBatis-Plus 的 IPage 接口,用于分页查询
import com.baomidou.mybatisplus.extension.service.IService; // 导入 MyBatis-Plus 的 IService 接口,提供基本的服务方法
import com.yf.exam.modules.sys.user.dto.SysRoleDTO; // 导入 SysRoleDTO 数据传输对象,用于封装角色数据
import com.yf.exam.modules.sys.user.entity.SysRole; // 导入 SysRole 实体类,表示角色
import com.yf.exam.core.api.dto.PagingReqDTO; // 导入分页请求 DTO用于封装分页请求参数
/**
* <p>
*
* </p>
*
* @author
* @since 2020-04-13 16:57
*/
public interface SysRoleService extends IService<SysRole> {
* <p>
*
* </p>
*
*
* @
* @ 2020-04-13 16:57
*/
public interface SysRoleService extends IService<SysRole> { // 继承 MyBatis-Plus 的 IService 接口,提供基本的 CRUD 操作
/**
*
* @param reqDTO
* @return
*/
IPage<SysRoleDTO> paging(PagingReqDTO<SysRoleDTO> reqDTO);
*
* @param reqDTO
* @return
*/
IPage<SysRoleDTO> paging(PagingReqDTO<SysRoleDTO> reqDTO); // 定义分页查询方法,返回角色的分页数据
}

@ -1,61 +1,64 @@
package com.yf.exam.modules.sys.user.service;
package com.yf.exam.modules.sys.user.service; // 包名:表示该类属于 sys.user.service 包
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.service.IService;
import com.yf.exam.modules.sys.user.dto.SysUserRoleDTO;
import com.yf.exam.modules.sys.user.entity.SysUserRole;
import com.yf.exam.core.api.dto.PagingReqDTO;
import com.baomidou.mybatisplus.core.metadata.IPage; // 导入 MyBatis-Plus 的 IPage 接口,用于分页查询
import com.baomidou.mybatisplus.extension.service.IService; // 导入 MyBatis-Plus 的 IService 接口,提供基本的服务方法
import com.yf.exam.modules.sys.user.dto.SysUserRoleDTO; // 导入 SysUserRoleDTO 数据传输对象,用于封装用户角色数据
import com.yf.exam.modules.sys.user.entity.SysUserRole; // 导入 SysUserRole 实体类,表示用户角色
import com.yf.exam.core.api.dto.PagingReqDTO; // 导入分页请求 DTO用于封装分页请求参数
import java.util.List;
import java.util.List; // 导入 List 接口用于存储多个角色ID
/**
* <p>
*
* </p>
*
* @author
* @since 2020-04-13 16:57
*/
public interface SysUserRoleService extends IService<SysUserRole> {
* <p>
*
* </p>
*
*
* @
* @ 2020-04-13 16:57
*/
public interface SysUserRoleService extends IService<SysUserRole> { // 继承 MyBatis-Plus 的 IService 接口,提供基本的 CRUD 操作
/**
*
* @param reqDTO
* @return
*/
IPage<SysUserRoleDTO> paging(PagingReqDTO<SysUserRoleDTO> reqDTO);
*
* @param reqDTO
* @return
*/
IPage<SysUserRoleDTO> paging(PagingReqDTO<SysUserRoleDTO> reqDTO); // 定义分页查询用户角色数据的方法,返回角色的分页数据
/**
*
* @param userId
* @return
* @param userId ID
* @return ID
*/
List<String> listRoles(String userId);
List<String> listRoles(String userId); // 根据用户ID查找该用户的角色ID列表
/**
*
* @param userId
* @param ids
* @return
* @param userId ID
* @param ids ID
* @return ID
*/
String saveRoles(String userId, List<String> ids);
String saveRoles(String userId, List<String> ids); // 保存指定用户的角色
/**
*
* @param userId
* @return
* @param userId ID
* @return truefalse
*/
boolean isStudent(String userId);
boolean isStudent(String userId); // 判断指定用户是否为学生
/**
*
* @param userId ID
* @return truefalse
*/
boolean isTeacher(String userId);
boolean isTeacher(String userId); // 判断指定用户是否为老师
/**
*
* @param userId
* @return
*
* @param userId ID
* @return truefalse
*/
boolean isAdmin(String userId);
boolean isAdmin(String userId); // 判断指定用户是否为管理员
}

@ -1,72 +1,75 @@
package com.yf.exam.modules.sys.user.service;
package com.yf.exam.modules.sys.user.service; // 包名:表示该类属于 sys.user.service 包
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.service.IService;
import com.yf.exam.modules.sys.user.dto.SysUserDTO;
import com.yf.exam.modules.sys.user.dto.request.SysUserSaveReqDTO;
import com.yf.exam.modules.sys.user.dto.response.SysUserLoginDTO;
import com.yf.exam.modules.sys.user.entity.SysUser;
import com.yf.exam.core.api.dto.PagingReqDTO;
import com.baomidou.mybatisplus.core.metadata.IPage; // 导入 MyBatis-Plus 的 IPage 接口,用于分页查询
import com.baomidou.mybatisplus.extension.service.IService; // 导入 MyBatis-Plus 的 IService 接口,提供基本的服务方法
import com.yf.exam.modules.sys.user.dto.SysUserDTO; // 导入 SysUserDTO 数据传输对象,用于封装用户数据
import com.yf.exam.modules.sys.user.dto.request.SysUserSaveReqDTO; // 导入 SysUserSaveReqDTO 请求 DTO用于保存用户信息
import com.yf.exam.modules.sys.user.dto.response.SysUserLoginDTO; // 导入 SysUserLoginDTO 响应 DTO用于返回登录信息
import com.yf.exam.modules.sys.user.entity.SysUser; // 导入 SysUser 实体类,表示管理员用户
import com.yf.exam.core.api.dto.PagingReqDTO; // 导入分页请求 DTO用于封装分页请求参数
/**
* <p>
*
* </p>
*
* @author
* @since 2020-04-13 16:57
*/
public interface SysUserService extends IService<SysUser> {
* <p>
*
* </p>
*
*
* @
* @ 2020-04-13 16:57
*/
public interface SysUserService extends IService<SysUser> { // 继承 MyBatis-Plus 的 IService 接口,提供基本的 CRUD 操作
/**
*
* @param reqDTO
* @return
*/
IPage<SysUserDTO> paging(PagingReqDTO<SysUserDTO> reqDTO);
*
* @param reqDTO
* @return
*/
IPage<SysUserDTO> paging(PagingReqDTO<SysUserDTO> reqDTO); // 定义分页查询用户数据的方法,返回用户的分页数据
/**
*
* @param userName
* @param password
* @return
* @param userName
* @param password
* @return token
*/
SysUserLoginDTO login(String userName, String password);
SysUserLoginDTO login(String userName, String password); // 实现用户登录,验证用户名和密码
/**
*
* @param token
* @return
* @param token JWT token
* @return
*/
SysUserLoginDTO token(String token);
SysUserLoginDTO token(String token); // 根据 token 获取用户的会话信息并验证
/**
* 退
* @param token
* @param token JWT token
*/
void logout(String token);
void logout(String token); // 退出登录,销毁当前会话
/**
*
* @param reqDTO
* @param reqDTO
*/
void update(SysUserDTO reqDTO);
void update(SysUserDTO reqDTO); // 修改用户资料,包括密码等信息
/**
*
* @param reqDTO
* @param reqDTO
*/
void save(SysUserSaveReqDTO reqDTO);
void save(SysUserSaveReqDTO reqDTO); // 保存或更新系统用户
/**
*
* @param reqDTO
* @param reqDTO
* @return token
*/
SysUserLoginDTO reg(SysUserDTO reqDTO);
SysUserLoginDTO reg(SysUserDTO reqDTO); // 用户注册,保存用户信息并返回登录数据
/**
*
* @param reqDTO
* @param reqDTO
* @return token
*/
SysUserLoginDTO quickReg(SysUserDTO reqDTO);
SysUserLoginDTO quickReg(SysUserDTO reqDTO); // 快速注册,如果用户已存在则直接登录,否则进行注册
}

@ -1,42 +1,46 @@
package com.yf.exam.modules.sys.user.service.impl;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.TypeReference;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.yf.exam.modules.sys.user.dto.SysRoleDTO;
import com.yf.exam.modules.sys.user.entity.SysRole;
import com.yf.exam.modules.sys.user.mapper.SysRoleMapper;
import com.yf.exam.modules.sys.user.service.SysRoleService;
import com.yf.exam.core.api.dto.PagingReqDTO;
import org.springframework.stereotype.Service;
package com.yf.exam.modules.sys.user.service.impl; // 包名:表示该类属于 sys.user.service.impl 包
import com.alibaba.fastjson.JSON; // 导入 Fastjson 库,用于 JSON 处理
import com.alibaba.fastjson.TypeReference; // 导入 Fastjson 的 TypeReference用于泛型类型的转换
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; // 导入 MyBatis-Plus 的 QueryWrapper用于构建查询条件
import com.baomidou.mybatisplus.core.metadata.IPage; // 导入 MyBatis-Plus 分页接口
import com.baomidou.mybatisplus.extension.plugins.pagination.Page; // 导入 MyBatis-Plus 分页类
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; // 导入 MyBatis-Plus 的 ServiceImpl实现基本的服务层操作
import com.yf.exam.modules.sys.user.dto.SysRoleDTO; // 导入 SysRoleDTO 数据传输对象,用于封装角色数据
import com.yf.exam.modules.sys.user.entity.SysRole; // 导入 SysRole 实体类,表示角色
import com.yf.exam.modules.sys.user.mapper.SysRoleMapper; // 导入 SysRoleMapper用于数据库操作
import com.yf.exam.modules.sys.user.service.SysRoleService; // 导入 SysRoleService 服务接口
import com.yf.exam.core.api.dto.PagingReqDTO; // 导入分页请求 DTO
import org.springframework.stereotype.Service; // 导入 Spring 的 Service 注解,标识该类为服务层组件
/**
* <p>
*
* </p>
*
* @author
* @since 2020-04-13 16:57
*/
@Service
public class SysRoleServiceImpl extends ServiceImpl<SysRoleMapper, SysRole> implements SysRoleService {
* <p>
*
* </p>
* SysRoleService
*
* @
* @ 2020-04-13 16:57
*/
@Service // 标识该类为服务层组件
public class SysRoleServiceImpl extends ServiceImpl<SysRoleMapper, SysRole> implements SysRoleService { // 继承 MyBatis-Plus 的 ServiceImpl自动提供基础的 CRUD 操作
@Override
public IPage<SysRoleDTO> paging(PagingReqDTO<SysRoleDTO> reqDTO) {
public IPage<SysRoleDTO> paging(PagingReqDTO<SysRoleDTO> reqDTO) { // 重写分页查询方法
//创建分页对象
// 创建分页对象,设置当前页和每页显示的条数
IPage<SysRole> query = new Page<>(reqDTO.getCurrent(), reqDTO.getSize());
//查询条件
// 创建查询条件对象(此处没有具体条件,查询所有数据)
QueryWrapper<SysRole> wrapper = new QueryWrapper<>();
//获得数据
// 查询数据,获取分页结果
IPage<SysRole> page = this.page(query, wrapper);
//转换结果
IPage<SysRoleDTO> pageData = JSON.parseObject(JSON.toJSONString(page), new TypeReference<Page<SysRoleDTO>>(){});
// 将查询结果转换为 SysRoleDTO 类型的分页结果
IPage<SysRoleDTO> pageData = JSON.parseObject(JSON.toJSONString(page), new TypeReference<Page<SysRoleDTO>>() {});
// 返回分页数据
return pageData;
}
}
}

@ -1,128 +1,144 @@
package com.yf.exam.modules.sys.user.service.impl;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.TypeReference;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.yf.exam.modules.sys.user.dto.SysUserRoleDTO;
import com.yf.exam.modules.sys.user.entity.SysUserRole;
import com.yf.exam.modules.sys.user.mapper.SysUserRoleMapper;
import com.yf.exam.modules.sys.user.service.SysUserRoleService;
import com.yf.exam.core.api.dto.PagingReqDTO;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;
import java.util.ArrayList;
import java.util.List;
package com.yf.exam.modules.sys.user.service.impl; // 包名:表示该类属于 sys.user.service.impl 包
import com.alibaba.fastjson.JSON; // 导入 Fastjson 库,用于 JSON 处理
import com.alibaba.fastjson.TypeReference; // 导入 Fastjson 的 TypeReference用于泛型类型的转换
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; // 导入 MyBatis-Plus 的 QueryWrapper用于构建查询条件
import com.baomidou.mybatisplus.core.metadata.IPage; // 导入 MyBatis-Plus 分页接口
import com.baomidou.mybatisplus.extension.plugins.pagination.Page; // 导入 MyBatis-Plus 分页类
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; // 导入 MyBatis-Plus 的 ServiceImpl 类,提供基础的数据库操作
import com.yf.exam.modules.sys.user.dto.SysUserRoleDTO; // 导入 SysUserRoleDTO 数据传输对象,用于封装用户角色数据
import com.yf.exam.modules.sys.user.entity.SysUserRole; // 导入 SysUserRole 实体类,表示用户角色
import com.yf.exam.modules.sys.user.mapper.SysUserRoleMapper; // 导入 SysUserRoleMapper用于数据库操作
import com.yf.exam.modules.sys.user.service.SysUserRoleService; // 导入 SysUserRoleService 服务接口
import com.yf.exam.core.api.dto.PagingReqDTO; // 导入分页请求 DTO
import org.springframework.stereotype.Service; // 导入 Spring 的 Service 注解,标识该类为服务层组件
import org.springframework.util.CollectionUtils; // 导入 Spring 的 CollectionUtils 工具类,用于判断集合是否为空
import org.springframework.util.StringUtils; // 导入 Spring 的 StringUtils 工具类,用于判断字符串是否为空
import java.util.ArrayList; // 导入 ArrayList 类,用于创建列表
import java.util.List; // 导入 List 接口,用于存储角色列表
/**
* <p>
*
* </p>
*
* @author
* @since 2020-04-13 16:57
*/
@Service
public class SysUserRoleServiceImpl extends ServiceImpl<SysUserRoleMapper, SysUserRole> implements SysUserRoleService {
* <p>
*
* </p>
* SysUserRoleService
*
* @
* @ 2020-04-13 16:57
*/
@Service // 标识该类为服务层组件
public class SysUserRoleServiceImpl extends ServiceImpl<SysUserRoleMapper, SysUserRole> implements SysUserRoleService { // 继承 MyBatis-Plus 的 ServiceImpl自动提供基础的 CRUD 操作
@Override
public IPage<SysUserRoleDTO> paging(PagingReqDTO<SysUserRoleDTO> reqDTO) {
public IPage<SysUserRoleDTO> paging(PagingReqDTO<SysUserRoleDTO> reqDTO) { // 实现分页查询方法
//创建分页对象
// 创建分页对象,设置当前页和每页显示的条数
IPage<SysUserRole> query = new Page<>(reqDTO.getCurrent(), reqDTO.getSize());
//查询条件
// 创建查询条件对象
QueryWrapper<SysUserRole> wrapper = new QueryWrapper<>();
//获得数据
// 查询数据,获取分页结果
IPage<SysUserRole> page = this.page(query, wrapper);
//转换结果
IPage<SysUserRoleDTO> pageData = JSON.parseObject(JSON.toJSONString(page), new TypeReference<Page<SysUserRoleDTO>>(){});
// 将查询结果转换为 SysUserRoleDTO 类型的分页结果
IPage<SysUserRoleDTO> pageData = JSON.parseObject(JSON.toJSONString(page), new TypeReference<Page<SysUserRoleDTO>>() {});
// 返回分页数据
return pageData;
}
}
@Override
public List<String> listRoles(String userId) {
public List<String> listRoles(String userId) { // 根据用户ID获取该用户的角色列表
// 创建查询条件对象,筛选出指定用户的角色
QueryWrapper<SysUserRole> wrapper = new QueryWrapper<>();
wrapper.lambda().eq(SysUserRole::getUserId, userId);
// 查询角色列表
List<SysUserRole> list = this.list(wrapper);
List<String> roles = new ArrayList<>();
if(!CollectionUtils.isEmpty(list)){
for(SysUserRole item: list){
// 如果查询结果不为空将角色ID添加到列表中
if (!CollectionUtils.isEmpty(list)) {
for (SysUserRole item : list) {
roles.add(item.getRoleId());
}
}
// 返回角色ID列表
return roles;
}
@Override
public String saveRoles(String userId, List<String> ids) {
public String saveRoles(String userId, List<String> ids) { // 保存用户角色方法
// 删除全部角色
// 删除该用户所有角色
QueryWrapper<SysUserRole> wrapper = new QueryWrapper<>();
wrapper.lambda().eq(SysUserRole::getUserId, userId);
this.remove(wrapper);
if(!CollectionUtils.isEmpty(ids)){
// 如果角色列表不为空,保存新的角色
if (!CollectionUtils.isEmpty(ids)) {
List<SysUserRole> list = new ArrayList<>();
String roleIds = null;
for(String item: ids){
// 将角色ID列表转为 SysUserRole 实体对象列表
for (String item : ids) {
SysUserRole role = new SysUserRole();
role.setRoleId(item);
role.setUserId(userId);
list.add(role);
if(StringUtils.isEmpty(roleIds)){
if (StringUtils.isEmpty(roleIds)) {
roleIds = item;
}else{
roleIds+=","+item;
} else {
roleIds += "," + item; // 将角色ID拼接成字符串
}
}
// 批量保存角色数据
this.saveBatch(list);
return roleIds;
return roleIds; // 返回拼接后的角色ID字符串
}
return "";
return ""; // 如果角色列表为空,返回空字符串
}
@Override
public boolean isStudent(String userId) {
public boolean isStudent(String userId) { // 检查用户是否为学生
// 学生角色
// 查询用户是否拥有学生角色
QueryWrapper<SysUserRole> wrapper = new QueryWrapper<>();
wrapper.lambda().eq(SysUserRole::getUserId, userId)
.eq(SysUserRole::getRoleId, "student");
// 如果查询结果数量大于0则表示该用户是学生
return this.count(wrapper) > 0;
}
@Override
public boolean isTeacher(String userId) {
// 学生角色
public boolean isTeacher(String userId) { // 检查用户是否为教师
// 查询用户是否拥有教师角色
QueryWrapper<SysUserRole> wrapper = new QueryWrapper<>();
wrapper.lambda().eq(SysUserRole::getUserId, userId)
.eq(SysUserRole::getRoleId, "teacher");
// 如果查询结果数量大于0则表示该用户是教师
return this.count(wrapper) > 0;
}
@Override
public boolean isAdmin(String userId) {
// 学生角色
public boolean isAdmin(String userId) { // 检查用户是否为管理员
// 查询用户是否拥有管理员角色角色ID为 "sa"
QueryWrapper<SysUserRole> wrapper = new QueryWrapper<>();
wrapper.lambda().eq(SysUserRole::getUserId, userId)
.eq(SysUserRole::getRoleId, "sa");
// 如果查询结果数量大于0则表示该用户是管理员
return this.count(wrapper) > 0;
}
}

@ -1,176 +1,185 @@
package com.yf.exam.modules.sys.user.service.impl;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.TypeReference;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.IdWorker;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.yf.exam.core.api.ApiError;
import com.yf.exam.core.api.dto.PagingReqDTO;
import com.yf.exam.core.enums.CommonState;
import com.yf.exam.core.exception.ServiceException;
import com.yf.exam.core.utils.BeanMapper;
import com.yf.exam.core.utils.passwd.PassHandler;
import com.yf.exam.core.utils.passwd.PassInfo;
import com.yf.exam.ability.shiro.jwt.JwtUtils;
import com.yf.exam.modules.sys.user.dto.SysUserDTO;
import com.yf.exam.modules.sys.user.dto.request.SysUserSaveReqDTO;
import com.yf.exam.modules.sys.user.dto.response.SysUserLoginDTO;
import com.yf.exam.modules.sys.user.entity.SysUser;
import com.yf.exam.modules.sys.user.mapper.SysUserMapper;
import com.yf.exam.modules.sys.user.service.SysUserRoleService;
import com.yf.exam.modules.sys.user.service.SysUserService;
import com.yf.exam.modules.user.UserUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.shiro.SecurityUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import java.util.ArrayList;
import java.util.List;
package com.yf.exam.modules.sys.user.service.impl; // 包名:表示该类属于 sys.user.service.impl 包
import com.alibaba.fastjson.JSON; // 导入 Fastjson 库,用于 JSON 处理
import com.alibaba.fastjson.TypeReference; // 导入 Fastjson 的 TypeReference用于泛型类型的转换
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; // 导入 MyBatis-Plus 的 QueryWrapper用于构建查询条件
import com.baomidou.mybatisplus.core.metadata.IPage; // 导入 MyBatis-Plus 分页接口
import com.baomidou.mybatisplus.core.toolkit.IdWorker; // 导入 MyBatis-Plus 的 IdWorker用于生成唯一ID
import com.baomidou.mybatisplus.extension.plugins.pagination.Page; // 导入 MyBatis-Plus 分页类
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; // 导入 MyBatis-Plus 的 ServiceImpl 类,提供基础的数据库操作
import com.yf.exam.core.api.ApiError; // 导入 ApiError 用于错误码定义
import com.yf.exam.core.api.dto.PagingReqDTO; // 导入分页请求 DTO
import com.yf.exam.core.enums.CommonState; // 导入公共状态枚举,定义正常与异常状态
import com.yf.exam.core.exception.ServiceException; // 导入 ServiceException用于抛出自定义异常
import com.yf.exam.core.utils.BeanMapper; // 导入 BeanMapper 工具类,用于对象之间的属性拷贝
import com.yf.exam.core.utils.passwd.PassHandler; // 导入 PassHandler 用于密码处理
import com.yf.exam.core.utils.passwd.PassInfo; // 导入 PassInfo 用于存储密码和盐
import com.yf.exam.ability.shiro.jwt.JwtUtils; // 导入 JwtUtils 用于生成和验证 JWT
import com.yf.exam.modules.sys.user.dto.SysUserDTO; // 导入 SysUserDTO 数据传输对象,用于封装用户数据
import com.yf.exam.modules.sys.user.dto.request.SysUserSaveReqDTO; // 导入 SysUserSaveReqDTO 请求 DTO用于保存用户信息
import com.yf.exam.modules.sys.user.dto.response.SysUserLoginDTO; // 导入 SysUserLoginDTO 响应 DTO用于返回登录信息
import com.yf.exam.modules.sys.user.entity.SysUser; // 导入 SysUser 实体类,表示管理员用户
import com.yf.exam.modules.sys.user.mapper.SysUserMapper; // 导入 SysUserMapper用于数据库操作
import com.yf.exam.modules.sys.user.service.SysUserRoleService; // 导入 SysUserRoleService 服务接口,用于角色操作
import com.yf.exam.modules.sys.user.service.SysUserService; // 导入 SysUserService 服务接口,用于用户操作
import com.yf.exam.modules.user.UserUtils; // 导入 UserUtils 工具类,用于获取当前用户信息
import org.apache.commons.lang3.StringUtils; // 导入 StringUtils 工具类,用于判断字符串是否为空
import org.apache.shiro.SecurityUtils; // 导入 Shiro 的 SecurityUtils用于获取和处理用户会话
import org.springframework.beans.factory.annotation.Autowired; // 导入 Autowired 注解,用于自动注入依赖
import org.springframework.stereotype.Service; // 导入 Spring 的 Service 注解,标识该类为服务层组件
import org.springframework.transaction.annotation.Transactional; // 导入 Spring 的事务注解,支持事务管理
import org.springframework.util.CollectionUtils; // 导入 Spring 的 CollectionUtils 工具类,用于判断集合是否为空
import java.util.ArrayList; // 导入 ArrayList 类,用于创建列表
import java.util.List; // 导入 List 接口,用于存储角色列表
/**
* <p>
*
* </p>
*
* @author
* @since 2020-04-13 16:57
*/
@Service
public class SysUserServiceImpl extends ServiceImpl<SysUserMapper, SysUser> implements SysUserService {
* <p>
*
* </p>
* SysUserService
*
* @
* @ 2020-04-13 16:57
*/
@Service // 标识该类为服务层组件
public class SysUserServiceImpl extends ServiceImpl<SysUserMapper, SysUser> implements SysUserService { // 继承 MyBatis-Plus 的 ServiceImpl自动提供基础的 CRUD 操作
@Autowired
private SysUserRoleService sysUserRoleService;
private SysUserRoleService sysUserRoleService; // 注入 SysUserRoleService用于用户角色管理
@Override
public IPage<SysUserDTO> paging(PagingReqDTO<SysUserDTO> reqDTO) {
public IPage<SysUserDTO> paging(PagingReqDTO<SysUserDTO> reqDTO) { // 实现分页查询方法
//创建分页对象
// 创建分页对象,设置当前页和每页显示的条数
IPage<SysUser> query = new Page<>(reqDTO.getCurrent(), reqDTO.getSize());
//查询条件
// 创建查询条件对象
QueryWrapper<SysUser> wrapper = new QueryWrapper<>();
SysUserDTO params = reqDTO.getParams();
if(params!=null){
if(!StringUtils.isBlank(params.getUserName())){
// 根据传入的参数设置查询条件
if (params != null) {
if (!StringUtils.isBlank(params.getUserName())) {
wrapper.lambda().like(SysUser::getUserName, params.getUserName());
}
if(!StringUtils.isBlank(params.getRealName())){
if (!StringUtils.isBlank(params.getRealName())) {
wrapper.lambda().like(SysUser::getRealName, params.getRealName());
}
}
//获得数据
// 查询数据,获取分页结果
IPage<SysUser> page = this.page(query, wrapper);
//转换结果
IPage<SysUserDTO> pageData = JSON.parseObject(JSON.toJSONString(page), new TypeReference<Page<SysUserDTO>>(){});
// 将查询结果转换为 SysUserDTO 类型的分页结果
IPage<SysUserDTO> pageData = JSON.parseObject(JSON.toJSONString(page), new TypeReference<Page<SysUserDTO>>() {});
// 返回分页数据
return pageData;
}
}
@Override
public SysUserLoginDTO login(String userName, String password) {
public SysUserLoginDTO login(String userName, String password) { // 用户登录方法
// 查询用户是否存在
QueryWrapper<SysUser> wrapper = new QueryWrapper<>();
wrapper.lambda().eq(SysUser::getUserName, userName);
SysUser user = this.getOne(wrapper, false);
if(user == null){
throw new ServiceException(ApiError.ERROR_90010002);
if (user == null) {
throw new ServiceException(ApiError.ERROR_90010002); // 用户不存在,抛出异常
}
// 被禁用
if(user.getState().equals(CommonState.ABNORMAL)){
throw new ServiceException(ApiError.ERROR_90010005);
// 检查用户是否被禁用
if (user.getState().equals(CommonState.ABNORMAL)) {
throw new ServiceException(ApiError.ERROR_90010005); // 用户被禁用,抛出异常
}
boolean check = PassHandler.checkPass(password,user.getSalt(), user.getPassword());
if(!check){
throw new ServiceException(ApiError.ERROR_90010002);
// 校验密码
boolean check = PassHandler.checkPass(password, user.getSalt(), user.getPassword());
if (!check) {
throw new ServiceException(ApiError.ERROR_90010002); // 密码不正确,抛出异常
}
// 设置 JWT token 并返回登录信息
return this.setToken(user);
}
@Override
public SysUserLoginDTO token(String token) {
public SysUserLoginDTO token(String token) { // 根据 token 获取用户会话信息
// 获得会话
// 获取 token 中的用户名
String username = JwtUtils.getUsername(token);
// 校验结果
// 校验 token 是否有效
boolean check = JwtUtils.verify(token, username);
if(!check){
throw new ServiceException(ApiError.ERROR_90010002);
if (!check) {
throw new ServiceException(ApiError.ERROR_90010002); // token 无效,抛出异常
}
// 查询用户信息
QueryWrapper<SysUser> wrapper = new QueryWrapper<>();
wrapper.lambda().eq(SysUser::getUserName, username);
SysUser user = this.getOne(wrapper, false);
if(user == null){
throw new ServiceException(ApiError.ERROR_10010002);
if (user == null) {
throw new ServiceException(ApiError.ERROR_10010002); // 用户不存在,抛出异常
}
// 被禁用
if(user.getState().equals(CommonState.ABNORMAL)){
throw new ServiceException(ApiError.ERROR_90010005);
// 检查用户是否被禁用
if (user.getState().equals(CommonState.ABNORMAL)) {
throw new ServiceException(ApiError.ERROR_90010005); // 用户被禁用,抛出异常
}
// 设置 JWT token 并返回登录信息
return this.setToken(user);
}
@Override
public void logout(String token) {
public void logout(String token) { // 用户登出方法
// 退出当前会话
// 退出当前会话
SecurityUtils.getSubject().logout();
}
@Override
public void update(SysUserDTO reqDTO) {
String pass = reqDTO.getPassword();
if(!StringUtils.isBlank(pass)){
PassInfo passInfo = PassHandler.buildPassword(pass);
SysUser user = this.getById(UserUtils.getUserId());
user.setPassword(passInfo.getPassword());
user.setSalt(passInfo.getSalt());
this.updateById(user);
}
public void update(SysUserDTO reqDTO) { // 更新用户信息
String pass = reqDTO.getPassword();
if (!StringUtils.isBlank(pass)) {
// 如果提供了新密码,则更新密码
PassInfo passInfo = PassHandler.buildPassword(pass);
SysUser user = this.getById(UserUtils.getUserId());
user.setPassword(passInfo.getPassword());
user.setSalt(passInfo.getSalt());
this.updateById(user); // 更新用户数据
}
}
@Transactional(rollbackFor = Exception.class)
@Transactional(rollbackFor = Exception.class) // 启用事务管理,保证数据一致性
@Override
public void save(SysUserSaveReqDTO reqDTO) {
public void save(SysUserSaveReqDTO reqDTO) { // 保存或修改用户信息
List<String> roles = reqDTO.getRoles();
if(CollectionUtils.isEmpty(roles)){
throw new ServiceException(ApiError.ERROR_90010003);
if (CollectionUtils.isEmpty(roles)) {
throw new ServiceException(ApiError.ERROR_90010003); // 角色列表不能为空,抛出异常
}
// 保存基本信息
SysUser user = new SysUser();
BeanMapper.copy(reqDTO, user);
// 添加模式
if(StringUtils.isBlank(user.getId())){
// 添加模式,生成新的 ID
if (StringUtils.isBlank(user.getId())) {
user.setId(IdWorker.getIdStr());
}
// 修改密码
if(!StringUtils.isBlank(reqDTO.getPassword())){
// 如果提供了密码,则加密并保存
if (!StringUtils.isBlank(reqDTO.getPassword())) {
PassInfo pass = PassHandler.buildPassword(reqDTO.getPassword());
user.setPassword(pass.getPassword());
user.setSalt(pass.getSalt());
@ -179,23 +188,23 @@ public class SysUserServiceImpl extends ServiceImpl<SysUserMapper, SysUser> impl
// 保存角色信息
String roleIds = sysUserRoleService.saveRoles(user.getId(), roles);
user.setRoleIds(roleIds);
this.saveOrUpdate(user);
this.saveOrUpdate(user); // 保存或更新用户信息
}
@Transactional(rollbackFor = Exception.class)
@Transactional(rollbackFor = Exception.class) // 启用事务管理
@Override
public SysUserLoginDTO reg(SysUserDTO reqDTO) {
public SysUserLoginDTO reg(SysUserDTO reqDTO) { // 用户注册方法
QueryWrapper<SysUser> wrapper = new QueryWrapper<>();
wrapper.lambda().eq(SysUser::getUserName, reqDTO.getUserName());
int count = this.count(wrapper);
if(count > 0){
throw new ServiceException(1, "用户名已存在,换一个吧!");
if (count > 0) {
throw new ServiceException(1, "用户名已存在,换一个吧!"); // 用户名已存在,抛出异常
}
// 保存用户
SysUser user = new SysUser();
user.setId(IdWorker.getIdStr());
@ -212,21 +221,22 @@ public class SysUserServiceImpl extends ServiceImpl<SysUserMapper, SysUser> impl
user.setRoleIds(roleIds);
this.save(user);
// 返回生成的 token
return this.setToken(user);
}
@Override
public SysUserLoginDTO quickReg(SysUserDTO reqDTO) {
public SysUserLoginDTO quickReg(SysUserDTO reqDTO) { // 快速注册方法
QueryWrapper<SysUser> wrapper = new QueryWrapper<>();
wrapper.lambda().eq(SysUser::getUserName, reqDTO.getUserName());
wrapper.last(" LIMIT 1 ");
SysUser user = this.getOne(wrapper);
if(user!=null){
return this.setToken(user);
if (user != null) {
return this.setToken(user); // 如果用户已存在,直接返回登录信息
}
return this.reg(reqDTO);
return this.reg(reqDTO); // 如果用户不存在,进行注册
}
@ -235,16 +245,16 @@ public class SysUserServiceImpl extends ServiceImpl<SysUserMapper, SysUser> impl
* @param user
* @return
*/
private SysUserLoginDTO setToken(SysUser user){
private SysUserLoginDTO setToken(SysUser user) { // 生成并设置用户的 JWT token
SysUserLoginDTO respDTO = new SysUserLoginDTO();
BeanMapper.copy(user, respDTO);
// 生成Token
// 生成 JWT token
String token = JwtUtils.sign(user.getUserName());
respDTO.setToken(token);
// 填充角色
// 填充角色信息
List<String> roles = sysUserRoleService.listRoles(user.getId());
respDTO.setRoles(roles);

@ -1,56 +1,56 @@
package com.yf.exam.modules.user;
package com.yf.exam.modules.user; // 包名:表示该类属于 user 包
import com.yf.exam.core.api.ApiError;
import com.yf.exam.core.exception.ServiceException;
import com.yf.exam.modules.sys.user.dto.response.SysUserLoginDTO;
import org.apache.shiro.SecurityUtils;
import com.yf.exam.core.api.ApiError; // 导入 ApiError 类,定义 API 错误码
import com.yf.exam.core.exception.ServiceException; // 导入 ServiceException 类,定义自定义服务异常
import com.yf.exam.modules.sys.user.dto.response.SysUserLoginDTO; // 导入用户登录响应 DTO 类
import org.apache.shiro.SecurityUtils; // 导入 Shiro 的 SecurityUtils 类,用于获取当前登录用户的信息
/**
*
* @author bool
*
* @ bool
*/
public class UserUtils {
/**
* ID
* @param throwable
* @return
* @param throwable
* @return ID
*/
public static String getUserId(boolean throwable){
public static String getUserId(boolean throwable) { // 获取当前登录用户 ID 的方法
try {
// 使用 Shiro 获取当前用户的主体对象,然后从中提取用户 ID
return ((SysUserLoginDTO) SecurityUtils.getSubject().getPrincipal()).getId();
}catch (Exception e){
if(throwable){
throw new ServiceException(ApiError.ERROR_10010002);
} catch (Exception e) { // 捕获异常
if (throwable) { // 如果 throwable 为 true则抛出自定义服务异常
throw new ServiceException(ApiError.ERROR_10010002); // 异常码10010002
}
return null;
return null; // 如果发生异常且 throwable 为 false则返回 null
}
}
/**
* ID
* @param throwable
* @return
* @param throwable
* @return ID
*/
public static boolean isAdmin(boolean throwable){
public static boolean isAdmin(boolean throwable) { // 判断当前用户是否为管理员的方法
try {
SysUserLoginDTO dto = ((SysUserLoginDTO) SecurityUtils.getSubject().getPrincipal());
return dto.getRoles().contains("sa");
}catch (Exception e){
if(throwable){
throw new ServiceException(ApiError.ERROR_10010002);
SysUserLoginDTO dto = ((SysUserLoginDTO) SecurityUtils.getSubject().getPrincipal()); // 获取当前用户的登录信息
return dto.getRoles().contains("sa"); // 判断用户角色中是否包含管理员角色 "sa"
} catch (Exception e) { // 捕获异常
if (throwable) { // 如果 throwable 为 true则抛出自定义服务异常
throw new ServiceException(ApiError.ERROR_10010002); // 异常码10010002
}
}
return false;
return false; // 如果发生异常且 throwable 为 false则返回 false
}
/**
* ID
* @return
* @return ID
*/
public static String getUserId(){
return getUserId(true);
public static String getUserId() { // 默认抛出异常的获取用户 ID 方法
return getUserId(true); // 调用带有 throwable 参数的方法,默认抛出异常
}
}

@ -1,76 +1,79 @@
package com.yf.exam.modules.user.book.controller;
package com.yf.exam.modules.user.book.controller; // 包名:表示该类属于 user.book.controller 包
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.yf.exam.core.api.ApiRest;
import com.yf.exam.core.api.controller.BaseController;
import com.yf.exam.core.api.dto.BaseIdRespDTO;
import com.yf.exam.core.api.dto.BaseIdsReqDTO;
import com.yf.exam.core.api.dto.PagingReqDTO;
import com.yf.exam.modules.user.book.dto.UserBookDTO;
import com.yf.exam.modules.user.book.service.UserBookService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;
import com.baomidou.mybatisplus.core.metadata.IPage; // 导入 MyBatis-Plus 分页接口
import com.yf.exam.core.api.ApiRest; // 导入 ApiRest 类,定义接口返回的统一格式
import com.yf.exam.core.api.controller.BaseController; // 导入 BaseController 基础控制器类,提供一些基础功能
import com.yf.exam.core.api.dto.BaseIdRespDTO; // 导入 BaseIdRespDTO 数据传输对象,用于返回 ID 响应
import com.yf.exam.core.api.dto.BaseIdsReqDTO; // 导入 BaseIdsReqDTO 数据传输对象,用于接收 ID 列表请求
import com.yf.exam.core.api.dto.PagingReqDTO; // 导入 PagingReqDTO 数据传输对象,用于分页请求
import com.yf.exam.modules.user.book.dto.UserBookDTO; // 导入 UserBookDTO 数据传输对象,用于封装错题本数据
import com.yf.exam.modules.user.book.service.UserBookService; // 导入 UserBookService 服务接口,用于处理业务逻辑
import io.swagger.annotations.Api; // 导入 Swagger 的 Api 注解,用于生成 API 文档
import io.swagger.annotations.ApiOperation; // 导入 Swagger 的 ApiOperation 注解,用于描述 API 操作
import org.springframework.beans.factory.annotation.Autowired; // 导入 Autowired 注解,用于自动注入依赖
import org.springframework.web.bind.annotation.RequestBody; // 导入 RequestBody 注解,用于接收请求体数据
import org.springframework.web.bind.annotation.RequestMapping; // 导入 RequestMapping 注解,用于映射请求路径
import org.springframework.web.bind.annotation.RequestMethod; // 导入 RequestMethod 枚举,表示请求方法类型
import org.springframework.web.bind.annotation.RestController; // 导入 RestController 注解,表示这是一个控制器类
/**
* <p>
*
* </p>
*
* @author
* @since 2020-05-27 17:56
*/
@Api(tags={"错题本"})
@RestController
@RequestMapping("/exam/api/user/wrong-book")
public class UserBookController extends BaseController {
* <p>
*
* </p>
* API
*
* @
* @ 2020-05-27 17:56
*/
@Api(tags={"错题本"}) // 为这个控制器定义一个标签,用于生成 API 文档
@RestController // 标识该类为 Spring 的控制器类,自动注入到 Spring 上下文
@RequestMapping("/exam/api/user/wrong-book") // 设置该类的请求路径前缀
public class UserBookController extends BaseController { // 继承自 BaseController享受基础功能
@Autowired
private UserBookService baseService;
private UserBookService baseService; // 注入 UserBookService用于处理错题本的相关逻辑
/**
*
* @param reqDTO
* @return
*/
@ApiOperation(value = "批量删除")
@RequestMapping(value = "/delete", method = { RequestMethod.POST})
public ApiRest delete(@RequestBody BaseIdsReqDTO reqDTO) {
//根据ID删除
*
* @param reqDTO ID
* @return
*/
@ApiOperation(value = "批量删除") // 为该方法生成 Swagger 的文档描述
@RequestMapping(value = "/delete", method = { RequestMethod.POST }) // 映射 POST 请求路径 "/delete"
public ApiRest delete(@RequestBody BaseIdsReqDTO reqDTO) { // 接收请求体中的 ID 列表
// 根据 ID 删除错题本数据
baseService.removeByIds(reqDTO.getIds());
return super.success();
return super.success(); // 返回成功的响应
}
/**
*
* @param reqDTO
* @return
*/
@ApiOperation(value = "分页查找")
@RequestMapping(value = "/paging", method = { RequestMethod.POST})
public ApiRest<IPage<UserBookDTO>> paging(@RequestBody PagingReqDTO<UserBookDTO> reqDTO) {
*
* @param reqDTO
* @return
*/
@ApiOperation(value = "分页查找") // 为该方法生成 Swagger 的文档描述
@RequestMapping(value = "/paging", method = { RequestMethod.POST }) // 映射 POST 请求路径 "/paging"
public ApiRest<IPage<UserBookDTO>> paging(@RequestBody PagingReqDTO<UserBookDTO> reqDTO) { // 接收分页请求数据
//分页查询并转换
// 调用服务层的分页查询方法
IPage<UserBookDTO> page = baseService.paging(reqDTO);
return super.success(page);
return super.success(page); // 返回分页查询的结果
}
/**
* 200
* @param reqDTO
* @return
* @param reqDTO ID ID
* @return ID
*/
@ApiOperation(value = "查找列表")
@RequestMapping(value = "/next", method = { RequestMethod.POST})
public ApiRest<BaseIdRespDTO> nextQu(@RequestBody UserBookDTO reqDTO) {
//转换并返回
@ApiOperation(value = "查找列表") // 为该方法生成 Swagger 的文档描述
@RequestMapping(value = "/next", method = { RequestMethod.POST }) // 映射 POST 请求路径 "/next"
public ApiRest<BaseIdRespDTO> nextQu(@RequestBody UserBookDTO reqDTO) { // 接收包含考试 ID 和题目 ID 的请求数据
// 调用服务层的 findNext 方法查找下一题
String quId = baseService.findNext(reqDTO.getExamId(), reqDTO.getQuId());
return super.success(new BaseIdRespDTO(quId));
return super.success(new BaseIdRespDTO(quId)); // 返回下一题的 ID
}
}

@ -1,52 +1,51 @@
package com.yf.exam.modules.user.book.dto;
package com.yf.exam.modules.user.book.dto; // 包名:表示该类属于 user.book.dto 包
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import io.swagger.annotations.ApiModel; // 导入 Swagger 的 ApiModel 注解,用于生成 API 文档中的模型描述
import io.swagger.annotations.ApiModelProperty; // 导入 Swagger 的 ApiModelProperty 注解,用于描述模型的属性
import lombok.Data; // 导入 Lombok 的 Data 注解,自动生成 getters、setters、toString 等方法
import java.io.Serializable;
import java.util.Date;
import java.io.Serializable; // 导入 Serializable 接口,用于对象序列化
import java.util.Date; // 导入 Date 类,用于处理日期数据
/**
* <p>
*
* </p>
*
* @author
* @since 2020-05-27 17:56
*/
@Data
@ApiModel(value="错题本", description="错题本")
public class UserBookDTO implements Serializable {
* <p>
*
* </p>
*
*
* @
* @ 2020-05-27 17:56
*/
@Data // Lombok 注解,自动生成常用的 getter、setter、toString、equals 和 hashCode 方法
@ApiModel(value="错题本", description="错题本") // Swagger 注解,定义该类用于描述错题本
public class UserBookDTO implements Serializable { // 实现 Serializable 接口,支持对象序列化
private static final long serialVersionUID = 1L;
private static final long serialVersionUID = 1L; // 定义序列化版本 UID
@ApiModelProperty(value = "ID", required=true) // Swagger 注解,描述属性的含义和是否必填
private String id; // 错题本 ID
@ApiModelProperty(value = "ID", required=true)
private String id;
@ApiModelProperty(value = "考试ID", required=true) // Swagger 注解,描述考试 ID
private String examId; // 关联的考试 ID
@ApiModelProperty(value = "考试ID", required=true)
private String examId;
@ApiModelProperty(value = "用户ID", required=true) // Swagger 注解,描述用户 ID
private String userId; // 关联的用户 ID
@ApiModelProperty(value = "用户ID", required=true)
private String userId;
@ApiModelProperty(value = "题目ID", required=true) // Swagger 注解,描述题目 ID
private String quId; // 关联的题目 ID
@ApiModelProperty(value = "题目ID", required=true)
private String quId;
@ApiModelProperty(value = "加入时间", required=true) // Swagger 注解,描述错题本的加入时间
private Date createTime; // 错题本加入时间
@ApiModelProperty(value = "加入时间", required=true)
private Date createTime;
@ApiModelProperty(value = "最近错误时间", required=true) // Swagger 注解,描述最近一次错误的时间
private Date updateTime; // 最近一次错题的时间
@ApiModelProperty(value = "最近错误时间", required=true)
private Date updateTime;
@ApiModelProperty(value = "错误次数", required=true) // Swagger 注解,描述错题的错误次数
private Integer wrongCount; // 错题的错误次数
@ApiModelProperty(value = "错误时间", required=true)
private Integer wrongCount;
@ApiModelProperty(value = "题目标题", required=true) // Swagger 注解,描述题目标题
private String title; // 题目的标题
@ApiModelProperty(value = "题目标题", required=true)
private String title;
@ApiModelProperty(value = "错题序号", required=true)
private Integer sort;
}
@ApiModelProperty(value = "错题序号", required=true) // Swagger 注解,描述错题的序号
private Integer sort; // 错题的序号,用于排序
}

@ -1,78 +1,78 @@
package com.yf.exam.modules.user.book.entity;
package com.yf.exam.modules.user.book.entity; // 包名:表示该类属于 user.book.entity 包
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import com.baomidou.mybatisplus.extension.activerecord.Model;
import lombok.Data;
import com.baomidou.mybatisplus.annotation.IdType; // 导入 MyBatis-Plus 的 IdType用于设置 ID 类型
import com.baomidou.mybatisplus.annotation.TableField; // 导入 TableField 注解,用于标识表字段
import com.baomidou.mybatisplus.annotation.TableId; // 导入 TableId 注解,用于标识表的主键
import com.baomidou.mybatisplus.annotation.TableName; // 导入 TableName 注解,用于标识表名
import com.baomidou.mybatisplus.extension.activerecord.Model; // 导入 Model 类,用于支持 Active Record 模式
import lombok.Data; // 导入 Lombok 的 Data 注解,自动生成 getter、setter、toString 等方法
import java.util.Date;
import java.util.Date; // 导入 Date 类,用于处理日期类型数据
/**
* <p>
*
* </p>
*
* @author
* @since 2020-05-27 17:56
*/
@Data
@TableName("el_user_book")
public class UserBook extends Model<UserBook> {
* <p>
*
* </p>
*
*
* @
* @ 2020-05-27 17:56
*/
@Data // Lombok 注解,自动为类生成 getter、setter、toString、equals 和 hashCode 方法
@TableName("el_user_book") // 表示该类对应数据库中的 el_user_book 表
public class UserBook extends Model<UserBook> { // 继承自 MyBatis-Plus 的 Model 类,支持 Active Record 模式
private static final long serialVersionUID = 1L;
private static final long serialVersionUID = 1L; // 序列化版本 UID
/**
* ID
*/
@TableId(value = "id", type = IdType.ASSIGN_ID)
private String id;
@TableId(value = "id", type = IdType.ASSIGN_ID) // 设置表的主键 ID 类型为 ASSIGN_ID表示数据库自增长
private String id; // 错题本记录的 ID
/**
* ID
*/
@TableField("exam_id")
private String examId;
@TableField("exam_id") // 映射数据库表的 exam_id 字段
private String examId; // 关联的考试 ID
/**
* ID
*/
@TableField("user_id")
private String userId;
@TableField("user_id") // 映射数据库表的 user_id 字段
private String userId; // 关联的用户 ID
/**
* ID
*/
@TableField("qu_id")
private String quId;
@TableField("qu_id") // 映射数据库表的 qu_id 字段
private String quId; // 关联的题目 ID
/**
*
*/
@TableField("create_time")
private Date createTime;
@TableField("create_time") // 映射数据库表的 create_time 字段
private Date createTime; // 错题加入时间
/**
*
*/
@TableField("update_time")
private Date updateTime;
@TableField("update_time") // 映射数据库表的 update_time 字段
private Date updateTime; // 最近一次错误的时间
/**
*
*/
@TableField("wrong_count")
private Integer wrongCount;
@TableField("wrong_count") // 映射数据库表的 wrong_count 字段
private Integer wrongCount; // 错误的次数
/**
*
*/
private String title;
private String title; // 题目的标题
/**
*
*/
private Integer sort;
private Integer sort; // 错题的序号,用于排序
}

@ -1,16 +1,17 @@
package com.yf.exam.modules.user.book.mapper;
package com.yf.exam.modules.user.book.mapper; // 包名:表示该接口属于 user.book.mapper 包
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.yf.exam.modules.user.book.entity.UserBook;
import com.baomidou.mybatisplus.core.mapper.BaseMapper; // 导入 MyBatis-Plus 的 BaseMapper 接口,提供基本的 CRUD 操作
import com.yf.exam.modules.user.book.entity.UserBook; // 导入 UserBook 实体类,表示错题本数据
/**
* <p>
* Mapper
* </p>
*
* @author
* @since 2020-05-27 17:56
*/
public interface UserBookMapper extends BaseMapper<UserBook> {
* <p>
* Mapper
* </p>
* MyBatis-Plus BaseMapper
*
* @
* @ 2020-05-27 17:56
*/
public interface UserBookMapper extends BaseMapper<UserBook> { // 继承 MyBatis-Plus 的 BaseMapper 接口,自动具备对 UserBook 实体的基本 CRUD 操作
}

@ -1,40 +1,41 @@
package com.yf.exam.modules.user.book.service;
package com.yf.exam.modules.user.book.service; // 包名:表示该接口属于 user.book.service 包
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.service.IService;
import com.yf.exam.core.api.dto.PagingReqDTO;
import com.yf.exam.modules.user.book.dto.UserBookDTO;
import com.yf.exam.modules.user.book.entity.UserBook;
import com.baomidou.mybatisplus.core.metadata.IPage; // 导入 MyBatis-Plus 的 IPage 接口,用于分页查询
import com.baomidou.mybatisplus.extension.service.IService; // 导入 MyBatis-Plus 的 IService 接口,提供常用的 CRUD 操作
import com.yf.exam.core.api.dto.PagingReqDTO; // 导入分页请求数据传输对象
import com.yf.exam.modules.user.book.dto.UserBookDTO; // 导入错题本 DTO 类,用于封装错题本的数据
import com.yf.exam.modules.user.book.entity.UserBook; // 导入错题本实体类,映射数据库中的错题本表
/**
* <p>
*
* </p>
*
* @author
* @since 2020-05-27 17:56
*/
public interface UserBookService extends IService<UserBook> {
* <p>
*
* </p>
*
*
* @
* @ 2020-05-27 17:56
*/
public interface UserBookService extends IService<UserBook> { // 继承 MyBatis-Plus 的 IService 接口,提供基本的 CRUD 操作
/**
*
* @param reqDTO
* @return
*/
IPage<UserBookDTO> paging(PagingReqDTO<UserBookDTO> reqDTO);
*
* @param reqDTO
* @return
*/
IPage<UserBookDTO> paging(PagingReqDTO<UserBookDTO> reqDTO); // 分页查询错题本数据
/**
*
* @param quId
* @param examId
*
* @param examId ID
* @param quId ID
*/
void addBook(String examId, String quId);
void addBook(String examId, String quId); // 将指定的错题添加到错题本
/**
*
* @param quId
* @param examId
* @return
*
* @param quId ID
* @param examId ID
* @return ID
*/
String findNext(String examId, String quId);
String findNext(String examId, String quId); // 查找下一个错题 ID
}

@ -1,155 +1,153 @@
package com.yf.exam.modules.user.book.service.impl;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.TypeReference;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.yf.exam.core.api.dto.PagingReqDTO;
import com.yf.exam.modules.qu.entity.Qu;
import com.yf.exam.modules.qu.service.QuService;
import com.yf.exam.modules.user.UserUtils;
import com.yf.exam.modules.user.book.dto.UserBookDTO;
import com.yf.exam.modules.user.book.entity.UserBook;
import com.yf.exam.modules.user.book.mapper.UserBookMapper;
import com.yf.exam.modules.user.book.service.UserBookService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;
package com.yf.exam.modules.user.book.service.impl; // 包名:表示该类属于 user.book.service.impl 包
import com.alibaba.fastjson.JSON; // 导入 fastjson用于将对象转换为 JSON 字符串
import com.alibaba.fastjson.TypeReference; // 导入 TypeReference 用于反序列化复杂类型
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; // 导入 MyBatis-Plus 的 QueryWrapper 类,用于构建查询条件
import com.baomidou.mybatisplus.core.metadata.IPage; // 导入 MyBatis-Plus 的 IPage 接口,用于分页查询
import com.baomidou.mybatisplus.extension.plugins.pagination.Page; // 导入 MyBatis-Plus 的分页插件
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; // 导入 MyBatis-Plus 的 ServiceImpl 基类
import com.yf.exam.core.api.dto.PagingReqDTO; // 导入分页请求的 DTO 类
import com.yf.exam.modules.qu.entity.Qu; // 导入题目实体类
import com.yf.exam.modules.qu.service.QuService; // 导入题目服务接口
import com.yf.exam.modules.user.UserUtils; // 导入用户工具类,用于获取当前用户信息
import com.yf.exam.modules.user.book.dto.UserBookDTO; // 导入错题本 DTO
import com.yf.exam.modules.user.book.entity.UserBook; // 导入错题本实体类
import com.yf.exam.modules.user.book.mapper.UserBookMapper; // 导入错题本 Mapper 类
import com.yf.exam.modules.user.book.service.UserBookService; // 导入错题本服务接口
import org.springframework.beans.factory.annotation.Autowired; // 导入 Autowired 注解,用于自动注入依赖
import org.springframework.stereotype.Service; // 导入 Service 注解,标识该类为 Spring 服务层组件
import org.springframework.util.StringUtils; // 导入 StringUtils 工具类,用于字符串操作
/**
* <p>
*
* </p>
*
* @author
* @since 2020-05-27 17:56
*/
@Service
public class UserBookServiceImpl extends ServiceImpl<UserBookMapper, UserBook> implements UserBookService {
* <p>
*
* </p>
*
*
* @
* @ 2020-05-27 17:56
*/
@Service // 标识该类为 Spring 的服务类
public class UserBookServiceImpl extends ServiceImpl<UserBookMapper, UserBook> implements UserBookService { // 继承 MyBatis-Plus 的 ServiceImpl实现 UserBookService 接口
@Autowired
private QuService quService;
private QuService quService; // 注入题目服务,用于获取题目内容
@Override
public IPage<UserBookDTO> paging(PagingReqDTO<UserBookDTO> reqDTO) {
public IPage<UserBookDTO> paging(PagingReqDTO<UserBookDTO> reqDTO) { // 分页查询错题本数据
//创建分页对象
// 创建分页对象
Page query = new Page<>(reqDTO.getCurrent(), reqDTO.getSize());
//查询条件
// 查询条件
QueryWrapper<UserBook> wrapper = new QueryWrapper<>();
// 查找用户的错题
wrapper.lambda().eq(UserBook::getUserId, UserUtils.getUserId(true));
UserBookDTO params = reqDTO.getParams();
if(params!=null){
if(!StringUtils.isEmpty(params.getTitle())){
if(params != null) {
// 根据题目标题查询
if(!StringUtils.isEmpty(params.getTitle())) {
wrapper.lambda().like(UserBook::getTitle, params.getTitle());
}
if(!StringUtils.isEmpty(params.getExamId())){
// 根据考试 ID 查询
if(!StringUtils.isEmpty(params.getExamId())) {
wrapper.lambda().eq(UserBook::getExamId, params.getExamId());
}
}
//获得数据
// 执行分页查询
IPage<UserBook> page = this.page(query, wrapper);
//转换结果
IPage<UserBookDTO> pageData = JSON.parseObject(JSON.toJSONString(page), new TypeReference<Page<UserBookDTO>>(){});
// 转换结果为 DTO
IPage<UserBookDTO> pageData = JSON.parseObject(JSON.toJSONString(page), new TypeReference<Page<UserBookDTO>>() {});
return pageData;
}
}
@Override
public void addBook(String examId, String quId) {
public void addBook(String examId, String quId) { // 添加错题到错题本
QueryWrapper<UserBook> wrapper = new QueryWrapper<>();
wrapper.lambda()
.eq(UserBook::getUserId, UserUtils.getUserId())
.eq(UserBook::getExamId, examId)
.eq(UserBook::getQuId, quId);
.eq(UserBook::getUserId, UserUtils.getUserId()) // 查找当前用户的错题
.eq(UserBook::getExamId, examId) // 查找特定考试的错题
.eq(UserBook::getQuId, quId); // 查找特定题目的错题
//查找已有的错题信息
// 查找已有的错题信息
UserBook book = this.getOne(wrapper, false);
// 问题
// 获取题目信息
Qu qu = quService.getById(quId);
if (book == null) {
if (book == null) { // 如果错题本中没有该题目,则添加
book = new UserBook();
book.setExamId(examId);
book.setUserId(UserUtils.getUserId());
book.setTitle(qu.getContent());
book.setUserId(UserUtils.getUserId()); // 设置当前用户的 ID
book.setTitle(qu.getContent()); // 设置题目内容
book.setQuId(quId);
book.setWrongCount(1);
Integer maxSort = this.findMaxSort(examId, UserUtils.getUserId());
book.setSort(maxSort+1);
this.save(book);
} else {
book.setWrongCount(book.getWrongCount()+1);
this.updateById(book);
book.setWrongCount(1); // 错误次数初始化为 1
Integer maxSort = this.findMaxSort(examId, UserUtils.getUserId()); // 查找当前用户的最大排序号
book.setSort(maxSort + 1); // 设置错题的排序号
this.save(book); // 保存错题记录
} else { // 如果错题本中已有该题目,则更新错误次数
book.setWrongCount(book.getWrongCount() + 1); // 错误次数加 1
this.updateById(book); // 更新错题记录
}
}
@Override
public String findNext(String examId, String quId) {
public String findNext(String examId, String quId) { // 查找下一个错题
Integer sort = 999999;
if(!StringUtils.isEmpty(quId)){
if(!StringUtils.isEmpty(quId)) {
QueryWrapper<UserBook> wrapper = new QueryWrapper<>();
wrapper.lambda()
.eq(UserBook::getUserId, UserUtils.getUserId())
.eq(UserBook::getExamId, examId)
.eq(UserBook::getQuId, quId);
wrapper.last(" ORDER BY `sort` DESC");
.eq(UserBook::getUserId, UserUtils.getUserId()) // 查找当前用户的错题
.eq(UserBook::getExamId, examId) // 查找特定考试的错题
.eq(UserBook::getQuId, quId); // 查找特定题目的错题
wrapper.last(" ORDER BY `sort` DESC"); // 按照排序降序排列
UserBook last = this.getOne(wrapper, false);
if(last!=null){
sort = last.getSort();
if(last != null) {
sort = last.getSort(); // 获取当前错题的排序号
}
}
QueryWrapper<UserBook> wrapper = new QueryWrapper<>();
wrapper.lambda()
.eq(UserBook::getUserId, UserUtils.getUserId())
.eq(UserBook::getExamId, examId)
.lt(UserBook::getSort, sort);
wrapper.last(" ORDER BY `sort` DESC");
UserBook next = this.getOne(wrapper, false);
if(next != null){
return next.getQuId();
.eq(UserBook::getUserId, UserUtils.getUserId()) // 查找当前用户的错题
.eq(UserBook::getExamId, examId) // 查找特定考试的错题
.lt(UserBook::getSort, sort); // 查找排序号小于当前错题的错题
wrapper.last(" ORDER BY `sort` DESC"); // 按照排序降序排列
UserBook next = this.getOne(wrapper, false); // 查找下一个错题
if(next != null) {
return next.getQuId(); // 返回下一个错题的 ID
}
return null;
return null; // 如果没有下一个错题,返回 null
}
/**
*
* @param userId
* @return
* @param examId ID
* @param userId ID
* @return
*/
private Integer findMaxSort(String examId, String userId){
private Integer findMaxSort(String examId, String userId) { // 查找当前用户在某个考试中的最大排序号
QueryWrapper<UserBook> wrapper = new QueryWrapper<>();
wrapper.lambda()
.eq(UserBook::getExamId, examId)
.eq(UserBook::getUserId, userId);
wrapper.last(" ORDER BY `sort` DESC");
.eq(UserBook::getExamId, examId) // 查找特定考试的错题
.eq(UserBook::getUserId, userId); // 查找当前用户的错题
wrapper.last(" ORDER BY `sort` DESC"); // 按照排序号降序排列
UserBook book = this.getOne(wrapper, false);
if(book == null){
return 0;
UserBook book = this.getOne(wrapper, false); // 获取最大排序号的错题
if(book == null) {
return 0; // 如果没有错题,返回 0
}
return book.getSort();
return book.getSort(); // 返回最大排序号
}
}

@ -1,65 +1,64 @@
package com.yf.exam.modules.user.exam.controller;
package com.yf.exam.modules.user.exam.controller; // 包名:表示该类属于 user.exam.controller 包
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.yf.exam.core.api.ApiRest;
import com.yf.exam.core.api.controller.BaseController;
import com.yf.exam.core.api.dto.PagingReqDTO;
import com.yf.exam.modules.user.exam.dto.request.UserExamReqDTO;
import com.yf.exam.modules.user.exam.dto.response.UserExamRespDTO;
import com.yf.exam.modules.user.exam.service.UserExamService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;
import com.baomidou.mybatisplus.core.metadata.IPage; // 导入 MyBatis-Plus 的 IPage 接口,用于分页查询
import com.yf.exam.core.api.ApiRest; // 导入 API 响应封装类,用于统一返回格式
import com.yf.exam.core.api.controller.BaseController; // 导入基础控制器类,提供通用的接口方法
import com.yf.exam.core.api.dto.PagingReqDTO; // 导入分页请求 DTO 类,用于封装分页参数
import com.yf.exam.modules.user.exam.dto.request.UserExamReqDTO; // 导入用户考试请求 DTO 类,用于封装考试查询参数
import com.yf.exam.modules.user.exam.dto.response.UserExamRespDTO; // 导入用户考试响应 DTO 类,用于封装查询结果
import com.yf.exam.modules.user.exam.service.UserExamService; // 导入用户考试服务接口,用于处理考试相关的业务逻辑
import io.swagger.annotations.Api; // 导入 Swagger 注解,用于生成 API 文档中的标签
import io.swagger.annotations.ApiOperation; // 导入 Swagger 注解,用于描述接口方法
import org.springframework.beans.factory.annotation.Autowired; // 导入 Autowired 注解,用于自动注入依赖
import org.springframework.web.bind.annotation.RequestBody; // 导入 RequestBody 注解,用于绑定请求体参数
import org.springframework.web.bind.annotation.RequestMapping; // 导入 RequestMapping 注解,用于映射请求路径
import org.springframework.web.bind.annotation.RequestMethod; // 导入 RequestMethod 枚举,用于指定请求方法类型
import org.springframework.web.bind.annotation.RestController; // 导入 RestController 注解,标识该类为 RESTful 风格的控制器
/**
* <p>
*
* </p>
*
* @author
* @since 2020-09-21 15:13
*/
@Api(tags={"考试记录"})
@RestController
@RequestMapping("/exam/api/user/exam")
public class UserExamController extends BaseController {
* <p>
*
* </p>
*
*
* @
* @ 2020-09-21 15:13
*/
@Api(tags={"考试记录"}) // Swagger 注解,定义该类在 API 文档中的标签
@RestController // 标识该类为 RESTful 风格的控制器
@RequestMapping("/exam/api/user/exam") // 映射请求路径,所有接口都以 "/exam/api/user/exam" 开头
public class UserExamController extends BaseController { // 继承 BaseController提供基础的响应方法
@Autowired
private UserExamService baseService;
private UserExamService baseService; // 自动注入 UserExamService 服务,处理考试记录相关业务
/**
*
* @param reqDTO
* @return
*
* @param reqDTO
* @return
*/
@ApiOperation(value = "分页查找")
@RequestMapping(value = "/paging", method = { RequestMethod.POST})
public ApiRest<IPage<UserExamRespDTO>> paging(@RequestBody PagingReqDTO<UserExamReqDTO> reqDTO) {
@ApiOperation(value = "分页查找") // Swagger 注解,描述接口方法的作用
@RequestMapping(value = "/paging", method = { RequestMethod.POST}) // 映射 POST 请求路径 "/exam/api/user/exam/paging"
public ApiRest<IPage<UserExamRespDTO>> paging(@RequestBody PagingReqDTO<UserExamReqDTO> reqDTO) { // 接收分页请求,返回分页结果
//分页查询并转换
// 调用服务层方法进行分页查询将结果转换为响应 DTO
IPage<UserExamRespDTO> page = baseService.paging(reqDTO);
return super.success(page);
return super.success(page); // 调用父类的 success 方法返回查询结果
}
/**
*
* @param reqDTO
* @return
*/
@ApiOperation(value = "分页查找")
@RequestMapping(value = "/my-paging", method = { RequestMethod.POST})
public ApiRest<IPage<UserExamRespDTO>> myPaging(@RequestBody PagingReqDTO<UserExamReqDTO> reqDTO) {
*
* @param reqDTO
* @return
*/
@ApiOperation(value = "分页查找") // Swagger 注解,描述接口方法的作用
@RequestMapping(value = "/my-paging", method = { RequestMethod.POST}) // 映射 POST 请求路径 "/exam/api/user/exam/my-paging"
public ApiRest<IPage<UserExamRespDTO>> myPaging(@RequestBody PagingReqDTO<UserExamReqDTO> reqDTO) { // 接收分页请求,返回用户的分页考试记录
//分页查询并转换
// 调用服务层方法进行分页查询将结果转换为响应 DTO
IPage<UserExamRespDTO> page = baseService.myPaging(reqDTO);
return super.success(page);
return super.success(page); // 调用父类的 success 方法返回查询结果
}
}

@ -1,50 +1,72 @@
package com.yf.exam.modules.user.exam.dto;
package com.yf.exam.modules.user.exam.dto; // 包名:表示该类属于 user.exam.dto 包
import com.yf.exam.core.annon.Dict;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import java.util.Date;
import java.io.Serializable;
import com.yf.exam.core.annon.Dict; // 导入 Dict 注解,用于字段的字典数据转换
import io.swagger.annotations.ApiModel; // 导入 Swagger 注解,用于生成 API 文档中的描述
import io.swagger.annotations.ApiModelProperty; // 导入 Swagger 注解,用于描述类字段
import lombok.Data; // 导入 Lombok 的 Data 注解,用于自动生成 getter、setter 等方法
import java.util.Date; // 导入 Date 类,用于处理时间
import java.io.Serializable; // 导入 Serializable 接口,确保该类可以序列化
/**
* <p>
*
* </p>
*
* @author
* @since 2020-09-21 15:13
*/
@Data
@ApiModel(value="考试记录", description="考试记录")
public class UserExamDTO implements Serializable {
private static final long serialVersionUID = 1L;
private String id;
@ApiModelProperty(value = "用户ID", required=true)
private String userId;
@Dict(dictTable = "el_exam", dicText = "title", dicCode = "id")
@ApiModelProperty(value = "考试ID", required=true)
private String examId;
@ApiModelProperty(value = "考试次数", required=true)
private Integer tryCount;
@ApiModelProperty(value = "最高分数", required=true)
private Integer maxScore;
@ApiModelProperty(value = "是否通过", required=true)
private Boolean passed;
@ApiModelProperty(value = "创建时间")
private Date createTime;
@ApiModelProperty(value = "更新时间")
private Date updateTime;
* <p>
*
* </p>
*
*
* @
* @ 2020-09-21 15:13
*/
@Data // Lombok 注解,自动为类生成 getter、setter、toString 等方法
@ApiModel(value="考试记录", description="考试记录") // Swagger 注解,描述该类的作用,生成 API 文档时使用
public class UserExamDTO implements Serializable { // 实现 Serializable 接口,使该类可以序列化
private static final long serialVersionUID = 1L; // 序列化版本 UID
/**
* ID
*/
private String id; // 用户ID字段
/**
* ID
*/
@ApiModelProperty(value = "用户ID", required=true) // Swagger 注解,描述字段的作用,设置为必填项
private String userId; // 用户ID字段
/**
* ID
*/
@Dict(dictTable = "el_exam", dicText = "title", dicCode = "id") // 使用 Dict 注解,指定字典表及映射字段
@ApiModelProperty(value = "考试ID", required=true) // Swagger 注解,描述字段的作用,设置为必填项
private String examId; // 考试ID字段
/**
*
*/
@ApiModelProperty(value = "考试次数", required=true) // Swagger 注解,描述字段的作用,设置为必填项
private Integer tryCount; // 考试次数字段
/**
*
*/
@ApiModelProperty(value = "最高分数", required=true) // Swagger 注解,描述字段的作用,设置为必填项
private Integer maxScore; // 最高分数字段
/**
*
*/
@ApiModelProperty(value = "是否通过", required=true) // Swagger 注解,描述字段的作用,设置为必填项
private Boolean passed; // 是否通过字段
/**
*
*/
@ApiModelProperty(value = "创建时间") // Swagger 注解,描述字段的作用
private Date createTime; // 创建时间字段
/**
*
*/
@ApiModelProperty(value = "更新时间") // Swagger 注解,描述字段的作用
private Date updateTime; // 更新时间字段
}

@ -1,30 +1,34 @@
package com.yf.exam.modules.user.exam.dto.request;
package com.yf.exam.modules.user.exam.dto.request; // 包名:表示该类属于 user.exam.dto.request 包
import com.yf.exam.modules.user.exam.dto.UserExamDTO;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import com.yf.exam.modules.user.exam.dto.UserExamDTO; // 导入 UserExamDTO 类,作为父类,包含通用的考试记录信息
import io.swagger.annotations.ApiModel; // 导入 Swagger 注解,用于生成 API 文档中的描述
import io.swagger.annotations.ApiModelProperty; // 导入 Swagger 注解,用于描述类字段
import lombok.Data; // 导入 Lombok 的 Data 注解,用于自动生成 getter、setter 等方法
/**
* <p>
*
* </p>
*
* @author
* @since 2020-09-21 15:13
*/
@Data
@ApiModel(value="考试记录", description="考试记录")
public class UserExamReqDTO extends UserExamDTO {
private static final long serialVersionUID = 1L;
@ApiModelProperty(value = "考试名称", required=true)
private String title;
@ApiModelProperty(value = "人员名称", required=true)
private String realName;
* <p>
*
* </p>
*
*
* @
* @ 2020-09-21 15:13
*/
@Data // Lombok 注解,自动为类生成 getter、setter、toString 等方法
@ApiModel(value="考试记录", description="考试记录") // Swagger 注解,描述该类的作用,生成 API 文档时使用
public class UserExamReqDTO extends UserExamDTO { // 继承 UserExamDTO 类,扩展额外的请求字段
private static final long serialVersionUID = 1L; // 序列化版本 UID
/**
*
*/
@ApiModelProperty(value = "考试名称", required=true) // Swagger 注解,描述字段的作用,设置为必填项
private String title; // 考试名称字段
/**
*
*/
@ApiModelProperty(value = "人员名称", required=true) // Swagger 注解,描述字段的作用,设置为必填项
private String realName; // 人员名称字段
}

@ -1,29 +1,34 @@
package com.yf.exam.modules.user.exam.dto.response;
package com.yf.exam.modules.user.exam.dto.response; // 包名:表示该类属于 user.exam.dto.response 包
import com.yf.exam.modules.user.exam.dto.UserExamDTO;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import com.yf.exam.modules.user.exam.dto.UserExamDTO; // 导入 UserExamDTO 类,作为父类,包含通用的考试记录信息
import io.swagger.annotations.ApiModel; // 导入 Swagger 注解,用于生成 API 文档中的描述
import io.swagger.annotations.ApiModelProperty; // 导入 Swagger 注解,用于描述类字段
import lombok.Data; // 导入 Lombok 的 Data 注解,用于自动生成 getter、setter 等方法
/**
* <p>
*
* </p>
*
* @author
* @since 2020-09-21 15:13
*/
@Data
@ApiModel(value="考试记录", description="考试记录")
public class UserExamRespDTO extends UserExamDTO {
* <p>
*
* </p>
*
*
* @
* @ 2020-09-21 15:13
*/
@Data // Lombok 注解,自动为类生成 getter、setter、toString 等方法
@ApiModel(value="考试记录", description="考试记录") // Swagger 注解,描述该类的作用,生成 API 文档时使用
public class UserExamRespDTO extends UserExamDTO { // 继承 UserExamDTO 类,扩展额外的响应字段
private static final long serialVersionUID = 1L;
private static final long serialVersionUID = 1L; // 序列化版本 UID
/**
*
*/
@ApiModelProperty(value = "考试名称", required=true) // Swagger 注解,描述字段的作用,设置为必填项
private String title; // 考试名称字段
@ApiModelProperty(value = "考试名称", required=true)
private String title;
@ApiModelProperty(value = "人员名称", required=true)
private String realName;
/**
*
*/
@ApiModelProperty(value = "人员名称", required=true) // Swagger 注解,描述字段的作用,设置为必填项
private String realName; // 人员名称字段
}

@ -1,69 +1,72 @@
package com.yf.exam.modules.user.exam.entity;
package com.yf.exam.modules.user.exam.entity; // 包名:表示该类属于 user.exam.entity 包
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import com.baomidou.mybatisplus.extension.activerecord.Model;
import lombok.Data;
import java.util.Date;
import com.baomidou.mybatisplus.annotation.IdType; // 导入 MyBatis-Plus 注解,用于指定主键策略
import com.baomidou.mybatisplus.annotation.TableField; // 导入 MyBatis-Plus 注解,用于指定数据库表字段
import com.baomidou.mybatisplus.annotation.TableId; // 导入 MyBatis-Plus 注解,用于指定主键字段
import com.baomidou.mybatisplus.annotation.TableName; // 导入 MyBatis-Plus 注解,用于指定数据库表名
import com.baomidou.mybatisplus.extension.activerecord.Model; // 导入 MyBatis-Plus 提供的 Model 类,用于增强实体类
import lombok.Data; // 导入 Lombok 注解,用于自动生成 getter、setter 等方法
import java.util.Date; // 导入 Date 类,用于处理时间
/**
* <p>
*
* </p>
*
* @author
* @since 2020-09-21 15:13
*/
@Data
@TableName("el_user_exam")
public class UserExam extends Model<UserExam> {
* <p>
*
* </p>
*
*
* @
* @ 2020-09-21 15:13
*/
@Data // Lombok 注解,自动为类生成 getter、setter、toString 等方法
@TableName("el_user_exam") // MyBatis-Plus 注解,指定该实体类对应的数据库表名为 "el_user_exam"
public class UserExam extends Model<UserExam> { // 继承 Model 类,提供额外的 MyBatis-Plus 功能
private static final long serialVersionUID = 1L; // 序列化版本 UID
private static final long serialVersionUID = 1L;
@TableId(value = "id", type = IdType.ASSIGN_ID)
private String id;
/**
* ID
*/
@TableField("user_id")
private String userId;
* ID
*/
@TableId(value = "id", type = IdType.ASSIGN_ID) // MyBatis-Plus 注解,指定主键字段为 "id",主键类型为 "ASSIGN_ID"
private String id; // ID字段
/**
* ID
*/
@TableField("exam_id")
private String examId;
* ID
*/
@TableField("user_id") // MyBatis-Plus 注解,指定数据库字段 "user_id" 对应实体类的 "userId" 字段
private String userId; // 用户ID字段
/**
*
*/
@TableField("try_count")
private Integer tryCount;
* ID
*/
@TableField("exam_id") // MyBatis-Plus 注解,指定数据库字段 "exam_id" 对应实体类的 "examId" 字段
private String examId; // 考试ID字段
/**
*
*/
@TableField("max_score")
private Integer maxScore;
*
*/
@TableField("try_count") // MyBatis-Plus 注解,指定数据库字段 "try_count" 对应实体类的 "tryCount" 字段
private Integer tryCount; // 考试次数字段
/**
*
*/
private Boolean passed;
*
*/
@TableField("max_score") // MyBatis-Plus 注解,指定数据库字段 "max_score" 对应实体类的 "maxScore" 字段
private Integer maxScore; // 最高分数字段
/**
*
*/
private Boolean passed; // 是否通过字段
/**
*
*/
@TableField("create_time")
private Date createTime;
*
*/
@TableField("create_time") // MyBatis-Plus 注解,指定数据库字段 "create_time" 对应实体类的 "createTime" 字段
private Date createTime; // 创建时间字段
/**
*
*/
@TableField("update_time")
private Date updateTime;
*
*/
@TableField("update_time") // MyBatis-Plus 注解,指定数据库字段 "update_time" 对应实体类的 "updateTime" 字段
private Date updateTime; // 更新时间字段
}

@ -1,29 +1,29 @@
package com.yf.exam.modules.user.exam.mapper;
package com.yf.exam.modules.user.exam.mapper; // 包名:表示该类属于 user.exam.mapper 包
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.yf.exam.modules.user.exam.dto.request.UserExamReqDTO;
import com.yf.exam.modules.user.exam.dto.response.UserExamRespDTO;
import com.yf.exam.modules.user.exam.entity.UserExam;
import org.apache.ibatis.annotations.Param;
import com.baomidou.mybatisplus.core.mapper.BaseMapper; // 导入 MyBatis-Plus 的 BaseMapper 接口,提供基本的数据库操作
import com.baomidou.mybatisplus.core.metadata.IPage; // 导入 MyBatis-Plus 的 IPage 接口,用于分页查询
import com.baomidou.mybatisplus.extension.plugins.pagination.Page; // 导入 MyBatis-Plus 的 Page 类,用于分页查询
import com.yf.exam.modules.user.exam.dto.request.UserExamReqDTO; // 导入用户考试请求 DTO 类,用于封装分页查询请求
import com.yf.exam.modules.user.exam.dto.response.UserExamRespDTO; // 导入用户考试响应 DTO 类,用于封装分页查询结果
import com.yf.exam.modules.user.exam.entity.UserExam; // 导入用户考试实体类,用于映射数据库表
import org.apache.ibatis.annotations.Param; // 导入 MyBatis 的 Param 注解,用于标注方法参数
/**
* <p>
* Mapper
* </p>
*
* @author
* @since 2020-09-21 15:13
*/
public interface UserExamMapper extends BaseMapper<UserExam> {
* <p>
* Mapper
* </p>
* 访
*
* @
* @ 2020-09-21 15:13
*/
public interface UserExamMapper extends BaseMapper<UserExam> { // 继承 BaseMapper 提供基础的增删改查功能
/**
*
* @param page
* @param query
* @return
*
* @param page
* @param query
* @return
*/
IPage<UserExamRespDTO> paging(Page page, @Param("query") UserExamReqDTO query);
IPage<UserExamRespDTO> paging(Page page, @Param("query") UserExamReqDTO query); // 自定义分页查询方法,返回分页结果
}

@ -1,43 +1,43 @@
package com.yf.exam.modules.user.exam.service;
package com.yf.exam.modules.user.exam.service; // 包名:表示该类属于 user.exam.service 包
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.service.IService;
import com.yf.exam.core.api.dto.PagingReqDTO;
import com.yf.exam.modules.user.exam.dto.request.UserExamReqDTO;
import com.yf.exam.modules.user.exam.dto.response.UserExamRespDTO;
import com.yf.exam.modules.user.exam.entity.UserExam;
import com.baomidou.mybatisplus.core.metadata.IPage; // 导入 MyBatis-Plus 的 IPage 接口,用于分页查询
import com.baomidou.mybatisplus.extension.service.IService; // 导入 MyBatis-Plus 的 IService 接口,提供基础服务接口
import com.yf.exam.core.api.dto.PagingReqDTO; // 导入分页请求 DTO 类,用于封装分页查询请求
import com.yf.exam.modules.user.exam.dto.request.UserExamReqDTO; // 导入用户考试请求 DTO 类
import com.yf.exam.modules.user.exam.dto.response.UserExamRespDTO; // 导入用户考试响应 DTO 类
import com.yf.exam.modules.user.exam.entity.UserExam; // 导入用户考试实体类,用于映射数据库表
/**
* <p>
*
* </p>
*
* @author
* @since 2020-09-21 15:13
*/
public interface UserExamService extends IService<UserExam> {
/**
*
* @param reqDTO
* @return
*/
IPage<UserExamRespDTO> paging(PagingReqDTO<UserExamReqDTO> reqDTO);
* <p>
*
* </p>
*
*
* @
* @ 2020-09-21 15:13
*/
public interface UserExamService extends IService<UserExam> { // 继承 IService 接口,提供对 UserExam 实体的增删改查功能
/**
*
* @param reqDTO
* @return
* @param reqDTO DTO
* @return
*/
IPage<UserExamRespDTO> myPaging(PagingReqDTO<UserExamReqDTO> reqDTO);
IPage<UserExamRespDTO> paging(PagingReqDTO<UserExamReqDTO> reqDTO); // 用于分页查询考试记录
/**
*
* @param reqDTO DTO
* @return
*/
IPage<UserExamRespDTO> myPaging(PagingReqDTO<UserExamReqDTO> reqDTO); // 用于分页查询当前用户的考试记录
/**
*
* @param userId
* @param examId
* @param score
* @param passed
* @param userId ID
* @param examId ID
* @param score
* @param passed
*/
void joinResult(String userId, String examId, Integer score, boolean passed);
void joinResult(String userId, String examId, Integer score, boolean passed); // 记录用户考试结果
}

@ -1,88 +1,87 @@
package com.yf.exam.modules.user.exam.service.impl;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.yf.exam.core.api.dto.PagingReqDTO;
import com.yf.exam.modules.user.UserUtils;
import com.yf.exam.modules.user.exam.dto.request.UserExamReqDTO;
import com.yf.exam.modules.user.exam.dto.response.UserExamRespDTO;
import com.yf.exam.modules.user.exam.entity.UserExam;
import com.yf.exam.modules.user.exam.mapper.UserExamMapper;
import com.yf.exam.modules.user.exam.service.UserExamService;
import org.springframework.stereotype.Service;
import java.util.Date;
package com.yf.exam.modules.user.exam.service.impl; // 包名:表示该类属于 user.exam.service.impl 包
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; // 导入 MyBatis-Plus 的 QueryWrapper用于构建查询条件
import com.baomidou.mybatisplus.core.metadata.IPage; // 导入 MyBatis-Plus 的 IPage 接口,用于分页查询
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; // 导入 MyBatis-Plus 提供的 ServiceImpl 类,提供基础的服务层实现
import com.yf.exam.core.api.dto.PagingReqDTO; // 导入分页请求 DTO 类,用于封装分页查询请求
import com.yf.exam.modules.user.UserUtils; // 导入 UserUtils 工具类,用于获取当前用户的 ID
import com.yf.exam.modules.user.exam.dto.request.UserExamReqDTO; // 导入用户考试请求 DTO 类
import com.yf.exam.modules.user.exam.dto.response.UserExamRespDTO; // 导入用户考试响应 DTO 类
import com.yf.exam.modules.user.exam.entity.UserExam; // 导入用户考试实体类,用于映射数据库表
import com.yf.exam.modules.user.exam.mapper.UserExamMapper; // 导入用户考试 Mapper 类,提供数据库操作
import com.yf.exam.modules.user.exam.service.UserExamService; // 导入用户考试服务接口
import org.springframework.stereotype.Service; // 导入 Service 注解,标识该类为服务层组件
import java.util.Date; // 导入 Date 类,用于处理时间
/**
* <p>
*
* </p>
*
* @author
* @since 2020-09-21 15:13
*/
@Service
public class UserExamServiceImpl extends ServiceImpl<UserExamMapper, UserExam> implements UserExamService {
* <p>
*
* </p>
* UserExamService
*
* @
* @ 2020-09-21 15:13
*/
@Service // 标识该类为 Spring 服务层组件
public class UserExamServiceImpl extends ServiceImpl<UserExamMapper, UserExam> implements UserExamService { // 继承 ServiceImpl 类,提供基础的增删改查功能,并实现 UserExamService 接口
@Override
public IPage<UserExamRespDTO> paging(PagingReqDTO<UserExamReqDTO> reqDTO) {
public IPage<UserExamRespDTO> paging(PagingReqDTO<UserExamReqDTO> reqDTO) { // 分页查询方法
//转换结果
// 使用 MyBatis-Plus 提供的 paging 方法进行分页查询,并转换为响应 DTO 类型
IPage<UserExamRespDTO> pageData = baseMapper.paging(reqDTO.toPage(), reqDTO.getParams());
return pageData;
return pageData; // 返回分页查询结果
}
@Override
public IPage<UserExamRespDTO> myPaging(PagingReqDTO<UserExamReqDTO> reqDTO) {
public IPage<UserExamRespDTO> myPaging(PagingReqDTO<UserExamReqDTO> reqDTO) { // 我的考试分页查询方法
UserExamReqDTO params = reqDTO.getParams();
UserExamReqDTO params = reqDTO.getParams(); // 获取请求参数
if(params==null){
// 如果没有传入参数,则初始化为空的 UserExamReqDTO 对象
if(params == null) {
params = new UserExamReqDTO();
}
params.setUserId(UserUtils.getUserId());
params.setUserId(UserUtils.getUserId()); // 设置当前用户的 ID
//转换结果
// 使用 MyBatis-Plus 提供的 paging 方法进行分页查询,并转换为响应 DTO 类型
IPage<UserExamRespDTO> pageData = baseMapper.paging(reqDTO.toPage(), params);
return pageData;
return pageData; // 返回分页查询结果
}
@Override
public void joinResult(String userId, String examId, Integer score, boolean passed) {
public void joinResult(String userId, String examId, Integer score, boolean passed) { // 记录考试结果的方法
//查询条件
// 构建查询条件,查找用户的考试记录
QueryWrapper<UserExam> wrapper = new QueryWrapper<>();
wrapper.lambda().eq(UserExam::getUserId, userId)
.eq(UserExam::getExamId, examId);
wrapper.lambda().eq(UserExam::getUserId, userId) // 查询条件:用户 ID
.eq(UserExam::getExamId, examId); // 查询条件:考试 ID
UserExam record = this.getOne(wrapper, false);
if(record == null){
UserExam record = this.getOne(wrapper, false); // 查找匹配的记录
if(record == null) { // 如果记录不存在,则创建新记录
record = new UserExam();
record.setCreateTime(new Date());
record.setUpdateTime(new Date());
record.setUserId(userId);
record.setExamId(examId);
record.setMaxScore(score);
record.setPassed(passed);
this.save(record);
record.setCreateTime(new Date()); // 设置创建时间
record.setUpdateTime(new Date()); // 设置更新时间
record.setUserId(userId); // 设置用户 ID
record.setExamId(examId); // 设置考试 ID
record.setMaxScore(score); // 设置最大分数
record.setPassed(passed); // 设置是否通过
this.save(record); // 保存新记录
return;
}
// 修复低分数不加入统计问题
record.setTryCount(record.getTryCount()+1);
record.setUpdateTime(new Date());
// 如果记录存在,则更新该记录
record.setTryCount(record.getTryCount() + 1); // 增加考试次数
record.setUpdateTime(new Date()); // 更新更新时间
if(record.getMaxScore() < score){
record.setMaxScore(score);
record.setPassed(passed);
// 如果当前分数高于记录中的最大分数,则更新最大分数
if(record.getMaxScore() < score) {
record.setMaxScore(score); // 更新最大分数
record.setPassed(passed); // 更新是否通过
}
this.updateById(record);
this.updateById(record); // 更新记录
}
}

Binary file not shown.

@ -1,3 +0,0 @@
{
"java.compile.nullAnalysis.mode": "automatic"
}

@ -1,21 +0,0 @@
MIT License
Copyright (c) 2021 孤傲的小笼包
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

@ -1,97 +0,0 @@
# 云帆培训考试系统 开源版
# 项目演示
开源版本https://lite.yfhl.net
管理账号admin/admin
学员账号person/person
注意事项:演示环境数据每天晚上会重新初始化,不要往上面导入重要数据;如果账号密码被改无法登录,请联系我们;或等到第二天再访问 :joy:
# 商业版本
如果开源版本无法满足您的需求,或者有需求需要定制,可以考虑我们的商业版本
商业版演示地址https://exam.yfhl.net
商业版官网地址https://www.jeedocm.com/?plan=githuby
QQ交流群二757328773
QQ交流群一865330294已满
# 商业版咨询
杨经理:
邮箱626264481@qq.com
手机18710213152
微信号youyouwx0613
# 介绍
一款多角色在线培训考试系统,系统集成了用户管理、角色管理、部门管理、题库管理、试题管理、试题导入导出、考试管理、在线考试、错题训练等功能,考试流程完善。
# 技术栈
SpringBoot / Shiro / Vue / MySQL
# 产品功能
## 系统完善:完善的权限控制和用户系统
权限控制基于Shiro和JWT开发的权限控制功能。
用户系统:用户管理、部门管理、角色管理等。
## 多角色:多角色支持
考试端:学生学员角色、支持在线考试、查看分数、训练错题。
管理端:题库管理、试题管理、考试管理、用户部门管理、查看考试情况等等。
## 定员考试:考试权限定义
完全公开:任何人员都可以参与考试。
指定部门:只有选中部门的人员才可以看到考试。
## 多题型:常用题型支持
支持题型:单选题、多选题、判断题。
难易程度:普通、困难。
## 便捷组卷:题库组卷
题库组卷:指定题库、分数、数量;题目、选项随机排序、杜绝作弊
# 环境要求
JDK 1.8+ [点此下载](https://cdn.yfhl.net/java-win/jdk-8u181-windows-x64.exe)
Mysql5.7+ [点此下载](https://cdn.yfhl.net/java-win/mysql-installer-community-5.7.31.0.msi)
# 安装资源
1、安装JDK1.8
https://cdn.yfhl.net/java-win/jdk-8u181-windows-x64.exe
2、安装MySQL
https://cdn.yfhl.net/java-win/mysql-installer-community-5.7.31.0.msi
-- 安装过程可能需要VC++
-- https://www.microsoft.com/zh-CN/download/details.aspx?id=40784
-- 安装数据库管理工具
https://cdn.yfhl.net/java-win/SQLyog.12.3.1.0.zip
# 安装视频
https://www.ixigua.com/7041491265027834381?utm_source=xiguastudio
# 快速运行
1、自行安装MySQL数据库版本最好是5.7),将`安装资源中`的`数据库初始化.sql`导入到安装好的数据库
2、安装Java环境要求JDK版本大于1.8
3、请修改外置配置文件application-local.yml 改成您自己的MySQL配置
4、Windows通过start.bat运行Linux运行start.sh运行
5、如果无意外可通过http://localhost:8101 访问到项目了
6、管理员账号密码admin/admin 学员账号person/person
# 其它支持
网站https://www.jeedocm.com/?plan=githuby
QQ交流群二757328773
QQ交流群一865330294已满
![输入图片说明](https://images.gitee.com/uploads/images/2020/1207/173238_e6c22c67_2189748.jpeg "17-32-10.jpg")
![主界面](https://images.gitee.com/uploads/images/2020/1019/182239_4a87af30_2189748.jpeg "222.jpg")
![输入图片说明](https://images.gitee.com/uploads/images/2020/1019/182532_04c42741_2189748.jpeg "444.jpg")
![输入图片说明](https://images.gitee.com/uploads/images/2020/1019/182543_44dcc2d7_2189748.jpeg "555.jpg")
![输入图片说明](https://images.gitee.com/uploads/images/2020/1019/182551_4d404492_2189748.jpeg "666.jpg")
![输入图片说明](https://images.gitee.com/uploads/images/2020/1019/183109_fdc30de8_2189748.jpeg "777.jpg")
![输入图片说明](https://images.gitee.com/uploads/images/2020/1019/183117_30b44530_2189748.jpeg "888.jpg")
![输入图片说明](https://images.gitee.com/uploads/images/2020/1019/183023_2f3baeb9_2189748.jpeg "999.jpg")
![输入图片说明](https://images.gitee.com/uploads/images/2020/1019/183032_f5016335_2189748.jpeg "1010.jpg")
![输入图片说明](https://images.gitee.com/uploads/images/2020/1019/183040_38fd74ed_2189748.jpeg "1111.jpg")
![输入图片说明](https://images.gitee.com/uploads/images/2020/1019/183047_a31619cd_2189748.jpeg "1212.jpg")

@ -1,847 +0,0 @@
/*
Navicat Premium Data Transfer
Source Server : 127.0.0.1-
Source Server Type : MySQL
Source Server Version : 80028 (8.0.28)
Source Host : localhost:3306
Source Schema : yf_exam_lite
Target Server Type : MySQL
Target Server Version : 80028 (8.0.28)
File Encoding : 65001
Date: 20/02/2023 10:38:52
*/
SET NAMES utf8mb4;
SET FOREIGN_KEY_CHECKS = 0;
-- ----------------------------
-- Table structure for el_exam
-- ----------------------------
DROP TABLE IF EXISTS `el_exam`;
CREATE TABLE `el_exam` (
`id` varchar(64) COLLATE utf8mb4_general_ci NOT NULL COMMENT 'ID',
`title` varchar(255) COLLATE utf8mb4_general_ci NOT NULL COMMENT '考试名称',
`content` varchar(255) COLLATE utf8mb4_general_ci NOT NULL DEFAULT '' COMMENT '考试描述',
`open_type` int NOT NULL DEFAULT '1' COMMENT '1公开2部门3定员',
`state` int NOT NULL DEFAULT '0' COMMENT '考试状态',
`time_limit` tinyint NOT NULL DEFAULT '0' COMMENT '是否限时',
`start_time` datetime DEFAULT NULL COMMENT '开始时间',
`end_time` datetime DEFAULT NULL COMMENT '结束时间',
`create_time` datetime DEFAULT NULL COMMENT '创建时间',
`update_time` datetime DEFAULT NULL COMMENT '更新时间',
`total_score` int NOT NULL DEFAULT '0' COMMENT '总分数',
`total_time` int NOT NULL DEFAULT '0' COMMENT '总时长(分钟)',
`qualify_score` int NOT NULL DEFAULT '0' COMMENT '及格分数',
PRIMARY KEY (`id`) USING BTREE,
KEY `open_type` (`open_type`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci COMMENT='考试主表';
-- ----------------------------
-- Records of el_exam
-- ----------------------------
BEGIN;
INSERT INTO `el_exam` (`id`, `title`, `content`, `open_type`, `state`, `time_limit`, `start_time`, `end_time`, `create_time`, `update_time`, `total_score`, `total_time`, `qualify_score`) VALUES ('1587621704140427265', '【云帆演示】考试', '【云帆演示】考试', 1, 0, 0, NULL, NULL, '2022-11-02 09:44:46', '2022-11-02 09:44:46', 100, 30, 60);
COMMIT;
-- ----------------------------
-- Table structure for el_exam_depart
-- ----------------------------
DROP TABLE IF EXISTS `el_exam_depart`;
CREATE TABLE `el_exam_depart` (
`id` varchar(32) COLLATE utf8mb4_general_ci NOT NULL DEFAULT '' COMMENT 'ID',
`exam_id` varchar(32) COLLATE utf8mb4_general_ci NOT NULL DEFAULT '' COMMENT '考试ID',
`depart_id` varchar(32) COLLATE utf8mb4_general_ci NOT NULL DEFAULT '' COMMENT '部门ID',
PRIMARY KEY (`id`) USING BTREE,
KEY `exam_id` (`exam_id`),
KEY `depart_id` (`depart_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci COMMENT='考试部门';
-- ----------------------------
-- Records of el_exam_depart
-- ----------------------------
BEGIN;
COMMIT;
-- ----------------------------
-- Table structure for el_exam_repo
-- ----------------------------
DROP TABLE IF EXISTS `el_exam_repo`;
CREATE TABLE `el_exam_repo` (
`id` varchar(64) COLLATE utf8mb4_general_ci NOT NULL COMMENT 'ID',
`exam_id` varchar(64) COLLATE utf8mb4_general_ci NOT NULL COMMENT '考试ID',
`repo_id` varchar(64) COLLATE utf8mb4_general_ci NOT NULL COMMENT '题库ID',
`radio_count` int NOT NULL DEFAULT '0' COMMENT '单选题数量',
`radio_score` int NOT NULL DEFAULT '0' COMMENT '单选题分数',
`multi_count` int NOT NULL DEFAULT '0' COMMENT '多选题数量',
`multi_score` int NOT NULL DEFAULT '0' COMMENT '多选题分数',
`judge_count` int NOT NULL DEFAULT '0' COMMENT '判断题数量',
`judge_score` int NOT NULL DEFAULT '0' COMMENT '判断题分数',
`saq_count` int NOT NULL DEFAULT '0' COMMENT '简答题数量',
`saq_score` int NOT NULL DEFAULT '0' COMMENT '简答题分数',
PRIMARY KEY (`id`) USING BTREE,
UNIQUE KEY `exam_repo_id` (`exam_id`,`repo_id`),
KEY `rule_id` (`exam_id`) USING BTREE,
KEY `repo_id` (`repo_id`) USING BTREE
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci COMMENT='考试题库';
-- ----------------------------
-- Records of el_exam_repo
-- ----------------------------
BEGIN;
INSERT INTO `el_exam_repo` (`id`, `exam_id`, `repo_id`, `radio_count`, `radio_score`, `multi_count`, `multi_score`, `judge_count`, `judge_score`, `saq_count`, `saq_score`) VALUES ('1627496519370297345', '1587621704140427265', '1587622451624120321', 2, 10, 6, 10, 2, 10, 0, 0);
COMMIT;
-- ----------------------------
-- Table structure for el_paper
-- ----------------------------
DROP TABLE IF EXISTS `el_paper`;
CREATE TABLE `el_paper` (
`id` varchar(64) COLLATE utf8mb4_general_ci NOT NULL COMMENT '试卷ID',
`user_id` varchar(64) COLLATE utf8mb4_general_ci NOT NULL COMMENT '用户ID',
`depart_id` varchar(32) COLLATE utf8mb4_general_ci NOT NULL DEFAULT '' COMMENT '部门ID',
`exam_id` varchar(64) COLLATE utf8mb4_general_ci NOT NULL COMMENT '规则ID',
`title` varchar(64) COLLATE utf8mb4_general_ci NOT NULL COMMENT '考试标题',
`total_time` int NOT NULL DEFAULT '0' COMMENT '考试时长',
`user_time` int NOT NULL DEFAULT '0' COMMENT '用户时长',
`total_score` int NOT NULL DEFAULT '0' COMMENT '试卷总分',
`qualify_score` int NOT NULL DEFAULT '0' COMMENT '及格分',
`obj_score` int NOT NULL DEFAULT '0' COMMENT '客观分',
`subj_score` int NOT NULL DEFAULT '0' COMMENT '主观分',
`user_score` int NOT NULL COMMENT '用户得分',
`has_saq` tinyint NOT NULL DEFAULT '0' COMMENT '是否包含简答题',
`state` int NOT NULL DEFAULT '1' COMMENT '试卷状态',
`create_time` datetime DEFAULT NULL COMMENT '创建时间',
`update_time` datetime DEFAULT NULL COMMENT '更新时间',
`limit_time` datetime DEFAULT NULL COMMENT '截止时间',
PRIMARY KEY (`id`) USING BTREE,
KEY `user_id` (`user_id`) USING BTREE,
KEY `exam_id` (`exam_id`) USING BTREE
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci COMMENT='考试记录';
-- ----------------------------
-- Records of el_paper
-- ----------------------------
BEGIN;
COMMIT;
-- ----------------------------
-- Table structure for el_paper_qu
-- ----------------------------
DROP TABLE IF EXISTS `el_paper_qu`;
CREATE TABLE `el_paper_qu` (
`id` varchar(64) COLLATE utf8mb4_general_ci NOT NULL COMMENT 'ID',
`paper_id` varchar(64) COLLATE utf8mb4_general_ci NOT NULL COMMENT '试卷ID',
`qu_id` varchar(64) COLLATE utf8mb4_general_ci NOT NULL COMMENT '题目ID',
`qu_type` int NOT NULL COMMENT '题目类型',
`answered` tinyint NOT NULL DEFAULT '0' COMMENT '是否已答',
`answer` varchar(5000) COLLATE utf8mb4_general_ci NOT NULL DEFAULT '' COMMENT '主观答案',
`sort` int NOT NULL DEFAULT '0' COMMENT '问题排序',
`score` int NOT NULL DEFAULT '0' COMMENT '单题分分值',
`actual_score` int NOT NULL DEFAULT '0' COMMENT '实际得分(主观题)',
`is_right` tinyint NOT NULL DEFAULT '0' COMMENT '是否答对',
PRIMARY KEY (`id`) USING BTREE,
KEY `paper_id` (`paper_id`) USING BTREE,
KEY `qu_id` (`qu_id`) USING BTREE,
KEY `paper_qu_id` (`paper_id`,`qu_id`) USING BTREE,
KEY `sort` (`sort`) USING BTREE
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci COMMENT='考试记录考题';
-- ----------------------------
-- Records of el_paper_qu
-- ----------------------------
BEGIN;
COMMIT;
-- ----------------------------
-- Table structure for el_paper_qu_answer
-- ----------------------------
DROP TABLE IF EXISTS `el_paper_qu_answer`;
CREATE TABLE `el_paper_qu_answer` (
`id` varchar(64) COLLATE utf8mb4_general_ci NOT NULL COMMENT '自增ID',
`paper_id` varchar(64) COLLATE utf8mb4_general_ci NOT NULL COMMENT '试卷ID',
`answer_id` varchar(32) COLLATE utf8mb4_general_ci NOT NULL COMMENT '回答项ID',
`qu_id` varchar(32) COLLATE utf8mb4_general_ci NOT NULL COMMENT '题目ID',
`is_right` tinyint NOT NULL DEFAULT '0' COMMENT '是否正确项',
`checked` tinyint NOT NULL DEFAULT '0' COMMENT '是否选中',
`sort` int NOT NULL DEFAULT '0' COMMENT '排序',
`abc` varchar(64) COLLATE utf8mb4_general_ci NOT NULL DEFAULT '' COMMENT '选项标签',
PRIMARY KEY (`id`) USING BTREE,
KEY `paper_id` (`paper_id`) USING BTREE,
KEY `qu_id` (`qu_id`) USING BTREE,
KEY `paper_qu_id` (`paper_id`,`qu_id`) USING BTREE,
KEY `sort` (`sort`) USING BTREE
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci COMMENT='考试记录答案';
-- ----------------------------
-- Records of el_paper_qu_answer
-- ----------------------------
BEGIN;
COMMIT;
-- ----------------------------
-- Table structure for el_qu
-- ----------------------------
DROP TABLE IF EXISTS `el_qu`;
CREATE TABLE `el_qu` (
`id` varchar(64) COLLATE utf8mb4_general_ci NOT NULL COMMENT '题目ID',
`qu_type` int NOT NULL COMMENT '题目类型',
`level` int NOT NULL DEFAULT '1' COMMENT '1普通,2较难',
`image` varchar(500) COLLATE utf8mb4_general_ci NOT NULL DEFAULT '' COMMENT '题目图片',
`content` varchar(2000) COLLATE utf8mb4_general_ci NOT NULL COMMENT '题目内容',
`create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
`update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '更新时间',
`remark` varchar(255) COLLATE utf8mb4_general_ci NOT NULL DEFAULT '' COMMENT '题目备注',
`analysis` varchar(2000) COLLATE utf8mb4_general_ci NOT NULL DEFAULT '' COMMENT '整题解析',
PRIMARY KEY (`id`) USING BTREE,
KEY `qu_type` (`qu_type`) USING BTREE
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci COMMENT='试题主表';
-- ----------------------------
-- Records of el_qu
-- ----------------------------
BEGIN;
INSERT INTO `el_qu` (`id`, `qu_type`, `level`, `image`, `content`, `create_time`, `update_time`, `remark`, `analysis`) VALUES ('1587622642263625729', 1, 1, '', '五个答案中哪个是最好的类比?女儿对于父亲相当于侄女对于', '2022-11-02 09:48:29', '2022-11-02 09:48:29', '', '');
INSERT INTO `el_qu` (`id`, `qu_type`, `level`, `image`, `content`, `create_time`, `update_time`, `remark`, `analysis`) VALUES ('1587622642393649153', 1, 1, '', '五个答案中哪个是最好的类比?皮对于树相当于鳞对于', '2022-11-02 09:48:29', '2022-11-02 09:48:29', '', '');
INSERT INTO `el_qu` (`id`, `qu_type`, `level`, `image`, `content`, `create_time`, `update_time`, `remark`, `analysis`) VALUES ('1587622642473340930', 1, 1, '', '火车守车(车尾)长6.4米。机车的长度等于守车的长加上半节车厢的长。车厢长度等于守车长加上机车长。火车的机车、车厢、守车共长多少米?', '2022-11-02 09:48:29', '2022-11-02 09:48:29', '', '');
INSERT INTO `el_qu` (`id`, `qu_type`, `level`, `image`, `content`, `create_time`, `update_time`, `remark`, `analysis`) VALUES ('1587622642557227009', 1, 1, '', '角对于元相当于小时对于', '2022-11-02 09:48:29', '2022-11-02 09:48:29', '', '');
INSERT INTO `el_qu` (`id`, `qu_type`, `level`, `image`, `content`, `create_time`, `update_time`, `remark`, `analysis`) VALUES ('1587622642641113089', 1, 1, '', '如果把这个大立方体的六个面全部涂上黑色然后按图中虚线把它切成36个小方块两面有黑色的小方块有多少个', '2022-11-02 09:48:29', '2022-11-02 09:48:29', '', '');
INSERT INTO `el_qu` (`id`, `qu_type`, `level`, `image`, `content`, `create_time`, `update_time`, `remark`, `analysis`) VALUES ('1587622642699833345', 1, 1, '', '找出与众不同的一个:', '2022-11-02 09:48:29', '2022-11-02 09:48:29', '', '');
INSERT INTO `el_qu` (`id`, `qu_type`, `level`, `image`, `content`, `create_time`, `update_time`, `remark`, `analysis`) VALUES ('1587622642762747906', 2, 1, '', '以下哪些是中国的特别行政区?', '2022-11-02 09:48:29', '2022-11-02 09:48:29', '', '');
INSERT INTO `el_qu` (`id`, `qu_type`, `level`, `image`, `content`, `create_time`, `update_time`, `remark`, `analysis`) VALUES ('1587622642838245378', 2, 1, '', '中国东北三省是指()', '2022-11-02 09:48:29', '2022-11-02 09:48:29', '', '');
INSERT INTO `el_qu` (`id`, `qu_type`, `level`, `image`, `content`, `create_time`, `update_time`, `remark`, `analysis`) VALUES ('1587622642909548545', 3, 1, '', '咖啡的故乡是非洲吗?', '2022-11-02 09:48:29', '2022-11-02 09:48:29', '', '');
INSERT INTO `el_qu` (`id`, `qu_type`, `level`, `image`, `content`, `create_time`, `update_time`, `remark`, `analysis`) VALUES ('1587622642976657410', 3, 1, '', '世界上最长的山脉安第斯山脉', '2022-11-02 09:48:29', '2022-11-02 09:48:29', '', '');
INSERT INTO `el_qu` (`id`, `qu_type`, `level`, `image`, `content`, `create_time`, `update_time`, `remark`, `analysis`) VALUES ('1587622643039571970', 1, 1, '', '西亚波斯湾沿岸比较富裕,其原因是()', '2022-11-02 09:48:29', '2022-11-02 09:48:29', '', '西亚波斯湾沿岸国家比较富裕,是因为大量出口石油资源.');
INSERT INTO `el_qu` (`id`, `qu_type`, `level`, `image`, `content`, `create_time`, `update_time`, `remark`, `analysis`) VALUES ('1587622643102486530', 1, 1, '', '我国最北面的城市是哪个()', '2022-11-02 09:48:29', '2022-11-02 09:48:29', '', '漠河市,隶属黑龙江省大兴安岭地区。 [1] 地处黑龙江省北部。西与内蒙古自治区呼伦贝尔市额尔古纳市为邻南与内蒙古自治区根河市和呼中区交界东与塔河县接壤北隔黑龙江与俄罗斯外贝加尔边疆区原赤塔州和阿穆尔州相望是中国最北端的县级行政区地势南高北低南北呈坡降趋势属于寒温带大陆性季风气候。下辖6个镇总面积18427平方千米。 [2] 根据第七次人口普查数据截至2020年11月1日零时漠河市常住人口为54036人。');
INSERT INTO `el_qu` (`id`, `qu_type`, `level`, `image`, `content`, `create_time`, `update_time`, `remark`, `analysis`) VALUES ('1587622643173789698', 1, 1, '', '人们把社会生产的各个部门划分为三类产业,下列属于第三产业的是()', '2022-11-02 09:48:29', '2022-11-02 09:48:29', '', '通常人们把生产的各部门划分为三类产业.农业是第一产业,包括种植业、林业、畜牧业、渔业等;工业和建筑业是第二产业;流通部门和服务部门是第三产业');
INSERT INTO `el_qu` (`id`, `qu_type`, `level`, `image`, `content`, `create_time`, `update_time`, `remark`, `analysis`) VALUES ('1587622643240898561', 1, 1, '', '亚洲人中分布不是很均匀,其中人中较稀疏的部分是()', '2022-11-02 09:48:29', '2022-11-02 09:48:29', '', '人口稠密地区都处在中低纬度、近海、平原地区,亚洲人口稀疏的地区在纬度位置较高的北亚,沙漠广布的西亚及气候干旱的中亚地区.');
INSERT INTO `el_qu` (`id`, `qu_type`, `level`, `image`, `content`, `create_time`, `update_time`, `remark`, `analysis`) VALUES ('1587622643312201730', 1, 1, '', '亚洲各国经济发展不平衡,下列国家中人均国民生产总值最高的是()', '2022-11-02 09:48:29', '2022-11-02 09:48:29', '', '本题还可以考查人口人口超亿的国家有中国、印度、印度尼西亚、巴基斯坦、日本、孟加拉国等6个各大洲人口排序亚非欧南北美大洋洲各大洲人口增长率非南美亚大洋北美欧著名的民族文化亚洲三个人类文明发祥地华夏文化(黄河——长江中下游地区)、印度河流域文化、两河流域文化(由幼法拉底河和底格里斯河冲积而成的美索不达米亚平原地区);还有恒河文化、阿拉伯文化等。亚洲只有日本属于发达国家。');
INSERT INTO `el_qu` (`id`, `qu_type`, `level`, `image`, `content`, `create_time`, `update_time`, `remark`, `analysis`) VALUES ('1587622643396087810', 1, 1, '', '地球上0度经线和0度纬线的长度相比', '2022-11-02 09:48:29', '2022-11-02 09:48:29', '', '0度经线和0度纬线相比()0度纬线的长度是0度经线的2倍。 因为经线是半圆,赤道是大圆。');
INSERT INTO `el_qu` (`id`, `qu_type`, `level`, `image`, `content`, `create_time`, `update_time`, `remark`, `analysis`) VALUES ('1587622643467390977', 1, 1, '', '下列国家人口超过1亿的南亚国家是', '2022-11-02 09:48:29', '2022-11-02 09:48:29', '', '世界人口超过一亿的国家从多到少依次为中国、印度、美国、印度尼西亚、巴西、巴基斯坦、俄罗斯、孟加拉国、尼日利亚、日本和墨西哥共有11个其中属于南亚的是印度、巴基斯坦和孟加拉国');
INSERT INTO `el_qu` (`id`, `qu_type`, `level`, `image`, `content`, `create_time`, `update_time`, `remark`, `analysis`) VALUES ('1587622643551277058', 1, 1, '', '世界上跨东西、南北距离最长的大洲是()', '2022-11-02 09:48:29', '2022-11-02 09:48:29', '', '在全球的七大洲中,亚洲是世界上面积最大的一洲,也是南北跨纬度最多,热量差异大; 东西跨经度仅次于南极洲,东西距离最长的大洲;大洋洲是世界上最小的一洲 考点:本题主要考查大洲和大洋。');
INSERT INTO `el_qu` (`id`, `qu_type`, `level`, `image`, `content`, `create_time`, `update_time`, `remark`, `analysis`) VALUES ('1587622643626774530', 1, 1, '', '地球公转会产生()', '2022-11-02 09:48:30', '2022-11-02 09:48:30', '', '地球自转产生的现象有: 1、昼夜更替现象向着太阳的半球,是白天,背着太阳的半球,是黑夜; 2、南北半球的地转偏向力引起的各种运动旋转现象 3、地球上不同经度的地方,有不同的地方时经度每隔15度,地方时相差一小时; 4、东西部地区的时间差现象生物作息规律现象 5、对地球形状的影响.地球自转所产生的惯性离心力,使得地球由两级向赤道逐渐膨胀,成为目前略扁的旋转椭球体。 地球公转产生的现象有: 1、根据太阳高度的差异,划分出五带:北寒、北温、热带、南温、南寒; 2、根据获得热量多少的时间差异,划分出四季:春、夏、秋、冬; 3、昼夜长短的变化现象 4、天象位置的变化生物生长规律现象. 5、正午太阳高度的变化夏至日太阳直射北回归线全球正午太阳高度从北回归线向南北两侧逐渐递减二分日太阳直射赤道全球正午太阳高度从赤道向两极递减全球昼夜平分冬至日太阳直射南回归线全球正午高度从南回归线向南北两侧逐渐递减南回归线及其以南的地区正午太阳高度达到最大值北半球各纬度正午太阳高度达到最小值。');
INSERT INTO `el_qu` (`id`, `qu_type`, `level`, `image`, `content`, `create_time`, `update_time`, `remark`, `analysis`) VALUES ('1587622643693883394', 2, 1, '', '南极旅游的兴起,请下列哪些因素有关()', '2022-11-02 09:48:30', '2022-11-02 09:48:30', '', '');
INSERT INTO `el_qu` (`id`, `qu_type`, `level`, `image`, `content`, `create_time`, `update_time`, `remark`, `analysis`) VALUES ('1587622643760992258', 2, 1, '', '交通运输线路(公路、铁路),选址的原因有()', '2022-11-02 09:48:30', '2022-11-02 09:48:30', '', '');
INSERT INTO `el_qu` (`id`, `qu_type`, `level`, `image`, `content`, `create_time`, `update_time`, `remark`, `analysis`) VALUES ('1587622643823906818', 2, 1, 'http://localhost:8201/upload/file/2022/11/07/1589528183307354113.jpg', '地球自转产生的现象有()', '2022-11-02 09:48:30', '2022-11-02 09:48:30', '', '');
INSERT INTO `el_qu` (`id`, `qu_type`, `level`, `image`, `content`, `create_time`, `update_time`, `remark`, `analysis`) VALUES ('1587622643895209985', 2, 1, '', '地球公转产生的现象有()', '2022-11-02 09:48:30', '2022-11-02 09:48:30', '', '');
INSERT INTO `el_qu` (`id`, `qu_type`, `level`, `image`, `content`, `create_time`, `update_time`, `remark`, `analysis`) VALUES ('1587622643979096066', 3, 1, '', '地球上出现的潮汐是由于地月吸引力。', '2022-11-02 09:48:30', '2022-11-02 09:48:30', '', '');
INSERT INTO `el_qu` (`id`, `qu_type`, `level`, `image`, `content`, `create_time`, `update_time`, `remark`, `analysis`) VALUES ('1587622644054593538', 3, 1, '', '被称为“万园之园”的我国古典园林是颐和园。', '2022-11-02 09:48:30', '2022-11-02 09:48:30', '', '');
INSERT INTO `el_qu` (`id`, `qu_type`, `level`, `image`, `content`, `create_time`, `update_time`, `remark`, `analysis`) VALUES ('1587622644134285314', 3, 1, '', '世界最长的山脉是安第斯山脉。', '2022-11-02 09:48:30', '2022-11-02 09:48:30', '', '');
INSERT INTO `el_qu` (`id`, `qu_type`, `level`, `image`, `content`, `create_time`, `update_time`, `remark`, `analysis`) VALUES ('1587622644201394178', 3, 1, '', '仪表显示当前发动机转速是6000转克/分钟。', '2022-11-02 09:48:30', '2022-11-02 09:48:30', '', '仪表显示当前车速是20公里/小时。');
INSERT INTO `el_qu` (`id`, `qu_type`, `level`, `image`, `content`, `create_time`, `update_time`, `remark`, `analysis`) VALUES ('1587622644281085953', 3, 1, '', '仪表显示当前冷却液的温度是90°C。', '2022-11-02 09:48:30', '2022-11-02 09:48:30', '', '水温表:指示发动机冷却液的温度,单位为摄氏度(C)。水温表指针所指的位置显示当前冷却液的温度。\n如图所示指针指的位置是90表示当前冷却液的温度是9o°C。');
INSERT INTO `el_qu` (`id`, `qu_type`, `level`, `image`, `content`, `create_time`, `update_time`, `remark`, `analysis`) VALUES ('1587622644356583425', 1, 1, '', '我国面积最大的湖泊是()。', '2022-11-02 09:48:30', '2022-11-02 09:48:30', '', '青海湖是我国最大的湖泊它是一个咸水湖面积约4450平方公里说起来也不小了但是如果把它放到全世界范围来看的话青海湖实际上并非大型湖泊单就面积而言在全世界排名第34位和我国国土面积世界第三的位置很不相称世界最大湖泊里海的面积38万平方公里就相当于84个青海湖。');
COMMIT;
-- ----------------------------
-- Table structure for el_qu_answer
-- ----------------------------
DROP TABLE IF EXISTS `el_qu_answer`;
CREATE TABLE `el_qu_answer` (
`id` varchar(64) COLLATE utf8mb4_general_ci NOT NULL COMMENT '答案ID',
`qu_id` varchar(64) COLLATE utf8mb4_general_ci NOT NULL COMMENT '问题ID',
`is_right` tinyint NOT NULL DEFAULT '0' COMMENT '是否正确',
`image` varchar(500) COLLATE utf8mb4_general_ci NOT NULL DEFAULT '' COMMENT '选项图片',
`content` varchar(5000) COLLATE utf8mb4_general_ci NOT NULL DEFAULT '' COMMENT '答案内容',
`analysis` varchar(5000) COLLATE utf8mb4_general_ci NOT NULL DEFAULT '' COMMENT '答案分析',
PRIMARY KEY (`id`) USING BTREE,
KEY `qu_id` (`qu_id`) USING BTREE
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci COMMENT='试题答案选项';
-- ----------------------------
-- Records of el_qu_answer
-- ----------------------------
BEGIN;
INSERT INTO `el_qu_answer` (`id`, `qu_id`, `is_right`, `image`, `content`, `analysis`) VALUES ('1587622642309763073', '1587622642263625729', 0, '', '母亲', '');
INSERT INTO `el_qu_answer` (`id`, `qu_id`, `is_right`, `image`, `content`, `analysis`) VALUES ('1587622642318151681', '1587622642263625729', 0, '', '哥哥', '');
INSERT INTO `el_qu_answer` (`id`, `qu_id`, `is_right`, `image`, `content`, `analysis`) VALUES ('1587622642318151682', '1587622642263625729', 0, '', '侄子', '');
INSERT INTO `el_qu_answer` (`id`, `qu_id`, `is_right`, `image`, `content`, `analysis`) VALUES ('1587622642318151683', '1587622642263625729', 0, '', '表兄', '');
INSERT INTO `el_qu_answer` (`id`, `qu_id`, `is_right`, `image`, `content`, `analysis`) VALUES ('1587622642318151684', '1587622642263625729', 1, '', '叔叔', '');
INSERT INTO `el_qu_answer` (`id`, `qu_id`, `is_right`, `image`, `content`, `analysis`) VALUES ('1587622642402037761', '1587622642393649153', 0, '', '', '');
INSERT INTO `el_qu_answer` (`id`, `qu_id`, `is_right`, `image`, `content`, `analysis`) VALUES ('1587622642402037762', '1587622642393649153', 0, '', '大海', '');
INSERT INTO `el_qu_answer` (`id`, `qu_id`, `is_right`, `image`, `content`, `analysis`) VALUES ('1587622642402037763', '1587622642393649153', 0, '', '渔夫', '');
INSERT INTO `el_qu_answer` (`id`, `qu_id`, `is_right`, `image`, `content`, `analysis`) VALUES ('1587622642402037764', '1587622642393649153', 1, '', '', '');
INSERT INTO `el_qu_answer` (`id`, `qu_id`, `is_right`, `image`, `content`, `analysis`) VALUES ('1587622642402037765', '1587622642393649153', 0, '', '', '');
INSERT INTO `el_qu_answer` (`id`, `qu_id`, `is_right`, `image`, `content`, `analysis`) VALUES ('1587622642490118145', '1587622642473340930', 0, '', '25.6米', '');
INSERT INTO `el_qu_answer` (`id`, `qu_id`, `is_right`, `image`, `content`, `analysis`) VALUES ('1587622642490118146', '1587622642473340930', 0, '', '36米', '');
INSERT INTO `el_qu_answer` (`id`, `qu_id`, `is_right`, `image`, `content`, `analysis`) VALUES ('1587622642490118147', '1587622642473340930', 1, '', '51.2米', '');
INSERT INTO `el_qu_answer` (`id`, `qu_id`, `is_right`, `image`, `content`, `analysis`) VALUES ('1587622642490118148', '1587622642473340930', 0, '', '64.4米', '');
INSERT INTO `el_qu_answer` (`id`, `qu_id`, `is_right`, `image`, `content`, `analysis`) VALUES ('1587622642490118149', '1587622642473340930', 0, '', '76.2米', '');
INSERT INTO `el_qu_answer` (`id`, `qu_id`, `is_right`, `image`, `content`, `analysis`) VALUES ('1587622642569809922', '1587622642557227009', 1, '', '', '');
INSERT INTO `el_qu_answer` (`id`, `qu_id`, `is_right`, `image`, `content`, `analysis`) VALUES ('1587622642569809923', '1587622642557227009', 0, '', '', '');
INSERT INTO `el_qu_answer` (`id`, `qu_id`, `is_right`, `image`, `content`, `analysis`) VALUES ('1587622642569809924', '1587622642557227009', 0, '', '', '');
INSERT INTO `el_qu_answer` (`id`, `qu_id`, `is_right`, `image`, `content`, `analysis`) VALUES ('1587622642569809925', '1587622642557227009', 0, '', '', '');
INSERT INTO `el_qu_answer` (`id`, `qu_id`, `is_right`, `image`, `content`, `analysis`) VALUES ('1587622642569809926', '1587622642557227009', 0, '', '', '');
INSERT INTO `el_qu_answer` (`id`, `qu_id`, `is_right`, `image`, `content`, `analysis`) VALUES ('1587622642649501697', '1587622642641113089', 0, '', '10', '');
INSERT INTO `el_qu_answer` (`id`, `qu_id`, `is_right`, `image`, `content`, `analysis`) VALUES ('1587622642649501698', '1587622642641113089', 0, '', '12', '');
INSERT INTO `el_qu_answer` (`id`, `qu_id`, `is_right`, `image`, `content`, `analysis`) VALUES ('1587622642649501699', '1587622642641113089', 1, '', '16', '');
INSERT INTO `el_qu_answer` (`id`, `qu_id`, `is_right`, `image`, `content`, `analysis`) VALUES ('1587622642649501700', '1587622642641113089', 0, '', '20', '');
INSERT INTO `el_qu_answer` (`id`, `qu_id`, `is_right`, `image`, `content`, `analysis`) VALUES ('1587622642649501701', '1587622642641113089', 0, '', '8', '');
INSERT INTO `el_qu_answer` (`id`, `qu_id`, `is_right`, `image`, `content`, `analysis`) VALUES ('1587622642708221953', '1587622642699833345', 0, '', '西安', '');
INSERT INTO `el_qu_answer` (`id`, `qu_id`, `is_right`, `image`, `content`, `analysis`) VALUES ('1587622642708221954', '1587622642699833345', 0, '', '郑州', '');
INSERT INTO `el_qu_answer` (`id`, `qu_id`, `is_right`, `image`, `content`, `analysis`) VALUES ('1587622642708221955', '1587622642699833345', 1, '', '哈尔滨', '');
INSERT INTO `el_qu_answer` (`id`, `qu_id`, `is_right`, `image`, `content`, `analysis`) VALUES ('1587622642708221956', '1587622642699833345', 0, '', '昆明', '');
INSERT INTO `el_qu_answer` (`id`, `qu_id`, `is_right`, `image`, `content`, `analysis`) VALUES ('1587622642708221957', '1587622642699833345', 0, '', '南昌', '');
INSERT INTO `el_qu_answer` (`id`, `qu_id`, `is_right`, `image`, `content`, `analysis`) VALUES ('1587622642771136513', '1587622642762747906', 1, '', '香港', '');
INSERT INTO `el_qu_answer` (`id`, `qu_id`, `is_right`, `image`, `content`, `analysis`) VALUES ('1587622642775330818', '1587622642762747906', 1, '', '澳门', '');
INSERT INTO `el_qu_answer` (`id`, `qu_id`, `is_right`, `image`, `content`, `analysis`) VALUES ('1587622642775330819', '1587622642762747906', 0, '', '珠海', '');
INSERT INTO `el_qu_answer` (`id`, `qu_id`, `is_right`, `image`, `content`, `analysis`) VALUES ('1587622642775330820', '1587622642762747906', 0, '', '重庆', '');
INSERT INTO `el_qu_answer` (`id`, `qu_id`, `is_right`, `image`, `content`, `analysis`) VALUES ('1587622642846633985', '1587622642838245378', 1, '', '黑龙江省', '');
INSERT INTO `el_qu_answer` (`id`, `qu_id`, `is_right`, `image`, `content`, `analysis`) VALUES ('1587622642846633986', '1587622642838245378', 1, '', '吉林省', '');
INSERT INTO `el_qu_answer` (`id`, `qu_id`, `is_right`, `image`, `content`, `analysis`) VALUES ('1587622642846633987', '1587622642838245378', 1, '', '辽宁省', '');
INSERT INTO `el_qu_answer` (`id`, `qu_id`, `is_right`, `image`, `content`, `analysis`) VALUES ('1587622642846633988', '1587622642838245378', 0, '', '河北省', '');
INSERT INTO `el_qu_answer` (`id`, `qu_id`, `is_right`, `image`, `content`, `analysis`) VALUES ('1587622642917937153', '1587622642909548545', 1, '', '正确', '');
INSERT INTO `el_qu_answer` (`id`, `qu_id`, `is_right`, `image`, `content`, `analysis`) VALUES ('1587622642917937154', '1587622642909548545', 0, '', '错误', '');
INSERT INTO `el_qu_answer` (`id`, `qu_id`, `is_right`, `image`, `content`, `analysis`) VALUES ('1587622642985046018', '1587622642976657410', 1, '', '正确', '');
INSERT INTO `el_qu_answer` (`id`, `qu_id`, `is_right`, `image`, `content`, `analysis`) VALUES ('1587622642989240321', '1587622642976657410', 0, '', '错误', '');
INSERT INTO `el_qu_answer` (`id`, `qu_id`, `is_right`, `image`, `content`, `analysis`) VALUES ('1587622643047960578', '1587622643039571970', 0, '', '工亚基础雄厚', '');
INSERT INTO `el_qu_answer` (`id`, `qu_id`, `is_right`, `image`, `content`, `analysis`) VALUES ('1587622643047960579', '1587622643039571970', 1, '', '拥有丰富的石油资源', '');
INSERT INTO `el_qu_answer` (`id`, `qu_id`, `is_right`, `image`, `content`, `analysis`) VALUES ('1587622643047960580', '1587622643039571970', 0, '', '第三产业在国内生产总值中的比重大', '');
INSERT INTO `el_qu_answer` (`id`, `qu_id`, `is_right`, `image`, `content`, `analysis`) VALUES ('1587622643052154882', '1587622643039571970', 0, '', '大力发展出口加工工业', '');
INSERT INTO `el_qu_answer` (`id`, `qu_id`, `is_right`, `image`, `content`, `analysis`) VALUES ('1587622643110875137', '1587622643102486530', 0, '', '铁岭', '');
INSERT INTO `el_qu_answer` (`id`, `qu_id`, `is_right`, `image`, `content`, `analysis`) VALUES ('1587622643110875138', '1587622643102486530', 0, '', '齐齐哈尔', '');
INSERT INTO `el_qu_answer` (`id`, `qu_id`, `is_right`, `image`, `content`, `analysis`) VALUES ('1587622643110875139', '1587622643102486530', 0, '', '沈阳', '');
INSERT INTO `el_qu_answer` (`id`, `qu_id`, `is_right`, `image`, `content`, `analysis`) VALUES ('1587622643110875140', '1587622643102486530', 1, '', '漠河', '');
INSERT INTO `el_qu_answer` (`id`, `qu_id`, `is_right`, `image`, `content`, `analysis`) VALUES ('1587622643182178305', '1587622643173789698', 0, '', '工业', '');
INSERT INTO `el_qu_answer` (`id`, `qu_id`, `is_right`, `image`, `content`, `analysis`) VALUES ('1587622643182178306', '1587622643173789698', 0, '', '建筑业', '');
INSERT INTO `el_qu_answer` (`id`, `qu_id`, `is_right`, `image`, `content`, `analysis`) VALUES ('1587622643182178307', '1587622643173789698', 1, '', '服务业', '');
INSERT INTO `el_qu_answer` (`id`, `qu_id`, `is_right`, `image`, `content`, `analysis`) VALUES ('1587622643182178308', '1587622643173789698', 0, '', '农业', '');
INSERT INTO `el_qu_answer` (`id`, `qu_id`, `is_right`, `image`, `content`, `analysis`) VALUES ('1587622643249287170', '1587622643240898561', 0, '', '东亚', '');
INSERT INTO `el_qu_answer` (`id`, `qu_id`, `is_right`, `image`, `content`, `analysis`) VALUES ('1587622643253481474', '1587622643240898561', 0, '', '东南亚', '');
INSERT INTO `el_qu_answer` (`id`, `qu_id`, `is_right`, `image`, `content`, `analysis`) VALUES ('1587622643253481475', '1587622643240898561', 0, '', '南亚', '');
INSERT INTO `el_qu_answer` (`id`, `qu_id`, `is_right`, `image`, `content`, `analysis`) VALUES ('1587622643253481476', '1587622643240898561', 1, '', '西亚', '');
INSERT INTO `el_qu_answer` (`id`, `qu_id`, `is_right`, `image`, `content`, `analysis`) VALUES ('1587622643324784642', '1587622643312201730', 0, '', '韩国', '');
INSERT INTO `el_qu_answer` (`id`, `qu_id`, `is_right`, `image`, `content`, `analysis`) VALUES ('1587622643324784643', '1587622643312201730', 0, '', '新加坡', '');
INSERT INTO `el_qu_answer` (`id`, `qu_id`, `is_right`, `image`, `content`, `analysis`) VALUES ('1587622643324784644', '1587622643312201730', 1, '', '日本', '');
INSERT INTO `el_qu_answer` (`id`, `qu_id`, `is_right`, `image`, `content`, `analysis`) VALUES ('1587622643324784645', '1587622643312201730', 0, '', '马来西亚', '');
INSERT INTO `el_qu_answer` (`id`, `qu_id`, `is_right`, `image`, `content`, `analysis`) VALUES ('1587622643404476417', '1587622643396087810', 1, '', '0度纬线稍长', '');
INSERT INTO `el_qu_answer` (`id`, `qu_id`, `is_right`, `image`, `content`, `analysis`) VALUES ('1587622643404476418', '1587622643396087810', 0, '', '0度经线稍长', '');
INSERT INTO `el_qu_answer` (`id`, `qu_id`, `is_right`, `image`, `content`, `analysis`) VALUES ('1587622643404476419', '1587622643396087810', 0, '', '相等', '');
INSERT INTO `el_qu_answer` (`id`, `qu_id`, `is_right`, `image`, `content`, `analysis`) VALUES ('1587622643404476420', '1587622643396087810', 0, '', '0度经线不到0度纬线的1/2', '');
INSERT INTO `el_qu_answer` (`id`, `qu_id`, `is_right`, `image`, `content`, `analysis`) VALUES ('1587622643479973889', '1587622643467390977', 1, '', '孟加拉国', '');
INSERT INTO `el_qu_answer` (`id`, `qu_id`, `is_right`, `image`, `content`, `analysis`) VALUES ('1587622643479973890', '1587622643467390977', 0, '', '印度尼西亚', '');
INSERT INTO `el_qu_answer` (`id`, `qu_id`, `is_right`, `image`, `content`, `analysis`) VALUES ('1587622643479973891', '1587622643467390977', 0, '', '日本', '');
INSERT INTO `el_qu_answer` (`id`, `qu_id`, `is_right`, `image`, `content`, `analysis`) VALUES ('1587622643479973892', '1587622643467390977', 0, '', '韩国', '');
INSERT INTO `el_qu_answer` (`id`, `qu_id`, `is_right`, `image`, `content`, `analysis`) VALUES ('1587622643563859970', '1587622643551277058', 0, '', '非洲', '');
INSERT INTO `el_qu_answer` (`id`, `qu_id`, `is_right`, `image`, `content`, `analysis`) VALUES ('1587622643563859971', '1587622643551277058', 0, '', '北美洲', '');
INSERT INTO `el_qu_answer` (`id`, `qu_id`, `is_right`, `image`, `content`, `analysis`) VALUES ('1587622643563859972', '1587622643551277058', 0, '', '大洋洲', '');
INSERT INTO `el_qu_answer` (`id`, `qu_id`, `is_right`, `image`, `content`, `analysis`) VALUES ('1587622643563859973', '1587622643551277058', 1, '', '亚洲', '');
INSERT INTO `el_qu_answer` (`id`, `qu_id`, `is_right`, `image`, `content`, `analysis`) VALUES ('1587622643635163138', '1587622643626774530', 1, '', '四季现象', '');
INSERT INTO `el_qu_answer` (`id`, `qu_id`, `is_right`, `image`, `content`, `analysis`) VALUES ('1587622643639357441', '1587622643626774530', 0, '', '昼夜交替', '');
INSERT INTO `el_qu_answer` (`id`, `qu_id`, `is_right`, `image`, `content`, `analysis`) VALUES ('1587622643639357442', '1587622643626774530', 0, '', '时间差异', '');
INSERT INTO `el_qu_answer` (`id`, `qu_id`, `is_right`, `image`, `content`, `analysis`) VALUES ('1587622643639357443', '1587622643626774530', 0, '', '日期差异', '');
INSERT INTO `el_qu_answer` (`id`, `qu_id`, `is_right`, `image`, `content`, `analysis`) VALUES ('1587622643702272001', '1587622643693883394', 1, '', '人们的求知、探秘和猎奇欲望的增长', '');
INSERT INTO `el_qu_answer` (`id`, `qu_id`, `is_right`, `image`, `content`, `analysis`) VALUES ('1587622643702272002', '1587622643693883394', 1, '', '交通工具的发展', '');
INSERT INTO `el_qu_answer` (`id`, `qu_id`, `is_right`, `image`, `content`, `analysis`) VALUES ('1587622643702272003', '1587622643693883394', 0, '', '促使不同国家的地区的文化交增进友谊', '');
INSERT INTO `el_qu_answer` (`id`, `qu_id`, `is_right`, `image`, `content`, `analysis`) VALUES ('1587622643702272004', '1587622643693883394', 1, '', '科学技术的进步', '');
INSERT INTO `el_qu_answer` (`id`, `qu_id`, `is_right`, `image`, `content`, `analysis`) VALUES ('1587622643765186561', '1587622643760992258', 1, '', '等高线稀疏', '');
INSERT INTO `el_qu_answer` (`id`, `qu_id`, `is_right`, `image`, `content`, `analysis`) VALUES ('1587622643769380865', '1587622643760992258', 1, '', '地形坡度和缓', '');
INSERT INTO `el_qu_answer` (`id`, `qu_id`, `is_right`, `image`, `content`, `analysis`) VALUES ('1587622643769380866', '1587622643760992258', 0, '', '隧道多', '');
INSERT INTO `el_qu_answer` (`id`, `qu_id`, `is_right`, `image`, `content`, `analysis`) VALUES ('1587622643769380867', '1587622643760992258', 0, '', '地形复杂', '');
INSERT INTO `el_qu_answer` (`id`, `qu_id`, `is_right`, `image`, `content`, `analysis`) VALUES ('1587622643832295426', '1587622643823906818', 1, 'http://localhost:8201/upload/file/2022/11/07/1589528211451133954.jpg', '南北半球的地转偏向力引起的各种运动旋转现象;', '');
INSERT INTO `el_qu_answer` (`id`, `qu_id`, `is_right`, `image`, `content`, `analysis`) VALUES ('1587622643832295427', '1587622643823906818', 1, '', '地球上不同经度的地方,有不同的地方时经度每隔15度,地方时相差一小时;', '');
INSERT INTO `el_qu_answer` (`id`, `qu_id`, `is_right`, `image`, `content`, `analysis`) VALUES ('1587622643832295428', '1587622643823906818', 1, 'http://localhost:8201/upload/file/2022/11/07/1589528315486650369.jpeg', '东西部地区的时间差现象,生物作息规律现象;', '');
INSERT INTO `el_qu_answer` (`id`, `qu_id`, `is_right`, `image`, `content`, `analysis`) VALUES ('1587622643832295429', '1587622643823906818', 1, '', '对地球形状的影响.地球自转所产生的惯性离心力,使得地球由两级向赤道逐渐膨胀,成为目前略扁的旋转椭球体。', '');
INSERT INTO `el_qu_answer` (`id`, `qu_id`, `is_right`, `image`, `content`, `analysis`) VALUES ('1587622643832295430', '1587622643823906818', 1, '', '昼夜更替现象,向着太阳的半球,是白天,背着太阳的半球,是黑夜;', '');
INSERT INTO `el_qu_answer` (`id`, `qu_id`, `is_right`, `image`, `content`, `analysis`) VALUES ('1587622643903598594', '1587622643895209985', 1, '', '根据太阳高度的差异,划分出五带:北寒、北温、热带、南温、南寒;', '');
INSERT INTO `el_qu_answer` (`id`, `qu_id`, `is_right`, `image`, `content`, `analysis`) VALUES ('1587622643903598595', '1587622643895209985', 1, '', '根据获得热量多少的时间差异,划分出四季:春、夏、秋、冬;', '');
INSERT INTO `el_qu_answer` (`id`, `qu_id`, `is_right`, `image`, `content`, `analysis`) VALUES ('1587622643903598596', '1587622643895209985', 1, '', '昼夜长短的变化现象;', '');
INSERT INTO `el_qu_answer` (`id`, `qu_id`, `is_right`, `image`, `content`, `analysis`) VALUES ('1587622643903598597', '1587622643895209985', 1, '', '正午太阳高度的变化;夏至日太阳直射北回归线,全球正午太阳高度从北回归线向南北两侧逐渐递减;二分日太阳直射赤道,全球正午太阳高度从赤道向两极递减,全球昼夜平分;冬至日太阳直射南回归线,全球正午高度从南回归线向南北两侧逐渐递减,南回归线及其以南的地区正午太阳高度达到最大值,北半球各纬度正午太阳高度达到最小值。', '');
INSERT INTO `el_qu_answer` (`id`, `qu_id`, `is_right`, `image`, `content`, `analysis`) VALUES ('1587622643983290369', '1587622643979096066', 1, '', '正确', '');
INSERT INTO `el_qu_answer` (`id`, `qu_id`, `is_right`, `image`, `content`, `analysis`) VALUES ('1587622643987484674', '1587622643979096066', 0, '', '错误', '');
INSERT INTO `el_qu_answer` (`id`, `qu_id`, `is_right`, `image`, `content`, `analysis`) VALUES ('1587622644058787842', '1587622644054593538', 0, '', '正确', '');
INSERT INTO `el_qu_answer` (`id`, `qu_id`, `is_right`, `image`, `content`, `analysis`) VALUES ('1587622644062982146', '1587622644054593538', 1, '', '错误', '');
INSERT INTO `el_qu_answer` (`id`, `qu_id`, `is_right`, `image`, `content`, `analysis`) VALUES ('1587622644138479618', '1587622644134285314', 1, '', '正确', '');
INSERT INTO `el_qu_answer` (`id`, `qu_id`, `is_right`, `image`, `content`, `analysis`) VALUES ('1587622644142673922', '1587622644134285314', 0, '', '错误', '');
INSERT INTO `el_qu_answer` (`id`, `qu_id`, `is_right`, `image`, `content`, `analysis`) VALUES ('1587622644209782786', '1587622644201394178', 0, '', '正确', '');
INSERT INTO `el_qu_answer` (`id`, `qu_id`, `is_right`, `image`, `content`, `analysis`) VALUES ('1587622644209782787', '1587622644201394178', 1, '', '错误', '');
INSERT INTO `el_qu_answer` (`id`, `qu_id`, `is_right`, `image`, `content`, `analysis`) VALUES ('1587622644289474562', '1587622644281085953', 1, '', '正确', '');
INSERT INTO `el_qu_answer` (`id`, `qu_id`, `is_right`, `image`, `content`, `analysis`) VALUES ('1587622644289474563', '1587622644281085953', 0, '', '错误', '');
INSERT INTO `el_qu_answer` (`id`, `qu_id`, `is_right`, `image`, `content`, `analysis`) VALUES ('1587622644364972034', '1587622644356583425', 1, '', '青海湖', '');
INSERT INTO `el_qu_answer` (`id`, `qu_id`, `is_right`, `image`, `content`, `analysis`) VALUES ('1587622644364972035', '1587622644356583425', 0, '', '太湖', '');
INSERT INTO `el_qu_answer` (`id`, `qu_id`, `is_right`, `image`, `content`, `analysis`) VALUES ('1587622644364972036', '1587622644356583425', 0, '', '洞庭湖', '');
INSERT INTO `el_qu_answer` (`id`, `qu_id`, `is_right`, `image`, `content`, `analysis`) VALUES ('1587622644369166338', '1587622644356583425', 0, '', '鄱阳湖', '');
COMMIT;
-- ----------------------------
-- Table structure for el_qu_repo
-- ----------------------------
DROP TABLE IF EXISTS `el_qu_repo`;
CREATE TABLE `el_qu_repo` (
`id` varchar(64) COLLATE utf8mb4_general_ci NOT NULL,
`qu_id` varchar(64) COLLATE utf8mb4_general_ci NOT NULL COMMENT '试题',
`repo_id` varchar(64) COLLATE utf8mb4_general_ci NOT NULL COMMENT '归属题库',
`qu_type` int NOT NULL DEFAULT '0' COMMENT '题目类型',
`sort` int NOT NULL DEFAULT '0' COMMENT '排序',
PRIMARY KEY (`id`) USING BTREE,
KEY `qu_id` (`qu_id`) USING BTREE,
KEY `repo_id` (`repo_id`) USING BTREE
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci COMMENT='试题题库关联';
-- ----------------------------
-- Records of el_qu_repo
-- ----------------------------
BEGIN;
INSERT INTO `el_qu_repo` (`id`, `qu_id`, `repo_id`, `qu_type`, `sort`) VALUES ('1587622670122192897', '1587622643760992258', '1587622451624120321', 2, 1);
INSERT INTO `el_qu_repo` (`id`, `qu_id`, `repo_id`, `qu_type`, `sort`) VALUES ('1587622670143164418', '1587622644281085953', '1587622451624120321', 3, 2);
INSERT INTO `el_qu_repo` (`id`, `qu_id`, `repo_id`, `qu_type`, `sort`) VALUES ('1587622670159941633', '1587622643626774530', '1587622451624120321', 1, 3);
INSERT INTO `el_qu_repo` (`id`, `qu_id`, `repo_id`, `qu_type`, `sort`) VALUES ('1587622670180913153', '1587622644134285314', '1587622451624120321', 3, 4);
INSERT INTO `el_qu_repo` (`id`, `qu_id`, `repo_id`, `qu_type`, `sort`) VALUES ('1587622670201884673', '1587622643979096066', '1587622451624120321', 3, 5);
INSERT INTO `el_qu_repo` (`id`, `qu_id`, `repo_id`, `qu_type`, `sort`) VALUES ('1587622670243827714', '1587622644356583425', '1587622451624120321', 1, 6);
INSERT INTO `el_qu_repo` (`id`, `qu_id`, `repo_id`, `qu_type`, `sort`) VALUES ('1587622670268993537', '1587622643693883394', '1587622451624120321', 2, 7);
INSERT INTO `el_qu_repo` (`id`, `qu_id`, `repo_id`, `qu_type`, `sort`) VALUES ('1587622670315130881', '1587622644201394178', '1587622451624120321', 3, 8);
INSERT INTO `el_qu_repo` (`id`, `qu_id`, `repo_id`, `qu_type`, `sort`) VALUES ('1587622670340296706', '1587622644054593538', '1587622451624120321', 3, 9);
INSERT INTO `el_qu_repo` (`id`, `qu_id`, `repo_id`, `qu_type`, `sort`) VALUES ('1587622670361268226', '1587622643895209985', '1587622451624120321', 2, 10);
INSERT INTO `el_qu_repo` (`id`, `qu_id`, `repo_id`, `qu_type`, `sort`) VALUES ('1587622670382239745', '1587622642641113089', '1587622451624120321', 1, 11);
INSERT INTO `el_qu_repo` (`id`, `qu_id`, `repo_id`, `qu_type`, `sort`) VALUES ('1587622670411599873', '1587622643102486530', '1587622451624120321', 1, 12);
INSERT INTO `el_qu_repo` (`id`, `qu_id`, `repo_id`, `qu_type`, `sort`) VALUES ('1587622670436765698', '1587622642473340930', '1587622451624120321', 1, 13);
INSERT INTO `el_qu_repo` (`id`, `qu_id`, `repo_id`, `qu_type`, `sort`) VALUES ('1587622670461931522', '1587622642976657410', '1587622451624120321', 3, 14);
INSERT INTO `el_qu_repo` (`id`, `qu_id`, `repo_id`, `qu_type`, `sort`) VALUES ('1587622670491291650', '1587622642263625729', '1587622451624120321', 1, 15);
INSERT INTO `el_qu_repo` (`id`, `qu_id`, `repo_id`, `qu_type`, `sort`) VALUES ('1587622670520651778', '1587622643467390977', '1587622451624120321', 1, 16);
INSERT INTO `el_qu_repo` (`id`, `qu_id`, `repo_id`, `qu_type`, `sort`) VALUES ('1587622670545817602', '1587622642838245378', '1587622451624120321', 2, 17);
INSERT INTO `el_qu_repo` (`id`, `qu_id`, `repo_id`, `qu_type`, `sort`) VALUES ('1587622670575177730', '1587622643312201730', '1587622451624120321', 1, 18);
INSERT INTO `el_qu_repo` (`id`, `qu_id`, `repo_id`, `qu_type`, `sort`) VALUES ('1587622670604537858', '1587622642699833345', '1587622451624120321', 1, 19);
INSERT INTO `el_qu_repo` (`id`, `qu_id`, `repo_id`, `qu_type`, `sort`) VALUES ('1587622670638092289', '1587622643173789698', '1587622451624120321', 1, 20);
INSERT INTO `el_qu_repo` (`id`, `qu_id`, `repo_id`, `qu_type`, `sort`) VALUES ('1587622670667452417', '1587622642557227009', '1587622451624120321', 1, 21);
INSERT INTO `el_qu_repo` (`id`, `qu_id`, `repo_id`, `qu_type`, `sort`) VALUES ('1587622670696812545', '1587622643039571970', '1587622451624120321', 1, 22);
INSERT INTO `el_qu_repo` (`id`, `qu_id`, `repo_id`, `qu_type`, `sort`) VALUES ('1587622670721978369', '1587622643551277058', '1587622451624120321', 1, 23);
INSERT INTO `el_qu_repo` (`id`, `qu_id`, `repo_id`, `qu_type`, `sort`) VALUES ('1587622670751338497', '1587622642393649153', '1587622451624120321', 1, 24);
INSERT INTO `el_qu_repo` (`id`, `qu_id`, `repo_id`, `qu_type`, `sort`) VALUES ('1587622670776504322', '1587622642909548545', '1587622451624120321', 3, 25);
INSERT INTO `el_qu_repo` (`id`, `qu_id`, `repo_id`, `qu_type`, `sort`) VALUES ('1587622670810058754', '1587622643396087810', '1587622451624120321', 1, 26);
INSERT INTO `el_qu_repo` (`id`, `qu_id`, `repo_id`, `qu_type`, `sort`) VALUES ('1587622670843613186', '1587622642762747906', '1587622451624120321', 2, 27);
INSERT INTO `el_qu_repo` (`id`, `qu_id`, `repo_id`, `qu_type`, `sort`) VALUES ('1587622670872973313', '1587622643240898561', '1587622451624120321', 1, 28);
INSERT INTO `el_qu_repo` (`id`, `qu_id`, `repo_id`, `qu_type`, `sort`) VALUES ('1589528323552296962', '1587622643823906818', '1587622451624120321', 2, 29);
COMMIT;
-- ----------------------------
-- Table structure for el_repo
-- ----------------------------
DROP TABLE IF EXISTS `el_repo`;
CREATE TABLE `el_repo` (
`id` varchar(64) CHARACTER SET utf8 NOT NULL COMMENT '题库ID',
`code` varchar(255) CHARACTER SET utf8 NOT NULL DEFAULT '' COMMENT '题库编号',
`title` varchar(255) CHARACTER SET utf8 NOT NULL COMMENT '题库名称',
`remark` varchar(255) CHARACTER SET utf8 NOT NULL DEFAULT '' COMMENT '题库备注',
`create_time` datetime DEFAULT NULL COMMENT '创建时间',
`update_time` datetime DEFAULT NULL COMMENT '更新时间',
PRIMARY KEY (`id`) USING BTREE
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci COMMENT='题库信息';
-- ----------------------------
-- Records of el_repo
-- ----------------------------
BEGIN;
INSERT INTO `el_repo` (`id`, `code`, `title`, `remark`, `create_time`, `update_time`) VALUES ('1587622451624120321', '', '【云帆】演示题库', '【云帆】演示题库', '2022-11-02 09:47:44', '2022-11-02 09:47:44');
COMMIT;
-- ----------------------------
-- Table structure for el_user_book
-- ----------------------------
DROP TABLE IF EXISTS `el_user_book`;
CREATE TABLE `el_user_book` (
`id` varchar(64) COLLATE utf8mb4_general_ci NOT NULL COMMENT 'ID',
`exam_id` varchar(32) COLLATE utf8mb4_general_ci NOT NULL COMMENT '考试ID',
`user_id` varchar(64) COLLATE utf8mb4_general_ci NOT NULL COMMENT '用户ID',
`qu_id` varchar(64) COLLATE utf8mb4_general_ci NOT NULL COMMENT '题目ID',
`create_time` datetime DEFAULT NULL COMMENT '加入时间',
`update_time` datetime DEFAULT NULL COMMENT '最近错误时间',
`wrong_count` int NOT NULL COMMENT '错误时间',
`title` varchar(1000) COLLATE utf8mb4_general_ci NOT NULL COMMENT '题目标题',
`sort` int NOT NULL COMMENT '错题序号',
PRIMARY KEY (`id`) USING BTREE,
KEY `user_id` (`user_id`),
KEY `sort` (`sort`),
KEY `exam_id` (`exam_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci COMMENT='错题本';
-- ----------------------------
-- Records of el_user_book
-- ----------------------------
BEGIN;
COMMIT;
-- ----------------------------
-- Table structure for el_user_exam
-- ----------------------------
DROP TABLE IF EXISTS `el_user_exam`;
CREATE TABLE `el_user_exam` (
`id` varchar(32) COLLATE utf8mb4_general_ci NOT NULL,
`user_id` varchar(32) COLLATE utf8mb4_general_ci NOT NULL COMMENT '用户ID',
`exam_id` varchar(32) COLLATE utf8mb4_general_ci NOT NULL COMMENT '考试ID',
`try_count` int NOT NULL DEFAULT '1' COMMENT '考试次数',
`max_score` int NOT NULL DEFAULT '0' COMMENT '最高分数',
`passed` tinyint NOT NULL DEFAULT '0' COMMENT '是否通过',
`create_time` datetime DEFAULT NULL COMMENT '创建时间',
`update_time` datetime DEFAULT NULL COMMENT '更新时间',
PRIMARY KEY (`id`) USING BTREE,
UNIQUE KEY `user_id` (`user_id`,`exam_id`) USING BTREE
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci COMMENT='考试记录';
-- ----------------------------
-- Records of el_user_exam
-- ----------------------------
BEGIN;
COMMIT;
-- ----------------------------
-- Table structure for QRTZ_BLOB_TRIGGERS
-- ----------------------------
DROP TABLE IF EXISTS `QRTZ_BLOB_TRIGGERS`;
CREATE TABLE `QRTZ_BLOB_TRIGGERS` (
`SCHED_NAME` varchar(120) COLLATE utf8mb4_general_ci NOT NULL,
`TRIGGER_NAME` varchar(200) COLLATE utf8mb4_general_ci NOT NULL,
`TRIGGER_GROUP` varchar(200) COLLATE utf8mb4_general_ci NOT NULL,
`BLOB_DATA` blob,
PRIMARY KEY (`SCHED_NAME`,`TRIGGER_NAME`,`TRIGGER_GROUP`),
CONSTRAINT `qrtz_blob_triggers_ibfk_1` FOREIGN KEY (`SCHED_NAME`, `TRIGGER_NAME`, `TRIGGER_GROUP`) REFERENCES `QRTZ_TRIGGERS` (`SCHED_NAME`, `TRIGGER_NAME`, `TRIGGER_GROUP`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci;
-- ----------------------------
-- Records of QRTZ_BLOB_TRIGGERS
-- ----------------------------
BEGIN;
COMMIT;
-- ----------------------------
-- Table structure for QRTZ_CALENDARS
-- ----------------------------
DROP TABLE IF EXISTS `QRTZ_CALENDARS`;
CREATE TABLE `QRTZ_CALENDARS` (
`SCHED_NAME` varchar(120) COLLATE utf8mb4_general_ci NOT NULL,
`CALENDAR_NAME` varchar(200) COLLATE utf8mb4_general_ci NOT NULL,
`CALENDAR` blob NOT NULL,
PRIMARY KEY (`SCHED_NAME`,`CALENDAR_NAME`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci;
-- ----------------------------
-- Records of QRTZ_CALENDARS
-- ----------------------------
BEGIN;
COMMIT;
-- ----------------------------
-- Table structure for QRTZ_CRON_TRIGGERS
-- ----------------------------
DROP TABLE IF EXISTS `QRTZ_CRON_TRIGGERS`;
CREATE TABLE `QRTZ_CRON_TRIGGERS` (
`SCHED_NAME` varchar(120) COLLATE utf8mb4_general_ci NOT NULL,
`TRIGGER_NAME` varchar(200) COLLATE utf8mb4_general_ci NOT NULL,
`TRIGGER_GROUP` varchar(200) COLLATE utf8mb4_general_ci NOT NULL,
`CRON_EXPRESSION` varchar(200) COLLATE utf8mb4_general_ci NOT NULL,
`TIME_ZONE_ID` varchar(80) COLLATE utf8mb4_general_ci DEFAULT NULL,
PRIMARY KEY (`SCHED_NAME`,`TRIGGER_NAME`,`TRIGGER_GROUP`),
CONSTRAINT `qrtz_cron_triggers_ibfk_1` FOREIGN KEY (`SCHED_NAME`, `TRIGGER_NAME`, `TRIGGER_GROUP`) REFERENCES `QRTZ_TRIGGERS` (`SCHED_NAME`, `TRIGGER_NAME`, `TRIGGER_GROUP`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci;
-- ----------------------------
-- Records of QRTZ_CRON_TRIGGERS
-- ----------------------------
BEGIN;
COMMIT;
-- ----------------------------
-- Table structure for QRTZ_FIRED_TRIGGERS
-- ----------------------------
DROP TABLE IF EXISTS `QRTZ_FIRED_TRIGGERS`;
CREATE TABLE `QRTZ_FIRED_TRIGGERS` (
`SCHED_NAME` varchar(120) COLLATE utf8mb4_general_ci NOT NULL,
`ENTRY_ID` varchar(95) COLLATE utf8mb4_general_ci NOT NULL,
`TRIGGER_NAME` varchar(200) COLLATE utf8mb4_general_ci NOT NULL,
`TRIGGER_GROUP` varchar(200) COLLATE utf8mb4_general_ci NOT NULL,
`INSTANCE_NAME` varchar(200) COLLATE utf8mb4_general_ci NOT NULL,
`FIRED_TIME` bigint NOT NULL,
`SCHED_TIME` bigint NOT NULL,
`PRIORITY` int NOT NULL,
`STATE` varchar(16) COLLATE utf8mb4_general_ci NOT NULL,
`JOB_NAME` varchar(200) COLLATE utf8mb4_general_ci DEFAULT NULL,
`JOB_GROUP` varchar(200) COLLATE utf8mb4_general_ci DEFAULT NULL,
`IS_NONCONCURRENT` varchar(1) COLLATE utf8mb4_general_ci DEFAULT NULL,
`REQUESTS_RECOVERY` varchar(1) COLLATE utf8mb4_general_ci DEFAULT NULL,
PRIMARY KEY (`SCHED_NAME`,`ENTRY_ID`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci;
-- ----------------------------
-- Records of QRTZ_FIRED_TRIGGERS
-- ----------------------------
BEGIN;
COMMIT;
-- ----------------------------
-- Table structure for QRTZ_JOB_DETAILS
-- ----------------------------
DROP TABLE IF EXISTS `QRTZ_JOB_DETAILS`;
CREATE TABLE `QRTZ_JOB_DETAILS` (
`SCHED_NAME` varchar(120) COLLATE utf8mb4_general_ci NOT NULL,
`JOB_NAME` varchar(200) COLLATE utf8mb4_general_ci NOT NULL,
`JOB_GROUP` varchar(200) COLLATE utf8mb4_general_ci NOT NULL,
`DESCRIPTION` varchar(250) COLLATE utf8mb4_general_ci DEFAULT NULL,
`JOB_CLASS_NAME` varchar(250) COLLATE utf8mb4_general_ci NOT NULL,
`IS_DURABLE` varchar(1) COLLATE utf8mb4_general_ci NOT NULL,
`IS_NONCONCURRENT` varchar(1) COLLATE utf8mb4_general_ci NOT NULL,
`IS_UPDATE_DATA` varchar(1) COLLATE utf8mb4_general_ci NOT NULL,
`REQUESTS_RECOVERY` varchar(1) COLLATE utf8mb4_general_ci NOT NULL,
`JOB_DATA` blob,
PRIMARY KEY (`SCHED_NAME`,`JOB_NAME`,`JOB_GROUP`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci;
-- ----------------------------
-- Records of QRTZ_JOB_DETAILS
-- ----------------------------
BEGIN;
COMMIT;
-- ----------------------------
-- Table structure for QRTZ_LOCKS
-- ----------------------------
DROP TABLE IF EXISTS `QRTZ_LOCKS`;
CREATE TABLE `QRTZ_LOCKS` (
`SCHED_NAME` varchar(120) COLLATE utf8mb4_general_ci NOT NULL,
`LOCK_NAME` varchar(40) COLLATE utf8mb4_general_ci NOT NULL,
PRIMARY KEY (`SCHED_NAME`,`LOCK_NAME`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci;
-- ----------------------------
-- Records of QRTZ_LOCKS
-- ----------------------------
BEGIN;
COMMIT;
-- ----------------------------
-- Table structure for QRTZ_PAUSED_TRIGGER_GRPS
-- ----------------------------
DROP TABLE IF EXISTS `QRTZ_PAUSED_TRIGGER_GRPS`;
CREATE TABLE `QRTZ_PAUSED_TRIGGER_GRPS` (
`SCHED_NAME` varchar(120) COLLATE utf8mb4_general_ci NOT NULL,
`TRIGGER_GROUP` varchar(200) COLLATE utf8mb4_general_ci NOT NULL,
PRIMARY KEY (`SCHED_NAME`,`TRIGGER_GROUP`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci;
-- ----------------------------
-- Records of QRTZ_PAUSED_TRIGGER_GRPS
-- ----------------------------
BEGIN;
COMMIT;
-- ----------------------------
-- Table structure for QRTZ_SCHEDULER_STATE
-- ----------------------------
DROP TABLE IF EXISTS `QRTZ_SCHEDULER_STATE`;
CREATE TABLE `QRTZ_SCHEDULER_STATE` (
`SCHED_NAME` varchar(120) COLLATE utf8mb4_general_ci NOT NULL,
`INSTANCE_NAME` varchar(200) COLLATE utf8mb4_general_ci NOT NULL,
`LAST_CHECKIN_TIME` bigint NOT NULL,
`CHECKIN_INTERVAL` bigint NOT NULL,
PRIMARY KEY (`SCHED_NAME`,`INSTANCE_NAME`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci;
-- ----------------------------
-- Records of QRTZ_SCHEDULER_STATE
-- ----------------------------
BEGIN;
INSERT INTO `QRTZ_SCHEDULER_STATE` (`SCHED_NAME`, `INSTANCE_NAME`, `LAST_CHECKIN_TIME`, `CHECKIN_INTERVAL`) VALUES ('examScheduler', 'MacBook-Pro-16.local1676860344454', 1676860726631, 10000);
COMMIT;
-- ----------------------------
-- Table structure for QRTZ_SIMPLE_TRIGGERS
-- ----------------------------
DROP TABLE IF EXISTS `QRTZ_SIMPLE_TRIGGERS`;
CREATE TABLE `QRTZ_SIMPLE_TRIGGERS` (
`SCHED_NAME` varchar(120) COLLATE utf8mb4_general_ci NOT NULL,
`TRIGGER_NAME` varchar(200) COLLATE utf8mb4_general_ci NOT NULL,
`TRIGGER_GROUP` varchar(200) COLLATE utf8mb4_general_ci NOT NULL,
`REPEAT_COUNT` bigint NOT NULL,
`REPEAT_INTERVAL` bigint NOT NULL,
`TIMES_TRIGGERED` bigint NOT NULL,
PRIMARY KEY (`SCHED_NAME`,`TRIGGER_NAME`,`TRIGGER_GROUP`),
CONSTRAINT `qrtz_simple_triggers_ibfk_1` FOREIGN KEY (`SCHED_NAME`, `TRIGGER_NAME`, `TRIGGER_GROUP`) REFERENCES `QRTZ_TRIGGERS` (`SCHED_NAME`, `TRIGGER_NAME`, `TRIGGER_GROUP`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci;
-- ----------------------------
-- Records of QRTZ_SIMPLE_TRIGGERS
-- ----------------------------
BEGIN;
COMMIT;
-- ----------------------------
-- Table structure for QRTZ_SIMPROP_TRIGGERS
-- ----------------------------
DROP TABLE IF EXISTS `QRTZ_SIMPROP_TRIGGERS`;
CREATE TABLE `QRTZ_SIMPROP_TRIGGERS` (
`SCHED_NAME` varchar(120) COLLATE utf8mb4_general_ci NOT NULL,
`TRIGGER_NAME` varchar(200) COLLATE utf8mb4_general_ci NOT NULL,
`TRIGGER_GROUP` varchar(200) COLLATE utf8mb4_general_ci NOT NULL,
`STR_PROP_1` varchar(512) COLLATE utf8mb4_general_ci DEFAULT NULL,
`STR_PROP_2` varchar(512) COLLATE utf8mb4_general_ci DEFAULT NULL,
`STR_PROP_3` varchar(512) COLLATE utf8mb4_general_ci DEFAULT NULL,
`INT_PROP_1` int DEFAULT NULL,
`INT_PROP_2` int DEFAULT NULL,
`LONG_PROP_1` bigint DEFAULT NULL,
`LONG_PROP_2` bigint DEFAULT NULL,
`DEC_PROP_1` decimal(13,4) DEFAULT NULL,
`DEC_PROP_2` decimal(13,4) DEFAULT NULL,
`BOOL_PROP_1` varchar(1) COLLATE utf8mb4_general_ci DEFAULT NULL,
`BOOL_PROP_2` varchar(1) COLLATE utf8mb4_general_ci DEFAULT NULL,
PRIMARY KEY (`SCHED_NAME`,`TRIGGER_NAME`,`TRIGGER_GROUP`),
CONSTRAINT `qrtz_simprop_triggers_ibfk_1` FOREIGN KEY (`SCHED_NAME`, `TRIGGER_NAME`, `TRIGGER_GROUP`) REFERENCES `QRTZ_TRIGGERS` (`SCHED_NAME`, `TRIGGER_NAME`, `TRIGGER_GROUP`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci;
-- ----------------------------
-- Records of QRTZ_SIMPROP_TRIGGERS
-- ----------------------------
BEGIN;
COMMIT;
-- ----------------------------
-- Table structure for QRTZ_TRIGGERS
-- ----------------------------
DROP TABLE IF EXISTS `QRTZ_TRIGGERS`;
CREATE TABLE `QRTZ_TRIGGERS` (
`SCHED_NAME` varchar(120) COLLATE utf8mb4_general_ci NOT NULL,
`TRIGGER_NAME` varchar(200) COLLATE utf8mb4_general_ci NOT NULL,
`TRIGGER_GROUP` varchar(200) COLLATE utf8mb4_general_ci NOT NULL,
`JOB_NAME` varchar(200) COLLATE utf8mb4_general_ci NOT NULL,
`JOB_GROUP` varchar(200) COLLATE utf8mb4_general_ci NOT NULL,
`DESCRIPTION` varchar(250) COLLATE utf8mb4_general_ci DEFAULT NULL,
`NEXT_FIRE_TIME` bigint DEFAULT NULL,
`PREV_FIRE_TIME` bigint DEFAULT NULL,
`PRIORITY` int DEFAULT NULL,
`TRIGGER_STATE` varchar(16) COLLATE utf8mb4_general_ci NOT NULL,
`TRIGGER_TYPE` varchar(8) COLLATE utf8mb4_general_ci NOT NULL,
`START_TIME` bigint NOT NULL,
`END_TIME` bigint DEFAULT NULL,
`CALENDAR_NAME` varchar(200) COLLATE utf8mb4_general_ci DEFAULT NULL,
`MISFIRE_INSTR` smallint DEFAULT NULL,
`JOB_DATA` blob,
PRIMARY KEY (`SCHED_NAME`,`TRIGGER_NAME`,`TRIGGER_GROUP`),
KEY `SCHED_NAME` (`SCHED_NAME`,`JOB_NAME`,`JOB_GROUP`),
CONSTRAINT `qrtz_triggers_ibfk_1` FOREIGN KEY (`SCHED_NAME`, `JOB_NAME`, `JOB_GROUP`) REFERENCES `QRTZ_JOB_DETAILS` (`SCHED_NAME`, `JOB_NAME`, `JOB_GROUP`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci;
-- ----------------------------
-- Records of QRTZ_TRIGGERS
-- ----------------------------
BEGIN;
COMMIT;
-- ----------------------------
-- Table structure for sys_config
-- ----------------------------
DROP TABLE IF EXISTS `sys_config`;
CREATE TABLE `sys_config` (
`id` varchar(32) COLLATE utf8mb4_general_ci NOT NULL COMMENT 'ID',
`site_name` varchar(255) COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT '系统名称',
`front_logo` varchar(255) COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT '前端LOGO',
`back_logo` varchar(255) COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT '后台LOGO',
`copy_right` varchar(255) COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT '版权信息',
`create_time` datetime DEFAULT NULL COMMENT '创建时间',
`update_time` datetime DEFAULT NULL COMMENT '更新时间',
`create_by` varchar(255) COLLATE utf8mb4_general_ci DEFAULT '' COMMENT '创建人',
`update_by` varchar(255) COLLATE utf8mb4_general_ci DEFAULT '' COMMENT '修改人',
`data_flag` int DEFAULT '0' COMMENT '数据标识',
PRIMARY KEY (`id`) USING BTREE
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci COMMENT='系统设置';
-- ----------------------------
-- Records of sys_config
-- ----------------------------
BEGIN;
INSERT INTO `sys_config` (`id`, `site_name`, `front_logo`, `back_logo`, `copy_right`, `create_time`, `update_time`, `create_by`, `update_by`, `data_flag`) VALUES ('1', '云帆在线培训考试系统', NULL, NULL, NULL, '2020-12-03 16:51:30', '2020-12-03 16:51:30', '', '', 1);
COMMIT;
-- ----------------------------
-- Table structure for sys_depart
-- ----------------------------
DROP TABLE IF EXISTS `sys_depart`;
CREATE TABLE `sys_depart` (
`id` varchar(32) COLLATE utf8mb4_general_ci NOT NULL COMMENT 'ID',
`dept_type` int NOT NULL DEFAULT '1' COMMENT '1公司2部门',
`parent_id` varchar(32) COLLATE utf8mb4_general_ci NOT NULL COMMENT '所属上级',
`dept_name` varchar(255) COLLATE utf8mb4_general_ci NOT NULL DEFAULT '' COMMENT '部门名称',
`dept_code` varchar(255) COLLATE utf8mb4_general_ci NOT NULL DEFAULT '' COMMENT '部门编码',
`sort` int NOT NULL DEFAULT '0' COMMENT '排序',
PRIMARY KEY (`id`) USING BTREE
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci COMMENT='部门信息';
-- ----------------------------
-- Records of sys_depart
-- ----------------------------
BEGIN;
INSERT INTO `sys_depart` (`id`, `dept_type`, `parent_id`, `dept_name`, `dept_code`, `sort`) VALUES ('1302853644578000898', 1, '0', '北京云帆互联科技有限公司', 'A01', 1);
INSERT INTO `sys_depart` (`id`, `dept_type`, `parent_id`, `dept_name`, `dept_code`, `sort`) VALUES ('1302855940200284161', 1, '1302855776496599041', '后端组', 'A01A01A01', 2);
INSERT INTO `sys_depart` (`id`, `dept_type`, `parent_id`, `dept_name`, `dept_code`, `sort`) VALUES ('1302855994843676674', 1, '1302855776496599041', '前端组', 'A01A01A02', 1);
INSERT INTO `sys_depart` (`id`, `dept_type`, `parent_id`, `dept_name`, `dept_code`, `sort`) VALUES ('1302856017283203073', 1, '1302855776496599041', '产品组', 'A01A01A03', 3);
INSERT INTO `sys_depart` (`id`, `dept_type`, `parent_id`, `dept_name`, `dept_code`, `sort`) VALUES ('1302856084475953154', 1, '1302855776496599041', '测试组', 'A01A01A05', 5);
INSERT INTO `sys_depart` (`id`, `dept_type`, `parent_id`, `dept_name`, `dept_code`, `sort`) VALUES ('1302856266567467010', 1, '1302855896415944705', '客户一组', 'A01A05A01', 1);
INSERT INTO `sys_depart` (`id`, `dept_type`, `parent_id`, `dept_name`, `dept_code`, `sort`) VALUES ('1302856320602685442', 1, '1302855896415944705', '客服二组', 'A01A05A02', 2);
INSERT INTO `sys_depart` (`id`, `dept_type`, `parent_id`, `dept_name`, `dept_code`, `sort`) VALUES ('1318103313740320770', 1, '1302853644578000898', '技术部', 'A01A01', 1);
INSERT INTO `sys_depart` (`id`, `dept_type`, `parent_id`, `dept_name`, `dept_code`, `sort`) VALUES ('1318103339229106178', 1, '1302853644578000898', '人事部', 'A01A02', 2);
INSERT INTO `sys_depart` (`id`, `dept_type`, `parent_id`, `dept_name`, `dept_code`, `sort`) VALUES ('1318103362494910465', 1, '1302853644578000898', '财务部', 'A01A03', 3);
COMMIT;
-- ----------------------------
-- Table structure for sys_role
-- ----------------------------
DROP TABLE IF EXISTS `sys_role`;
CREATE TABLE `sys_role` (
`id` varchar(32) COLLATE utf8mb4_general_ci NOT NULL COMMENT '角色ID',
`role_name` varchar(255) COLLATE utf8mb4_general_ci NOT NULL DEFAULT '' COMMENT '角色名称',
PRIMARY KEY (`id`) USING BTREE
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci COMMENT='角色';
-- ----------------------------
-- Records of sys_role
-- ----------------------------
BEGIN;
INSERT INTO `sys_role` (`id`, `role_name`) VALUES ('sa', '超级管理员');
INSERT INTO `sys_role` (`id`, `role_name`) VALUES ('student', '学员');
COMMIT;
-- ----------------------------
-- Table structure for sys_user
-- ----------------------------
DROP TABLE IF EXISTS `sys_user`;
CREATE TABLE `sys_user` (
`id` varchar(32) COLLATE utf8mb4_general_ci NOT NULL COMMENT 'ID',
`user_name` varchar(255) COLLATE utf8mb4_general_ci NOT NULL DEFAULT '' COMMENT '用户名',
`real_name` varchar(255) COLLATE utf8mb4_general_ci NOT NULL DEFAULT '' COMMENT '真实姓名',
`password` varchar(255) COLLATE utf8mb4_general_ci NOT NULL DEFAULT '' COMMENT '密码',
`salt` varchar(255) COLLATE utf8mb4_general_ci NOT NULL DEFAULT '' COMMENT '密码盐',
`role_ids` varchar(500) COLLATE utf8mb4_general_ci NOT NULL DEFAULT '' COMMENT '角色列表',
`depart_id` varchar(32) COLLATE utf8mb4_general_ci NOT NULL DEFAULT '' COMMENT '部门ID',
`create_time` datetime DEFAULT NULL COMMENT '创建时间',
`update_time` datetime DEFAULT NULL COMMENT '更新时间',
`state` int NOT NULL DEFAULT '0' COMMENT '状态',
`data_flag` int NOT NULL DEFAULT '0' COMMENT '0正常,1隐藏',
PRIMARY KEY (`id`) USING BTREE
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci COMMENT='管理用户';
-- ----------------------------
-- Records of sys_user
-- ----------------------------
BEGIN;
INSERT INTO `sys_user` (`id`, `user_name`, `real_name`, `password`, `salt`, `role_ids`, `depart_id`, `create_time`, `update_time`, `state`, `data_flag`) VALUES ('10001', 'admin', '超管A', '06681cd08837b21adf6b5ef9279d403d', 'XoFFuS', 'sa', '1318103313740320770', '2020-04-20 13:51:03', '2020-04-20 13:51:03', 0, 0);
INSERT INTO `sys_user` (`id`, `user_name`, `real_name`, `password`, `salt`, `role_ids`, `depart_id`, `create_time`, `update_time`, `state`, `data_flag`) VALUES ('1252125239901696002', 'person', '张三', '6dfdd6761a3e8319719f32abb9aeae9c', 'tZCjLq', 'student', '1318103339229106178', '2020-04-20 14:41:35', '2020-04-20 14:41:35', 0, 0);
COMMIT;
-- ----------------------------
-- Table structure for sys_user_role
-- ----------------------------
DROP TABLE IF EXISTS `sys_user_role`;
CREATE TABLE `sys_user_role` (
`id` varchar(32) COLLATE utf8mb4_general_ci NOT NULL COMMENT 'ID',
`user_id` varchar(32) COLLATE utf8mb4_general_ci NOT NULL COMMENT '用户ID',
`role_id` varchar(32) COLLATE utf8mb4_general_ci NOT NULL COMMENT '角色ID',
PRIMARY KEY (`id`) USING BTREE
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci COMMENT='用户角色';
-- ----------------------------
-- Records of sys_user_role
-- ----------------------------
BEGIN;
INSERT INTO `sys_user_role` (`id`, `user_id`, `role_id`) VALUES ('1318103579445284865', '10001', 'sa');
INSERT INTO `sys_user_role` (`id`, `user_id`, `role_id`) VALUES ('1318128865264132097', '1252125239901696002', 'student');
INSERT INTO `sys_user_role` (`id`, `user_id`, `role_id`) VALUES ('1587574421424279555', '1587574421424279554', 'student');
COMMIT;
SET FOREIGN_KEY_CHECKS = 1;

@ -1,4 +0,0 @@
1、把运行包中的exam-api.jar和application-local.yml复制到本目录
2、运行命令注册为Windows系统服务yf-exam.exe install
3、在服务中即可找到名称为CloudExam的服务启动即可告别黑窗烦恼
注:本功能适合.NetFramework 4.0版本,如果无法注册,请检查环境是否匹配

@ -1,8 +0,0 @@
<service>
<id>yf-exam</id>
<name>CloudExam</name>
<description>云帆在线考试系统服务运行在http://localhost:8101</description>
<executable>java</executable>
<arguments>-jar exam-api.jar --spring.config.location=application-local.yml</arguments>
<log mode="roll"></log>
</service>

@ -1,85 +0,0 @@
# 独立配置文件可以拿到jar外面跑
spring:
application:
name: yf-exam-lite
profiles:
active: dev
main:
allow-bean-definition-overriding: true
# 数据库配置
datasource:
type: com.alibaba.druid.pool.DruidDataSource
driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://localhost:3306/yf_exam?useSSL=false&serverTimezone=Asia/Shanghai&useUnicode=true&characterEncoding=utf-8&allowPublicKeyRetrieval=true
username: root
password: 20040813@shl
# druid相关配置
druid:
max-active: 5000
initial-size: 20
min-idle: 5
async-init: true
# 监控统计
filters: stat,wall
filter:
stat:
log-slow-sql: true
slow-sql-millis: 5000
wall:
config:
create-table-allow: false
alter-table-allow: false
drop-table-allow: false
truncate-allow: false
# 定时任务配置
quartz:
# 数据库方式
job-store-type: jdbc
# quartz 相关属性配置
properties:
org:
quartz:
scheduler:
instanceName: examScheduler
instanceId: AUTO
jobStore:
class: org.quartz.impl.jdbcjobstore.JobStoreTX
driverDelegateClass: org.quartz.impl.jdbcjobstore.StdJDBCDelegate
tablePrefix: QRTZ_
isClustered: true
clusterCheckinInterval: 10000
useProperties: false
threadPool:
class: org.quartz.simpl.SimpleThreadPool
threadCount: 10
threadPriority: 5
threadsInheritContextClassLoaderOfInitializingThread: true
server:
port: 8101
# 启用服务端压缩
compression:
enabled: true
min-response-size: 10
mime-types: application/json,application/xml,text/html,text/xml,text/plain,application/javascript,text/css
# 文件上传配置
conf:
upload:
# 物理文件存储位置,以/结束windows已正斜杠d:/exam-upload/
dir: C:\Users\15775\Desktop\yfexam-exam-main\exam-api\src\main\java\com\yf\exam\ability/upload/
# 访问地址,注意不要去除/upload/file/,此节点为虚拟标识符
# 如http://localhost:8101/upload/file/exam.jpg对应物理文件为/data/upload/exam.jpg
url: http://localhost:8101/upload/file/
# 允许上传的文件后缀
allow-extensions: jpg,jpeg,png
# 开启文档
swagger:
enable: true
logging:
level:
root: debug
path: logs/${spring.application.name}/

File diff suppressed because one or more lines are too long

@ -1 +0,0 @@
java -jar exam-api.jar --spring.config.location=application-local.yml

@ -1 +0,0 @@
java -jar exam-api.jar --spring.config.location=application-local.yml

@ -1,7 +0,0 @@
1、下载编译好的jar包到本目录或您自行编译https://cdn.yfhl.net/lite/exam-api.jar
2、自行安装MySQL数据库版本最好是5.7),将`安装资源中`的`数据库初始化.sql`导入到安装好的数据库
3、安装Java环境要求JDK版本大于1.8
4、请修改外置配置文件application-local.yml 改成您自己的MySQL配置
5、Windows通过start.bat运行Linux运行start.sh运行
6、如果无意外可通过http://localhost:8101 访问到项目了
7、管理员账号密码admin/admin 学员账号person/person

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.2 MiB

@ -1,215 +0,0 @@
<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/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.yfhl</groupId>
<artifactId>exam-api</artifactId>
<packaging>jar</packaging>
<version>1.0</version>
<name>exam-api</name>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.1.4.RELEASE</version>
</parent>
<properties>
<fastjson.version>2.0.24</fastjson.version>
<oss.version>3.7.0</oss.version>
<aliyun.sdk.version>4.1.1</aliyun.sdk.version>
<swagger.version>2.9.2</swagger.version>
<dozer.version>5.5.1</dozer.version>
<apache.commons.version>3.8</apache.commons.version>
<mysql.driver.version>8.0.11</mysql.driver.version>
<mybatis-plus.version>3.4.1</mybatis-plus.version>
<lombok.version>1.18.4</lombok.version>
<thymeleaf.version>3.0.11.RELEASE</thymeleaf.version>
<alicloud.version>2.1.1.RELEASE</alicloud.version>
<poi.version>3.9</poi.version>
<log4j2.version>2.17.2</log4j2.version>
</properties>
<dependencies>
<!-- WEB支持 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!--spring quartz依赖-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-quartz</artifactId>
</dependency>
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<version>1.9.5</version>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>${fastjson.version}</version>
</dependency>
<dependency>
<groupId>net.sf.dozer</groupId>
<artifactId>dozer</artifactId>
<version>${dozer.version}</version>
<exclusions>
<exclusion>
<groupId>commons-collections</groupId>
<artifactId>commons-collections</artifactId>
</exclusion>
<exclusion>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus</artifactId>
<version>${mybatis-plus.version}</version>
</dependency>
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<version>${mybatis-plus.version}</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>${mysql.driver.version}</version>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>${lombok.version}</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.dom4j</groupId>
<artifactId>dom4j</artifactId>
<version>2.1.1</version>
</dependency>
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger2</artifactId>
<version>${swagger.version}</version>
<exclusions>
<exclusion>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>com.github.xiaoymin</groupId>
<artifactId>swagger-bootstrap-ui</artifactId>
<version>1.9.3</version>
</dependency>
<!-- poi office -->
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi</artifactId>
<version>${poi.version}</version>
</dependency>
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi-ooxml</artifactId>
<version>${poi.version}</version>
</dependency>
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi-ooxml-schemas</artifactId>
<version>${poi.version}</version>
</dependency>
<!--JWT-->
<dependency>
<groupId>com.auth0</groupId>
<artifactId>java-jwt</artifactId>
<version>3.7.0</version>
</dependency>
<!-- Shiro -->
<dependency>
<groupId>org.apache.shiro</groupId>
<artifactId>shiro-spring-boot-starter</artifactId>
<version>1.8.0</version>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid-spring-boot-starter</artifactId>
<version>1.2.6</version>
</dependency>
<dependency>
<groupId>commons-io</groupId>
<artifactId>commons-io</artifactId>
<version>2.11.0</version>
</dependency>
</dependencies>
<build>
<finalName>${project.name}</finalName>
<defaultGoal>compile</defaultGoal>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<executions>
<execution>
<goals>
<goal>repackage</goal>
</goals>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.7.0</version>
<configuration>
<source>1.8</source>
<target>1.8</target>
<encoding>UTF-8</encoding>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>2.22.1</version>
<configuration>
<skipTests>true</skipTests>
</configuration>
</plugin>
</plugins>
</build>
</project>

@ -1,53 +0,0 @@
package com.yf.exam;
import com.yf.exam.core.api.utils.JsonConverter;
import lombok.extern.log4j.Log4j2;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.core.env.Environment;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
import java.net.InetAddress;
import java.net.UnknownHostException;
import java.util.List;
/**
* 线
* @author bool
* @email 18365918@qq.com
* @date 2020-03-04 19:41
*/
@Log4j2
@SpringBootApplication
public class ExamApplication implements WebMvcConfigurer {
public static void main(String[] args) throws UnknownHostException {
ConfigurableApplicationContext application = SpringApplication.run(ExamApplication.class, args);
Environment env = application.getEnvironment();
String ip = InetAddress.getLocalHost().getHostAddress();
String port = env.getProperty("server.port");
String path = env.getProperty("server.servlet.context-path");
// 未配置默认空白
if(path == null){
path = "";
}
log.info("\n----------------------------------------------------------\n\t" +
"云帆考试系统启动成功,访问路径如下:\n\t" +
"本地路径: \t\thttp://localhost:" + port + path + "/\n\t" +
"网络地址: \thttp://" + ip + ":" + port + path + "/\n\t" +
"API文档: \t\thttp://" + ip + ":" + port + path + "/doc.html\n" +
"----------------------------------------------------------");
}
@Override
public void extendMessageConverters(List<HttpMessageConverter<?>> converters) {
//保留原有converter,把新增fastConverter插入集合头,保证优先级
converters.add(0, JsonConverter.fastConverter());
}
}

@ -1,15 +0,0 @@
package com.yf.exam.ability;
/**
*
* @author bool
*/
public class Constant {
/**
*
*/
public static final String FILE_PREFIX = "/upload/file/";
}

@ -1,13 +0,0 @@
package com.yf.exam.ability.job.enums;
/**
*
* @author van
*/
public interface JobGroup {
/**
*
*/
String SYSTEM = "system";
}

@ -1,14 +0,0 @@
package com.yf.exam.ability.job.enums;
/**
*
* @author bool
*/
public interface JobPrefix {
/**
*
*/
String BREAK_EXAM = "break_exam_";
}

@ -1,53 +0,0 @@
package com.yf.exam.ability.job.service;
/**
*
* @author bool
* @date 2020/11/29 2:17
*/
public interface JobService {
/**
*
*/
String TASK_DATA = "taskData";
/**
*
* @param jobClass
* @param jobName
* @param cron
* @param data
*/
void addCronJob(Class jobClass, String jobName, String cron, String data);
/**
*
* @param jobClass
* @param jobName
* @param data
*/
void addCronJob(Class jobClass, String jobName, String data);
/**
*
* @param jobName
* @param jobGroup
*/
void pauseJob(String jobName, String jobGroup);
/**
*
* @param triggerName
* @param triggerGroup
*/
void resumeJob(String triggerName, String triggerGroup);
/**
* job
* @param jobName
* @param jobGroup
*/
void deleteJob(String jobName, String jobGroup);
}

@ -1,123 +0,0 @@
package com.yf.exam.ability.job.service.impl;
import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.toolkit.IdWorker;
import com.yf.exam.ability.job.enums.JobGroup;
import com.yf.exam.ability.job.service.JobService;
import lombok.extern.log4j.Log4j2;
import org.quartz.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.quartz.SchedulerFactoryBean;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;
/**
* @author bool
*/
@Log4j2
@Service
public class JobServiceImpl implements JobService {
/**
* Quartz
*/
private Scheduler scheduler;
/**
*
* @param schedulerFactoryBean
*/
public JobServiceImpl(@Autowired SchedulerFactoryBean schedulerFactoryBean) {
scheduler = schedulerFactoryBean.getScheduler();
}
@Override
public void addCronJob(Class jobClass, String jobName, String cron, String data) {
String jobGroup = JobGroup.SYSTEM;
// 自动命名
if(StringUtils.isEmpty(jobName)){
jobName = jobClass.getSimpleName().toUpperCase() + "_"+IdWorker.getIdStr();
}
try {
JobKey jobKey = JobKey.jobKey(jobName, jobGroup);
JobDetail jobDetail = scheduler.getJobDetail(jobKey);
if (jobDetail != null) {
log.info("++++++++++任务:{} 已存在", jobName);
this.deleteJob(jobName, jobGroup);
}
log.info("++++++++++构建任务:{},{},{},{},{} ", jobClass.toString(), jobName, jobGroup, cron, data);
//构建job信息
jobDetail = JobBuilder.newJob(jobClass).withIdentity(jobName, jobGroup).build();
//用JopDataMap来传递数据
jobDetail.getJobDataMap().put(TASK_DATA, data);
//按新的cronExpression表达式构建一个新的trigger
Trigger trigger = null;
// 有表达式的按表达式
if(!StringUtils.isEmpty(cron)){
log.info("+++++表达式执行:"+ JSON.toJSONString(jobDetail));
//表达式调度构建器
CronScheduleBuilder scheduleBuilder = CronScheduleBuilder.cronSchedule(cron);
trigger = TriggerBuilder.newTrigger().withIdentity(jobName, jobGroup).withSchedule(scheduleBuilder).build();
}else{
// 无表达式则立即执行
log.info("+++++立即执行:"+ JSON.toJSONString(jobDetail));
trigger = TriggerBuilder.newTrigger().withIdentity(jobName, jobGroup).startNow().build();
}
scheduler.scheduleJob(jobDetail, trigger);
} catch (Exception e) {
e.printStackTrace();
}
}
@Override
public void addCronJob(Class jobClass, String jobName, String data) {
// 立即执行任务
this.addCronJob(jobClass, jobName, null, data);
}
@Override
public void pauseJob(String jobName, String jobGroup) {
try {
TriggerKey triggerKey = TriggerKey.triggerKey(jobName, jobGroup);
scheduler.pauseTrigger(triggerKey);
log.info("++++++++++暂停任务:{}", jobName);
} catch (SchedulerException e) {
e.printStackTrace();
}
}
@Override
public void resumeJob(String jobName, String jobGroup) {
try {
TriggerKey triggerKey = TriggerKey.triggerKey(jobName, jobGroup);
scheduler.resumeTrigger(triggerKey);
log.info("++++++++++重启任务:{}", jobName);
} catch (SchedulerException e) {
e.printStackTrace();
}
}
@Override
public void deleteJob(String jobName, String jobGroup) {
try {
JobKey jobKey = JobKey.jobKey(jobName,jobGroup);
scheduler.deleteJob(jobKey);
log.info("++++++++++删除任务:{}", jobKey);
} catch (SchedulerException e) {
e.printStackTrace();
}
}
}

@ -1,29 +0,0 @@
package com.yf.exam.ability.shiro;
import org.apache.shiro.spring.web.ShiroFilterFactoryBean;
import org.apache.shiro.web.filter.InvalidRequestFilter;
import org.apache.shiro.web.filter.mgt.DefaultFilter;
import org.apache.shiro.web.filter.mgt.FilterChainManager;
import javax.servlet.Filter;
import java.util.Map;
/**
* URL
* 400https://youdomain.com/upload/file/云帆考试系统用户手册.pdf
* @author van
*/
public class CNFilterFactoryBean extends ShiroFilterFactoryBean {
@Override
protected FilterChainManager createFilterChainManager() {
FilterChainManager manager = super.createFilterChainManager();
// URL携带中文400servletPath中文校验bug
Map<String, Filter> filterMap = manager.getFilters();
Filter invalidRequestFilter = filterMap.get(DefaultFilter.invalidRequest.name());
if (invalidRequestFilter instanceof InvalidRequestFilter) {
((InvalidRequestFilter) invalidRequestFilter).setBlockNonAscii(false);
}
return manager;
}
}

@ -1,131 +0,0 @@
package com.yf.exam.ability.shiro;
import com.yf.exam.ability.shiro.jwt.JwtToken;
import com.yf.exam.ability.shiro.jwt.JwtUtils;
import com.yf.exam.modules.sys.user.dto.response.SysUserLoginDTO;
import com.yf.exam.modules.sys.user.service.SysUserRoleService;
import com.yf.exam.modules.sys.user.service.SysUserService;
import lombok.extern.slf4j.Slf4j;
import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.AuthenticationInfo;
import org.apache.shiro.authc.AuthenticationToken;
import org.apache.shiro.authc.SimpleAuthenticationInfo;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.authz.SimpleAuthorizationInfo;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Component;
import java.util.HashSet;
import java.util.List;
/**
*
* @author bool
*/
@Component
@Slf4j
public class ShiroRealm extends AuthorizingRealm {
@Autowired
@Lazy
private SysUserService sysUserService;
@Autowired
@Lazy
private SysUserRoleService sysUserRoleService;
@Override
public boolean supports(AuthenticationToken token) {
return token instanceof JwtToken;
}
/**
*
* @param principals
* @return
*/
@Override
protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
String userId = null;
if (principals != null) {
SysUserLoginDTO user = (SysUserLoginDTO) principals.getPrimaryPrincipal();
userId = user.getId();
}
SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();
// 查找用户角色
List<String> roles = sysUserRoleService.listRoles(userId);
info.setRoles(new HashSet<>(roles));
log.info("++++++++++校验详细权限完成");
return info;
}
/**
*
* @param auth
* @return
* @throws AuthenticationException
*/
@Override
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken auth) throws AuthenticationException {
String token = (String) auth.getCredentials();
if (token == null) {
throw new AuthenticationException("token为空!");
}
// 校验token有效性
SysUserLoginDTO user = this.checkToken(token);
return new SimpleAuthenticationInfo(user, token, getName());
}
/**
* Token
* @param token
* @return
* @throws AuthenticationException
*/
public SysUserLoginDTO checkToken(String token) throws AuthenticationException {
// 查询用户信息
log.debug("++++++++++校验用户token "+ token);
// 从token中获取用户名
String username = JwtUtils.getUsername(token);
log.debug("++++++++++用户名: "+ username);
if (username == null) {
throw new AuthenticationException("无效的token");
}
// 查找登录用户对象
SysUserLoginDTO user = sysUserService.token(token);
// 校验token是否失效
if (!JwtUtils.verify(token, username)) {
throw new AuthenticationException("登陆失效,请重试登陆!");
}
return user;
}
/**
*
* @param principals
*/
@Override
public void clearCache(PrincipalCollection principals) {
super.clearCache(principals);
}
}

@ -1,53 +0,0 @@
package com.yf.exam.ability.shiro.aop;
import com.yf.exam.ability.shiro.jwt.JwtToken;
import com.yf.exam.aspect.utils.InjectUtils;
import com.yf.exam.modules.Constant;
import lombok.extern.slf4j.Slf4j;
import org.apache.shiro.web.filter.authc.BasicHttpAuthenticationFilter;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
/**
*
* @author bool
*/
@Slf4j
public class JwtFilter extends BasicHttpAuthenticationFilter {
/**
*
* @param request
* @param response
* @param mappedValue
* @return
*/
@Override
protected boolean isAccessAllowed(ServletRequest request, ServletResponse response, Object mappedValue) {
try {
executeLogin(request, response);
return true;
} catch (Exception e) {
// 写出统一错误信息
InjectUtils.restError((HttpServletResponse) response);
return false;
}
}
@Override
protected boolean executeLogin(ServletRequest request, ServletResponse response) throws Exception {
HttpServletRequest httpServletRequest = (HttpServletRequest) request;
String token = httpServletRequest.getHeader(Constant.TOKEN);
JwtToken jwtToken = new JwtToken(token);
// 提交给realm进行登入如果错误他会抛出异常并被捕获
getSubject(request, response).login(jwtToken);
// 如果没有抛出异常则代表登入成功返回true
return true;
}
}

@ -1,33 +0,0 @@
package com.yf.exam.ability.shiro.jwt;
import lombok.Data;
import org.apache.shiro.authc.AuthenticationToken;
/**
* @author bool
*/
@Data
public class JwtToken implements AuthenticationToken {
private static final long serialVersionUID = 1L;
/**
* JWTtoken
*/
private String token;
public JwtToken(String token) {
this.token = token;
}
@Override
public Object getPrincipal() {
return token;
}
@Override
public Object getCredentials() {
return token;
}
}

@ -1,99 +0,0 @@
package com.yf.exam.ability.shiro.jwt;
import com.auth0.jwt.JWT;
import com.auth0.jwt.JWTVerifier;
import com.auth0.jwt.algorithms.Algorithm;
import com.auth0.jwt.exceptions.JWTDecodeException;
import com.auth0.jwt.interfaces.DecodedJWT;
import com.yf.exam.core.utils.file.Md5Util;
import java.util.Calendar;
import java.util.Date;
/**
* JWT
* @author bool
*/
public class JwtUtils {
/**
* 24
*/
private static final long EXPIRE_TIME = 24 * 60 * 60 * 1000;
/**
*
* @param token
* @param username
* @return
*/
public static boolean verify(String token, String username) {
try {
// 根据密码生成JWT效验器
Algorithm algorithm = Algorithm.HMAC256(encryptSecret(username));
JWTVerifier verifier = JWT.require(algorithm)
.withClaim("username", username)
.build();
// 效验TOKEN
verifier.verify(token);
return true;
} catch (Exception exception) {
return false;
}
}
/**
* Token
* @param token
* @return
*/
public static String getUsername(String token) {
try {
DecodedJWT jwt = JWT.decode(token);
return jwt.getClaim("username").asString();
} catch (JWTDecodeException e) {
return null;
}
}
/**
* JWT Token
* @param username
* @return
*/
public static String sign(String username) {
Date date = new Date(System.currentTimeMillis() + EXPIRE_TIME);
Algorithm algorithm = Algorithm.HMAC256(encryptSecret(username));
// 附带username信息
return JWT.create()
.withClaim("username", username)
.withExpiresAt(date).sign(algorithm);
}
/**
* JWT
* @param userName
* @return
*/
private static String encryptSecret(String userName){
// 一个简单的登录规则,用户名+当前月份为加密串,意思每个月会变,要重新登录
// 可自行修改此规则
Calendar cl = Calendar.getInstance();
cl.setTimeInMillis(System.currentTimeMillis());
StringBuffer sb = new StringBuffer(userName)
.append("&")
.append(cl.get(Calendar.MONTH));
// 获取MD5
String secret = Md5Util.md5(sb.toString());
return Md5Util.md5(userName + "&" + secret);
}
}

@ -1,32 +0,0 @@
package com.yf.exam.ability.upload.config;
import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Configuration;
/**
*
* @author van
*/
@Data
@Configuration
@ConfigurationProperties(prefix = "conf.upload")
public class UploadConfig {
/**
* 访
*/
private String url;
/**
*
*/
private String dir;
/**
*
*/
private String [] allowExtensions;
}

@ -1,57 +0,0 @@
package com.yf.exam.ability.upload.controller;
import com.yf.exam.ability.Constant;
import com.yf.exam.ability.upload.dto.UploadReqDTO;
import com.yf.exam.ability.upload.dto.UploadRespDTO;
import com.yf.exam.ability.upload.service.UploadService;
import com.yf.exam.core.api.ApiRest;
import com.yf.exam.core.api.controller.BaseController;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.log4j.Log4j2;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RestController;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
/**
*
* @author bool
*/
@Log4j2
@Api(tags = {"文件上传"})
@RestController
public class UploadController extends BaseController {
@Autowired
private UploadService uploadService;
/**
*
* @param reqDTO
* @return
*/
@PostMapping("/common/api/file/upload")
@ApiOperation(value = "文件上传", notes = "此接口较为特殊参数都通过表单方式提交而非JSON")
public ApiRest<UploadRespDTO> upload(@ModelAttribute UploadReqDTO reqDTO) {
// 上传并返回URL
UploadRespDTO respDTO = uploadService.upload(reqDTO);
return super.success(respDTO);
}
/**
*
* @param request
* @param response
*/
@GetMapping(Constant.FILE_PREFIX+"**")
@ApiOperation(value = "文件下载", notes = "文件下载")
public void download(HttpServletRequest request, HttpServletResponse response) {
uploadService.download(request, response);
}
}

@ -1,22 +0,0 @@
package com.yf.exam.ability.upload.dto;
import com.yf.exam.core.api.dto.BaseDTO;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import org.springframework.web.multipart.MultipartFile;
/**
*
* @author
* @date 2019-12-26 17:54
*/
@Data
@ApiModel(value="文件上传参数", description="文件上传参数")
public class UploadReqDTO extends BaseDTO {
@ApiModelProperty(value = "上传文件内容", required=true)
private MultipartFile file;
}

@ -1,23 +0,0 @@
package com.yf.exam.ability.upload.dto;
import com.yf.exam.core.api.dto.BaseDTO;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
/**
*
* @author bool
*/
@Data
@AllArgsConstructor
@NoArgsConstructor
@ApiModel(value="文件上传响应", description="文件上传响应")
public class UploadRespDTO extends BaseDTO {
@ApiModelProperty(value = "上传后的完整的URL地址", required=true)
private String url;
}

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

Loading…
Cancel
Save