From 24210dd1b7d1448d766c19fe536c0c11d33c0fdd Mon Sep 17 00:00:00 2001 From: huababa1 <2037205722@qq.com> Date: Sat, 18 Oct 2025 15:28:35 +0800 Subject: [PATCH] =?UTF-8?q?=E3=80=90=E4=BF=AE=E6=94=B9=E3=80=91=E8=A1=A8?= =?UTF-8?q?=E6=A0=BC=E4=BF=AE=E6=94=B9=E9=A1=B9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../admin/app/AppCheckController.java | 3 +- .../admin/monitor/vo/MonitorPageReqVO.java | 4 +- .../admin/monitor/vo/MonitorRespVO.java | 3 + .../paper/EducationPaperTaskController.java | 26 +- .../admin/paper/vo/PaperTaskPageVo.java | 1 + .../specialty/ExamSpecialtyController.java | 3 +- .../module/exam/dal/dataobject/AdminUser.java | 129 +++++++++ .../dal/dataobject/EducationPaperTask.java | 2 + .../exam/dal/dataobject/TenantSpcialty.java | 24 ++ .../mysql/paper/EducationPaperTaskMapper.java | 28 +- .../mysql/specialty/ExamSpecialtyMapper.java | 5 + .../service/monitor/MonitorServiceImpl.java | 4 +- .../monitor/MonitorTaskServiceImpl.java | 5 +- .../EducationPaperSchemeServiceImpl.java | 30 +- .../paper/EducationPaperServiceImpl.java | 4 +- .../EducationPaperSessionServiceImpl.java | 6 + .../paper/EducationPaperTaskServiceImpl.java | 261 +++++++++++++++++- .../paper/IEducationPaperTaskService.java | 2 + .../exam/EducationPaperSessionMapper.xml | 1 + .../mapper/exam/EducationPaperTaskMapper.xml | 6 +- .../mapper/monitor/MonitorMapper.xml | 1 - .../mapper/specialty/ExamSpecialtyMapper.xml | 10 + .../admin/AutoWps/AutoWpsController.java | 4 +- .../wps_excel/JudgementWpsExcelService.java | 2 +- .../JudgementWpsExcelServiceImpl.java | 4 +- .../utils/wps_excel/xlsx4j/XlsxMaster.java | 5 +- .../utils/wps_excel/xlsx4j/cell/CellIng.java | 88 +++--- .../wps_word/docx4j/section/SectionPage.java | 2 +- .../controller/admin/auth/AuthController.java | 7 +- .../admin/tenant/TenantController.java | 17 +- .../tenant/vo/tenant/ResetPasswordReqVO.java | 9 + .../admin/tenant/vo/tenant/TenantRespVO.java | 12 +- .../dal/dataobject/tenant/TenantDO.java | 6 + .../dal/mysql/user/AdminUserMapper.java | 3 + .../system/service/tenant/TenantService.java | 2 + .../service/tenant/TenantServiceImpl.java | 31 ++- .../service/user/AdminUserServiceImpl.java | 47 ++-- .../module/system/util/oauth2/MacUtils.java | 161 +++++++++++ .../resources/mapper/user/AdminUserMapper.xml | 11 + .../exam/pp/server/config/MacValidator.java | 49 ++++ .../pp/server/config/SystemMacProperties.java | 18 ++ .../src/main/resources/application-local.yaml | 6 +- 42 files changed, 943 insertions(+), 99 deletions(-) create mode 100644 exam-module-exam/exam-module-exam-biz/src/main/java/pc/exam/pp/module/exam/dal/dataobject/AdminUser.java create mode 100644 exam-module-exam/exam-module-exam-biz/src/main/java/pc/exam/pp/module/exam/dal/dataobject/TenantSpcialty.java create mode 100644 exam-module-system/exam-module-system-biz/src/main/java/pc/exam/pp/module/system/controller/admin/tenant/vo/tenant/ResetPasswordReqVO.java create mode 100644 exam-module-system/exam-module-system-biz/src/main/java/pc/exam/pp/module/system/util/oauth2/MacUtils.java create mode 100644 exam-server/src/main/java/pc/exam/pp/server/config/MacValidator.java create mode 100644 exam-server/src/main/java/pc/exam/pp/server/config/SystemMacProperties.java diff --git a/exam-module-exam/exam-module-exam-biz/src/main/java/pc/exam/pp/module/exam/controller/admin/app/AppCheckController.java b/exam-module-exam/exam-module-exam-biz/src/main/java/pc/exam/pp/module/exam/controller/admin/app/AppCheckController.java index 2725eec4..dfe62434 100644 --- a/exam-module-exam/exam-module-exam-biz/src/main/java/pc/exam/pp/module/exam/controller/admin/app/AppCheckController.java +++ b/exam-module-exam/exam-module-exam-biz/src/main/java/pc/exam/pp/module/exam/controller/admin/app/AppCheckController.java @@ -78,7 +78,8 @@ public class AppCheckController { appCheckDO.setTaskId(taskId); appCheckDO.setAppName(exams.getRoles()); // 判断是否在数组中存在 - boolean exists = appCheckDOList.contains(appCheckDO); + boolean exists = appCheckDOList.stream() + .anyMatch(a -> exams.getRoles().equals(a.getAppName())); // 根据 appName 判断 if (!exists) { appCheckDOList.add(appCheckDO); } diff --git a/exam-module-exam/exam-module-exam-biz/src/main/java/pc/exam/pp/module/exam/controller/admin/monitor/vo/MonitorPageReqVO.java b/exam-module-exam/exam-module-exam-biz/src/main/java/pc/exam/pp/module/exam/controller/admin/monitor/vo/MonitorPageReqVO.java index a02be5ae..b1a300f9 100644 --- a/exam-module-exam/exam-module-exam-biz/src/main/java/pc/exam/pp/module/exam/controller/admin/monitor/vo/MonitorPageReqVO.java +++ b/exam-module-exam/exam-module-exam-biz/src/main/java/pc/exam/pp/module/exam/controller/admin/monitor/vo/MonitorPageReqVO.java @@ -57,6 +57,8 @@ public class MonitorPageReqVO extends PageParam { @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND) private LocalDateTime[] createTime; - + @Schema(description = "更新时间") + @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND) + private LocalDateTime[] updateTime; } \ No newline at end of file diff --git a/exam-module-exam/exam-module-exam-biz/src/main/java/pc/exam/pp/module/exam/controller/admin/monitor/vo/MonitorRespVO.java b/exam-module-exam/exam-module-exam-biz/src/main/java/pc/exam/pp/module/exam/controller/admin/monitor/vo/MonitorRespVO.java index cab52d25..ac62c72a 100644 --- a/exam-module-exam/exam-module-exam-biz/src/main/java/pc/exam/pp/module/exam/controller/admin/monitor/vo/MonitorRespVO.java +++ b/exam-module-exam/exam-module-exam-biz/src/main/java/pc/exam/pp/module/exam/controller/admin/monitor/vo/MonitorRespVO.java @@ -51,8 +51,11 @@ public class MonitorRespVO { @ExcelProperty(value = "剩余时间", converter = SecondsToTimeConverter.class) private String remainingTime; + private LocalDateTime createTime; + private LocalDateTime updateTime; + @ExcelProperty("开始时间") private String startTime; diff --git a/exam-module-exam/exam-module-exam-biz/src/main/java/pc/exam/pp/module/exam/controller/admin/paper/EducationPaperTaskController.java b/exam-module-exam/exam-module-exam-biz/src/main/java/pc/exam/pp/module/exam/controller/admin/paper/EducationPaperTaskController.java index be37b55b..6a941f11 100644 --- a/exam-module-exam/exam-module-exam-biz/src/main/java/pc/exam/pp/module/exam/controller/admin/paper/EducationPaperTaskController.java +++ b/exam-module-exam/exam-module-exam-biz/src/main/java/pc/exam/pp/module/exam/controller/admin/paper/EducationPaperTaskController.java @@ -1,6 +1,7 @@ package pc.exam.pp.module.exam.controller.admin.paper; +import cn.hutool.core.bean.BeanUtil; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.tags.Tag; import jakarta.annotation.security.PermitAll; @@ -22,6 +23,8 @@ import pc.exam.pp.module.exam.service.paper.IEducationPaperTaskService; import static pc.exam.pp.framework.common.exception.enums.GlobalErrorCodeConstants.INTERNAL_SERVER_ERROR; import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; /** @@ -46,7 +49,15 @@ public class EducationPaperTaskController { PageResult pageResult = educationPaperTaskService.selectEducationPaperTaskList(educationPaperTask); return CommonResult.success(BeanUtils.toBean(pageResult, EducationPaperTask.class)); } - + /** + * 查询试卷任务列表(服务器端) + */ + @Operation(summary = "查询试卷任务列表(服务器端)") + @GetMapping("/listMoBan") + public CommonResult> listMoBan(PaperTaskPageVo educationPaperTask) { + PageResult pageResult = educationPaperTaskService.selectEducationPaperTaskListlistMoBan(educationPaperTask); + return CommonResult.success(BeanUtils.toBean(pageResult, EducationPaperTask.class)); + } @Operation(summary = "查询试卷任务列表(带试卷)") @GetMapping("/listPaper") public CommonResult> taskAndPaperlist(PaperTaskPageVo educationPaperTask) { @@ -59,9 +70,18 @@ public class EducationPaperTaskController { */ @Operation(summary = "查询试卷任务列表(学生端)") @GetMapping("/stulist") - public CommonResult> stulist(PaperTaskPageVo educationPaperTask) { + public CommonResult>> stulist(PaperTaskPageVo educationPaperTask) { PageResult pageResult = educationPaperTaskService.selectEducationPaperTaskListByStu(educationPaperTask); - return CommonResult.success(BeanUtils.toBean(pageResult, EducationPaperTask.class)); + List> newList = pageResult.getList().stream() + .map(task -> { + Map map = BeanUtil.beanToMap(task, false, true); + map.put("status", task.getStatus() == null ? "" : String.valueOf(task.getStatus())); + return map; + }) + .collect(Collectors.toList()); + + PageResult> newPage = new PageResult<>(newList, pageResult.getTotal()); + return CommonResult.success(newPage); } diff --git a/exam-module-exam/exam-module-exam-biz/src/main/java/pc/exam/pp/module/exam/controller/admin/paper/vo/PaperTaskPageVo.java b/exam-module-exam/exam-module-exam-biz/src/main/java/pc/exam/pp/module/exam/controller/admin/paper/vo/PaperTaskPageVo.java index 144978cc..f2072f34 100644 --- a/exam-module-exam/exam-module-exam-biz/src/main/java/pc/exam/pp/module/exam/controller/admin/paper/vo/PaperTaskPageVo.java +++ b/exam-module-exam/exam-module-exam-biz/src/main/java/pc/exam/pp/module/exam/controller/admin/paper/vo/PaperTaskPageVo.java @@ -43,6 +43,7 @@ public class PaperTaskPageVo extends PageParam { private String status; + private String creator; @Schema(description = "创建时间", example = "[2022-07-01 00:00:00, 2022-07-01 23:59:59]") diff --git a/exam-module-exam/exam-module-exam-biz/src/main/java/pc/exam/pp/module/exam/controller/admin/specialty/ExamSpecialtyController.java b/exam-module-exam/exam-module-exam-biz/src/main/java/pc/exam/pp/module/exam/controller/admin/specialty/ExamSpecialtyController.java index f3c4f22a..1bbbcc2f 100644 --- a/exam-module-exam/exam-module-exam-biz/src/main/java/pc/exam/pp/module/exam/controller/admin/specialty/ExamSpecialtyController.java +++ b/exam-module-exam/exam-module-exam-biz/src/main/java/pc/exam/pp/module/exam/controller/admin/specialty/ExamSpecialtyController.java @@ -171,7 +171,8 @@ public class ExamSpecialtyController { public CommonResult getRole(@PathVariable("id") String id) { String roles = examSpecialtyService.getRoleById(id); if (roles != null) { - return success(Integer.parseInt(roles)); +// return success(Integer.parseInt(roles)); + return success(roles); } return success(""); } diff --git a/exam-module-exam/exam-module-exam-biz/src/main/java/pc/exam/pp/module/exam/dal/dataobject/AdminUser.java b/exam-module-exam/exam-module-exam-biz/src/main/java/pc/exam/pp/module/exam/dal/dataobject/AdminUser.java new file mode 100644 index 00000000..4fe624e0 --- /dev/null +++ b/exam-module-exam/exam-module-exam-biz/src/main/java/pc/exam/pp/module/exam/dal/dataobject/AdminUser.java @@ -0,0 +1,129 @@ +package pc.exam.pp.module.exam.dal.dataobject; + +import com.baomidou.mybatisplus.annotation.KeySequence; +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import com.baomidou.mybatisplus.extension.handlers.JacksonTypeHandler; +import lombok.*; +import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; +import pc.exam.pp.framework.common.enums.CommonStatusEnum; +import pc.exam.pp.framework.tenant.core.db.TenantBaseDO; +import pc.exam.pp.module.system.enums.common.SexEnum; + +import java.time.LocalDateTime; +import java.util.Set; + +/** + * 管理后台的用户 DO + * + * @author 朋辰 + */ +@TableName(value = "system_users", autoResultMap = true) // 由于 SQL Server 的 system_user 是关键字,所以使用 system_users +@KeySequence("system_users_seq") // 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 MySQL 等数据库,可不写。 +@Data +@EqualsAndHashCode(callSuper = true) +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class AdminUser extends TenantBaseDO { + + /** + * 用户ID + */ + @TableId + private Long id; + /** + * 用户账号 + */ + private String username; + /** + * 加密后的密码 + * + * 因为目前使用 {@link BCryptPasswordEncoder} 加密器,所以无需自己处理 salt 盐 + */ + private String password; + /** + * 身份证 + */ + private String sfz; + /** + * 用户昵称 + */ + private String nickname; + /** + * 学校名称 + */ + private String schoolName; + /** + * 备注 + */ + private String remark; + /** + * 部门 ID + */ + private Long deptId; + /** + * 班级 ID + */ + private Long classId; + /** + * 岗位编号数组 + */ + @TableField(typeHandler = JacksonTypeHandler.class) + private Set postIds; + + /** + * 班级编号数组 + */ + @TableField(typeHandler = JacksonTypeHandler.class) + private Set classIds; + + /** + * 专业编号数组 + */ + @TableField(typeHandler = JacksonTypeHandler.class) + private Set specialtyIds; + + /** + * 用户类型 + */ + private String userType; + + /** + * 用户邮箱 + */ + private String email; + /** + * 手机号码 + */ + private String mobile; + /** + * 用户性别 + * + * 枚举类 {@link SexEnum} + */ + private Integer sex; + /** + * 用户头像 + */ + private String avatar; + /** + * 帐号状态 + * + * 枚举 {@link CommonStatusEnum} + */ + private Integer status; + /** + * 最后登录IP + */ + private String loginIp; + /** + * 最后登录时间 + */ + private LocalDateTime loginDate; + + + private String queueName; + +} diff --git a/exam-module-exam/exam-module-exam-biz/src/main/java/pc/exam/pp/module/exam/dal/dataobject/EducationPaperTask.java b/exam-module-exam/exam-module-exam-biz/src/main/java/pc/exam/pp/module/exam/dal/dataobject/EducationPaperTask.java index 81166d58..2a4fa06a 100644 --- a/exam-module-exam/exam-module-exam-biz/src/main/java/pc/exam/pp/module/exam/dal/dataobject/EducationPaperTask.java +++ b/exam-module-exam/exam-module-exam-biz/src/main/java/pc/exam/pp/module/exam/dal/dataobject/EducationPaperTask.java @@ -46,6 +46,8 @@ public class EducationPaperTask extends TenantBaseDO private String taskType; private String isOne; + /** 是否共享 */ + private Integer share; /** 是否为模板 */ //@Excel(name = "是否为模板") diff --git a/exam-module-exam/exam-module-exam-biz/src/main/java/pc/exam/pp/module/exam/dal/dataobject/TenantSpcialty.java b/exam-module-exam/exam-module-exam-biz/src/main/java/pc/exam/pp/module/exam/dal/dataobject/TenantSpcialty.java new file mode 100644 index 00000000..980210a1 --- /dev/null +++ b/exam-module-exam/exam-module-exam-biz/src/main/java/pc/exam/pp/module/exam/dal/dataobject/TenantSpcialty.java @@ -0,0 +1,24 @@ +package pc.exam.pp.module.exam.dal.dataobject; + + +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.*; + +@TableName(value = "exam_tenant_specialty") +@Data +@ToString(callSuper = true) +@Builder +@AllArgsConstructor +@NoArgsConstructor +public class TenantSpcialty { + + @TableId(value = "id") + private Long id; + + private Long tenantId; + + private Long specialtyId; + + private String points; +} diff --git a/exam-module-exam/exam-module-exam-biz/src/main/java/pc/exam/pp/module/exam/dal/mysql/paper/EducationPaperTaskMapper.java b/exam-module-exam/exam-module-exam-biz/src/main/java/pc/exam/pp/module/exam/dal/mysql/paper/EducationPaperTaskMapper.java index 47519116..d1c084ae 100644 --- a/exam-module-exam/exam-module-exam-biz/src/main/java/pc/exam/pp/module/exam/dal/mysql/paper/EducationPaperTaskMapper.java +++ b/exam-module-exam/exam-module-exam-biz/src/main/java/pc/exam/pp/module/exam/dal/mysql/paper/EducationPaperTaskMapper.java @@ -49,10 +49,28 @@ public interface EducationPaperTaskMapper extends BaseMapperX + wrapper + // 自己创建的 + .eq(EducationPaperTask::getCreator, pageReqVO.getCreator()) + // 或者被共享的(share=0) + .or() + .eq(EducationPaperTask::getShare, 0) + ) ); } - + default PageResult selectEducationPaperTaskStuList(PaperTaskPageVo pageReqVO) { + return selectPage(pageReqVO, new LambdaQueryWrapperX() + .likeIfPresent(EducationPaperTask::getTaskType, pageReqVO.getTaskType()) + .likeIfPresent(EducationPaperTask::getTaskName , pageReqVO.getTaskName()) + .likeIfPresent(EducationPaperTask::getStatus , pageReqVO.getStatus()) + .likeIfPresent(EducationPaperTask::getTaskNum , pageReqVO.getTaskNum()) + .likeIfPresent(EducationPaperTask::getTaskSpecialty , pageReqVO.getTaskSpecialty()) + .likeIfPresent(EducationPaperTask::getIsTemplate , pageReqVO.getIsTemplate()) + .betweenIfPresent(EducationPaperTask::getCreateTime, pageReqVO.getCreateTime()) + ); + } /** * 新增试卷任务 * @@ -171,6 +189,14 @@ public interface EducationPaperTaskMapper extends BaseMapperX + wrapper + // 自己创建的 + .eq(EducationPaperTask::getCreator, pageReqVO.getCreator()) + // 或者被共享的(share=1) + .or() + .eq(EducationPaperTask::getShare, 0) + ) ).getTotal(); } diff --git a/exam-module-exam/exam-module-exam-biz/src/main/java/pc/exam/pp/module/exam/dal/mysql/specialty/ExamSpecialtyMapper.java b/exam-module-exam/exam-module-exam-biz/src/main/java/pc/exam/pp/module/exam/dal/mysql/specialty/ExamSpecialtyMapper.java index 58c988b9..7ba53450 100644 --- a/exam-module-exam/exam-module-exam-biz/src/main/java/pc/exam/pp/module/exam/dal/mysql/specialty/ExamSpecialtyMapper.java +++ b/exam-module-exam/exam-module-exam-biz/src/main/java/pc/exam/pp/module/exam/dal/mysql/specialty/ExamSpecialtyMapper.java @@ -7,6 +7,8 @@ import pc.exam.pp.framework.mybatis.core.mapper.BaseMapperX; import pc.exam.pp.module.exam.controller.admin.specialty.vo.SpecialtListReqVo; import pc.exam.pp.module.exam.controller.admin.specialty.vo.SpecialtyQueryVo; import pc.exam.pp.module.exam.controller.admin.specialty.vo.TenantSpcialtyVo; +import pc.exam.pp.module.exam.dal.dataobject.AdminUser; +import pc.exam.pp.module.exam.dal.dataobject.TenantSpcialty; import pc.exam.pp.module.exam.dal.dataobject.knowledge.ExamKnowledgePoints; import pc.exam.pp.module.exam.dal.dataobject.monitor.TentSpecialy; import pc.exam.pp.module.exam.dal.dataobject.specialty.ExamSpecialty; @@ -145,4 +147,7 @@ public interface ExamSpecialtyMapper extends BaseMapperX { List selectAllIdToParent(Long loginTenantId); + List getSpecialtyPoints(Long tenantId); + + AdminUser selectUserById(Long id); } diff --git a/exam-module-exam/exam-module-exam-biz/src/main/java/pc/exam/pp/module/exam/service/monitor/MonitorServiceImpl.java b/exam-module-exam/exam-module-exam-biz/src/main/java/pc/exam/pp/module/exam/service/monitor/MonitorServiceImpl.java index dff129d8..1fdec7b8 100644 --- a/exam-module-exam/exam-module-exam-biz/src/main/java/pc/exam/pp/module/exam/service/monitor/MonitorServiceImpl.java +++ b/exam-module-exam/exam-module-exam-biz/src/main/java/pc/exam/pp/module/exam/service/monitor/MonitorServiceImpl.java @@ -125,8 +125,8 @@ public class MonitorServiceImpl implements MonitorService { public PageResult getMonitorPage(MonitorPageReqVO pageReqVO) { PageResult page = monitorMapper.selectPage(pageReqVO); page.getList().forEach(monitor -> { - // 获取考试状态 - if (!monitor.getExamStatus().equals("0")) { + // 获取考试状态,结束的考试 starttime归零了,这里只取正在考试的时间 + if ("1".equals(monitor.getExamStatus())) { String startTime = monitor.getStartTime(); LocalDateTime nowTime = LocalDateTime.now(); LocalDateTime endTime = LocalDateTime.parse(startTime, DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")); diff --git a/exam-module-exam/exam-module-exam-biz/src/main/java/pc/exam/pp/module/exam/service/monitor/MonitorTaskServiceImpl.java b/exam-module-exam/exam-module-exam-biz/src/main/java/pc/exam/pp/module/exam/service/monitor/MonitorTaskServiceImpl.java index 4ea3baa2..43c27271 100644 --- a/exam-module-exam/exam-module-exam-biz/src/main/java/pc/exam/pp/module/exam/service/monitor/MonitorTaskServiceImpl.java +++ b/exam-module-exam/exam-module-exam-biz/src/main/java/pc/exam/pp/module/exam/service/monitor/MonitorTaskServiceImpl.java @@ -6,6 +6,7 @@ import jakarta.annotation.Resource; import org.springframework.stereotype.Service; import org.springframework.validation.annotation.Validated; import pc.exam.pp.framework.common.pojo.PageResult; +import pc.exam.pp.framework.security.core.util.SecurityFrameworkUtils; import pc.exam.pp.module.exam.controller.admin.monitor.vo.MonitorPageReqVO; import pc.exam.pp.module.exam.controller.admin.paper.vo.PaperTaskPageVo; import pc.exam.pp.module.exam.dal.dataobject.EducationPaper; @@ -40,7 +41,9 @@ public class MonitorTaskServiceImpl implements MonitorTaskService{ private EducationPaperQuMapper educationPaperQuMapper; @Override public PageResult getMonitorPage(PaperTaskPageVo pageReqVO) { - + //获取创建人 + Long loginUserId = SecurityFrameworkUtils.getLoginUserId(); + pageReqVO.setCreator(String.valueOf(loginUserId)); PageResult educationPaperTasks = educationPaperTaskMapper.selectEducationPaperTaskList(pageReqVO); long total= educationPaperTaskMapper.selectEducationPaperTaskTotal(pageReqVO); List list = educationPaperTasks.getList(); diff --git a/exam-module-exam/exam-module-exam-biz/src/main/java/pc/exam/pp/module/exam/service/paper/EducationPaperSchemeServiceImpl.java b/exam-module-exam/exam-module-exam-biz/src/main/java/pc/exam/pp/module/exam/service/paper/EducationPaperSchemeServiceImpl.java index 2f5d7455..5b44c8aa 100644 --- a/exam-module-exam/exam-module-exam-biz/src/main/java/pc/exam/pp/module/exam/service/paper/EducationPaperSchemeServiceImpl.java +++ b/exam-module-exam/exam-module-exam-biz/src/main/java/pc/exam/pp/module/exam/service/paper/EducationPaperSchemeServiceImpl.java @@ -1,10 +1,16 @@ package pc.exam.pp.module.exam.service.paper; +import jakarta.annotation.Resource; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import pc.exam.pp.module.exam.dal.dataobject.EducationPaperScheme; +import pc.exam.pp.module.exam.dal.dataobject.app.AppCheckDO; +import pc.exam.pp.module.exam.dal.dataobject.specialty.ExamSpecialty; import pc.exam.pp.module.exam.dal.mysql.paper.EducationPaperSchemeMapper; +import pc.exam.pp.module.exam.dal.mysql.specialty.ExamSpecialtyMapper; +import pc.exam.pp.module.exam.service.app.AppCheckService; +import pc.exam.pp.module.exam.service.specialty.ExamSpecialtyService; import pc.exam.pp.module.exam.utils.uuid.IdUtils; import java.util.List; @@ -20,7 +26,10 @@ import java.util.stream.Collectors; public class EducationPaperSchemeServiceImpl implements IEducationPaperSchemeService { @Autowired private EducationPaperSchemeMapper educationPaperSchemeMapper; - + @Autowired + private ExamSpecialtyMapper examSpecialtyMapper; + @Resource + AppCheckService appCheckService; /** * 查询试卷方案 * @@ -68,6 +77,25 @@ public class EducationPaperSchemeServiceImpl implements IEducationPaperSchemeSer educationPaperScheme.setKeywords(keywordStr); educationPaperScheme.setPointNames(pointNameStr); + List appCheckDOList = appCheckService.getAppList(educationPaperScheme.getTaskId()); + + // 根据题型名称查询软件环境 + List examSpecialty = examSpecialtyMapper.selectExamSpecialtyBySpName(educationPaperScheme.getSpName()); + if (examSpecialty != null && !examSpecialty.isEmpty()) { + ExamSpecialty exams = examSpecialty.get(0); + if (exams.getRoles() != null && !exams.getRoles().isEmpty()) { + + // 判断是否在数组中存在 + boolean exists = appCheckDOList.stream() + .anyMatch(a -> exams.getRoles().equals(a.getAppName())); // 根据 appName 判断 + if (!exists) { + AppCheckDO appCheckDO = new AppCheckDO(); + appCheckDO.setTaskId(educationPaperScheme.getTaskId()); + appCheckDO.setAppName(exams.getRoles()); + appCheckService.insertAppCheck(appCheckDO); + } + } + } // 然后插入到数据库 return educationPaperSchemeMapper.insertEducationPaperScheme(educationPaperScheme); diff --git a/exam-module-exam/exam-module-exam-biz/src/main/java/pc/exam/pp/module/exam/service/paper/EducationPaperServiceImpl.java b/exam-module-exam/exam-module-exam-biz/src/main/java/pc/exam/pp/module/exam/service/paper/EducationPaperServiceImpl.java index de454388..891d78c3 100644 --- a/exam-module-exam/exam-module-exam-biz/src/main/java/pc/exam/pp/module/exam/service/paper/EducationPaperServiceImpl.java +++ b/exam-module-exam/exam-module-exam-biz/src/main/java/pc/exam/pp/module/exam/service/paper/EducationPaperServiceImpl.java @@ -163,6 +163,8 @@ public class EducationPaperServiceImpl implements IEducationPaperService public int addPaperList(Integer num, String taskid,String taskSpecialty) { //根据试卷任务id查找方案集合 List educationPaperSchemeList= educationPaperSchemeMapper.selectEducationPaperTaskByTaskId(taskid); + //根据任务查找任务里面是否有试卷,如果没有给新创建的试卷 抽卷方式为 随机 + List educationPapers = educationPaperMapper.selectPaperListByTaskId(taskid); for (int i = 0; i examQuestionIds = new ArrayList<>(); int totalScore = 0; @@ -211,8 +213,6 @@ public class EducationPaperServiceImpl implements IEducationPaperService // 格式化为8位,不足前面补0 String formattedNumber = String.format("%08d", ++number); - //根据任务查找任务里面是否有试卷,如果没有给新创建的试卷 抽卷方式为 随机 - List educationPapers = educationPaperMapper.selectPaperListByTaskId(taskid); //构建试卷 diff --git a/exam-module-exam/exam-module-exam-biz/src/main/java/pc/exam/pp/module/exam/service/paper/EducationPaperSessionServiceImpl.java b/exam-module-exam/exam-module-exam-biz/src/main/java/pc/exam/pp/module/exam/service/paper/EducationPaperSessionServiceImpl.java index 27789336..be3b3150 100644 --- a/exam-module-exam/exam-module-exam-biz/src/main/java/pc/exam/pp/module/exam/service/paper/EducationPaperSessionServiceImpl.java +++ b/exam-module-exam/exam-module-exam-biz/src/main/java/pc/exam/pp/module/exam/service/paper/EducationPaperSessionServiceImpl.java @@ -60,6 +60,12 @@ public class EducationPaperSessionServiceImpl implements IEducationPaperSessionS { String uuid = IdUtils.simpleUUID(); educationPaperSession.setSessionId(uuid); + List educationPaperSessions = educationPaperSessionMapper.selectEducationPaperSessionByTaskId(educationPaperSession.getTaskId()); + int size = educationPaperSessions.size()+1; + String batch= "第"+size+"场"; + educationPaperSession.setBatch(batch); + + return educationPaperSessionMapper.insertEducationPaperSession(educationPaperSession); } diff --git a/exam-module-exam/exam-module-exam-biz/src/main/java/pc/exam/pp/module/exam/service/paper/EducationPaperTaskServiceImpl.java b/exam-module-exam/exam-module-exam-biz/src/main/java/pc/exam/pp/module/exam/service/paper/EducationPaperTaskServiceImpl.java index 3d0b913e..067202a5 100644 --- a/exam-module-exam/exam-module-exam-biz/src/main/java/pc/exam/pp/module/exam/service/paper/EducationPaperTaskServiceImpl.java +++ b/exam-module-exam/exam-module-exam-biz/src/main/java/pc/exam/pp/module/exam/service/paper/EducationPaperTaskServiceImpl.java @@ -1,7 +1,9 @@ package pc.exam.pp.module.exam.service.paper; +import cn.hutool.core.collection.CollUtil; import com.alibaba.excel.util.StringUtils; +import jakarta.annotation.Resource; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; @@ -9,6 +11,7 @@ import pc.exam.pp.framework.common.pojo.PageResult; import pc.exam.pp.framework.security.core.util.SecurityFrameworkUtils; import pc.exam.pp.framework.tenant.core.aop.TenantIgnore; import pc.exam.pp.framework.tenant.core.context.TenantContextHolder; +import pc.exam.pp.framework.web.core.util.WebFrameworkUtils; import pc.exam.pp.module.exam.controller.admin.exception.QueTypeException; import pc.exam.pp.module.exam.controller.admin.paper.dto.PaperQueUpdateDTO; import pc.exam.pp.module.exam.controller.admin.paper.dto.SchemeParam; @@ -16,11 +19,16 @@ import pc.exam.pp.module.exam.controller.admin.paper.dto.TempDto; import pc.exam.pp.module.exam.controller.admin.paper.vo.ExamPaperVo; import pc.exam.pp.module.exam.controller.admin.paper.vo.PaperTaskPageVo; import pc.exam.pp.module.exam.controller.admin.paper.vo.StuInfoPaper; +import pc.exam.pp.module.exam.controller.admin.specialty.vo.SpecialtyQueryVo; import pc.exam.pp.module.exam.dal.dataobject.*; +import pc.exam.pp.module.exam.dal.dataobject.app.AppCheckDO; +import pc.exam.pp.module.exam.dal.dataobject.specialty.ExamSpecialty; +import pc.exam.pp.module.exam.dal.mysql.app.AppCheckMapper; import pc.exam.pp.module.exam.dal.mysql.monitor.MonitorMapper; import pc.exam.pp.module.exam.dal.mysql.paper.*; import pc.exam.pp.module.exam.dal.mysql.question.ExamQuestionMapper; import pc.exam.pp.module.exam.dal.mysql.question.ExamQuestionFileMapper; +import pc.exam.pp.module.exam.dal.mysql.specialty.ExamSpecialtyMapper; import pc.exam.pp.module.exam.utils.date.DateUtils; import pc.exam.pp.module.exam.utils.uuid.IdUtils; @@ -31,6 +39,8 @@ import java.util.*; import java.util.function.Function; import java.util.stream.Collectors; +import static pc.exam.pp.framework.common.util.collection.CollectionUtils.convertSet; + /** * 试卷任务Service业务层处理 * @@ -65,9 +75,12 @@ public class EducationPaperTaskServiceImpl implements IEducationPaperTaskService private MonitorMapper monitorMapper; //@Autowired //private ExamQuestionMapper - + @Resource + private ExamSpecialtyMapper examSpecialtyMapper; @Autowired private ExamQuestionMapper examQuestionMapper; + @Resource + AppCheckMapper appCheckMapper; /** * 查询试卷任务 @@ -88,6 +101,9 @@ public class EducationPaperTaskServiceImpl implements IEducationPaperTaskService */ @Override public PageResult selectEducationPaperTaskList(PaperTaskPageVo educationPaperTask) { + //获取创建人 + Long loginUserId = SecurityFrameworkUtils.getLoginUserId(); + educationPaperTask.setCreator(String.valueOf(loginUserId)); PageResult educationPaperTasks = educationPaperTaskMapper.selectEducationPaperTaskList(educationPaperTask); List list = educationPaperTasks.getList(); if (list != null && list.size() > 0) { @@ -144,7 +160,6 @@ public class EducationPaperTaskServiceImpl implements IEducationPaperTaskService educationPaperParam.setIsConnect("0"); educationPaperParam.setIsAnswerId("1"); educationPaperParam.setIsTime("0"); - educationPaperParam.setIsDelete("0"); educationPaperParam.setDirectory("KSWJ"); educationPaperParam.setUploadTime("5"); educationPaperParam.setIsCopy("1"); @@ -161,7 +176,9 @@ public class EducationPaperTaskServiceImpl implements IEducationPaperTaskService educationPaperParam.setIsConnect("30"); educationPaperParam.setIsScore("1"); educationPaperParam.setIsScoreDetail("1"); + educationPaperParam.setIsDelete("1"); } else { + educationPaperParam.setIsDelete("0"); educationPaperParam.setIsRepeat("0"); educationPaperParam.setIsAnswer("0"); educationPaperParam.setIsLook("0"); @@ -176,7 +193,7 @@ public class EducationPaperTaskServiceImpl implements IEducationPaperTaskService // 新增任务参数 educationPaperParamMapper.insertEducationPaperParam(educationPaperParam); // 新增任务 - return educationPaperTaskMapper.insertEducationPaperTask(educationPaperTask); + return educationPaperTaskMapper.insert(educationPaperTask); } /** @@ -326,7 +343,122 @@ public class EducationPaperTaskServiceImpl implements IEducationPaperTaskService @Override public List getCourseList() { - return educationPaperTaskMapper.getCourseList(); + Long userId = WebFrameworkUtils.getLoginUserId(); + // 获取考点ID + Long tenantId = TenantContextHolder.getTenantId(); + AdminUser adminUserDO = getUser(userId); + List specialtyQueryVos = new ArrayList<>(); + // 判断是否是中心服务器,如果是中心服务器的话直接返回所有,如果不是查询对应的授权数据 + if (tenantId == 1) { + // 判断用户类型 管理员所有专业 + if (adminUserDO.getUserType().equals("0")) { + // 查询所有专业数据 + specialtyQueryVos = examSpecialtyMapper.selectExamSpecialtyAll(); + } else { + // 判断专业是否为空,为空的话查询所有 + if (adminUserDO.getSpecialtyIds() == null) { + // 查询所有数据 + specialtyQueryVos = examSpecialtyMapper.selectExamSpecialtyAll(); + } else { + // 查询部分数据 + specialtyQueryVos = examSpecialtyMapper.selectExamSpecialtyByids(adminUserDO.getSpecialtyIds()); + + } + } + } else { + // 需要先界定 数据范围,通过考点服务器ID进行查询考点服务器的授权范围 + List tenantSpcialtyDOS = examSpecialtyMapper.getSpecialtyPoints(tenantId); + // 通过ID查询对应的科目信息 + for (TenantSpcialty spcialtyDO : tenantSpcialtyDOS) { + ExamSpecialty examSpecialty = examSpecialtyMapper.selectExamSpecialtyBySpId(spcialtyDO.getSpecialtyId()); + // 获取对应的父级参数 + ExamSpecialty examSpecialtyForUp = examSpecialtyMapper.selectExamSpecialtyBySpId(examSpecialty.getParentId()); + if (examSpecialty.getParentId() == 0) { + // 说明是整个专业下面所有的 + List examSpecialties = getChildExamSpecialtyList(Collections.singleton(examSpecialtyForUp.getSpId())); + for (ExamSpecialty examSpecialtyInfo : examSpecialties) { + // 检查是否已存在相同ID的元素 + boolean exists = specialtyQueryVos.stream() + .anyMatch(v -> v.getId().equals(examSpecialtyInfo.getSpId())); + if (!exists) { + SpecialtyQueryVo specialtyQueryVo = new SpecialtyQueryVo(); + specialtyQueryVo.setStatus(examSpecialtyInfo.getStatus()); + specialtyQueryVo.setName(examSpecialtyInfo.getSpName()); + specialtyQueryVo.setAncestors(examSpecialtyInfo.getAncestors()); + specialtyQueryVo.setOrderNum(examSpecialtyInfo.getOrderNum()); + specialtyQueryVo.setId(examSpecialtyInfo.getSpId()); + specialtyQueryVo.setRoles(examSpecialtyInfo.getRoles()); + specialtyQueryVo.setParentId(examSpecialtyInfo.getParentId()); + specialtyQueryVo.setAncestors(examSpecialtyInfo.getAncestors()); + specialtyQueryVos.add(specialtyQueryVo); + } + } + } else { + // 检查是否已存在相同ID的元素 + boolean exists = specialtyQueryVos.stream() + .anyMatch(v -> v.getId().equals(examSpecialty.getSpId())); + if (!exists) { + SpecialtyQueryVo specialtyQueryVo = new SpecialtyQueryVo(); + specialtyQueryVo.setStatus(examSpecialty.getStatus()); + specialtyQueryVo.setName(examSpecialty.getSpName()); + specialtyQueryVo.setAncestors(examSpecialty.getAncestors()); + specialtyQueryVo.setOrderNum(examSpecialty.getOrderNum()); + specialtyQueryVo.setId(examSpecialty.getSpId()); + specialtyQueryVo.setRoles(examSpecialty.getRoles()); + specialtyQueryVo.setParentId(examSpecialty.getParentId()); + specialtyQueryVo.setAncestors(examSpecialty.getAncestors()); + specialtyQueryVos.add(specialtyQueryVo); + } + boolean existsUp = specialtyQueryVos.stream() + .anyMatch(v -> v.getId().equals(examSpecialtyForUp.getSpId())); + if (!existsUp) { + SpecialtyQueryVo specialtyQueryVo = new SpecialtyQueryVo(); + specialtyQueryVo.setStatus(examSpecialtyForUp.getStatus()); + specialtyQueryVo.setName(examSpecialtyForUp.getSpName()); + specialtyQueryVo.setAncestors(examSpecialtyForUp.getAncestors()); + specialtyQueryVo.setOrderNum(examSpecialtyForUp.getOrderNum()); + specialtyQueryVo.setId(examSpecialtyForUp.getSpId()); + specialtyQueryVo.setRoles(examSpecialtyForUp.getRoles()); + specialtyQueryVo.setParentId(examSpecialtyForUp.getParentId()); + specialtyQueryVo.setAncestors(examSpecialtyForUp.getAncestors()); + specialtyQueryVos.add(specialtyQueryVo); + } + List examSpecialties = getChildExamSpecialtyList(Collections.singleton(examSpecialty.getSpId())); + for (ExamSpecialty examSpecialtyInfo : examSpecialties) { + // 检查是否已存在相同ID的元素 + boolean existsDown = specialtyQueryVos.stream() + .anyMatch(v -> v.getId().equals(examSpecialtyInfo.getSpId())); + if (!existsDown) { + SpecialtyQueryVo specialtyQueryVo = new SpecialtyQueryVo(); + specialtyQueryVo.setStatus(examSpecialtyInfo.getStatus()); + specialtyQueryVo.setName(examSpecialtyInfo.getSpName()); + specialtyQueryVo.setAncestors(examSpecialtyInfo.getAncestors()); + specialtyQueryVo.setOrderNum(examSpecialtyInfo.getOrderNum()); + specialtyQueryVo.setId(examSpecialtyInfo.getSpId()); + specialtyQueryVo.setRoles(examSpecialtyInfo.getRoles()); + specialtyQueryVo.setParentId(examSpecialtyInfo.getParentId()); + specialtyQueryVo.setAncestors(examSpecialtyInfo.getAncestors()); + specialtyQueryVos.add(specialtyQueryVo); + } + } + } + } + // 通过ID查询下面的参数 + // 判断用户类型 管理员所有专业 , 不是管理员的话需要筛选 + if (!adminUserDO.getUserType().equals("0")) { + // 判断专业是否为空,为空的话查询所有 + if (adminUserDO.getSpecialtyIds() == null) { + // 查询所有数据 + specialtyQueryVos = examSpecialtyMapper.selectExamSpecialtyAll(); + } else { + // 查询部分数据 + specialtyQueryVos = examSpecialtyMapper.selectExamSpecialtyByids(adminUserDO.getSpecialtyIds()); + + } + } + } + List courseNames = getThirdLevelNames(specialtyQueryVos); + return courseNames; } @Override @@ -405,7 +537,7 @@ public class EducationPaperTaskServiceImpl implements IEducationPaperTaskService // 格式化时间为字符串 String timeString = now.format(formatter); educationPaperTask.setTaskName(educationPaperTask.getTaskName() + timeString); - + educationPaperTask.setCreateTime(now); educationPaperTask.setIsTemplate(1); educationPaperTaskMapper.insertEducationPaperTask(educationPaperTask); @@ -419,6 +551,17 @@ public class EducationPaperTaskServiceImpl implements IEducationPaperTaskService educationPaperSchemeList.forEach(scheme -> scheme.setTaskId(newtaskId)); //构建新方案 educationPaperSchemeMapper.insertEducationPaperSchemeList(educationPaperSchemeList); + List appCheckDOList = new ArrayList<>(); + List appCheckDOS = appCheckMapper.selectList(taskId); + if (appCheckDOS!=null&&appCheckDOS.size()>0){ + for (AppCheckDO appCheckDO : appCheckDOS) { + AppCheckDO newAppCheckDO = new AppCheckDO(); + newAppCheckDO.setTaskId(newtaskId); + newAppCheckDO.setAppName(appCheckDO.getAppName()); + appCheckDOList.add(newAppCheckDO); + } + appCheckMapper.insert(appCheckDOList); + } } @@ -464,6 +607,18 @@ public class EducationPaperTaskServiceImpl implements IEducationPaperTaskService EducationPaperParam educationPaperParam = educationPaperParamMapper.selectEducationPaperParamByTaskId(taskId); educationPaperParam.setTaskId(newtaskId); educationPaperParam.setParamId(IdUtils.simpleUUID()); + //考试不删除学生文件 + String taskType = educationPaperTask.getTaskType(); + if ("1".equals(taskType)){ + educationPaperParam.setIsDelete("1"); + educationPaperParam.setIsRepeat("1"); + educationPaperParam.setIsAnswer("1"); + educationPaperParam.setIsLook("1"); + educationPaperParam.setIsConnect("30"); + educationPaperParam.setIsScore("1"); + educationPaperParam.setIsScoreDetail("1"); + educationPaperParam.setIsDelete("1"); + } educationPaperParamMapper.insertEducationPaperParam(educationPaperParam); } @@ -618,7 +773,7 @@ public class EducationPaperTaskServiceImpl implements IEducationPaperTaskService public PageResult selectEducationPaperTaskListByStu(PaperTaskPageVo educationPaperTask) { String taskType = educationPaperTask.getTaskType(); - PageResult educationPaperTasks = educationPaperTaskMapper.selectEducationPaperTaskList(educationPaperTask); + PageResult educationPaperTasks = educationPaperTaskMapper.selectEducationPaperTaskStuList(educationPaperTask); Long stuId = SecurityFrameworkUtils.getLoginUserId(); List list = educationPaperTasks.getList(); List taskIds = educationPaperPersonMapper.selectTaskIdByStuid(stuId); @@ -671,11 +826,12 @@ public class EducationPaperTaskServiceImpl implements IEducationPaperTaskService //查找 考试状态还没结束的 任务id ,取 交集 List taskNoEndIds = monitorMapper.selectByStuIdAndTaskId(stuId); - if (taskType.equals("1")) { + if ("1".equals(taskType)) { if (list != null && list.size() > 0 && taskNoEndIds != null && taskNoEndIds.size() > 0) { list = list.stream() .filter(task -> taskNoEndIds.contains(task.getTaskId())) .collect(Collectors.toList()); + } } @@ -729,4 +885,95 @@ public class EducationPaperTaskServiceImpl implements IEducationPaperTaskService } } + + @Override + public PageResult selectEducationPaperTaskListlistMoBan(PaperTaskPageVo educationPaperTask) { + PageResult educationPaperTasks = educationPaperTaskMapper.selectEducationPaperTaskList(educationPaperTask); + List list = educationPaperTasks.getList(); + if (list != null && list.size() > 0) { + for (EducationPaperTask paperTask : list) { + int count = 0; + List educationPapers = educationPaperMapper.selectPaperListByTaskId(paperTask.getTaskId()); + if (educationPapers != null && educationPapers.size() > 0) { + for (EducationPaper educationPaper : educationPapers) { + try { + count += Integer.parseInt(educationPaper.getCounts()); + } catch (NumberFormatException e) { + // 可选:记录异常或忽略非法数字 + System.err.println("无效的 counts 值: " + educationPaper.getCounts()); + } + + } + } + paperTask.setCount(String.valueOf(count)); + + EducationPaperParam educationPaperParam = educationPaperParamMapper.selectEducationPaperParamByTaskId(paperTask.getTaskId()); + paperTask.setEducationPaperParam(educationPaperParam); + } + } + + return educationPaperTasks; + } + + public List getChildExamSpecialtyList(Collection ids) { + List children = new LinkedList<>(); + // 遍历每一层 + Collection parentIds = ids; + for (int i = 0; i < Short.MAX_VALUE; i++) { // 使用 Short.MAX_VALUE 避免 bug 场景下,存在死循环 + // 查询当前层,所有的子Xlsx考点 + List Xlsxs = examSpecialtyMapper.selectListByParentId(parentIds); + // 1. 如果没有子Xlsx考点,则结束遍历 + if (CollUtil.isEmpty(Xlsxs)) { + break; + } + // 2. 如果有子Xlsx考点,继续遍历 + children.addAll(Xlsxs); + parentIds = convertSet(Xlsxs, ExamSpecialty::getSpId); + } + return children; + } + public static List getThirdLevelNames(List list) { + // ✅ 判空 + if (list == null || list.isEmpty()) { + return Collections.emptyList(); + } + + // 第1层:专业(parentId = 0) + Set level1Ids = list.stream() + .filter(Objects::nonNull) + .filter(item -> item.getParentId() != null && item.getParentId() == 0) + .map(SpecialtyQueryVo::getId) + .filter(Objects::nonNull) + .collect(Collectors.toSet()); + + if (level1Ids.isEmpty()) { + return Collections.emptyList(); + } + + // 第2层:课程(父节点是专业) + Set level2Ids = list.stream() + .filter(Objects::nonNull) + .filter(item -> item.getParentId() != null && level1Ids.contains(item.getParentId())) + .map(SpecialtyQueryVo::getId) + .filter(Objects::nonNull) + .collect(Collectors.toSet()); + + if (level2Ids.isEmpty()) { + return Collections.emptyList(); + } + + // 第3层:题型(父节点是课程) + return list.stream() + .filter(Objects::nonNull) + .filter(item -> item.getParentId() != null && level2Ids.contains(item.getParentId())) + .map(SpecialtyQueryVo::getName) // ✅ 只返回 name + .filter(Objects::nonNull) + .distinct() // 去重(可选) + .collect(Collectors.toList()); + } + + + public AdminUser getUser(Long id) { + return examSpecialtyMapper.selectUserById(id); + } } diff --git a/exam-module-exam/exam-module-exam-biz/src/main/java/pc/exam/pp/module/exam/service/paper/IEducationPaperTaskService.java b/exam-module-exam/exam-module-exam-biz/src/main/java/pc/exam/pp/module/exam/service/paper/IEducationPaperTaskService.java index ce2b89f8..27ae2b3c 100644 --- a/exam-module-exam/exam-module-exam-biz/src/main/java/pc/exam/pp/module/exam/service/paper/IEducationPaperTaskService.java +++ b/exam-module-exam/exam-module-exam-biz/src/main/java/pc/exam/pp/module/exam/service/paper/IEducationPaperTaskService.java @@ -119,5 +119,7 @@ public interface IEducationPaperTaskService void checkType(PaperQueUpdateDTO dto); + PageResult selectEducationPaperTaskListlistMoBan(PaperTaskPageVo educationPaperTask); + } diff --git a/exam-module-exam/exam-module-exam-biz/src/main/resources/mapper/exam/EducationPaperSessionMapper.xml b/exam-module-exam/exam-module-exam-biz/src/main/resources/mapper/exam/EducationPaperSessionMapper.xml index bf1cfd76..b1fab403 100644 --- a/exam-module-exam/exam-module-exam-biz/src/main/resources/mapper/exam/EducationPaperSessionMapper.xml +++ b/exam-module-exam/exam-module-exam-biz/src/main/resources/mapper/exam/EducationPaperSessionMapper.xml @@ -31,6 +31,7 @@ diff --git a/exam-module-exam/exam-module-exam-biz/src/main/resources/mapper/specialty/ExamSpecialtyMapper.xml b/exam-module-exam/exam-module-exam-biz/src/main/resources/mapper/specialty/ExamSpecialtyMapper.xml index 2d90079f..1d3662c9 100644 --- a/exam-module-exam/exam-module-exam-biz/src/main/resources/mapper/specialty/ExamSpecialtyMapper.xml +++ b/exam-module-exam/exam-module-exam-biz/src/main/resources/mapper/specialty/ExamSpecialtyMapper.xml @@ -194,6 +194,16 @@ and status = '0' and tenant_id = #{loginTenantId} + + diff --git a/exam-module-judgement/exam-module-judgement-biz/src/main/java/pc/exam/pp/module/judgement/controller/admin/AutoWps/AutoWpsController.java b/exam-module-judgement/exam-module-judgement-biz/src/main/java/pc/exam/pp/module/judgement/controller/admin/AutoWps/AutoWpsController.java index d51d7b88..080a9fca 100644 --- a/exam-module-judgement/exam-module-judgement-biz/src/main/java/pc/exam/pp/module/judgement/controller/admin/AutoWps/AutoWpsController.java +++ b/exam-module-judgement/exam-module-judgement-biz/src/main/java/pc/exam/pp/module/judgement/controller/admin/AutoWps/AutoWpsController.java @@ -120,7 +120,7 @@ public class AutoWpsController { * @throws Exception */ @PostMapping(value = "/xlsxMaster", consumes = MediaType.MULTIPART_FORM_DATA_VALUE) - public CommonResult> xlsxMaster(@RequestPart("data") String jsonData, @RequestPart("file") MultipartFile file, @RequestParam(value = "cell", required = false) List cell) throws Exception { + public CommonResult> xlsxMaster(@RequestPart("data") String jsonData, @RequestPart("file") MultipartFile file, @RequestParam(value = "cell", required = false) List cell,@RequestParam(value = "keyWords", required = false) String keyWords ) throws Exception { // 手动解析JSON数组 ObjectMapper objectMapper = new ObjectMapper(); List wpsXlsxInfoVos = objectMapper.readValue( @@ -128,7 +128,7 @@ public class AutoWpsController { new TypeReference>() { } ); - return CommonResult.success(judgementWpsExcelService.xlsxMaster(wpsXlsxInfoVos, file, cell)); + return CommonResult.success(judgementWpsExcelService.xlsxMaster(wpsXlsxInfoVos, file, cell,keyWords)); } diff --git a/exam-module-judgement/exam-module-judgement-biz/src/main/java/pc/exam/pp/module/judgement/service/wps_excel/JudgementWpsExcelService.java b/exam-module-judgement/exam-module-judgement-biz/src/main/java/pc/exam/pp/module/judgement/service/wps_excel/JudgementWpsExcelService.java index 06d06042..34db3643 100644 --- a/exam-module-judgement/exam-module-judgement-biz/src/main/java/pc/exam/pp/module/judgement/service/wps_excel/JudgementWpsExcelService.java +++ b/exam-module-judgement/exam-module-judgement-biz/src/main/java/pc/exam/pp/module/judgement/service/wps_excel/JudgementWpsExcelService.java @@ -15,7 +15,7 @@ import java.util.List; */ public interface JudgementWpsExcelService { - List xlsxMaster(List wpsXlsxInfoVos, MultipartFile file,List cell) throws Exception; + List xlsxMaster(List wpsXlsxInfoVos, MultipartFile file,List cell,String keyWords) throws Exception; List xlsxDataInfo(MultipartFile file) throws Exception; } diff --git a/exam-module-judgement/exam-module-judgement-biz/src/main/java/pc/exam/pp/module/judgement/service/wps_excel/JudgementWpsExcelServiceImpl.java b/exam-module-judgement/exam-module-judgement-biz/src/main/java/pc/exam/pp/module/judgement/service/wps_excel/JudgementWpsExcelServiceImpl.java index ddd7c56a..e4095897 100644 --- a/exam-module-judgement/exam-module-judgement-biz/src/main/java/pc/exam/pp/module/judgement/service/wps_excel/JudgementWpsExcelServiceImpl.java +++ b/exam-module-judgement/exam-module-judgement-biz/src/main/java/pc/exam/pp/module/judgement/service/wps_excel/JudgementWpsExcelServiceImpl.java @@ -17,8 +17,8 @@ public class JudgementWpsExcelServiceImpl implements JudgementWpsExcelService { @Override - public List xlsxMaster(List wpsXlsxInfoVos, MultipartFile file,List cell) throws Exception { - return XlsxMaster.xlsxMaster(wpsXlsxInfoVos, file,cell); + public List xlsxMaster(List wpsXlsxInfoVos, MultipartFile file,List cell,String keyWords) throws Exception { + return XlsxMaster.xlsxMaster(wpsXlsxInfoVos, file,cell,keyWords); } @Override diff --git a/exam-module-judgement/exam-module-judgement-biz/src/main/java/pc/exam/pp/module/judgement/utils/wps_excel/xlsx4j/XlsxMaster.java b/exam-module-judgement/exam-module-judgement-biz/src/main/java/pc/exam/pp/module/judgement/utils/wps_excel/xlsx4j/XlsxMaster.java index 98099069..5dfc1a16 100644 --- a/exam-module-judgement/exam-module-judgement-biz/src/main/java/pc/exam/pp/module/judgement/utils/wps_excel/xlsx4j/XlsxMaster.java +++ b/exam-module-judgement/exam-module-judgement-biz/src/main/java/pc/exam/pp/module/judgement/utils/wps_excel/xlsx4j/XlsxMaster.java @@ -45,7 +45,7 @@ public class XlsxMaster { * @throws IOException IO * @throws Docx4JException 异常 */ - public static List xlsxMaster(List wpsXlsxInfoVos, MultipartFile file,List cell) throws IOException, Docx4JException { + public static List xlsxMaster(List wpsXlsxInfoVos, MultipartFile file,List cell,String keyWords) throws IOException, Docx4JException { List judgementXlsxVOS = new ArrayList<>(); // 1、获取想要判断的文件地址(文件流) try (InputStream inputStream = file.getInputStream()) { @@ -91,6 +91,7 @@ public class XlsxMaster { Class[] paramTypes = { org.apache.poi.ss.usermodel.Cell.class, org.apache.poi.ss.usermodel.Workbook.class, + String.class }; Method methodWithArgs = excelFunctions.getClass().getMethod(function, paramTypes); @@ -99,7 +100,7 @@ public class XlsxMaster { for (String cellRef : cell) { org.apache.poi.ss.usermodel.Cell poiCell = getPoiCellFromRef(workbook, sheetName, cellRef); if (poiCell == null) continue; - String value = (String) methodWithArgs.invoke(excelFunctions, poiCell, workbook); + String value = (String) methodWithArgs.invoke(excelFunctions, poiCell, workbook,keyWords); if (value != null) { if ("getCellDataFormat".equals(function)){ diff --git a/exam-module-judgement/exam-module-judgement-biz/src/main/java/pc/exam/pp/module/judgement/utils/wps_excel/xlsx4j/cell/CellIng.java b/exam-module-judgement/exam-module-judgement-biz/src/main/java/pc/exam/pp/module/judgement/utils/wps_excel/xlsx4j/cell/CellIng.java index a6d1aa89..a53316e0 100644 --- a/exam-module-judgement/exam-module-judgement-biz/src/main/java/pc/exam/pp/module/judgement/utils/wps_excel/xlsx4j/cell/CellIng.java +++ b/exam-module-judgement/exam-module-judgement-biz/src/main/java/pc/exam/pp/module/judgement/utils/wps_excel/xlsx4j/cell/CellIng.java @@ -36,13 +36,13 @@ public class CellIng { Map.entry("SLANTEDDASHDOT", "斜点划线") ); // 获取左框线样式 - public String getLeftBorderStyle(Cell cell, org.apache.poi.ss.usermodel.Workbook wb) { + public String getLeftBorderStyle(Cell cell, org.apache.poi.ss.usermodel.Workbook wb,String keyWords) { CellStyle style = cell.getCellStyle(); BorderStyle border = style.getBorderLeft(); return border != null ? borderStyleChineseMap.getOrDefault(border.name() , border.name() ): "无"; } // 获取左框线颜色 - public String getLeftBorderColor(Cell cell, org.apache.poi.ss.usermodel.Workbook wb) { + public String getLeftBorderColor(Cell cell, org.apache.poi.ss.usermodel.Workbook wb,String keyWords) { CellStyle style = cell.getCellStyle(); if (style instanceof XSSFCellStyle) { XSSFCellStyle xssfStyle = (XSSFCellStyle) style; @@ -53,14 +53,14 @@ public class CellIng { } // 获取上框线样式 - public String getTopBorderStyle(Cell cell, org.apache.poi.ss.usermodel.Workbook wb) { + public String getTopBorderStyle(Cell cell, org.apache.poi.ss.usermodel.Workbook wb,String keyWords) { CellStyle style = cell.getCellStyle(); BorderStyle border = style.getBorderTop(); return border != null ? borderStyleChineseMap.getOrDefault(border.name() , border.name() ): "无"; } // 获取上框线颜色 - public String getTopBorderColor(Cell cell, org.apache.poi.ss.usermodel.Workbook wb) { + public String getTopBorderColor(Cell cell, org.apache.poi.ss.usermodel.Workbook wb,String keyWords) { CellStyle style = cell.getCellStyle(); if (style instanceof XSSFCellStyle) { XSSFCellStyle xssfStyle = (XSSFCellStyle) style; @@ -70,14 +70,14 @@ public class CellIng { } // 获取右框线样式 - public String getRightBorderStyle(Cell cell, org.apache.poi.ss.usermodel.Workbook wb) { + public String getRightBorderStyle(Cell cell, org.apache.poi.ss.usermodel.Workbook wb,String keyWords) { CellStyle style = cell.getCellStyle(); BorderStyle border = style.getBorderRight(); return border != null ? borderStyleChineseMap.getOrDefault(border.name() , border.name() ): "无"; } // 获取右框线颜色 - public String getRightBorderColor(Cell cell, org.apache.poi.ss.usermodel.Workbook wb) { + public String getRightBorderColor(Cell cell, org.apache.poi.ss.usermodel.Workbook wb,String keyWords) { CellStyle style = cell.getCellStyle(); if (style instanceof XSSFCellStyle) { XSSFCellStyle xssfStyle = (XSSFCellStyle) style; @@ -87,14 +87,14 @@ public class CellIng { } // 获取下框线样式 - public String getBottomBorderStyle(Cell cell, org.apache.poi.ss.usermodel.Workbook wb) { + public String getBottomBorderStyle(Cell cell, org.apache.poi.ss.usermodel.Workbook wb,String keyWords) { CellStyle style = cell.getCellStyle(); BorderStyle border = style.getBorderBottom(); return border != null ? borderStyleChineseMap.getOrDefault(border.name() , border.name() ): "无"; } // 获取下框线颜色 - public String getBottomBorderColor(Cell cell, org.apache.poi.ss.usermodel.Workbook wb) { + public String getBottomBorderColor(Cell cell, org.apache.poi.ss.usermodel.Workbook wb,String keyWords) { CellStyle style = cell.getCellStyle(); if (style instanceof XSSFCellStyle) { XSSFCellStyle xssfStyle = (XSSFCellStyle) style; @@ -103,16 +103,34 @@ public class CellIng { return "无"; } // 获取单元格的公式表达式(字符串形式) - public String getFormulaExpression(Cell cell, Workbook wb) { + public String getFormulaExpression(Cell cell, Workbook wb,String keyWords) { if (cell == null) return "无"; if (cell.getCellType() == CellType.FORMULA) { return cell.getCellFormula(); } return "无"; } + // 获取单元格的公式表达式关键字 + public String getFormulaExpressionContains(Cell cell, Workbook wb,String keyWords) { + if (cell == null) return "无"; + + if (cell.getCellType() == CellType.FORMULA) { + String formula = cell.getCellFormula(); + // 转为小写再比较 + if (formula.toLowerCase().contains(keyWords.toLowerCase())) { + return formula; // 包含关键字时返回公式内容 + } else { + return "否"; // 不包含关键字 + } + } + return "否"; + } + + + // 获取单元格的公式计算结果(已经计算出来的值,字符串形式) - public String getFormulaResult(Cell cell, Workbook wb) { + public String getFormulaResult(Cell cell, Workbook wb,String keyWords) { if (cell == null) return "无"; if (cell.getCellType() != CellType.FORMULA) { return null; // 不是公式单元格返回null @@ -138,7 +156,7 @@ public class CellIng { } // 获取单元格字体名称 - public String getFontName(Cell cell, Workbook wb) { + public String getFontName(Cell cell, Workbook wb,String keyWords) { if (cell == null) return "无"; CellStyle style = cell.getCellStyle(); if (style == null) return "无"; @@ -152,7 +170,7 @@ public class CellIng { } // 获取单元格字体字号 - public String getFontSize(Cell cell, Workbook wb) { + public String getFontSize(Cell cell, Workbook wb,String keyWords) { if (cell == null) return "无"; CellStyle style = cell.getCellStyle(); if (style == null) return "无"; @@ -170,7 +188,7 @@ public class CellIng { // 获取单元格字形(加粗 / 斜体 ) - public String getFontStyle(Cell cell, Workbook wb) { + public String getFontStyle(Cell cell, Workbook wb,String keyWords) { if (cell == null) return "无"; CellStyle style = cell.getCellStyle(); if (style == null) return "无"; @@ -190,7 +208,7 @@ public class CellIng { // 获取单元格下划线 // 获取单元格下划线类型 - public String getUnderline(Cell cell, Workbook wb) { + public String getUnderline(Cell cell, Workbook wb,String keyWords) { if (cell == null) return "无"; CellStyle style = cell.getCellStyle(); if (style == null) return "无"; @@ -217,7 +235,7 @@ public class CellIng { } // 获取单元格颜色 - public String getFontColor(Cell cell, Workbook wb) { + public String getFontColor(Cell cell, Workbook wb,String keyWords) { if (cell == null) return "无"; CellStyle style = cell.getCellStyle(); if (style == null) return "无"; @@ -242,7 +260,7 @@ public class CellIng { return "无"; } // 删除线 - public static String getCellStrikeThrough(Cell cell, Workbook wb) { + public static String getCellStrikeThrough(Cell cell, Workbook wb,String keyWords) { if (cell == null) return "否"; CellStyle style = cell.getCellStyle(); if (style == null) return "否"; @@ -251,7 +269,7 @@ public class CellIng { } // 上标 - public static String getCellSuperScript(Cell cell, Workbook wb) { + public static String getCellSuperScript(Cell cell, Workbook wb,String keyWords) { if (cell == null) return "否"; CellStyle style = cell.getCellStyle(); if (style == null) return "否"; @@ -260,7 +278,7 @@ public class CellIng { } // 下标 - public static String getCellSubScript(Cell cell, Workbook wb) { + public static String getCellSubScript(Cell cell, Workbook wb,String keyWords) { if (cell == null) return "否"; CellStyle style = cell.getCellStyle(); if (style == null) return "否"; @@ -271,7 +289,7 @@ public class CellIng { // 获取斜下框线样式 - public static String getDiagonalDownBorderStyle(Cell cell, Workbook wb) { + public static String getDiagonalDownBorderStyle(Cell cell, Workbook wb,String keyWords) { if (cell == null || !(cell instanceof XSSFCell)) return "无"; XSSFCellStyle style = (XSSFCellStyle) cell.getCellStyle(); @@ -297,7 +315,7 @@ public class CellIng { } // 斜下框线→颜色 - public static String getDiagonalDownBorderColor(Cell cell, Workbook wb) { + public static String getDiagonalDownBorderColor(Cell cell, Workbook wb,String keyWords) { if (cell == null || !(cell instanceof XSSFCell)) return "无"; XSSFCellStyle style = (XSSFCellStyle) cell.getCellStyle(); @@ -320,7 +338,7 @@ public class CellIng { } // 斜上框线→样式 - public static String getDiagonalUpBorderStyle(Cell cell, Workbook wb) { + public static String getDiagonalUpBorderStyle(Cell cell, Workbook wb,String keyWords) { if (cell == null || !(cell instanceof XSSFCell)) return "无"; XSSFCellStyle style = (XSSFCellStyle) cell.getCellStyle(); @@ -342,7 +360,7 @@ public class CellIng { } // 斜上框线→颜色 - public static String getDiagonalUpBorderColor(Cell cell, Workbook wb) { + public static String getDiagonalUpBorderColor(Cell cell, Workbook wb,String keyWords) { if (cell == null || !(cell instanceof XSSFCell)) return "无"; XSSFCellStyle style = (XSSFCellStyle) cell.getCellStyle(); @@ -380,14 +398,14 @@ public class CellIng { // ===== 获取单元格文本(String) ===== - public String getCellText(Cell cell, Workbook wb) { + public String getCellText(Cell cell, Workbook wb,String keyWords) { if (cell == null) return "无"; DataFormatter formatter = new DataFormatter(); return formatter.formatCellValue(cell); } // ===== 获取单元格值 - public String getCellValue(Cell cell, Workbook wb) { + public String getCellValue(Cell cell, Workbook wb,String keyWords) { if (cell == null) return ""; switch (cell.getCellType()) { @@ -436,7 +454,7 @@ public class CellIng { } // 数字格式 - public static String getCellDataFormat(Cell cell, Workbook wb) { + public static String getCellDataFormat(Cell cell, Workbook wb,String keyWords) { if (cell == null) return "无"; CellStyle style = cell.getCellStyle(); if (style == null) return "无"; @@ -444,7 +462,7 @@ public class CellIng { } // 水平对齐 - public static String getCellHorizontalAlignment(Cell cell, Workbook wb) { + public static String getCellHorizontalAlignment(Cell cell, Workbook wb,String keyWords) { if (cell == null) return "无"; CellStyle style = cell.getCellStyle(); if (style == null) return "无"; @@ -453,7 +471,7 @@ public class CellIng { } // 垂直对齐 - public static String getCellVerticalAlignment(Cell cell, Workbook wb) { + public static String getCellVerticalAlignment(Cell cell, Workbook wb,String keyWords) { if (cell == null) return "无"; CellStyle style = cell.getCellStyle(); if (style == null) return "无"; @@ -462,7 +480,7 @@ public class CellIng { } // 缩进 - public static String getCellIndent(Cell cell, Workbook wb) { + public static String getCellIndent(Cell cell, Workbook wb,String keyWords) { if (cell == null) return "0"; CellStyle style = cell.getCellStyle(); if (style == null) return "0"; @@ -470,7 +488,7 @@ public class CellIng { } // 自动换行 - public static String getCellWrapText(Cell cell, Workbook wb) { + public static String getCellWrapText(Cell cell, Workbook wb,String keyWords) { if (cell == null) return "否"; CellStyle style = cell.getCellStyle(); if (style == null) return "否"; @@ -478,7 +496,7 @@ public class CellIng { } // 缩小字体填充(ShrinkToFit) - public static String getCellShrinkToFit(Cell cell, Workbook wb) { + public static String getCellShrinkToFit(Cell cell, Workbook wb,String keyWords) { if (cell == null) return "否"; CellStyle style = cell.getCellStyle(); if (style == null) return "否"; @@ -486,7 +504,7 @@ public class CellIng { } // 合并单元格 - public static String getCellMerged(Cell cell, Workbook wb) { + public static String getCellMerged(Cell cell, Workbook wb,String keyWords) { if (cell == null || wb == null) return "否"; Sheet sheet = cell.getSheet(); if (sheet == null) return "否"; @@ -505,7 +523,7 @@ public class CellIng { // 文本方向(rotation) - public static String getCellTextRotation(Cell cell, Workbook wb) { + public static String getCellTextRotation(Cell cell, Workbook wb,String keyWords) { if (cell == null) return "0"; CellStyle style = cell.getCellStyle(); if (style == null) return "0"; @@ -513,7 +531,7 @@ public class CellIng { } // 文本样式(加粗/斜体/下划线等) - public static String getCellFontStyle(Cell cell, Workbook wb) { + public static String getCellFontStyle(Cell cell, Workbook wb,String keyWords) { if (cell == null) return "无"; CellStyle style = cell.getCellStyle(); if (style == null) return "无"; @@ -536,7 +554,7 @@ public class CellIng { } // 高度(行高) - public static String getCellRowHeight(Cell cell, Workbook wb) { + public static String getCellRowHeight(Cell cell, Workbook wb,String keyWords) { if (cell == null || cell.getSheet() == null) return "默认"; Row row = cell.getRow(); if (row == null) return "默认"; @@ -544,7 +562,7 @@ public class CellIng { } // 宽度(列宽) - public static String getCellColumnWidth(Cell cell, Workbook wb) { + public static String getCellColumnWidth(Cell cell, Workbook wb,String keyWords) { if (cell == null || cell.getSheet() == null) return "默认"; int colWidth = cell.getSheet().getColumnWidth(cell.getColumnIndex()); // 单位 1/256字符 return String.format("%.2f pt", colWidth / 256.0 * 7); // 约 7pt/字符宽,可根据字体调整 diff --git a/exam-module-judgement/exam-module-judgement-biz/src/main/java/pc/exam/pp/module/judgement/utils/wps_word/docx4j/section/SectionPage.java b/exam-module-judgement/exam-module-judgement-biz/src/main/java/pc/exam/pp/module/judgement/utils/wps_word/docx4j/section/SectionPage.java index 8d7829a5..aabc569f 100644 --- a/exam-module-judgement/exam-module-judgement-biz/src/main/java/pc/exam/pp/module/judgement/utils/wps_word/docx4j/section/SectionPage.java +++ b/exam-module-judgement/exam-module-judgement-biz/src/main/java/pc/exam/pp/module/judgement/utils/wps_word/docx4j/section/SectionPage.java @@ -1686,7 +1686,7 @@ public class SectionPage { } // 横向匹配 if (Math.abs(width - sh) <= tol && Math.abs(height - sw) <= tol) { - return entry.getKey() + " (横向)"; + return entry.getKey(); } } diff --git a/exam-module-system/exam-module-system-biz/src/main/java/pc/exam/pp/module/system/controller/admin/auth/AuthController.java b/exam-module-system/exam-module-system-biz/src/main/java/pc/exam/pp/module/system/controller/admin/auth/AuthController.java index 98eebf1d..cbdd11d6 100644 --- a/exam-module-system/exam-module-system-biz/src/main/java/pc/exam/pp/module/system/controller/admin/auth/AuthController.java +++ b/exam-module-system/exam-module-system-biz/src/main/java/pc/exam/pp/module/system/controller/admin/auth/AuthController.java @@ -18,6 +18,7 @@ import pc.exam.pp.module.system.convert.auth.AuthConvert; import pc.exam.pp.module.system.dal.dataobject.oauth2.OAuth2AccessTokenDO; import pc.exam.pp.module.system.dal.dataobject.permission.MenuDO; import pc.exam.pp.module.system.dal.dataobject.permission.RoleDO; +import pc.exam.pp.module.system.dal.dataobject.tenant.TenantDO; import pc.exam.pp.module.system.dal.dataobject.user.AdminUserDO; import pc.exam.pp.module.system.enums.logger.LoginLogTypeEnum; import pc.exam.pp.module.system.service.auth.AdminAuthService; @@ -25,6 +26,7 @@ import pc.exam.pp.module.system.service.permission.MenuService; import pc.exam.pp.module.system.service.permission.PermissionService; import pc.exam.pp.module.system.service.permission.RoleService; import pc.exam.pp.module.system.service.social.SocialClientService; +import pc.exam.pp.module.system.service.tenant.TenantService; import pc.exam.pp.module.system.service.user.AdminUserService; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.Parameter; @@ -37,6 +39,7 @@ import jakarta.validation.Valid; import lombok.extern.slf4j.Slf4j; import org.springframework.validation.annotation.Validated; import org.springframework.web.bind.annotation.*; +import pc.exam.pp.module.system.util.oauth2.MacUtils; import java.util.Collections; import java.util.List; @@ -79,6 +82,8 @@ public class AuthController { private ConfigService configService; @Resource private StringRedisTemplate stringRedisTemplate; + @Resource + private TenantService tenantService; @GetMapping("/login_config") @PermitAll @@ -142,7 +147,7 @@ public class AuthController { // 先判断管理员密码 ConfigDO config = configService.getConfigByKey("system_username_logout"); if (!config.getValue().equals(loginoutVo.getLoginOutPassword())) { - return CommonResult.error(900002, "系统管理员密码错误!"); + return success("900002"); } Set oauth2_access_token_set = stringRedisTemplate.keys("oauth2_access_token:*"); for (String oauth2_access_token : oauth2_access_token_set) { diff --git a/exam-module-system/exam-module-system-biz/src/main/java/pc/exam/pp/module/system/controller/admin/tenant/TenantController.java b/exam-module-system/exam-module-system-biz/src/main/java/pc/exam/pp/module/system/controller/admin/tenant/TenantController.java index 992df19b..8666cbe6 100644 --- a/exam-module-system/exam-module-system-biz/src/main/java/pc/exam/pp/module/system/controller/admin/tenant/TenantController.java +++ b/exam-module-system/exam-module-system-biz/src/main/java/pc/exam/pp/module/system/controller/admin/tenant/TenantController.java @@ -7,10 +7,8 @@ import pc.exam.pp.framework.common.pojo.PageParam; import pc.exam.pp.framework.common.pojo.PageResult; import pc.exam.pp.framework.common.util.object.BeanUtils; import pc.exam.pp.framework.excel.core.util.ExcelUtils; -import pc.exam.pp.module.system.controller.admin.tenant.vo.tenant.TenantPageReqVO; -import pc.exam.pp.module.system.controller.admin.tenant.vo.tenant.TenantRespVO; -import pc.exam.pp.module.system.controller.admin.tenant.vo.tenant.TenantSaveReqVO; -import pc.exam.pp.module.system.controller.admin.tenant.vo.tenant.TenantSpecialtyPointsVO; +import pc.exam.pp.framework.tenant.core.aop.TenantIgnore; +import pc.exam.pp.module.system.controller.admin.tenant.vo.tenant.*; import pc.exam.pp.module.system.dal.dataobject.tenant.TenantDO; import pc.exam.pp.module.system.dal.dataobject.tenant.TenantSpcialtyDO; import pc.exam.pp.module.system.service.tenant.TenantService; @@ -113,6 +111,7 @@ public class TenantController { @GetMapping("/page") @Operation(summary = "获得租户分页") @PreAuthorize("@ss.hasPermission('system:tenant:query')") + @TenantIgnore public CommonResult> getTenantPage(@Valid TenantPageReqVO pageVO) { PageResult pageResult = tenantService.getTenantPage(pageVO); return success(BeanUtils.toBean(pageResult, TenantRespVO.class)); @@ -131,4 +130,14 @@ public class TenantController { BeanUtils.toBean(list, TenantRespVO.class)); } + /** + * 重置租户管理员密码 + */ + @PostMapping("/reset-password") + @Operation(summary = "重置租户管理员密码") + @TenantIgnore + public CommonResult resetPassword(@RequestBody ResetPasswordReqVO reqVO) { + tenantService.resetPassword(reqVO); + return success("密码重置成功!"); + } } diff --git a/exam-module-system/exam-module-system-biz/src/main/java/pc/exam/pp/module/system/controller/admin/tenant/vo/tenant/ResetPasswordReqVO.java b/exam-module-system/exam-module-system-biz/src/main/java/pc/exam/pp/module/system/controller/admin/tenant/vo/tenant/ResetPasswordReqVO.java new file mode 100644 index 00000000..acf654fd --- /dev/null +++ b/exam-module-system/exam-module-system-biz/src/main/java/pc/exam/pp/module/system/controller/admin/tenant/vo/tenant/ResetPasswordReqVO.java @@ -0,0 +1,9 @@ +package pc.exam.pp.module.system.controller.admin.tenant.vo.tenant; + +import lombok.Data; + +@Data +public class ResetPasswordReqVO { + private Long id; // 租户ID 或 管理员ID + private String password; // 新密码 +} diff --git a/exam-module-system/exam-module-system-biz/src/main/java/pc/exam/pp/module/system/controller/admin/tenant/vo/tenant/TenantRespVO.java b/exam-module-system/exam-module-system-biz/src/main/java/pc/exam/pp/module/system/controller/admin/tenant/vo/tenant/TenantRespVO.java index c916a315..99502136 100644 --- a/exam-module-system/exam-module-system-biz/src/main/java/pc/exam/pp/module/system/controller/admin/tenant/vo/tenant/TenantRespVO.java +++ b/exam-module-system/exam-module-system-biz/src/main/java/pc/exam/pp/module/system/controller/admin/tenant/vo/tenant/TenantRespVO.java @@ -19,8 +19,8 @@ public class TenantRespVO { @ExcelProperty("租户编号") private Long id; - @Schema(description = "租户名", requiredMode = Schema.RequiredMode.REQUIRED, example = "芋道") - @ExcelProperty("租户名") + @Schema(description = "学校用户名", requiredMode = Schema.RequiredMode.REQUIRED, example = "芋道") + @ExcelProperty("学校用户名") private String name; @Schema(description = "联系人", requiredMode = Schema.RequiredMode.REQUIRED, example = "芋艿") @@ -36,7 +36,11 @@ public class TenantRespVO { @DictFormat(DictTypeConstants.COMMON_STATUS) private Integer status; - @Schema(description = "绑定域名", example = "https://www.iocoder.cn") + @Schema(description = "管理员账号", requiredMode = Schema.RequiredMode.REQUIRED, example = "admin") + @ExcelProperty("管理员账号") + private String username; + + @Schema(description = "绑定MAC地址", example = "https://www.iocoder.cn") private String website; @Schema(description = "租户套餐编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024") @@ -52,4 +56,6 @@ public class TenantRespVO { @ExcelProperty("创建时间") private LocalDateTime createTime; + private String contactUserId; + } diff --git a/exam-module-system/exam-module-system-biz/src/main/java/pc/exam/pp/module/system/dal/dataobject/tenant/TenantDO.java b/exam-module-system/exam-module-system-biz/src/main/java/pc/exam/pp/module/system/dal/dataobject/tenant/TenantDO.java index 59b615ed..d476af00 100644 --- a/exam-module-system/exam-module-system-biz/src/main/java/pc/exam/pp/module/system/dal/dataobject/tenant/TenantDO.java +++ b/exam-module-system/exam-module-system-biz/src/main/java/pc/exam/pp/module/system/dal/dataobject/tenant/TenantDO.java @@ -1,5 +1,6 @@ package pc.exam.pp.module.system.dal.dataobject.tenant; +import com.baomidou.mybatisplus.annotation.TableField; import pc.exam.pp.framework.common.enums.CommonStatusEnum; import pc.exam.pp.framework.mybatis.core.dataobject.BaseDO; import pc.exam.pp.module.system.dal.dataobject.user.AdminUserDO; @@ -79,5 +80,10 @@ public class TenantDO extends BaseDO { private String queueName; + /** + * 管理员账号 + */ + @TableField(exist = false) + private String username; } diff --git a/exam-module-system/exam-module-system-biz/src/main/java/pc/exam/pp/module/system/dal/mysql/user/AdminUserMapper.java b/exam-module-system/exam-module-system-biz/src/main/java/pc/exam/pp/module/system/dal/mysql/user/AdminUserMapper.java index 642860af..9f93836e 100644 --- a/exam-module-system/exam-module-system-biz/src/main/java/pc/exam/pp/module/system/dal/mysql/user/AdminUserMapper.java +++ b/exam-module-system/exam-module-system-biz/src/main/java/pc/exam/pp/module/system/dal/mysql/user/AdminUserMapper.java @@ -70,4 +70,7 @@ public interface AdminUserMapper extends BaseMapperX { List selectUserByIdList(@Param("id") Long id); + String selectOneById(Long id); + + void updateByIdToPassword(@Param("password")String password, @Param("id")Long id); } diff --git a/exam-module-system/exam-module-system-biz/src/main/java/pc/exam/pp/module/system/service/tenant/TenantService.java b/exam-module-system/exam-module-system-biz/src/main/java/pc/exam/pp/module/system/service/tenant/TenantService.java index c7cd469e..6c7ba445 100644 --- a/exam-module-system/exam-module-system-biz/src/main/java/pc/exam/pp/module/system/service/tenant/TenantService.java +++ b/exam-module-system/exam-module-system-biz/src/main/java/pc/exam/pp/module/system/service/tenant/TenantService.java @@ -2,6 +2,7 @@ package pc.exam.pp.module.system.service.tenant; import pc.exam.pp.framework.common.pojo.PageResult; import pc.exam.pp.framework.tenant.core.context.TenantContextHolder; +import pc.exam.pp.module.system.controller.admin.tenant.vo.tenant.ResetPasswordReqVO; import pc.exam.pp.module.system.controller.admin.tenant.vo.tenant.TenantPageReqVO; import pc.exam.pp.module.system.controller.admin.tenant.vo.tenant.TenantSaveReqVO; import pc.exam.pp.module.system.controller.admin.tenant.vo.tenant.TenantSpecialtyPointsVO; @@ -145,4 +146,5 @@ public interface TenantService { */ void validTenant(Long id); + void resetPassword(ResetPasswordReqVO reqVO); } diff --git a/exam-module-system/exam-module-system-biz/src/main/java/pc/exam/pp/module/system/service/tenant/TenantServiceImpl.java b/exam-module-system/exam-module-system-biz/src/main/java/pc/exam/pp/module/system/service/tenant/TenantServiceImpl.java index 19b8b090..811612bd 100644 --- a/exam-module-system/exam-module-system-biz/src/main/java/pc/exam/pp/module/system/service/tenant/TenantServiceImpl.java +++ b/exam-module-system/exam-module-system-biz/src/main/java/pc/exam/pp/module/system/service/tenant/TenantServiceImpl.java @@ -4,16 +4,19 @@ import cn.hutool.core.collection.CollUtil; import cn.hutool.core.lang.Assert; import cn.hutool.core.util.ObjectUtil; import cn.hutool.core.util.StrUtil; +import org.springframework.security.crypto.password.PasswordEncoder; import pc.exam.pp.framework.common.enums.CommonStatusEnum; import pc.exam.pp.framework.common.pojo.PageResult; import pc.exam.pp.framework.common.util.collection.CollectionUtils; import pc.exam.pp.framework.common.util.date.DateUtils; import pc.exam.pp.framework.common.util.object.BeanUtils; +import pc.exam.pp.framework.mybatis.core.query.LambdaQueryWrapperX; import pc.exam.pp.framework.tenant.config.TenantProperties; import pc.exam.pp.framework.tenant.core.context.TenantContextHolder; import pc.exam.pp.framework.tenant.core.util.TenantUtils; import pc.exam.pp.module.exam.utils.rabbitmq.RabbitmqUtils; import pc.exam.pp.module.system.controller.admin.permission.vo.role.RoleSaveReqVO; +import pc.exam.pp.module.system.controller.admin.tenant.vo.tenant.ResetPasswordReqVO; import pc.exam.pp.module.system.controller.admin.tenant.vo.tenant.TenantPageReqVO; import pc.exam.pp.module.system.controller.admin.tenant.vo.tenant.TenantSaveReqVO; import pc.exam.pp.module.system.controller.admin.tenant.vo.tenant.TenantSpecialtyPointsVO; @@ -23,8 +26,10 @@ import pc.exam.pp.module.system.dal.dataobject.permission.RoleDO; import pc.exam.pp.module.system.dal.dataobject.tenant.TenantDO; import pc.exam.pp.module.system.dal.dataobject.tenant.TenantPackageDO; import pc.exam.pp.module.system.dal.dataobject.tenant.TenantSpcialtyDO; +import pc.exam.pp.module.system.dal.dataobject.user.AdminUserDO; import pc.exam.pp.module.system.dal.mysql.tenant.TenantMapper; import pc.exam.pp.module.system.dal.mysql.tenant.TenantSpecialtyMapper; +import pc.exam.pp.module.system.dal.mysql.user.AdminUserMapper; import pc.exam.pp.module.system.enums.permission.RoleCodeEnum; import pc.exam.pp.module.system.enums.permission.RoleTypeEnum; import pc.exam.pp.module.system.service.permission.MenuService; @@ -81,7 +86,10 @@ public class TenantServiceImpl implements TenantService { private MenuService menuService; @Resource private PermissionService permissionService; - + @Resource + private AdminUserMapper userMapper; + @Resource + private PasswordEncoder passwordEncoder; @Override public List getTenantIdList() { List tenants = tenantMapper.selectList(); @@ -102,6 +110,13 @@ public class TenantServiceImpl implements TenantService { } } + @Override + public void resetPassword(ResetPasswordReqVO reqVO) { + AdminUserDO adminUserDO=new AdminUserDO(); + String newPassword = passwordEncoder.encode(reqVO.getPassword()); + userMapper.updateByIdToPassword(newPassword,reqVO.getId()); + } + @Override @DSTransactional // 多数据源,使用 @DSTransactional 保证本地事务,以及数据源的切换 public Long createTenant(TenantSaveReqVO createReqVO) { @@ -276,7 +291,19 @@ public class TenantServiceImpl implements TenantService { @Override public PageResult getTenantPage(TenantPageReqVO pageReqVO) { - return tenantMapper.selectPage(pageReqVO); + PageResult tenantDOPageResult = tenantMapper.selectPage(pageReqVO); + List list = tenantDOPageResult.getList(); + if (list!=null&&list.size()>0){ + for (TenantDO tenantDO : list) { + Long contactUserId = tenantDO.getContactUserId(); + String userName= userMapper.selectOneById(contactUserId); + if (userName != null) { + tenantDO.setUsername(userName); //设置管理员账号 + } + } + } + tenantDOPageResult.setList(list); + return tenantDOPageResult; } @Override diff --git a/exam-module-system/exam-module-system-biz/src/main/java/pc/exam/pp/module/system/service/user/AdminUserServiceImpl.java b/exam-module-system/exam-module-system-biz/src/main/java/pc/exam/pp/module/system/service/user/AdminUserServiceImpl.java index 935f5626..2998b7c1 100644 --- a/exam-module-system/exam-module-system-biz/src/main/java/pc/exam/pp/module/system/service/user/AdminUserServiceImpl.java +++ b/exam-module-system/exam-module-system-biz/src/main/java/pc/exam/pp/module/system/service/user/AdminUserServiceImpl.java @@ -840,17 +840,19 @@ public class AdminUserServiceImpl implements AdminUserService { specialtyQueryVos = examSpecialtyMapper.selectExamSpecialtyAll(); } else { // 查询部分数据 - List specialtyList = examSpecialtyMapper.selectExamSpecialtyByids(adminUserDO.getSpecialtyIds()); - for (SpecialtyQueryVo specialtyQueryVo : specialtyList) { - specialtyQueryVos.add(specialtyQueryVo); - // 查询题型 - if (specialtyQueryVo.getAncestors().contains(",")) { - List specialtyLists = examSpecialtyMapper.selectExamSpecialtyByParentId(specialtyQueryVo.getId()); - for (SpecialtyQueryVo specialtyQueryVosInfo : specialtyLists) { - specialtyQueryVos.add(specialtyQueryVosInfo); - } - } - } + specialtyQueryVos = examSpecialtyMapper.selectExamSpecialtyByids(adminUserDO.getSpecialtyIds()); + +// List specialtyList = examSpecialtyMapper.selectExamSpecialtyByids(adminUserDO.getSpecialtyIds()); +// for (SpecialtyQueryVo specialtyQueryVo : specialtyList) { +// specialtyQueryVos.add(specialtyQueryVo); +// // 查询题型 +// if (specialtyQueryVo.getAncestors().contains(",")) { +// List specialtyLists = examSpecialtyMapper.selectExamSpecialtyByParentId(specialtyQueryVo.getId()); +// for (SpecialtyQueryVo specialtyQueryVosInfo : specialtyLists) { +// specialtyQueryVos.add(specialtyQueryVosInfo); +// } +// } +// } } } } else { @@ -940,17 +942,18 @@ public class AdminUserServiceImpl implements AdminUserService { specialtyQueryVos = examSpecialtyMapper.selectExamSpecialtyAll(); } else { // 查询部分数据 - List specialtyList = examSpecialtyMapper.selectExamSpecialtyByids(adminUserDO.getSpecialtyIds()); - for (SpecialtyQueryVo specialtyQueryVo : specialtyList) { - specialtyQueryVos.add(specialtyQueryVo); - // 查询题型 - if (specialtyQueryVo.getAncestors().contains(",")) { - List specialtyLists = examSpecialtyMapper.selectExamSpecialtyByParentId(specialtyQueryVo.getId()); - for (SpecialtyQueryVo specialtyQueryVosInfo : specialtyLists) { - specialtyQueryVos.add(specialtyQueryVosInfo); - } - } - } + specialtyQueryVos = examSpecialtyMapper.selectExamSpecialtyByids(adminUserDO.getSpecialtyIds()); +// List specialtyList = examSpecialtyMapper.selectExamSpecialtyByids(adminUserDO.getSpecialtyIds()); +// for (SpecialtyQueryVo specialtyQueryVo : specialtyList) { +// specialtyQueryVos.add(specialtyQueryVo); +// // 查询题型 +// if (specialtyQueryVo.getAncestors().contains(",")) { +// List specialtyLists = examSpecialtyMapper.selectExamSpecialtyByParentId(specialtyQueryVo.getId()); +// for (SpecialtyQueryVo specialtyQueryVosInfo : specialtyLists) { +// specialtyQueryVos.add(specialtyQueryVosInfo); +// } +// } +// } } } } diff --git a/exam-module-system/exam-module-system-biz/src/main/java/pc/exam/pp/module/system/util/oauth2/MacUtils.java b/exam-module-system/exam-module-system-biz/src/main/java/pc/exam/pp/module/system/util/oauth2/MacUtils.java new file mode 100644 index 00000000..361c4a5d --- /dev/null +++ b/exam-module-system/exam-module-system-biz/src/main/java/pc/exam/pp/module/system/util/oauth2/MacUtils.java @@ -0,0 +1,161 @@ +package pc.exam.pp.module.system.util.oauth2; +import java.net.InetAddress; +import java.net.NetworkInterface; +import java.util.*; + + +public class MacUtils { + + public static String getFirstNonLoopbackMac() { + try { + // 先尝试按本机 InetAddress 对应的网卡 + InetAddress localHost = InetAddress.getLocalHost(); + NetworkInterface ni = NetworkInterface.getByInetAddress(localHost); + if (ni != null) { + byte[] mac = ni.getHardwareAddress(); + if (mac != null && mac.length > 0) { + return formatMac(mac); + } + } + + // 否则遍历所有网卡,返回第一个符合条件的 + Enumeration interfaces = NetworkInterface.getNetworkInterfaces(); + for (NetworkInterface netIf : Collections.list(interfaces)) { + try { + if (netIf == null) continue; + if (netIf.isLoopback() || netIf.isVirtual() || !netIf.isUp()) continue; + byte[] mac = netIf.getHardwareAddress(); + if (mac != null && mac.length > 0) { + return formatMac(mac); + } + } catch (Exception ignore) { + // 忽略单个网卡异常,继续下一个 + } + } + } catch (Exception e) { + // 可选:记录日志 + e.printStackTrace(); + } + return null; + } + + /** + * 返回所有网卡的 MAC 地址映射:网卡名 -> MAC 字符串(若无 MAC 则不包含该网卡)。 + */ + public static Map getAllMacs() { + Map result = new LinkedHashMap<>(); + try { + Enumeration interfaces = NetworkInterface.getNetworkInterfaces(); + for (NetworkInterface netIf : Collections.list(interfaces)) { + try { + if (netIf == null) continue; + byte[] mac = netIf.getHardwareAddress(); + if (mac != null && mac.length > 0) { + result.put(netIf.getName(), formatMac(mac)); + } + } catch (Exception ignore) { + } + } + } catch (Exception e) { + e.printStackTrace(); + } + return result; + } + + + /** + * 获取最可能的物理(全局唯一)MAC 地址,格式 AA:BB:CC:DD:EE:FF + * 返回 Optional.empty() 表示未能找到。 + */ + public static String getPhysicalMac() { + try { + Enumeration interfaces = NetworkInterface.getNetworkInterfaces(); + if (interfaces == null) return ""; + + List list = Collections.list(interfaces); + + // 排序:把更有可能的真实物理网卡放到前面(优先有IPv4地址且不是虚拟) + list.sort(Comparator.comparingInt(MacUtils::scoreInterface).reversed()); + + String fallback = null; + + for (NetworkInterface ni : list) { + try { + if (ni == null) continue; + + // 基本过滤 + if (ni.isLoopback()) continue; + if (!ni.isUp()) continue; + if (ni.isVirtual()) continue; + if (ni.isPointToPoint()) continue; + + String name = ni.getName() == null ? "" : ni.getName().toLowerCase(); + String display = ni.getDisplayName() == null ? "" : ni.getDisplayName().toLowerCase(); + + // 跳过常见虚拟或容器接口 + if (name.startsWith("veth") || name.startsWith("vmnet") || name.startsWith("docker") + || name.startsWith("br-") || name.startsWith("virbr") || name.startsWith("vbox") + || name.startsWith("tun") || name.startsWith("tap") + || name.startsWith("lo") || name.contains("virtual") || display.contains("virtual") + || (name.startsWith("wlx") && name.contains("virtual"))) { + continue; + } + + byte[] mac = ni.getHardwareAddress(); + if (mac == null || mac.length != 6) continue; + + String macStr = formatMac(mac); + + // 检查是否全局唯一 MAC(locally-administered bit == 0) + boolean locallyAdministered = (mac[0] & 0x02) != 0; + boolean multicast = (mac[0] & 0x01) != 0; + + if (multicast) continue; + + if (!locallyAdministered) { + // 厂商分配的全局唯一 MAC + return macStr; + } else if (fallback == null) { + fallback = macStr; + } + } catch (Throwable ignored) { + } + } + + // 若未找到全局唯一 MAC,则返回第一个符合条件的 + return fallback != null ? fallback : ""; + } catch (Exception e) { + return ""; + } + } + + /** + * 根据接口是否有 IP、是否有名字等打分,便于把好接口排前面 + */ + private static int scoreInterface(NetworkInterface ni) { + int score = 0; + try { + if (ni == null) return score; + if (ni.getHardwareAddress() != null) score += 10; + if (!ni.isVirtual()) score += 5; + if (ni.getInterfaceAddresses() != null && !ni.getInterfaceAddresses().isEmpty()) score += 3; + String name = ni.getName() == null ? "" : ni.getName().toLowerCase(); + if (name.startsWith("eth") || name.startsWith("en") || name.startsWith("wlan") || name.startsWith("wl")) score += 2; + } catch (Exception ignore) {} + return score; + } + /** + * 把 byte[] mac 格式化为 "AA-BB-CC-DD-EE-FF" + */ + private static String formatMac(byte[] mac) { + StringBuilder sb = new StringBuilder(); + for (int i = 0; i < mac.length; i++) { + sb.append(String.format("%02X", mac[i])); + if (i < mac.length - 1) sb.append("-"); + } + return sb.toString(); + } + public static String normalizeMac(String mac) { + return mac == null ? "" : mac.replaceAll("[-:]", "").toUpperCase(); + } +} diff --git a/exam-module-system/exam-module-system-biz/src/main/resources/mapper/user/AdminUserMapper.xml b/exam-module-system/exam-module-system-biz/src/main/resources/mapper/user/AdminUserMapper.xml index 68b1a86a..3a1fafa3 100644 --- a/exam-module-system/exam-module-system-biz/src/main/resources/mapper/user/AdminUserMapper.xml +++ b/exam-module-system/exam-module-system-biz/src/main/resources/mapper/user/AdminUserMapper.xml @@ -20,5 +20,16 @@ LEFT JOIN exam_class ec ON ec.id = su.class_id WHERE stc.user_id = #{id} + + + UPDATE system_users + SET password = #{password} + WHERE id = #{id} + \ No newline at end of file diff --git a/exam-server/src/main/java/pc/exam/pp/server/config/MacValidator.java b/exam-server/src/main/java/pc/exam/pp/server/config/MacValidator.java new file mode 100644 index 00000000..f7c9d17e --- /dev/null +++ b/exam-server/src/main/java/pc/exam/pp/server/config/MacValidator.java @@ -0,0 +1,49 @@ +package pc.exam.pp.server.config; + + +import jakarta.annotation.PostConstruct; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Component; +import pc.exam.pp.module.system.util.oauth2.MacUtils; + +import java.util.List; + +@Slf4j +@Component +public class MacValidator { + + private final SystemMacProperties macProperties; + + public MacValidator(SystemMacProperties macProperties) { + this.macProperties = macProperties; + } + + @PostConstruct + public void validateMac() { + try { + String localMac = String.valueOf(MacUtils.getPhysicalMac()); + if (localMac == null || localMac.isEmpty()) { + throw new IllegalStateException("无法获取本机 MAC 地址!"); + } + + String allowed = macProperties.getAllowedMac(); + if (allowed == null || allowed.isEmpty()) { + throw new IllegalStateException("系统未配置允许的 MAC 地址!"); + } + + boolean match = normalize(allowed).equals(normalize(localMac)); + if (!match) { + throw new IllegalStateException("该机器 MAC 地址未授权!本机:" + localMac); + } + + log.info("✅ MAC 验证通过,本机 MAC: {}", localMac); + } catch (Exception e) { + log.error("❌ MAC 验证失败: {}", e.getMessage()); + System.exit(1); // 阻止启动 + } + } + + private String normalize(String mac) { + return mac == null ? "" : mac.replaceAll("[-:]", "").toUpperCase(); + } +} diff --git a/exam-server/src/main/java/pc/exam/pp/server/config/SystemMacProperties.java b/exam-server/src/main/java/pc/exam/pp/server/config/SystemMacProperties.java new file mode 100644 index 00000000..a5189b2a --- /dev/null +++ b/exam-server/src/main/java/pc/exam/pp/server/config/SystemMacProperties.java @@ -0,0 +1,18 @@ +package pc.exam.pp.server.config; + +import lombok.Data; +import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.stereotype.Component; + +import java.util.List; + +@Data +@Component +@ConfigurationProperties(prefix = "system") // 对应 application.yml 中的 system: 节点 +public class SystemMacProperties { + + /** + * 允许的 MAC 地址列表 + */ + private String allowedMac; +} diff --git a/exam-server/src/main/resources/application-local.yaml b/exam-server/src/main/resources/application-local.yaml index 3f37a996..52a72db5 100644 --- a/exam-server/src/main/resources/application-local.yaml +++ b/exam-server/src/main/resources/application-local.yaml @@ -73,7 +73,7 @@ spring: redis: host: 115.120.213.238 # 地址 port: 6379 # 端口 - database: 0 # 数据库索引 + database: 1 # 数据库索引 password: sadjklasnfasd # 密码,建议生产环境开启 --- #################### 定时任务相关配置 #################### @@ -262,4 +262,6 @@ justauth: --- #################### iot相关配置 #################### pf4j: # pluginsDir: /tmp/ - pluginsDir: ../plugins \ No newline at end of file + pluginsDir: ../plugins +system: + allowed-mac: E4-54-E8-25-F6-14