用户档案、大模型bug修改
This commit is contained in:
parent
2931e0e1c0
commit
5456739b22
|
|
@ -186,6 +186,7 @@ public class PsyAssessmentController extends BaseController
|
||||||
/**
|
/**
|
||||||
* 开始测评
|
* 开始测评
|
||||||
* 允许管理员和学员访问
|
* 允许管理员和学员访问
|
||||||
|
* 每个用户对同一量表只能有一条未完成的测评记录
|
||||||
*/
|
*/
|
||||||
@PostMapping("/start")
|
@PostMapping("/start")
|
||||||
public AjaxResult start(@Validated @RequestBody AssessmentStartVO startVO)
|
public AjaxResult start(@Validated @RequestBody AssessmentStartVO startVO)
|
||||||
|
|
@ -200,35 +201,53 @@ public class PsyAssessmentController extends BaseController
|
||||||
currentUsername = SecurityUtils.getUsername();
|
currentUsername = SecurityUtils.getUsername();
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
logger.warn("获取用户信息失败,可能是匿名访问: {}", e.getMessage());
|
logger.warn("获取用户信息失败,可能是匿名访问: {}", e.getMessage());
|
||||||
// 如果是匿名访问,userId 和 username 可以为 null
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// 确定实际的测评用户ID
|
// 确定实际的测评用户ID
|
||||||
// 如果传入了targetUserId(管理员代替用户测评),使用targetUserId
|
|
||||||
// 否则使用当前登录用户ID
|
|
||||||
Long assessmentUserId = startVO.getTargetUserId() != null ? startVO.getTargetUserId() : currentUserId;
|
Long assessmentUserId = startVO.getTargetUserId() != null ? startVO.getTargetUserId() : currentUserId;
|
||||||
|
|
||||||
|
// 检查是否已存在该用户对该量表的未完成测评记录
|
||||||
|
if (assessmentUserId != null && startVO.getScaleId() != null)
|
||||||
|
{
|
||||||
|
// 使用不过滤的查询方法,获取所有测评记录
|
||||||
|
List<PsyAssessment> 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();
|
PsyAssessment assessment = new PsyAssessment();
|
||||||
assessment.setScaleId(startVO.getScaleId());
|
assessment.setScaleId(startVO.getScaleId());
|
||||||
assessment.setAssesseeName(startVO.getAssesseeName());
|
assessment.setAssesseeName(startVO.getAssesseeName());
|
||||||
assessment.setAssesseeGender(startVO.getAssesseeGender());
|
assessment.setAssesseeGender(startVO.getAssesseeGender());
|
||||||
assessment.setAssesseeAge(startVO.getAssesseeAge());
|
assessment.setAssesseeAge(startVO.getAssesseeAge());
|
||||||
assessment.setAssesseePhone(startVO.getAssesseePhone());
|
assessment.setAssesseePhone(startVO.getAssesseePhone());
|
||||||
assessment.setStatus("0");
|
assessment.setStatus("3"); // 初始状态为"已暂停"
|
||||||
assessment.setStartTime(new Date());
|
assessment.setStartTime(new Date());
|
||||||
assessment.setIpAddress(IpUtils.getIpAddr());
|
assessment.setIpAddress(IpUtils.getIpAddr());
|
||||||
assessment.setUserAgent(ServletUtils.getRequest().getHeader("User-Agent"));
|
assessment.setUserAgent(ServletUtils.getRequest().getHeader("User-Agent"));
|
||||||
|
|
||||||
// 设置用户ID(优先使用targetUserId)
|
|
||||||
if (assessmentUserId != null) {
|
if (assessmentUserId != null) {
|
||||||
assessment.setUserId(assessmentUserId);
|
assessment.setUserId(assessmentUserId);
|
||||||
}
|
}
|
||||||
|
|
||||||
// 设置创建者(记录是谁创建的测评)
|
|
||||||
if (currentUsername != null && !currentUsername.isEmpty()) {
|
if (currentUsername != null && !currentUsername.isEmpty()) {
|
||||||
assessment.setCreateBy(currentUsername);
|
assessment.setCreateBy(currentUsername);
|
||||||
} else {
|
} else {
|
||||||
assessment.setCreateBy("system"); // 默认值
|
assessment.setCreateBy("system");
|
||||||
}
|
}
|
||||||
|
|
||||||
logger.info("创建测评 - scaleId: {}, targetUserId: {}, assessmentUserId: {}, currentUserId: {}, assesseeName: {}",
|
logger.info("创建测评 - scaleId: {}, targetUserId: {}, assessmentUserId: {}, currentUserId: {}, assesseeName: {}",
|
||||||
|
|
@ -252,6 +271,53 @@ public class PsyAssessmentController extends BaseController
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 重置测评(删除未完成的测评记录,重新开始)
|
||||||
|
* 允许管理员和学员访问(学员只能重置自己的测评)
|
||||||
|
*/
|
||||||
|
@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<PsyAssessment> 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());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 修改测评
|
* 修改测评
|
||||||
*/
|
*/
|
||||||
|
|
|
||||||
|
|
@ -49,6 +49,15 @@ public interface PsyAssessmentMapper
|
||||||
*/
|
*/
|
||||||
public List<PsyAssessment> selectPausedAssessmentList(Long userId);
|
public List<PsyAssessment> selectPausedAssessmentList(Long userId);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 查询用户对某个量表的所有测评记录(不过滤,用于内部逻辑)
|
||||||
|
*
|
||||||
|
* @param userId 用户ID
|
||||||
|
* @param scaleId 量表ID
|
||||||
|
* @return 测评集合
|
||||||
|
*/
|
||||||
|
public List<PsyAssessment> selectAssessmentByUserAndScale(@Param("userId") Long userId, @Param("scaleId") Long scaleId);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 新增测评
|
* 新增测评
|
||||||
*
|
*
|
||||||
|
|
|
||||||
|
|
@ -85,6 +85,12 @@ public class PsyAssessmentServiceImpl implements IPsyAssessmentService
|
||||||
return assessmentMapper.selectPausedAssessmentList(userId);
|
return assessmentMapper.selectPausedAssessmentList(userId);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<PsyAssessment> selectAssessmentByUserAndScale(Long userId, Long scaleId)
|
||||||
|
{
|
||||||
|
return assessmentMapper.selectAssessmentByUserAndScale(userId, scaleId);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int insertAssessment(PsyAssessment assessment)
|
public int insertAssessment(PsyAssessment assessment)
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -141,16 +141,10 @@ public class PsyUserProfileServiceImpl implements IPsyUserProfileService
|
||||||
profile.setInfoNumber(infoNumber);
|
profile.setInfoNumber(infoNumber);
|
||||||
validateInfoNumberUnique(infoNumber, null);
|
validateInfoNumberUnique(infoNumber, null);
|
||||||
|
|
||||||
// 验证姓名:如果提供,只能包含汉字和数字
|
// 处理姓名:去除首尾空格
|
||||||
if (StringUtils.isNotEmpty(profile.getUserName()))
|
if (StringUtils.isNotEmpty(profile.getUserName()))
|
||||||
{
|
{
|
||||||
String userName = profile.getUserName().trim();
|
profile.setUserName(profile.getUserName().trim());
|
||||||
if (!userName.matches("^[\\u4e00-\\u9fa5\\d]+$"))
|
|
||||||
{
|
|
||||||
log.error("创建用户档案失败:姓名格式错误,只能输入汉字和数字,userName: {}", userName);
|
|
||||||
throw new ServiceException("姓名只能输入汉字和数字");
|
|
||||||
}
|
|
||||||
profile.setUserName(userName);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Long userId = profile.getUserId();
|
Long userId = profile.getUserId();
|
||||||
|
|
@ -311,15 +305,10 @@ public class PsyUserProfileServiceImpl implements IPsyUserProfileService
|
||||||
profile.setInfoNumber(infoNumber);
|
profile.setInfoNumber(infoNumber);
|
||||||
validateInfoNumberUnique(infoNumber, profile.getProfileId());
|
validateInfoNumberUnique(infoNumber, profile.getProfileId());
|
||||||
|
|
||||||
// 验证姓名:如果提供,只能包含汉字和数字
|
// 处理姓名:去除首尾空格,并同步到用户表
|
||||||
if (StringUtils.isNotEmpty(profile.getUserName()))
|
if (StringUtils.isNotEmpty(profile.getUserName()))
|
||||||
{
|
{
|
||||||
String userName = profile.getUserName().trim();
|
String userName = profile.getUserName().trim();
|
||||||
if (!userName.matches("^[\\u4e00-\\u9fa5\\d]+$"))
|
|
||||||
{
|
|
||||||
log.error("修改用户档案失败:姓名格式错误,只能输入汉字和数字,userName: {}", userName);
|
|
||||||
throw new ServiceException("姓名只能输入汉字和数字");
|
|
||||||
}
|
|
||||||
profile.setUserName(userName);
|
profile.setUserName(userName);
|
||||||
syncUserName(profile.getUserId(), userName);
|
syncUserName(profile.getUserId(), userName);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -48,6 +48,15 @@ public interface IPsyAssessmentService
|
||||||
*/
|
*/
|
||||||
public List<PsyAssessment> selectPausedAssessmentList(Long userId);
|
public List<PsyAssessment> selectPausedAssessmentList(Long userId);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 查询用户对某个量表的所有测评记录(不过滤,用于内部逻辑)
|
||||||
|
*
|
||||||
|
* @param userId 用户ID
|
||||||
|
* @param scaleId 量表ID
|
||||||
|
* @return 测评集合
|
||||||
|
*/
|
||||||
|
public List<PsyAssessment> selectAssessmentByUserAndScale(Long userId, Long scaleId);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 新增测评
|
* 新增测评
|
||||||
*
|
*
|
||||||
|
|
|
||||||
|
|
@ -34,7 +34,9 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
|
||||||
</resultMap>
|
</resultMap>
|
||||||
|
|
||||||
<sql id="selectAssessmentVo">
|
<sql id="selectAssessmentVo">
|
||||||
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.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.resume_time, a.pause_count, a.submit_time, a.complete_time, a.total_score, a.status,
|
||||||
a.ip_address, a.user_agent,
|
a.ip_address, a.user_agent,
|
||||||
|
|
@ -43,6 +45,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
|
||||||
from psy_assessment a
|
from psy_assessment a
|
||||||
left join psy_scale s on a.scale_id = s.scale_id
|
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 psy_assessment_report r on a.assessment_id = r.assessment_id
|
||||||
|
left join sys_user u on a.user_id = u.user_id
|
||||||
</sql>
|
</sql>
|
||||||
|
|
||||||
<select id="selectAssessmentById" parameterType="Long" resultMap="PsyAssessmentResult">
|
<select id="selectAssessmentById" parameterType="Long" resultMap="PsyAssessmentResult">
|
||||||
|
|
@ -53,6 +56,12 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
|
||||||
<select id="selectAssessmentList" parameterType="com.ddnai.system.domain.psychology.PsyAssessment" resultMap="PsyAssessmentResult">
|
<select id="selectAssessmentList" parameterType="com.ddnai.system.domain.psychology.PsyAssessment" resultMap="PsyAssessmentResult">
|
||||||
<include refid="selectAssessmentVo"/>
|
<include refid="selectAssessmentVo"/>
|
||||||
<where>
|
<where>
|
||||||
|
<!-- 只显示每个用户对每个量表的最新记录 -->
|
||||||
|
a.assessment_id IN (
|
||||||
|
SELECT MAX(t.assessment_id)
|
||||||
|
FROM psy_assessment t
|
||||||
|
GROUP BY t.user_id, t.scale_id
|
||||||
|
)
|
||||||
<if test="scaleId != null">
|
<if test="scaleId != null">
|
||||||
AND a.scale_id = #{scaleId}
|
AND a.scale_id = #{scaleId}
|
||||||
</if>
|
</if>
|
||||||
|
|
@ -66,13 +75,20 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
|
||||||
AND a.status = #{status}
|
AND a.status = #{status}
|
||||||
</if>
|
</if>
|
||||||
</where>
|
</where>
|
||||||
order by a.create_time desc
|
order by a.start_time desc
|
||||||
</select>
|
</select>
|
||||||
|
|
||||||
<select id="selectAssessmentListByUserId" parameterType="Long" resultMap="PsyAssessmentResult">
|
<select id="selectAssessmentListByUserId" parameterType="Long" resultMap="PsyAssessmentResult">
|
||||||
<include refid="selectAssessmentVo"/>
|
<include refid="selectAssessmentVo"/>
|
||||||
where a.user_id = #{userId}
|
where a.user_id = #{userId}
|
||||||
order by a.create_time desc
|
<!-- 只显示每个量表的最新记录 -->
|
||||||
|
AND a.assessment_id IN (
|
||||||
|
SELECT MAX(t.assessment_id)
|
||||||
|
FROM psy_assessment t
|
||||||
|
WHERE t.user_id = #{userId}
|
||||||
|
GROUP BY t.scale_id
|
||||||
|
)
|
||||||
|
order by a.start_time desc
|
||||||
</select>
|
</select>
|
||||||
|
|
||||||
<select id="selectPausedAssessmentList" parameterType="Long" resultMap="PsyAssessmentResult">
|
<select id="selectPausedAssessmentList" parameterType="Long" resultMap="PsyAssessmentResult">
|
||||||
|
|
@ -86,6 +102,13 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
|
||||||
order by a.pause_time desc
|
order by a.pause_time desc
|
||||||
</select>
|
</select>
|
||||||
|
|
||||||
|
<!-- 查询用户对某个量表的所有测评记录(不过滤,用于内部逻辑) -->
|
||||||
|
<select id="selectAssessmentByUserAndScale" resultMap="PsyAssessmentResult">
|
||||||
|
<include refid="selectAssessmentVo"/>
|
||||||
|
where a.user_id = #{userId} and a.scale_id = #{scaleId}
|
||||||
|
order by a.assessment_id desc
|
||||||
|
</select>
|
||||||
|
|
||||||
<insert id="insertAssessment" parameterType="com.ddnai.system.domain.psychology.PsyAssessment" useGeneratedKeys="true" keyProperty="assessmentId">
|
<insert id="insertAssessment" parameterType="com.ddnai.system.domain.psychology.PsyAssessment" useGeneratedKeys="true" keyProperty="assessmentId">
|
||||||
insert into psy_assessment (
|
insert into psy_assessment (
|
||||||
<if test="scaleId != null">scale_id, </if>
|
<if test="scaleId != null">scale_id, </if>
|
||||||
|
|
@ -130,6 +153,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
|
||||||
<if test="assesseeGender != null">assessee_gender = #{assesseeGender}, </if>
|
<if test="assesseeGender != null">assessee_gender = #{assesseeGender}, </if>
|
||||||
<if test="assesseeAge != null">assessee_age = #{assesseeAge}, </if>
|
<if test="assesseeAge != null">assessee_age = #{assesseeAge}, </if>
|
||||||
<if test="totalScore != null">total_score = #{totalScore}, </if>
|
<if test="totalScore != null">total_score = #{totalScore}, </if>
|
||||||
|
<if test="startTime != null">start_time = #{startTime}, </if>
|
||||||
<if test="submitTime != null">submit_time = #{submitTime}, </if>
|
<if test="submitTime != null">submit_time = #{submitTime}, </if>
|
||||||
<if test="completeTime != null">complete_time = #{completeTime}, </if>
|
<if test="completeTime != null">complete_time = #{completeTime}, </if>
|
||||||
<if test="status != null">status = #{status}, </if>
|
<if test="status != null">status = #{status}, </if>
|
||||||
|
|
@ -155,6 +179,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
|
||||||
update psy_assessment
|
update psy_assessment
|
||||||
<set>
|
<set>
|
||||||
resume_time = sysdate(),
|
resume_time = sysdate(),
|
||||||
|
start_time = sysdate(),
|
||||||
status = '0',
|
status = '0',
|
||||||
<if test="updateBy != null and updateBy != ''">update_by = #{updateBy},</if>
|
<if test="updateBy != null and updateBy != ''">update_by = #{updateBy},</if>
|
||||||
update_time = sysdate()
|
update_time = sysdate()
|
||||||
|
|
|
||||||
|
|
@ -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.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.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,
|
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
|
||||||
</sql>
|
</sql>
|
||||||
|
|
||||||
<select id="selectProfileById" parameterType="Long" resultMap="PsyUserProfileResult">
|
<select id="selectProfileById" parameterType="Long" resultMap="PsyUserProfileResult">
|
||||||
|
|
@ -69,7 +69,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
|
||||||
|
|
||||||
<!-- 查询用户档案列表,从 sys_user 开始,LEFT JOIN psy_user_profile,与系统用户管理查询一致 -->
|
<!-- 查询用户档案列表,从 sys_user 开始,LEFT JOIN psy_user_profile,与系统用户管理查询一致 -->
|
||||||
<select id="selectProfileList" parameterType="com.ddnai.system.domain.psychology.PsyUserProfile" resultMap="PsyUserProfileResult">
|
<select id="selectProfileList" parameterType="com.ddnai.system.domain.psychology.PsyUserProfile" resultMap="PsyUserProfileResult">
|
||||||
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,
|
d.dept_name, d.leader,
|
||||||
p.profile_id, p.profile_type, p.profile_data, p.avatar, p.id_card, p.birthday,
|
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,
|
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_id = #{userId}
|
||||||
</if>
|
</if>
|
||||||
<if test="userName != null and userName != ''">
|
<if test="userName != null and userName != ''">
|
||||||
AND u.user_name like concat('%', #{userName}, '%')
|
AND u.nick_name like concat('%', #{userName}, '%')
|
||||||
</if>
|
</if>
|
||||||
<if test="profileType != null and profileType != ''">
|
<if test="profileType != null and profileType != ''">
|
||||||
AND p.profile_type = #{profileType}
|
AND p.profile_type = #{profileType}
|
||||||
|
|
@ -215,7 +215,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
|
||||||
|
|
||||||
<!-- 查询学员用户档案列表:只返回拥有学员角色的用户 -->
|
<!-- 查询学员用户档案列表:只返回拥有学员角色的用户 -->
|
||||||
<select id="selectStudentProfileList" parameterType="com.ddnai.system.domain.psychology.PsyUserProfile" resultMap="PsyUserProfileResult">
|
<select id="selectStudentProfileList" parameterType="com.ddnai.system.domain.psychology.PsyUserProfile" resultMap="PsyUserProfileResult">
|
||||||
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,
|
d.dept_name, d.leader,
|
||||||
p.profile_id, p.profile_type, p.profile_data, p.avatar, p.id_card, p.birthday,
|
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,
|
p.prison, p.prison_area, p.gender, p.nation, p.education_level, p.crime_name,
|
||||||
|
|
@ -236,7 +236,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
|
||||||
AND u.user_id = #{userId}
|
AND u.user_id = #{userId}
|
||||||
</if>
|
</if>
|
||||||
<if test="userName != null and userName != ''">
|
<if test="userName != null and userName != ''">
|
||||||
AND u.user_name like concat('%', #{userName}, '%')
|
AND u.nick_name like concat('%', #{userName}, '%')
|
||||||
</if>
|
</if>
|
||||||
<if test="profileType != null and profileType != ''">
|
<if test="profileType != null and profileType != ''">
|
||||||
AND p.profile_type = #{profileType}
|
AND p.profile_type = #{profileType}
|
||||||
|
|
|
||||||
|
|
@ -63,7 +63,10 @@ export function saveAnswer(data) {
|
||||||
return request({
|
return request({
|
||||||
url: '/psychology/assessment/answer',
|
url: '/psychology/assessment/answer',
|
||||||
method: 'post',
|
method: 'post',
|
||||||
data: data
|
data: data,
|
||||||
|
headers: {
|
||||||
|
repeatSubmit: false // 跳过防重复提交检查,允许快速保存答案
|
||||||
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -71,7 +74,10 @@ export function saveAnswer(data) {
|
||||||
export function pauseAssessment(assessmentId) {
|
export function pauseAssessment(assessmentId) {
|
||||||
return request({
|
return request({
|
||||||
url: '/psychology/assessment/pause/' + assessmentId,
|
url: '/psychology/assessment/pause/' + assessmentId,
|
||||||
method: 'post'
|
method: 'post',
|
||||||
|
headers: {
|
||||||
|
repeatSubmit: false // 跳过防重复提交检查
|
||||||
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -79,7 +85,10 @@ export function pauseAssessment(assessmentId) {
|
||||||
export function resumeAssessment(assessmentId) {
|
export function resumeAssessment(assessmentId) {
|
||||||
return request({
|
return request({
|
||||||
url: '/psychology/assessment/resume/' + assessmentId,
|
url: '/psychology/assessment/resume/' + assessmentId,
|
||||||
method: 'post'
|
method: 'post',
|
||||||
|
headers: {
|
||||||
|
repeatSubmit: false // 跳过防重复提交检查
|
||||||
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -145,3 +154,12 @@ export function getScaleDeptStats(data) {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// 重置测评(删除未完成的测评记录,重新开始)
|
||||||
|
export function resetAssessment(data) {
|
||||||
|
return request({
|
||||||
|
url: '/psychology/assessment/reset',
|
||||||
|
method: 'post',
|
||||||
|
data: data
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -104,6 +104,15 @@
|
||||||
v-if="scope.row.status === '0' || scope.row.status === '3'"
|
v-if="scope.row.status === '0' || scope.row.status === '3'"
|
||||||
v-hasPermi="['psychology:assessment:edit']"
|
v-hasPermi="['psychology:assessment:edit']"
|
||||||
>继续答题</el-button>
|
>继续答题</el-button>
|
||||||
|
<el-button
|
||||||
|
size="mini"
|
||||||
|
type="text"
|
||||||
|
icon="el-icon-refresh"
|
||||||
|
style="color: #E6A23C;"
|
||||||
|
@click="handleReset(scope.row)"
|
||||||
|
v-if="scope.row.status === '0' || scope.row.status === '3'"
|
||||||
|
v-hasPermi="['psychology:assessment:edit']"
|
||||||
|
>重新开始</el-button>
|
||||||
<el-button
|
<el-button
|
||||||
size="mini"
|
size="mini"
|
||||||
type="text"
|
type="text"
|
||||||
|
|
@ -190,7 +199,7 @@
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import { listAssessment, getAssessment, delAssessment, pausedAssessmentList, getAssessmentAnswers, getAssessmentItems } from "@/api/psychology/assessment";
|
import { listAssessment, getAssessment, delAssessment, pausedAssessmentList, getAssessmentAnswers, getAssessmentItems, resetAssessment } from "@/api/psychology/assessment";
|
||||||
import { listScale } from "@/api/psychology/scale";
|
import { listScale } from "@/api/psychology/scale";
|
||||||
import { listOption } from "@/api/psychology/option";
|
import { listOption } from "@/api/psychology/option";
|
||||||
|
|
||||||
|
|
@ -317,6 +326,31 @@ export default {
|
||||||
this.$modal.msgSuccess("删除成功");
|
this.$modal.msgSuccess("删除成功");
|
||||||
}).catch(() => {});
|
}).catch(() => {});
|
||||||
},
|
},
|
||||||
|
/** 重置测评(删除当前记录,重新开始) */
|
||||||
|
handleReset(row) {
|
||||||
|
this.$modal.confirm('确定要重新开始测评吗?当前的答题记录将被清除。').then(() => {
|
||||||
|
const resetData = {
|
||||||
|
scaleId: row.scaleId,
|
||||||
|
targetUserId: row.userId,
|
||||||
|
assesseeName: row.assesseeName,
|
||||||
|
assesseeGender: row.assesseeGender || '0',
|
||||||
|
assesseeAge: row.assesseeAge || 0,
|
||||||
|
assesseePhone: row.assesseePhone,
|
||||||
|
anonymous: false
|
||||||
|
};
|
||||||
|
|
||||||
|
resetAssessment(resetData).then(response => {
|
||||||
|
if (response.code === 200) {
|
||||||
|
this.$modal.msgSuccess("测评已重置");
|
||||||
|
const assessmentId = response.data;
|
||||||
|
this.$router.push({ path: '/psychology/assessment/taking', query: { assessmentId: assessmentId } });
|
||||||
|
}
|
||||||
|
}).catch(error => {
|
||||||
|
console.error('重置测评失败:', error);
|
||||||
|
this.$modal.msgError("重置测评失败,请重试");
|
||||||
|
});
|
||||||
|
});
|
||||||
|
},
|
||||||
/** 查看答题详情 */
|
/** 查看答题详情 */
|
||||||
handleViewAnswers(row) {
|
handleViewAnswers(row) {
|
||||||
this.currentAssessment = row;
|
this.currentAssessment = row;
|
||||||
|
|
|
||||||
|
|
@ -67,7 +67,7 @@
|
||||||
<span>{{ parseTime(scope.row.startTime, '{y}-{m}-{d} {h}:{i}:{s}') }}</span>
|
<span>{{ parseTime(scope.row.startTime, '{y}-{m}-{d} {h}:{i}:{s}') }}</span>
|
||||||
</template>
|
</template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
<el-table-column label="操作" align="center" width="150">
|
<el-table-column label="操作" align="center" width="200">
|
||||||
<template slot-scope="scope">
|
<template slot-scope="scope">
|
||||||
<el-button
|
<el-button
|
||||||
size="mini"
|
size="mini"
|
||||||
|
|
@ -75,6 +75,13 @@
|
||||||
icon="el-icon-edit-outline"
|
icon="el-icon-edit-outline"
|
||||||
@click="handleContinue(scope.row)"
|
@click="handleContinue(scope.row)"
|
||||||
>继续测评</el-button>
|
>继续测评</el-button>
|
||||||
|
<el-button
|
||||||
|
size="mini"
|
||||||
|
type="text"
|
||||||
|
icon="el-icon-refresh"
|
||||||
|
style="color: #E6A23C;"
|
||||||
|
@click="handleReset(scope.row)"
|
||||||
|
>重新开始</el-button>
|
||||||
</template>
|
</template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
</el-table>
|
</el-table>
|
||||||
|
|
@ -83,7 +90,7 @@
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import { startAssessment, pausedAssessmentList, resumeAssessment } from "@/api/psychology/assessment";
|
import { startAssessment, pausedAssessmentList, resumeAssessment, resetAssessment } from "@/api/psychology/assessment";
|
||||||
import { listScale } from "@/api/psychology/scale";
|
import { listScale } from "@/api/psychology/scale";
|
||||||
import { listStudentProfile } from "@/api/psychology/profile";
|
import { listStudentProfile } from "@/api/psychology/profile";
|
||||||
|
|
||||||
|
|
@ -459,6 +466,36 @@ export default {
|
||||||
this.$router.push({ path: '/psychology/assessment/taking', query: { assessmentId: row.assessmentId } });
|
this.$router.push({ path: '/psychology/assessment/taking', query: { assessmentId: row.assessmentId } });
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
/** 重置测评(删除当前记录,重新开始) */
|
||||||
|
handleReset(row) {
|
||||||
|
this.$modal.confirm('确定要重新开始测评吗?当前的答题记录将被清除。').then(() => {
|
||||||
|
this.loading = true;
|
||||||
|
// 找到对应的用户档案
|
||||||
|
const profile = this.profileList.find(p => p.userId === row.userId);
|
||||||
|
const resetData = {
|
||||||
|
scaleId: row.scaleId,
|
||||||
|
targetUserId: row.userId,
|
||||||
|
assesseeName: profile ? profile.userName : row.assesseeName,
|
||||||
|
assesseeGender: '0',
|
||||||
|
assesseeAge: 0,
|
||||||
|
assesseePhone: profile ? profile.phone : null,
|
||||||
|
anonymous: false
|
||||||
|
};
|
||||||
|
|
||||||
|
resetAssessment(resetData).then(response => {
|
||||||
|
if (response.code === 200) {
|
||||||
|
this.$modal.msgSuccess("测评已重置");
|
||||||
|
const assessmentId = response.data;
|
||||||
|
this.$router.push({ path: '/psychology/assessment/taking', query: { assessmentId: assessmentId } });
|
||||||
|
}
|
||||||
|
this.loading = false;
|
||||||
|
}).catch(error => {
|
||||||
|
console.error('重置测评失败:', error);
|
||||||
|
this.$modal.msgError("重置测评失败,请重试");
|
||||||
|
this.loading = false;
|
||||||
|
});
|
||||||
|
});
|
||||||
|
},
|
||||||
/** 返回 */
|
/** 返回 */
|
||||||
handleBack() {
|
handleBack() {
|
||||||
this.$router.push('assessment');
|
this.$router.push('assessment');
|
||||||
|
|
|
||||||
|
|
@ -67,7 +67,7 @@
|
||||||
v-for="option in currentOptions"
|
v-for="option in currentOptions"
|
||||||
:key="option.optionId"
|
:key="option.optionId"
|
||||||
class="option-item"
|
class="option-item"
|
||||||
@click="selectedOption = option.optionId"
|
@click="selectSingleOption(option.optionId)"
|
||||||
>
|
>
|
||||||
<el-radio :label="option.optionId">{{ option.optionCode }}. {{ option.optionContent }}</el-radio>
|
<el-radio :label="option.optionId">{{ option.optionCode }}. {{ option.optionContent }}</el-radio>
|
||||||
<el-button
|
<el-button
|
||||||
|
|
@ -139,7 +139,7 @@
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import { getAssessment, pauseAssessment, getAssessmentItems, submitAssessment, getAssessmentAnswers } from "@/api/psychology/assessment";
|
import { getAssessment, pauseAssessment, resumeAssessment, getAssessmentItems, submitAssessment, getAssessmentAnswers } from "@/api/psychology/assessment";
|
||||||
import { listOption } from "@/api/psychology/option";
|
import { listOption } from "@/api/psychology/option";
|
||||||
import { saveAnswer } from "@/api/psychology/assessment";
|
import { saveAnswer } from "@/api/psychology/assessment";
|
||||||
import voiceIcon from '@/assets/images/voice.png';
|
import voiceIcon from '@/assets/images/voice.png';
|
||||||
|
|
@ -158,6 +158,7 @@ export default {
|
||||||
answersMap: {},
|
answersMap: {},
|
||||||
loading: false,
|
loading: false,
|
||||||
saveTimer: null, // 防抖定时器
|
saveTimer: null, // 防抖定时器
|
||||||
|
hasResumed: false, // 是否已经调用过 resume API
|
||||||
// TTS
|
// TTS
|
||||||
isTtsSupported: false,
|
isTtsSupported: false,
|
||||||
useAndroidTts: false,
|
useAndroidTts: false,
|
||||||
|
|
@ -184,13 +185,15 @@ export default {
|
||||||
answeredCount() {
|
answeredCount() {
|
||||||
// 计算已答题数量
|
// 计算已答题数量
|
||||||
return this.itemList.filter(item => {
|
return this.itemList.filter(item => {
|
||||||
const answer = this.answersMap[item.itemId];
|
// 确保使用字符串类型的 key 进行查找,避免类型不匹配
|
||||||
|
const itemIdStr = String(item.itemId);
|
||||||
|
const answer = this.answersMap[item.itemId] || this.answersMap[itemIdStr];
|
||||||
if (!answer) {
|
if (!answer) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
// 单选题需要 optionId,多选题需要 optionIds(字符串,用逗号分隔)
|
// 单选题需要 optionId,多选题需要 optionIds(字符串,用逗号分隔)
|
||||||
if (item.itemType === 'single') {
|
if (item.itemType === 'single' || item.itemType === 'matrix') {
|
||||||
return answer.optionId != null;
|
return answer.optionId != null && answer.optionId !== '';
|
||||||
} else if (item.itemType === 'multiple') {
|
} else if (item.itemType === 'multiple') {
|
||||||
return answer.optionIds != null && answer.optionIds.trim().length > 0;
|
return answer.optionIds != null && answer.optionIds.trim().length > 0;
|
||||||
}
|
}
|
||||||
|
|
@ -409,20 +412,36 @@ export default {
|
||||||
|
|
||||||
// 加载已保存的答案
|
// 加载已保存的答案
|
||||||
const savedAnswers = answersRes.data || [];
|
const savedAnswers = answersRes.data || [];
|
||||||
|
console.log('从服务器加载的答案数量:', savedAnswers.length);
|
||||||
savedAnswers.forEach(answer => {
|
savedAnswers.forEach(answer => {
|
||||||
this.answersMap[answer.itemId] = {
|
// 使用 $set 确保响应式,并统一使用数字类型的 itemId 作为 key
|
||||||
|
const itemIdKey = answer.itemId;
|
||||||
|
this.$set(this.answersMap, itemIdKey, {
|
||||||
assessmentId: answer.assessmentId,
|
assessmentId: answer.assessmentId,
|
||||||
itemId: answer.itemId,
|
itemId: answer.itemId,
|
||||||
optionId: answer.optionId,
|
optionId: answer.optionId,
|
||||||
optionIds: answer.optionIds,
|
optionIds: answer.optionIds,
|
||||||
answerScore: answer.answerScore
|
answerScore: answer.answerScore
|
||||||
};
|
});
|
||||||
});
|
});
|
||||||
|
console.log('加载后的 answersMap:', JSON.stringify(this.answersMap));
|
||||||
|
|
||||||
// 加载所有题目的选项
|
// 加载所有题目的选项
|
||||||
this.loadAllOptions().then(() => {
|
this.loadAllOptions().then(() => {
|
||||||
// 选项加载完成后,加载当前题目的答案
|
// 选项加载完成后,加载当前题目的答案
|
||||||
this.loadCurrentAnswer();
|
this.loadCurrentAnswer();
|
||||||
|
|
||||||
|
// 进入答题页面后,调用 resume API 更新状态为"进行中"并更新开始时间
|
||||||
|
// 只调用一次,避免重复提交
|
||||||
|
if (!this.hasResumed) {
|
||||||
|
this.hasResumed = true;
|
||||||
|
resumeAssessment(this.assessmentId).then(() => {
|
||||||
|
console.log('测评状态已更新为进行中');
|
||||||
|
}).catch(error => {
|
||||||
|
console.warn('更新测评状态失败:', error);
|
||||||
|
// 不影响答题,继续
|
||||||
|
});
|
||||||
|
}
|
||||||
}).catch(error => {
|
}).catch(error => {
|
||||||
console.error('加载选项失败:', error);
|
console.error('加载选项失败:', error);
|
||||||
this.$modal.msgError("加载题目选项失败,请刷新重试");
|
this.$modal.msgError("加载题目选项失败,请刷新重试");
|
||||||
|
|
@ -454,14 +473,14 @@ export default {
|
||||||
handleAnswerChange() {
|
handleAnswerChange() {
|
||||||
const itemId = this.currentItem.itemId;
|
const itemId = this.currentItem.itemId;
|
||||||
const answer = {
|
const answer = {
|
||||||
assessmentId: this.assessmentId,
|
assessmentId: parseInt(this.assessmentId),
|
||||||
itemId: itemId,
|
itemId: parseInt(itemId),
|
||||||
optionId: null,
|
optionId: null,
|
||||||
optionIds: null,
|
optionIds: null,
|
||||||
answerScore: 0
|
answerScore: 0
|
||||||
};
|
};
|
||||||
|
|
||||||
if (this.currentItem.itemType === 'single') {
|
if (this.currentItem.itemType === 'single' || this.currentItem.itemType === 'matrix') {
|
||||||
answer.optionId = this.selectedOption;
|
answer.optionId = this.selectedOption;
|
||||||
// 计算得分
|
// 计算得分
|
||||||
const selectedOpt = this.currentOptions.find(opt => opt.optionId === this.selectedOption);
|
const selectedOpt = this.currentOptions.find(opt => opt.optionId === this.selectedOption);
|
||||||
|
|
@ -470,6 +489,7 @@ export default {
|
||||||
}
|
}
|
||||||
// 使用 $set 确保响应式更新
|
// 使用 $set 确保响应式更新
|
||||||
this.$set(this.answersMap, itemId, answer);
|
this.$set(this.answersMap, itemId, answer);
|
||||||
|
console.log('单选题答案已保存到本地 - itemId:', itemId, 'optionId:', answer.optionId, 'answersMap:', JSON.stringify(this.answersMap));
|
||||||
} else if (this.currentItem.itemType === 'multiple') {
|
} else if (this.currentItem.itemType === 'multiple') {
|
||||||
answer.optionIds = this.selectedOptions.length > 0 ? this.selectedOptions.join(',') : null;
|
answer.optionIds = this.selectedOptions.length > 0 ? this.selectedOptions.join(',') : null;
|
||||||
// 计算多选题得分(所有选中选项的分数之和)
|
// 计算多选题得分(所有选中选项的分数之和)
|
||||||
|
|
@ -483,6 +503,7 @@ export default {
|
||||||
answer.answerScore = totalScore;
|
answer.answerScore = totalScore;
|
||||||
// 使用 $set 确保响应式更新
|
// 使用 $set 确保响应式更新
|
||||||
this.$set(this.answersMap, itemId, answer);
|
this.$set(this.answersMap, itemId, answer);
|
||||||
|
console.log('多选题答案已保存到本地 - itemId:', itemId, 'optionIds:', answer.optionIds);
|
||||||
}
|
}
|
||||||
|
|
||||||
// 自动保存答案(添加防抖,避免重复提交)
|
// 自动保存答案(添加防抖,避免重复提交)
|
||||||
|
|
@ -501,11 +522,13 @@ export default {
|
||||||
saveAnswerToServer(answer) {
|
saveAnswerToServer(answer) {
|
||||||
// 检查答案是否有效
|
// 检查答案是否有效
|
||||||
if (!answer.optionId && !answer.optionIds) {
|
if (!answer.optionId && !answer.optionIds) {
|
||||||
|
console.log('答案无效,跳过保存 - optionId:', answer.optionId, 'optionIds:', answer.optionIds);
|
||||||
return; // 没有选择任何选项,不保存
|
return; // 没有选择任何选项,不保存
|
||||||
}
|
}
|
||||||
|
|
||||||
saveAnswer(answer).then(() => {
|
console.log('正在保存答案到服务器:', JSON.stringify(answer));
|
||||||
// 静默保存成功
|
saveAnswer(answer).then((response) => {
|
||||||
|
console.log('答案保存成功:', response);
|
||||||
}).catch(error => {
|
}).catch(error => {
|
||||||
console.error('保存答案失败:', error);
|
console.error('保存答案失败:', error);
|
||||||
// 只在非重复提交的错误时显示提示
|
// 只在非重复提交的错误时显示提示
|
||||||
|
|
@ -529,6 +552,14 @@ export default {
|
||||||
this.loadCurrentAnswer();
|
this.loadCurrentAnswer();
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
/** 选择单选选项 */
|
||||||
|
selectSingleOption(optionId) {
|
||||||
|
// 只有当选项改变时才触发
|
||||||
|
if (this.selectedOption !== optionId) {
|
||||||
|
this.selectedOption = optionId;
|
||||||
|
this.handleAnswerChange();
|
||||||
|
}
|
||||||
|
},
|
||||||
/** 切换多选选项 */
|
/** 切换多选选项 */
|
||||||
toggleMultipleOption(optionId) {
|
toggleMultipleOption(optionId) {
|
||||||
const index = this.selectedOptions.indexOf(optionId);
|
const index = this.selectedOptions.indexOf(optionId);
|
||||||
|
|
@ -537,6 +568,8 @@ export default {
|
||||||
} else {
|
} else {
|
||||||
this.selectedOptions.push(optionId);
|
this.selectedOptions.push(optionId);
|
||||||
}
|
}
|
||||||
|
// 多选也需要触发答案保存
|
||||||
|
this.handleAnswerChange();
|
||||||
},
|
},
|
||||||
/** 加载当前题目的答案 */
|
/** 加载当前题目的答案 */
|
||||||
loadCurrentAnswer() {
|
loadCurrentAnswer() {
|
||||||
|
|
@ -544,10 +577,13 @@ export default {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
const itemId = this.currentItem.itemId;
|
const itemId = this.currentItem.itemId;
|
||||||
const answer = this.answersMap[itemId];
|
// 尝试两种类型的 key 查找答案
|
||||||
|
const answer = this.answersMap[itemId] || this.answersMap[String(itemId)];
|
||||||
|
|
||||||
if (this.currentItem.itemType === 'single') {
|
console.log('加载题目答案 - itemId:', itemId, 'itemType:', this.currentItem.itemType, 'answer:', answer);
|
||||||
this.selectedOption = answer && answer.optionId ? answer.optionId : null;
|
|
||||||
|
if (this.currentItem.itemType === 'single' || this.currentItem.itemType === 'matrix') {
|
||||||
|
this.selectedOption = answer && answer.optionId != null ? answer.optionId : null;
|
||||||
this.selectedOptions = [];
|
this.selectedOptions = [];
|
||||||
} else if (this.currentItem.itemType === 'multiple') {
|
} else if (this.currentItem.itemType === 'multiple') {
|
||||||
this.selectedOption = null;
|
this.selectedOption = null;
|
||||||
|
|
@ -795,6 +831,7 @@ export default {
|
||||||
this.answersMap = {};
|
this.answersMap = {};
|
||||||
this.loading = false;
|
this.loading = false;
|
||||||
this.isTtsSupported = false;
|
this.isTtsSupported = false;
|
||||||
|
this.hasResumed = false; // 重置 resume 标志
|
||||||
if (this.saveTimer) {
|
if (this.saveTimer) {
|
||||||
clearTimeout(this.saveTimer);
|
clearTimeout(this.saveTimer);
|
||||||
this.saveTimer = null;
|
this.saveTimer = null;
|
||||||
|
|
|
||||||
|
|
@ -213,8 +213,7 @@
|
||||||
<el-form-item label="罪犯姓名" prop="userName">
|
<el-form-item label="罪犯姓名" prop="userName">
|
||||||
<el-input
|
<el-input
|
||||||
v-model="form.userName"
|
v-model="form.userName"
|
||||||
placeholder="请输入姓名(仅汉字)"
|
placeholder="请输入姓名"
|
||||||
@input="handleUserNameInput"
|
|
||||||
maxlength="50"
|
maxlength="50"
|
||||||
/>
|
/>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
|
|
@ -549,8 +548,7 @@ export default {
|
||||||
{ pattern: /^\d+$/, message: "信息编号只能输入数字", trigger: "blur" }
|
{ pattern: /^\d+$/, message: "信息编号只能输入数字", trigger: "blur" }
|
||||||
],
|
],
|
||||||
userName: [
|
userName: [
|
||||||
{ required: true, message: "罪犯姓名不能为空", trigger: "blur" },
|
{ required: true, message: "罪犯姓名不能为空", trigger: "blur" }
|
||||||
{ pattern: /^[\u4e00-\u9fa5\d]+$/, message: "姓名只能输入汉字和数字", trigger: "blur" }
|
|
||||||
],
|
],
|
||||||
prisonArea: [
|
prisonArea: [
|
||||||
{ required: true, message: "监区不能为空", trigger: "blur" }
|
{ required: true, message: "监区不能为空", trigger: "blur" }
|
||||||
|
|
@ -718,11 +716,7 @@ export default {
|
||||||
const numericValue = value.replace(/\D/g, '')
|
const numericValue = value.replace(/\D/g, '')
|
||||||
this.form.infoNumber = numericValue
|
this.form.infoNumber = numericValue
|
||||||
},
|
},
|
||||||
// 处理姓名输入,只允许汉字
|
|
||||||
handleUserNameInput(value) {
|
|
||||||
// 移除所有非汉字和非数字字符
|
|
||||||
this.form.userName = value.replace(/[^\u4e00-\u9fa5\d]/g, '')
|
|
||||||
},
|
|
||||||
/** 搜索按钮操作 */
|
/** 搜索按钮操作 */
|
||||||
handleQuery() {
|
handleQuery() {
|
||||||
this.queryParams.pageNum = 1
|
this.queryParams.pageNum = 1
|
||||||
|
|
|
||||||
|
|
@ -151,15 +151,15 @@ export default {
|
||||||
generating: false,
|
generating: false,
|
||||||
reportDialogVisible: false,
|
reportDialogVisible: false,
|
||||||
comprehensiveReport: '',
|
comprehensiveReport: '',
|
||||||
// ========== Ollama本地大模型配置 ==========
|
// ========== Kimi API ==========
|
||||||
API_URL: 'http://192.168.0.106:11434/api/chat',
|
API_URL: 'https://api.moonshot.cn/v1/chat/completions',
|
||||||
API_KEY: '', // 本地模型不需要API Key
|
API_KEY: 'sk-U9fdriPxwBcrpWW0Ite3N0eVtX7VxnqqqYUIBAdWd1hgEA9m',
|
||||||
MODEL: 'deepseek-r1:32b',
|
MODEL: 'moonshot-v1-32k',
|
||||||
|
|
||||||
// ========== 备用配置(Kimi API)==========
|
// ========== 备用配置(Ollama本地大模型)==========
|
||||||
// API_URL: 'https://api.moonshot.cn/v1/chat/completions',
|
// API_URL: 'http://192.168.0.106:11434/api/chat',
|
||||||
// API_KEY: 'sk-U9fdriPxwBcrpWW0Ite3N0eVtX7VxnqqqYUIBAdWd1hgEA9m',
|
// API_KEY: '', // 本地模型不需要API Key
|
||||||
// MODEL: 'moonshot-v1-32k'
|
// MODEL: 'deepseek-r1:32b'
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
created() {
|
created() {
|
||||||
|
|
|
||||||
|
|
@ -403,14 +403,14 @@ export default {
|
||||||
this.aiError = '';
|
this.aiError = '';
|
||||||
this.aiResult = '';
|
this.aiResult = '';
|
||||||
|
|
||||||
// Ollama本地大模型配置
|
// Kimi API
|
||||||
const API_URL = 'http://192.168.0.106:11434/api/chat';
|
const API_URL = 'https://api.moonshot.cn/v1/chat/completions';
|
||||||
const API_KEY = ''; // 本地模型不需要API Key
|
const API_KEY = 'sk-U9fdriPxwBcrpWW0Ite3N0eVtX7VxnqqqYUIBAdWd1hgEA9m';
|
||||||
const MODEL = 'deepseek-r1:32b';
|
const MODEL = 'moonshot-v1-32k';
|
||||||
// 备用:Kimi API
|
// 备用:Ollama本地大模型配置
|
||||||
// const API_URL = 'https://api.moonshot.cn/v1/chat/completions';
|
// const API_URL = 'http://192.168.0.106:11434/api/chat';
|
||||||
// const API_KEY = 'sk-U9fdriPxwBcrpWW0Ite3N0eVtX7VxnqqqYUIBAdWd1hgEA9m';
|
// const API_KEY = ''; // 本地模型不需要API Key
|
||||||
// const MODEL = 'moonshot-v1-32k';
|
// const MODEL = 'deepseek-r1:32b';
|
||||||
|
|
||||||
// 构建系统提示词
|
// 构建系统提示词
|
||||||
const SYSTEM_PROMPT = [
|
const SYSTEM_PROMPT = [
|
||||||
|
|
@ -451,7 +451,8 @@ export default {
|
||||||
timeout: 60000 // 60秒超时
|
timeout: 60000 // 60秒超时
|
||||||
});
|
});
|
||||||
|
|
||||||
let rawResponse = data?.choices?.[0]?.message?.content ?? '无法解析模型输出';
|
// 兼容 Kimi API (OpenAI 格式) 和 Ollama 格式
|
||||||
|
let rawResponse = data?.choices?.[0]?.message?.content ?? data?.message?.content ?? '无法解析模型输出';
|
||||||
|
|
||||||
// 过滤掉思考过程标签
|
// 过滤掉思考过程标签
|
||||||
rawResponse = rawResponse
|
rawResponse = rawResponse
|
||||||
|
|
|
||||||
|
|
@ -709,14 +709,14 @@ export default {
|
||||||
},
|
},
|
||||||
/** AI分析报告内容 */
|
/** AI分析报告内容 */
|
||||||
async generateAIAnalysis(reportContent, reportTitle, reportType) {
|
async generateAIAnalysis(reportContent, reportTitle, reportType) {
|
||||||
// Ollama本地大模型配置
|
// Kimi API
|
||||||
const API_URL = 'http://192.168.0.106:11434/api/chat';
|
const API_URL = 'https://api.moonshot.cn/v1/chat/completions';
|
||||||
const API_KEY = ''; // 本地模型不需要API Key
|
const API_KEY = 'sk-U9fdriPxwBcrpWW0Ite3N0eVtX7VxnqqqYUIBAdWd1hgEA9m';
|
||||||
const MODEL = 'deepseek-r1:32b';
|
const MODEL = 'moonshot-v1-32k';
|
||||||
// 备用:Kimi API
|
// 备用:Ollama本地大模型配置
|
||||||
// const API_URL = 'https://api.moonshot.cn/v1/chat/completions';
|
// const API_URL = 'http://192.168.0.106:11434/api/chat';
|
||||||
// const API_KEY = 'sk-U9fdriPxwBcrpWW0Ite3N0eVtX7VxnqqqYUIBAdWd1hgEA9m';
|
// const API_KEY = ''; // 本地模型不需要API Key
|
||||||
// const MODEL = 'moonshot-v1-32k';
|
// const MODEL = 'deepseek-r1:32b';
|
||||||
|
|
||||||
// 构建系统提示词
|
// 构建系统提示词
|
||||||
const SYSTEM_PROMPT = [
|
const SYSTEM_PROMPT = [
|
||||||
|
|
@ -752,7 +752,10 @@ export default {
|
||||||
timeout: 60000 // 60秒超时
|
timeout: 60000 // 60秒超时
|
||||||
});
|
});
|
||||||
|
|
||||||
let rawResponse = data?.choices?.[0]?.message?.content ?? '';
|
console.log('AI响应数据:', data);
|
||||||
|
|
||||||
|
// 兼容 Kimi API (OpenAI 格式) 和 Ollama 格式
|
||||||
|
let rawResponse = data?.choices?.[0]?.message?.content ?? data?.message?.content ?? '';
|
||||||
|
|
||||||
// 过滤掉思考过程标签
|
// 过滤掉思考过程标签
|
||||||
rawResponse = rawResponse
|
rawResponse = rawResponse
|
||||||
|
|
|
||||||
|
|
@ -68,7 +68,7 @@
|
||||||
* 作用:显示所有开放的心理测试题,学员可以选择进行测试
|
* 作用:显示所有开放的心理测试题,学员可以选择进行测试
|
||||||
*/
|
*/
|
||||||
import { listScale } from "@/api/psychology/scale"
|
import { listScale } from "@/api/psychology/scale"
|
||||||
import { startAssessment, pausedAssessmentList, resumeAssessment } from "@/api/psychology/assessment"
|
import { startAssessment, pausedAssessmentList, resumeAssessment, resetAssessment } from "@/api/psychology/assessment"
|
||||||
import { Message } from 'element-ui'
|
import { Message } from 'element-ui'
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
|
|
@ -304,17 +304,36 @@ export default {
|
||||||
}
|
}
|
||||||
|
|
||||||
this.loading = true
|
this.loading = true
|
||||||
const { delAssessment } = require("@/api/psychology/assessment")
|
// 使用 resetAssessment API,学员可以重置自己的测评
|
||||||
delAssessment(pausedRecord.assessmentId)
|
const resetData = {
|
||||||
.then(() => {
|
scaleId: pausedRecord.scaleId || test.scaleId,
|
||||||
// 删除成功后,刷新暂停列表并创建新测评
|
targetUserId: pausedRecord.userId,
|
||||||
this.loadPausedList()
|
assesseeName: pausedRecord.assesseeName,
|
||||||
this.createAssessment(test)
|
assesseeGender: pausedRecord.assesseeGender || '0',
|
||||||
|
assesseeAge: pausedRecord.assesseeAge || 0,
|
||||||
|
assesseePhone: pausedRecord.assesseePhone,
|
||||||
|
anonymous: false
|
||||||
|
}
|
||||||
|
|
||||||
|
resetAssessment(resetData)
|
||||||
|
.then(response => {
|
||||||
|
if (response.code === 200) {
|
||||||
|
// 重置成功后,刷新暂停列表并跳转到答题页面
|
||||||
|
this.loadPausedList()
|
||||||
|
const assessmentId = response.data
|
||||||
|
this.$router.push({
|
||||||
|
path: '/psychology/assessment/taking',
|
||||||
|
query: { assessmentId: assessmentId }
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
Message.error(response.msg || "重置测评失败")
|
||||||
|
}
|
||||||
|
this.loading = false
|
||||||
})
|
})
|
||||||
.catch(error => {
|
.catch(error => {
|
||||||
console.error("删除暂停记录失败:", error)
|
console.error("重置测评失败:", error)
|
||||||
this.loading = false
|
this.loading = false
|
||||||
Message.error("删除旧记录失败,请稍后重试")
|
Message.error("重置测评失败,请稍后重试")
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue
Block a user