|
@@ -481,6 +481,99 @@ public class ReportBlockAssembler {
|
|
|
return blocks;
|
|
return blocks;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
+ /** category → 中文组标题 映射(DAN 各报告类型的指标分组) */
|
|
|
|
|
+ private static final java.util.Map<String, String> DAN_CATEGORY_TITLES = buildDanCategoryTitles();
|
|
|
|
|
+
|
|
|
|
|
+ private static java.util.Map<String, String> buildDanCategoryTitles() {
|
|
|
|
|
+ java.util.Map<String, String> m = new LinkedHashMap<>();
|
|
|
|
|
+ m.put("bigFive", "大五人格");
|
|
|
|
|
+ m.put("social", "社会关系");
|
|
|
|
|
+ m.put("emotion", "情绪状态");
|
|
|
|
|
+ m.put("ability", "综合能力");
|
|
|
|
|
+ m.put("selfConcept", "自我概念");
|
|
|
|
|
+ m.put("growthMindset", "成长型思维");
|
|
|
|
|
+ m.put("selfDriving", "自驱力");
|
|
|
|
|
+ m.put("cognitive", "认知能力");
|
|
|
|
|
+ m.put("executiveFunction", "执行功能");
|
|
|
|
|
+ m.put("learningMotivation", "学习动机");
|
|
|
|
|
+ m.put("learningStrategy", "学习策略");
|
|
|
|
|
+ m.put("behavior", "行为表现");
|
|
|
|
|
+ m.put("family", "家庭环境");
|
|
|
|
|
+ m.put("hollandInterest", "职业兴趣");
|
|
|
|
|
+ m.put("multipleIntelligence", "多元智能");
|
|
|
|
|
+ m.put("careerValue", "职业价值观");
|
|
|
|
|
+ m.put("emotionRegulation", "情绪调节");
|
|
|
|
|
+ m.put("academicStress", "学业压力");
|
|
|
|
|
+ m.put("interpersonal", "人际关系");
|
|
|
|
|
+ m.put("socialAbility", "社交能力");
|
|
|
|
|
+ m.put("sleep", "睡眠状况");
|
|
|
|
|
+ m.put("exercise", "运动状况");
|
|
|
|
|
+ m.put("internet", "网络使用");
|
|
|
|
|
+ m.put("compass", "人际指南针");
|
|
|
|
|
+ m.put("overall", "综合评估");
|
|
|
|
|
+ m.put("auto", "其他指标");
|
|
|
|
|
+ return m;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ /**
|
|
|
|
|
+ * DAN 报告 → blocks(按 category 分组)。
|
|
|
|
|
+ * score 块(总分/百分位)+ indicator 块(每个 category 一组)+ text 块(评语/建议)。
|
|
|
|
|
+ * 不同报告类型(A1/A2/B2/B3/B4/B5/B6/C1)的 category 集合不同,天然分别展示。
|
|
|
|
|
+ */
|
|
|
|
|
+ public List<Map<String, Object>> assembleDanByType(String itemsJson, String summary, String suggestions) {
|
|
|
|
|
+ List<Map<String, Object>> blocks = new ArrayList<>();
|
|
|
|
|
+ List<DanReportParseService.DataItem> items = new ArrayList<>();
|
|
|
|
|
+ if (itemsJson != null && !itemsJson.isEmpty()) {
|
|
|
|
|
+ try {
|
|
|
|
|
+ items = new com.fasterxml.jackson.databind.ObjectMapper().readValue(
|
|
|
|
|
+ itemsJson,
|
|
|
|
|
+ new com.fasterxml.jackson.core.type.TypeReference<List<DanReportParseService.DataItem>>() {});
|
|
|
|
|
+ } catch (Exception e) {
|
|
|
|
|
+ // 解析失败按空处理
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ // 1. score 块:total_score / percentile
|
|
|
|
|
+ List<Map<String, Object>> scoreItems = new ArrayList<>();
|
|
|
|
|
+ // 2. indicator 块:按 category 分组
|
|
|
|
|
+ Map<String, List<Map<String, Object>>> byCategory = new LinkedHashMap<>();
|
|
|
|
|
+ for (DanReportParseService.DataItem item : items) {
|
|
|
|
|
+ if (item.getValue() == null || item.getValue().isEmpty()) continue;
|
|
|
|
|
+ if ("total_score".equals(item.getCode())) {
|
|
|
|
|
+ scoreItems.add(scoreItem("总得分", item.getValue()));
|
|
|
|
|
+ } else if ("percentile".equals(item.getCode())) {
|
|
|
|
|
+ scoreItems.add(scoreItem("百分位", item.getValue()));
|
|
|
|
|
+ } else {
|
|
|
|
|
+ String cat = item.getCategory() == null || item.getCategory().isEmpty() ? "auto" : item.getCategory();
|
|
|
|
|
+ Map<String, Object> m = new LinkedHashMap<>();
|
|
|
|
|
+ m.put("name", item.getName());
|
|
|
|
|
+ m.put("value", item.getValue());
|
|
|
|
|
+ byCategory.computeIfAbsent(cat, k -> new ArrayList<>()).add(m);
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ if (!scoreItems.isEmpty()) {
|
|
|
|
|
+ Map<String, Object> block = new LinkedHashMap<>();
|
|
|
|
|
+ block.put("type", "score");
|
|
|
|
|
+ block.put("title", "测评结果");
|
|
|
|
|
+ block.put("items", scoreItems);
|
|
|
|
|
+ blocks.add(block);
|
|
|
|
|
+ }
|
|
|
|
|
+ // 按固定 category 顺序输出(保证同类型报告展示顺序稳定)
|
|
|
|
|
+ for (Map.Entry<String, String> e : DAN_CATEGORY_TITLES.entrySet()) {
|
|
|
|
|
+ List<Map<String, Object>> items2 = byCategory.get(e.getKey());
|
|
|
|
|
+ if (items2 != null && !items2.isEmpty()) {
|
|
|
|
|
+ Map<String, Object> block = new LinkedHashMap<>();
|
|
|
|
|
+ block.put("type", "indicator");
|
|
|
|
|
+ block.put("title", e.getValue());
|
|
|
|
|
+ block.put("items", items2);
|
|
|
|
|
+ blocks.add(block);
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ // text 块:summary / suggestions
|
|
|
|
|
+ if (summary != null && !summary.isEmpty()) blocks.add(textBlock("报告评语", summary));
|
|
|
|
|
+ if (suggestions != null && !suggestions.isEmpty()) blocks.add(textBlock("成长建议", suggestions));
|
|
|
|
|
+ return blocks;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
private Map<String, Object> scoreItem(String label, String value) {
|
|
private Map<String, Object> scoreItem(String label, String value) {
|
|
|
Map<String, Object> m = new LinkedHashMap<>();
|
|
Map<String, Object> m = new LinkedHashMap<>();
|
|
|
m.put("label", label);
|
|
m.put("label", label);
|