|
|
@@ -22,15 +22,18 @@ import org.dromara.demo.domain.dto.KaoshixingRequest;
|
|
|
import org.dromara.demo.domain.dto.KaoshixingScoreListRequest;
|
|
|
import org.dromara.demo.domain.dto.KaoshixingUserExamListRequest;
|
|
|
import org.dromara.demo.service.impl.KaoshixingService;
|
|
|
+import org.dromara.main.domain.MainAbilityConfig;
|
|
|
import org.dromara.main.domain.bo.MainExamEvaluationBo;
|
|
|
import org.dromara.main.domain.bo.MainExamEvaluationSyncBo;
|
|
|
import org.dromara.main.domain.vo.MainExamApplyListVo;
|
|
|
+import org.dromara.main.domain.vo.MainExamResultVo;
|
|
|
import org.dromara.main.domain.vo.MainExamSyncEmployeeOptionVo;
|
|
|
import org.dromara.main.domain.vo.MainExamEvaluationVo;
|
|
|
import org.dromara.main.service.IMainExamEvaluationService;
|
|
|
import org.springframework.validation.annotation.Validated;
|
|
|
import org.springframework.web.bind.annotation.*;
|
|
|
|
|
|
+import java.math.BigDecimal;
|
|
|
import java.util.Arrays;
|
|
|
import java.util.Collection;
|
|
|
import java.util.List;
|
|
|
@@ -45,6 +48,7 @@ public class MainExamEvaluationController extends BaseController {
|
|
|
|
|
|
private final IMainExamEvaluationService examEvaluationService;
|
|
|
private final KaoshixingService kaoshixingService;
|
|
|
+ private final org.dromara.main.mapper.MainExamApplyMapper applyMapper;
|
|
|
|
|
|
/**
|
|
|
* 查询测评列表
|
|
|
@@ -278,13 +282,7 @@ public class MainExamEvaluationController extends BaseController {
|
|
|
|
|
|
/**
|
|
|
* 小程序专用:考生静默登录(action_id=203)
|
|
|
- * 流程:先尝试203静默登录;若用户不存在,自动以201注册并登录。
|
|
|
- * 成功后返回考试星跳转url,前端用web-view打开即可完成登录进入考试。
|
|
|
- *
|
|
|
- * @param params user_id 考生唯一标识(必填,通常用 studentId)
|
|
|
- * user_name 考生姓名(首次注册时必填)
|
|
|
- * department 部门(首次注册时必填,缺省传 "学员")
|
|
|
- * custom_url 登录后跳转地址(可选,*.kaoshixing.com 域名)
|
|
|
+ * 逻辑调整:支持一场测评对应多个考试链接,并从 main_ability_config 获取。
|
|
|
*/
|
|
|
@PostMapping("/silent-login")
|
|
|
@Log(title = "考试星静默登录", businessType = BusinessType.OTHER)
|
|
|
@@ -297,37 +295,195 @@ public class MainExamEvaluationController extends BaseController {
|
|
|
String department = (String) params.getOrDefault("department", "学员");
|
|
|
String customUrl = (String) params.get("custom_url");
|
|
|
|
|
|
- KaoshixingAutoLoginRequest req = new KaoshixingAutoLoginRequest();
|
|
|
- req.setUserId(userId);
|
|
|
- req.setUserName(userName);
|
|
|
- req.setDepartment(department);
|
|
|
- req.setCustomUrl(customUrl);
|
|
|
+ // 获取测评ID
|
|
|
+ Long evaluationId = null;
|
|
|
+ Object evalIdObj = params.get("evaluationId");
|
|
|
+ if (evalIdObj != null && !evalIdObj.toString().isBlank()) {
|
|
|
+ try {
|
|
|
+ evaluationId = Long.valueOf(evalIdObj.toString());
|
|
|
+ } catch (Exception e) {
|
|
|
+ log.warn("无效的测评ID: {}", evalIdObj);
|
|
|
+ }
|
|
|
+ }
|
|
|
|
|
|
try {
|
|
|
- String resp = kaoshixingService.fetchAutoLogin(req);
|
|
|
- // 解析考试星返回的url字段
|
|
|
- com.fasterxml.jackson.databind.ObjectMapper mapper =
|
|
|
- new com.fasterxml.jackson.databind.ObjectMapper();
|
|
|
- com.fasterxml.jackson.databind.JsonNode root = mapper.readTree(resp);
|
|
|
-
|
|
|
- int code = root.path("code").asInt(0);
|
|
|
- if (code != 10000) {
|
|
|
- String msg = root.path("msg").asText("登录失败");
|
|
|
- return R.fail(msg);
|
|
|
+ List<Map<String, String>> exams = new java.util.ArrayList<>();
|
|
|
+ com.fasterxml.jackson.databind.ObjectMapper mapper = new com.fasterxml.jackson.databind.ObjectMapper();
|
|
|
+
|
|
|
+ // 如果传了测评ID,优先从能力配置表获取链接
|
|
|
+ if (evaluationId != null) {
|
|
|
+ MainExamEvaluationVo evaluationVo = examEvaluationService.queryById(evaluationId);
|
|
|
+ if (evaluationVo != null && evaluationVo.getAbilityConfigs() != null) {
|
|
|
+ for (org.dromara.main.domain.MainAbilityConfig config : evaluationVo.getAbilityConfigs()) {
|
|
|
+ if (org.dromara.common.core.utils.StringUtils.isNotBlank(config.getThirdExamLink())) {
|
|
|
+ // 为每个配置的考试生成带Token的链接
|
|
|
+ KaoshixingAutoLoginRequest req = new KaoshixingAutoLoginRequest();
|
|
|
+ req.setUserId(userId);
|
|
|
+ req.setUserName(userName);
|
|
|
+ req.setDepartment(department);
|
|
|
+ req.setCustomUrl(config.getThirdExamLink());
|
|
|
+
|
|
|
+ String resp = kaoshixingService.fetchAutoLogin(req);
|
|
|
+ com.fasterxml.jackson.databind.JsonNode root = mapper.readTree(resp);
|
|
|
+ if (root.path("code").asInt() == 10000) {
|
|
|
+ String url = root.path("url").asText(null);
|
|
|
+ if (url != null) {
|
|
|
+ Map<String, String> examMap = new java.util.HashMap<>();
|
|
|
+ examMap.put("name", config.getAbilityName()); // 考试/维度名称
|
|
|
+ examMap.put("url", url); // 授权后的链接
|
|
|
+ exams.add(examMap);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
- String url = root.path("url").asText(null);
|
|
|
- if (url == null || url.isBlank()) {
|
|
|
- return R.fail("考试星未返回跳转链接");
|
|
|
+ Map<String, Object> data = new java.util.HashMap<>();
|
|
|
+ // 如果找到了配置的考试链接
|
|
|
+ if (!exams.isEmpty()) {
|
|
|
+ data.put("exams", exams);
|
|
|
+ data.put("url", exams.get(0).get("url")); // 默认提供第一个链接
|
|
|
+ return R.ok(data);
|
|
|
}
|
|
|
|
|
|
- Map<String, Object> data = new java.util.HashMap<>();
|
|
|
- data.put("url", url);
|
|
|
+ // 兜底逻辑:如果没配置或查询失败,走原有的跳转逻辑
|
|
|
+ KaoshixingAutoLoginRequest req = new KaoshixingAutoLoginRequest();
|
|
|
+ req.setUserId(userId);
|
|
|
+ req.setUserName(userName);
|
|
|
+ req.setDepartment(department);
|
|
|
+ req.setCustomUrl(customUrl);
|
|
|
+
|
|
|
+ String resp = kaoshixingService.fetchAutoLogin(req);
|
|
|
+ com.fasterxml.jackson.databind.JsonNode root = mapper.readTree(resp);
|
|
|
+ if (root.path("code").asInt() != 10000) {
|
|
|
+ return R.fail(root.path("msg").asText("登录失败"));
|
|
|
+ }
|
|
|
+ data.put("url", root.path("url").asText());
|
|
|
return R.ok(data);
|
|
|
} catch (Exception e) {
|
|
|
log.error("考试星静默登录失败", e);
|
|
|
return R.fail("登录失败:" + e.getMessage());
|
|
|
}
|
|
|
}
|
|
|
+
|
|
|
+
|
|
|
+ @GetMapping("/result/{evaluationId}")
|
|
|
+ public R<MainExamResultVo> getEvaluationResult(@PathVariable Long evaluationId, @RequestParam Long studentId) {
|
|
|
+ // 1. 获取该测评下的所有能力配置
|
|
|
+ MainExamEvaluationVo evaluationVo = examEvaluationService.queryById(evaluationId);
|
|
|
+ List<MainAbilityConfig> configs = evaluationVo.getAbilityConfigs();
|
|
|
+ if (configs == null || configs.isEmpty()) {
|
|
|
+ return R.fail("测评未配置能力项");
|
|
|
+ }
|
|
|
+
|
|
|
+ // 2. 调用考试星 702 接口获取用户的所有考试结果
|
|
|
+ KaoshixingUserExamListRequest req = new KaoshixingUserExamListRequest();
|
|
|
+ req.setUserId(String.valueOf(studentId));
|
|
|
+ req.setPage(1);
|
|
|
+ String resp = kaoshixingService.fetchUserExamList(req);
|
|
|
+
|
|
|
+ // 3. 解析第三方数据并对比
|
|
|
+ MainExamResultVo resultVo = new MainExamResultVo();
|
|
|
+ List<MainExamResultVo.AbilityResult> abilityResults = new java.util.ArrayList<>();
|
|
|
+ List<String> categories = new java.util.ArrayList<>();
|
|
|
+ List<BigDecimal> scores = new java.util.ArrayList<>();
|
|
|
+
|
|
|
+ int finishedCount = 0;
|
|
|
+ boolean isAllPass = true;
|
|
|
+
|
|
|
+ try {
|
|
|
+ com.fasterxml.jackson.databind.JsonNode root = new com.fasterxml.jackson.databind.ObjectMapper().readTree(resp);
|
|
|
+ com.fasterxml.jackson.databind.JsonNode rows = root.path("bizContent").path("rows");
|
|
|
+
|
|
|
+ for (MainAbilityConfig config : configs) {
|
|
|
+ categories.add(config.getAbilityName());
|
|
|
+ boolean found = false;
|
|
|
+
|
|
|
+ // 在第三方记录中查找对应的考试ID
|
|
|
+ for (com.fasterxml.jackson.databind.JsonNode row : rows) {
|
|
|
+ if (row.path("examInfoId").asLong() == config.getThirdExamInfoId()) {
|
|
|
+ String status = row.path("status").asText();
|
|
|
+ if ("checked".equals(status)) {
|
|
|
+ BigDecimal score = new BigDecimal(row.path("results").asText("0"));
|
|
|
+ BigDecimal passScore = config.getThirdExamPassMark();
|
|
|
+
|
|
|
+ MainExamResultVo.AbilityResult ar = new MainExamResultVo.AbilityResult();
|
|
|
+ ar.setName(config.getAbilityName());
|
|
|
+ ar.setScore(score);
|
|
|
+ ar.setPassScore(passScore);
|
|
|
+ ar.setIsPass(score.compareTo(passScore) >= 0);
|
|
|
+ ar.setInquireLink(row.path("inquireLink").asText(null));
|
|
|
+
|
|
|
+ abilityResults.add(ar);
|
|
|
+ scores.add(score);
|
|
|
+
|
|
|
+ if (!ar.getIsPass()) isAllPass = false;
|
|
|
+ finishedCount++;
|
|
|
+ found = true;
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ if (!found) {
|
|
|
+ scores.add(BigDecimal.ZERO);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ boolean allFinished = (finishedCount == configs.size());
|
|
|
+ String finalResult = isAllPass ? "1" : "2";
|
|
|
+
|
|
|
+ resultVo.setAllFinished(allFinished);
|
|
|
+ resultVo.setFinalResult(finalResult);
|
|
|
+ resultVo.setAbilityResults(abilityResults);
|
|
|
+
|
|
|
+ MainExamResultVo.RadarChartData radar = new MainExamResultVo.RadarChartData();
|
|
|
+ radar.setCategories(categories);
|
|
|
+ radar.setSeries(scores);
|
|
|
+ resultVo.setRadarChart(radar);
|
|
|
+
|
|
|
+ // 4. 同步更新 main_exam_apply 记录
|
|
|
+ try {
|
|
|
+ org.dromara.main.domain.MainExamApply apply = applyMapper.selectOne(new com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper<org.dromara.main.domain.MainExamApply>()
|
|
|
+ .eq(org.dromara.main.domain.MainExamApply::getEvaluationId, evaluationId)
|
|
|
+ .eq(org.dromara.main.domain.MainExamApply::getStudentId, studentId)
|
|
|
+ .eq(org.dromara.main.domain.MainExamApply::getDelFlag, "0")
|
|
|
+ .last("LIMIT 1"));
|
|
|
+
|
|
|
+ if (apply != null) {
|
|
|
+ boolean changed = false;
|
|
|
+ // 如果全部完成,更新状态为已完成(2)
|
|
|
+ if (allFinished && !"2".equals(apply.getApplyStatus())) {
|
|
|
+ apply.setApplyStatus("2");
|
|
|
+ apply.setFinishedTime(new java.util.Date());
|
|
|
+ changed = true;
|
|
|
+ } else if (finishedCount > 0 && "0".equals(apply.getApplyStatus())) {
|
|
|
+ // 如果有答题记录但没完,更新为进行中(1)
|
|
|
+ apply.setApplyStatus("1");
|
|
|
+ changed = true;
|
|
|
+ }
|
|
|
+
|
|
|
+ // 更新通过结果
|
|
|
+ if (allFinished && !finalResult.equals(apply.getFinalResult())) {
|
|
|
+ apply.setFinalResult(finalResult);
|
|
|
+ changed = true;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (changed) {
|
|
|
+ applyMapper.updateById(apply);
|
|
|
+ log.info("同步更新测评申请状态成功,applyId: {}, status: {}, result: {}", apply.getId(), apply.getApplyStatus(), apply.getFinalResult());
|
|
|
+ }
|
|
|
+ }
|
|
|
+ } catch (Exception e) {
|
|
|
+ log.error("更新测评申请记录失败", e);
|
|
|
+ }
|
|
|
+
|
|
|
+ return R.ok(resultVo);
|
|
|
+ } catch (Exception e) {
|
|
|
+ log.error("解析考试结果失败", e);
|
|
|
+ return R.fail("获取结果失败");
|
|
|
+ }
|
|
|
+ }
|
|
|
}
|
|
|
|