From 02177e65c3443c8714301e4a3d891d7d12cde633 Mon Sep 17 00:00:00 2001
From: yeg <1347747024@qq.com>
Date: 星期三, 09 九月 2026 12:03:44 +0800
Subject: [PATCH] 裁剪修订详情的大字段查询并直接返回记录数量

---
 ruoyi-admin/src/test/java/com/battery/business/web/ConsoleSingleSheetImportDatabaseTest.java |   85 ++++++++++++++++++++++++++++++++++++++++++
 1 files changed, 84 insertions(+), 1 deletions(-)

diff --git a/ruoyi-admin/src/test/java/com/battery/business/web/ConsoleSingleSheetImportDatabaseTest.java b/ruoyi-admin/src/test/java/com/battery/business/web/ConsoleSingleSheetImportDatabaseTest.java
index a82596b..bc52da0 100644
--- a/ruoyi-admin/src/test/java/com/battery/business/web/ConsoleSingleSheetImportDatabaseTest.java
+++ b/ruoyi-admin/src/test/java/com/battery/business/web/ConsoleSingleSheetImportDatabaseTest.java
@@ -25,7 +25,7 @@
 import org.springframework.test.util.ReflectionTestUtils;
 
 /** 使用生产 Mapper 和 Spring 事务验证导入;内存数据库不连接共享开发库。 */
