Просмотр исходного кода

feat(backend): ReportBlockAssembler DAN 组装(score/list/text)

Xiaogang Liao 1 месяц назад
Родитель
Сommit
2093506ab2

+ 66 - 0
cfc-backend/src/main/java/com/etotem/cfc/service/ReportBlockAssembler.java

@@ -190,6 +190,72 @@ public class ReportBlockAssembler {
         try { return Integer.valueOf(v.toString()); } catch (Exception e) { return null; }
     }
 
+    /** DAN 报告 → blocks(itemsJson 为 DanParsedReport.items 的 JSON 序列化) */
+    public List<Map<String, Object>> assembleDanFromJson(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) {
+                // 解析失败按空处理
+            }
+        }
+        // score 块:total_score / percentile
+        List<Map<String, Object>> scoreItems = new ArrayList<>();
+        List<Map<String, Object>> listItems = new ArrayList<>();
+        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 {
+                Map<String, Object> m = new LinkedHashMap<>();
+                m.put("name", item.getName());
+                m.put("value", item.getValue());
+                listItems.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);
+        }
+        if (!listItems.isEmpty()) {
+            Map<String, Object> block = new LinkedHashMap<>();
+            block.put("type", "list");
+            block.put("title", "维度得分");
+            block.put("columns", java.util.Arrays.asList(col("name", "项目"), col("value", "得分")));
+            block.put("items", listItems);
+            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) {
+        Map<String, Object> m = new LinkedHashMap<>();
+        m.put("label", label);
+        m.put("value", value);
+        m.put("max", 100);
+        return m;
+    }
+
+    private Map<String, Object> textBlock(String title, String content) {
+        Map<String, Object> block = new LinkedHashMap<>();
+        block.put("type", "text");
+        block.put("title", title);
+        block.put("content", content);
+        return block;
+    }
+
     private String str(Object v) {
         return v == null ? null : v.toString();
     }

+ 21 - 0
cfc-backend/src/test/java/com/etotem/cfc/service/ReportBlockAssemblerTest.java

@@ -77,4 +77,25 @@ class ReportBlockAssemblerTest {
         assertEquals(26, p.getSummary().getHarmfulScore());
         assertEquals(85, p.getSummary().getCoreGenusScore());
     }
+
+    @Test
+    void assembleDan_shouldExtractScoreListAndText() {
+        String itemsJson = "[{\"code\":\"total_score\",\"name\":\"总得分\",\"value\":\"112\",\"category\":\"\"},"
+                + "{\"code\":\"percentile\",\"name\":\"百分位\",\"value\":\"79\",\"category\":\"\"},"
+                + "{\"code\":\"perception_score\",\"name\":\"感知觉得分\",\"value\":\"41\",\"category\":\"认知维度\"},"
+                + "{\"code\":\"attention_score\",\"name\":\"注意力得分\",\"value\":\"55\",\"category\":\"认知维度\"}]";
+        List<Map<String, Object>> blocks = assembler.assembleDanFromJson(itemsJson, "综合评语", "成长建议");
+        Map<String, Object> scoreBlock = blocks.stream()
+                .filter(b -> "score".equals(b.get("type"))).findFirst().orElse(null);
+        assertNotNull(scoreBlock, "应有score块");
+        assertEquals("总得分", ((List<Map<String, Object>>) scoreBlock.get("items")).get(0).get("label"));
+        // text 块:summary + suggestions
+        long textCount = blocks.stream().filter(b -> "text".equals(b.get("type"))).count();
+        assertEquals(2, textCount, "应有summary和suggestions两个text块");
+        // list 块:认知维度分组
+        Map<String, Object> listBlock = blocks.stream()
+                .filter(b -> "list".equals(b.get("type"))).findFirst().orElse(null);
+        assertNotNull(listBlock, "应有list块");
+        assertEquals(2, ((List<Map<String, Object>>) listBlock.get("items")).size());
+    }
 }