diff --git a/ry-xinli-admin/src/main/java/com/ddnai/web/controller/psychology/PsyAssessmentController.java b/ry-xinli-admin/src/main/java/com/ddnai/web/controller/psychology/PsyAssessmentController.java index edaf179c..be1f3c02 100644 --- a/ry-xinli-admin/src/main/java/com/ddnai/web/controller/psychology/PsyAssessmentController.java +++ b/ry-xinli-admin/src/main/java/com/ddnai/web/controller/psychology/PsyAssessmentController.java @@ -186,6 +186,7 @@ public class PsyAssessmentController extends BaseController /** * 开始测评 * 允许管理员和学员访问 + * 每个用户对同一量表只能有一条未完成的测评记录 */ @PostMapping("/start") public AjaxResult start(@Validated @RequestBody AssessmentStartVO startVO) @@ -200,35 +201,53 @@ public class PsyAssessmentController extends BaseController currentUsername = SecurityUtils.getUsername(); } catch (Exception e) { logger.warn("获取用户信息失败,可能是匿名访问: {}", e.getMessage()); - // 如果是匿名访问,userId 和 username 可以为 null } // 确定实际的测评用户ID - // 如果传入了targetUserId(管理员代替用户测评),使用targetUserId - // 否则使用当前登录用户ID Long assessmentUserId = startVO.getTargetUserId() != null ? startVO.getTargetUserId() : currentUserId; + // 检查是否已存在该用户对该量表的未完成测评记录 + if (assessmentUserId != null && startVO.getScaleId() != null) + { + // 使用不过滤的查询方法,获取所有测评记录 + List existingList = assessmentService.selectAssessmentByUserAndScale(assessmentUserId, startVO.getScaleId()); + + // 查找未完成的测评(状态为进行中或已暂停) + for (PsyAssessment existing : existingList) + { + if ("0".equals(existing.getStatus()) || "3".equals(existing.getStatus())) + { + // 已存在未完成的测评,直接返回该测评ID + // 不在这里改变状态,让前端在进入答题页面后调用 resume API + logger.info("复用已存在的测评记录 - assessmentId: {}, status: {}", + existing.getAssessmentId(), existing.getStatus()); + + return success(existing.getAssessmentId()); + } + } + } + + // 没有未完成的测评,创建新的测评记录 + // 初始状态为"已暂停",等用户真正进入答题页面后再改为"进行中" PsyAssessment assessment = new PsyAssessment(); assessment.setScaleId(startVO.getScaleId()); assessment.setAssesseeName(startVO.getAssesseeName()); assessment.setAssesseeGender(startVO.getAssesseeGender()); assessment.setAssesseeAge(startVO.getAssesseeAge()); assessment.setAssesseePhone(startVO.getAssesseePhone()); - assessment.setStatus("0"); + assessment.setStatus("3"); // 初始状态为"已暂停" assessment.setStartTime(new Date()); assessment.setIpAddress(IpUtils.getIpAddr()); assessment.setUserAgent(ServletUtils.getRequest().getHeader("User-Agent")); - // 设置用户ID(优先使用targetUserId) if (assessmentUserId != null) { assessment.setUserId(assessmentUserId); } - // 设置创建者(记录是谁创建的测评) if (currentUsername != null && !currentUsername.isEmpty()) { assessment.setCreateBy(currentUsername); } else { - assessment.setCreateBy("system"); // 默认值 + assessment.setCreateBy("system"); } logger.info("创建测评 - scaleId: {}, targetUserId: {}, assessmentUserId: {}, currentUserId: {}, assesseeName: {}", @@ -251,6 +270,53 @@ public class PsyAssessmentController extends BaseController return error("开始测评失败:" + (e.getMessage() != null ? e.getMessage() : e.getClass().getSimpleName())); } } + + /** + * 重置测评(删除未完成的测评记录,重新开始) + * 允许管理员和学员访问(学员只能重置自己的测评) + */ + @PostMapping("/reset") + public AjaxResult reset(@RequestBody AssessmentStartVO startVO) + { + try { + Long currentUserId = SecurityUtils.getUserId(); + Long assessmentUserId = startVO.getTargetUserId() != null ? startVO.getTargetUserId() : currentUserId; + + if (assessmentUserId == null || startVO.getScaleId() == null) + { + return error("参数不完整"); + } + + // 检查权限:学员只能重置自己的测评 + boolean hasManagePerm = false; + try { + hasManagePerm = SecurityUtils.hasPermi("psychology:assessment:edit"); + } catch (Exception ignored) {} + + if (!hasManagePerm && !assessmentUserId.equals(currentUserId)) { + return error("无权重置其他用户的测评"); + } + + // 查找该用户对该量表的所有测评记录 + List existingList = assessmentService.selectAssessmentByUserAndScale(assessmentUserId, startVO.getScaleId()); + + // 删除所有未完成的测评 + for (PsyAssessment existing : existingList) + { + if ("0".equals(existing.getStatus()) || "3".equals(existing.getStatus())) + { + assessmentService.deleteAssessmentByIds(new Long[]{existing.getAssessmentId()}); + logger.info("删除未完成的测评记录 - assessmentId: {}", existing.getAssessmentId()); + } + } + + // 创建新的测评记录 + return start(startVO); + } catch (Exception e) { + logger.error("重置测评异常", e); + return error("重置测评失败:" + e.getMessage()); + } + } /** * 修改测评 diff --git a/ry-xinli-system/src/main/java/com/ddnai/system/mapper/psychology/PsyAssessmentMapper.java b/ry-xinli-system/src/main/java/com/ddnai/system/mapper/psychology/PsyAssessmentMapper.java index df11cb43..e48a0e26 100644 --- a/ry-xinli-system/src/main/java/com/ddnai/system/mapper/psychology/PsyAssessmentMapper.java +++ b/ry-xinli-system/src/main/java/com/ddnai/system/mapper/psychology/PsyAssessmentMapper.java @@ -49,6 +49,15 @@ public interface PsyAssessmentMapper */ public List selectPausedAssessmentList(Long userId); + /** + * 查询用户对某个量表的所有测评记录(不过滤,用于内部逻辑) + * + * @param userId 用户ID + * @param scaleId 量表ID + * @return 测评集合 + */ + public List selectAssessmentByUserAndScale(@Param("userId") Long userId, @Param("scaleId") Long scaleId); + /** * 新增测评 * diff --git a/ry-xinli-system/src/main/java/com/ddnai/system/service/impl/psychology/PsyAssessmentServiceImpl.java b/ry-xinli-system/src/main/java/com/ddnai/system/service/impl/psychology/PsyAssessmentServiceImpl.java index 64dede31..f43eb497 100644 --- a/ry-xinli-system/src/main/java/com/ddnai/system/service/impl/psychology/PsyAssessmentServiceImpl.java +++ b/ry-xinli-system/src/main/java/com/ddnai/system/service/impl/psychology/PsyAssessmentServiceImpl.java @@ -85,6 +85,12 @@ public class PsyAssessmentServiceImpl implements IPsyAssessmentService return assessmentMapper.selectPausedAssessmentList(userId); } + @Override + public List selectAssessmentByUserAndScale(Long userId, Long scaleId) + { + return assessmentMapper.selectAssessmentByUserAndScale(userId, scaleId); + } + @Override public int insertAssessment(PsyAssessment assessment) { diff --git a/ry-xinli-system/src/main/java/com/ddnai/system/service/impl/psychology/PsyUserProfileServiceImpl.java b/ry-xinli-system/src/main/java/com/ddnai/system/service/impl/psychology/PsyUserProfileServiceImpl.java index d2d10bdf..c48768d0 100644 --- a/ry-xinli-system/src/main/java/com/ddnai/system/service/impl/psychology/PsyUserProfileServiceImpl.java +++ b/ry-xinli-system/src/main/java/com/ddnai/system/service/impl/psychology/PsyUserProfileServiceImpl.java @@ -141,16 +141,10 @@ public class PsyUserProfileServiceImpl implements IPsyUserProfileService profile.setInfoNumber(infoNumber); validateInfoNumberUnique(infoNumber, null); - // 验证姓名:如果提供,只能包含汉字和数字 + // 处理姓名:去除首尾空格 if (StringUtils.isNotEmpty(profile.getUserName())) { - String userName = profile.getUserName().trim(); - if (!userName.matches("^[\\u4e00-\\u9fa5\\d]+$")) - { - log.error("创建用户档案失败:姓名格式错误,只能输入汉字和数字,userName: {}", userName); - throw new ServiceException("姓名只能输入汉字和数字"); - } - profile.setUserName(userName); + profile.setUserName(profile.getUserName().trim()); } Long userId = profile.getUserId(); @@ -311,15 +305,10 @@ public class PsyUserProfileServiceImpl implements IPsyUserProfileService profile.setInfoNumber(infoNumber); validateInfoNumberUnique(infoNumber, profile.getProfileId()); - // 验证姓名:如果提供,只能包含汉字和数字 + // 处理姓名:去除首尾空格,并同步到用户表 if (StringUtils.isNotEmpty(profile.getUserName())) { String userName = profile.getUserName().trim(); - if (!userName.matches("^[\\u4e00-\\u9fa5\\d]+$")) - { - log.error("修改用户档案失败:姓名格式错误,只能输入汉字和数字,userName: {}", userName); - throw new ServiceException("姓名只能输入汉字和数字"); - } profile.setUserName(userName); syncUserName(profile.getUserId(), userName); } diff --git a/ry-xinli-system/src/main/java/com/ddnai/system/service/psychology/IPsyAssessmentService.java b/ry-xinli-system/src/main/java/com/ddnai/system/service/psychology/IPsyAssessmentService.java index 50e6d587..697f8287 100644 --- a/ry-xinli-system/src/main/java/com/ddnai/system/service/psychology/IPsyAssessmentService.java +++ b/ry-xinli-system/src/main/java/com/ddnai/system/service/psychology/IPsyAssessmentService.java @@ -48,6 +48,15 @@ public interface IPsyAssessmentService */ public List selectPausedAssessmentList(Long userId); + /** + * 查询用户对某个量表的所有测评记录(不过滤,用于内部逻辑) + * + * @param userId 用户ID + * @param scaleId 量表ID + * @return 测评集合 + */ + public List selectAssessmentByUserAndScale(Long userId, Long scaleId); + /** * 新增测评 * diff --git a/ry-xinli-system/src/main/resources/mapper/system/psychology/PsyAssessmentMapper.xml b/ry-xinli-system/src/main/resources/mapper/system/psychology/PsyAssessmentMapper.xml index 95be61eb..8c3ba493 100644 --- a/ry-xinli-system/src/main/resources/mapper/system/psychology/PsyAssessmentMapper.xml +++ b/ry-xinli-system/src/main/resources/mapper/system/psychology/PsyAssessmentMapper.xml @@ -34,7 +34,9 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" - select a.assessment_id, a.scale_id, s.scale_name, a.user_id, a.assessee_name, a.assessee_gender, a.assessee_age, + select a.assessment_id, a.scale_id, s.scale_name, a.user_id, + COALESCE(u.nick_name, a.assessee_name) as assessee_name, + a.assessee_gender, a.assessee_age, a.assessee_id_card, a.assessee_phone, a.assessee_email, a.start_time, a.pause_time, a.resume_time, a.pause_count, a.submit_time, a.complete_time, a.total_score, a.status, a.ip_address, a.user_agent, @@ -43,6 +45,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" from psy_assessment a left join psy_scale s on a.scale_id = s.scale_id left join psy_assessment_report r on a.assessment_id = r.assessment_id + left join sys_user u on a.user_id = u.user_id + + a.assessment_id IN ( + SELECT MAX(t.assessment_id) + FROM psy_assessment t + GROUP BY t.user_id, t.scale_id + ) AND a.scale_id = #{scaleId} @@ -66,13 +75,20 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" AND a.status = #{status} - order by a.create_time desc + order by a.start_time desc + + + insert into psy_assessment ( @@ -130,6 +153,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" assessee_gender = #{assesseeGender}, assessee_age = #{assesseeAge}, total_score = #{totalScore}, + start_time = #{startTime}, submit_time = #{submitTime}, complete_time = #{completeTime}, status = #{status}, @@ -155,6 +179,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" update psy_assessment resume_time = sysdate(), + start_time = sysdate(), status = '0', update_by = #{updateBy}, update_time = sysdate() diff --git a/ry-xinli-system/src/main/resources/mapper/system/psychology/PsyUserProfileMapper.xml b/ry-xinli-system/src/main/resources/mapper/system/psychology/PsyUserProfileMapper.xml index c57e1af7..9e5724f2 100644 --- a/ry-xinli-system/src/main/resources/mapper/system/psychology/PsyUserProfileMapper.xml +++ b/ry-xinli-system/src/main/resources/mapper/system/psychology/PsyUserProfileMapper.xml @@ -40,7 +40,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" p.prison, p.prison_area, p.gender, p.nation, p.education_level, p.crime_name, p.sentence_term, p.sentence_start_date, p.sentence_end_date, p.entry_date, p.info_number, p.create_by, p.create_time, p.update_by, p.update_time, p.remark, - u.user_name, u.phonenumber as phone, u.nick_name, u.email, u.sex, u.status, u.dept_id, u.create_time as user_create_time + u.nick_name as user_name, u.phonenumber as phone, u.nick_name, u.email, u.sex, u.status, u.dept_id, u.create_time as user_create_time - select u.user_id, u.dept_id, u.nick_name, u.user_name, u.email, u.avatar as user_avatar, u.phonenumber as phone, u.sex, u.status, u.del_flag, u.login_ip, u.login_date, u.create_by as user_create_by, u.create_time as user_create_time, u.remark as user_remark, + select u.user_id, u.dept_id, u.nick_name, u.nick_name as user_name, u.email, u.avatar as user_avatar, u.phonenumber as phone, u.sex, u.status, u.del_flag, u.login_ip, u.login_date, u.create_by as user_create_by, u.create_time as user_create_time, u.remark as user_remark, d.dept_name, d.leader, p.profile_id, p.profile_type, p.profile_data, p.avatar, p.id_card, p.birthday, p.prison, p.prison_area, p.gender, p.nation, p.education_level, p.crime_name, @@ -83,7 +83,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" AND u.user_id = #{userId} - AND u.user_name like concat('%', #{userName}, '%') + AND u.nick_name like concat('%', #{userName}, '%') AND p.profile_type = #{profileType} @@ -215,7 +215,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"