-class ConsoleSingleSheetImportDatabaseTest
+public class ConsoleSingleSheetImportDatabaseTest
 {
     private java.sql.Connection keepAlive;
     private TTestController controller;
@@ -38,6 +38,8 @@
         var source = new UnpooledDataSource("org.h2.Driver", "jdbc:h2:mem:" + UUID.randomUUID() + ";MODE=MySQL;DATABASE_TO_LOWER=TRUE", "sa", "");
         keepAlive = source.getConnection();
         jdbc = new JdbcTemplate(source);
+        // H2 无 MySQL JSON_LENGTH;仅在测试中适配计数,真实 SQL 另在 MySQL 验证。
+        jdbc.execute("create alias JSON_LENGTH for 'com.battery.business.web.ConsoleSingleSheetImportDatabaseTest.jsonLength'");
         jdbc.execute("create table sys_user(user_id bigint, nick_name varchar(64), del_flag varchar(1))");
         jdbc.execute("create table t_test_type(test_type_id bigint, test_type_name varchar(64), del_flag int)");
         jdbc.execute("create table t_test(test_id bigint primary key, test_name varchar(100), creator_id bigint, principal_id bigint, test_type_id bigint, test_purpose varchar(100), test_status varchar(20), reception_status varchar(20), monitor_timeout_minutes int, started_at_utc timestamp, reception_boundary_at_utc timestamp, ended_at_utc timestamp, del_flag int default 0, create_by varchar(64), create_time timestamp, update_by varchar(64), update_time timestamp, remark varchar(100), logic_step_mappings_json varchar(100), console_detail_json varchar(100))");
@@ -79,6 +81,15 @@
 
     @AfterEach void closeDatabase() throws Exception { if (keepAlive != null) keepAlive.close(); }
 
+    /** 模拟 JSON 数组长度;H2 的 JSON 参数可能多包一层字符串。 */
+    public static Integer jsonLength(String value)
+    {
+        if (value == null) return null;
+        Object parsed = JSON.parse(value);
+        if (parsed instanceof String text) parsed = JSON.parse(text);
+        return parsed instanceof List<?> rows ? rows.size() : 1;
+    }
+
     @Test void threeTypesPersistActualBindingsTimesAndNumbersAndSkipRetries()
     {
         for (String type : List.of("REALTIME", "STEP", "CYCLE"))
@@ -104,6 +115,66 @@
         assertThrows(RuntimeException.class, () -> submit("REALTIME", List.of(row(), failing)));
         assertTrue(mapper.selectImportDataRecords(1L, "REALTIME").isEmpty());
         assertTrue(service.selectActions(new TTestDataRevisionAction()).isEmpty());
+    }
+
+    @Test void importAndDeleteDetailsReturnOnlySummaryWhileAuditRemainsStored() throws Exception
+    {
+        for (String operation : List.of("IMPORT", "DELETE"))
+        {
+            var action = new TTestDataRevisionAction();
+            action.setTestId(1L); action.setDataType("REALTIME"); action.setOperationType(operation);
+            action.setScopeSummary("批量8000条"); action.setReason("摘要查询验证");
+            action.setIdentitySummary(JSON.toJSONString(java.util.stream.IntStream.range(0, 8000).mapToObj(i -> "realtime:" + i).toList()));
+            action.setChangesSummary(JSON.toJSONString(java.util.Collections.nCopies(8000, Map.of("voltage", 1.5))));
+            action.setBeforeContentJson(action.getChangesSummary());
+            mapper.insertDataRevisionAction(action);
+            var summary = service.selectActionById(action.getActionId());
+            assertNull(summary.getIdentitySummary(), "详情查询不得将批量身份 JSON 加载到服务层");
+            assertNull(summary.getChangesSummary(), "详情查询不得将批量变化 JSON 加载到服务层");
+            assertNull(summary.getBeforeContentJson(), "详情查询不得加载完整审计快照");
+            var details = new TTestDataRevisionController();
+            ReflectionTestUtils.setField(details, "service", service);
+            var json = new com.fasterxml.jackson.databind.ObjectMapper();
+            String response = json.writeValueAsString(details.detail(action.getActionId()));
+            assertEquals(8000, json.readTree(response).get("data").get("affectedRecordCount").intValue());
+            assertTrue(response.length() < 1500, "摘要响应不能随批量明细膨胀");
+            // 展示裁剪只发生在 SELECT;数据库审计原文仍完整保留。
+            assertTrue(jdbc.queryForObject("select length(cast(changes_summary as varchar)) from t_test_data_revision_action where action_id=?", Integer.class, action.getActionId()) > 100000);
+        }
+        var list = service.selectActions(new TTestDataRevisionAction());
+        assertEquals(2, list.size());
+        assertTrue(list.stream().allMatch(row -> row.getIdentitySummary() == null && row.getChangesSummary() == null && row.getBeforeContentJson() == null));
+    }
+
+    @Test void stepMedianVoltagesPersistAndRemainIndependentOfLegacyPeaks()
+    {
+        var imported = row();
+        imported.put("chargeMedianVoltage", 0);
+        imported.put("dischargeMedianVoltage", 1.1709);
+        submit("STEP", List.of(imported));
+        var stored = mapper.selectImportDataRecords(1L, "STEP").get(0);
+        var extension = JSON.parseObject(stored.get("extension_measurements_json").toString());
+        assertNotNull(extension.getBigDecimal("chargeMedianVoltage"));
+        assertEquals(0, extension.getBigDecimal("chargeMedianVoltage").signum());
+        assertEquals(new java.math.BigDecimal("1.1709"), extension.getBigDecimal("dischargeMedianVoltage"));
+        assertEquals(1, submit("STEP", List.of(imported)).get("skippedCount"));
+
+        // 旧峰谷值仍是独立事实;不能在查询时作为缺失中值的回退来源。
+        var queryMapper = org.mockito.Mockito.mock(TTestMapper.class);
+        var query = new com.battery.business.service.impl.TestDataQueryServiceImpl(queryMapper,
+                org.mockito.Mockito.mock(com.battery.business.service.ITTestService.class));
+        var current = new LinkedHashMap<String, Object>(Map.of("extensionMeasurementsJson", extension.toJSONString()));
+        var legacy = new LinkedHashMap<String, Object>(Map.of("extensionMeasurementsJson", "{\"chargePeakVoltage\":1.8,\"dischargeValleyVoltage\":0.8}"));
+        org.mockito.Mockito.when(queryMapper.selectPersistedFinalStepRecords(1L)).thenReturn(List.of(current, legacy));
+        var result = query.steps(1L);
+        assertEquals(new java.math.BigDecimal("1.1709"), result.get(0).get("dischargeMedianVoltage"));
+        assertEquals(0.0, ((Number) result.get(0).get("chargeMedianVoltage")).doubleValue());
+        assertNull(result.get(1).get("chargeMedianVoltage"));
+        assertNull(result.get(1).get("dischargeMedianVoltage"));
+
+        imported.put("dischargeMedianVoltage", 1.2);
+        assertTrue(assertThrows(RuntimeException.class, () -> submit("STEP", List.of(imported))).getMessage().contains("冲突拒绝"));
+        assertEquals(1, service.selectActions(new TTestDataRevisionAction()).size());
     }
 
     @Test void workbookImportsThreeSheetsWithOneRevisionAndSkipsRetry()
@@ -238,6 +309,18 @@
             assertEquals(count, submit(type, rows).get("importedCount"));
             assertEquals(count, mapper.selectImportDataRecords(1L, type).size());
             assertEquals(count, submit(type, rows).get("skippedCount"));
+            if ("STEP".equals(type))
+            {
+                var persisted = mapper.selectImportDataRecords(1L, type).stream().collect(java.util.stream.Collectors.toMap(
+                        record -> record.get("source_record_id").toString(), record -> record));
+                for (var input : rows)
+                {
+                    var stored = JSON.parseObject(persisted.get(input.get("recordNo").toString()).get("extension_measurements_json").toString());
+                    for (String field : List.of("chargeMedianVoltage", "dischargeMedianVoltage"))
+                        if (input.get(field) == null) assertNull(stored.get(field));
+                        else assertEquals(0, new java.math.BigDecimal(input.get(field).toString()).compareTo(stored.getBigDecimal(field)), field);
+                }
+            }
         }
         assertEquals(3, service.selectActions(new TTestDataRevisionAction()).size());
     }

--
Gitblit v1.7.1