From 3b0d51d628c772c47845d9fd0b95ebde8a969d07 Mon Sep 17 00:00:00 2001
From: yeg <1347747024@qq.com>
Date: 星期二, 01 九月 2026 11:59:12 +0800
Subject: [PATCH] 实现数据修订行为模型
---
ruoyi-admin/src/test/java/com/ruoyi/config/Ticket26MigrationContractTest.java | 25 +++
ruoyi-admin/src/test/java/com/ruoyi/system/service/impl/TestConsoleDataRevisionQueryServiceTest.java | 116 ++++++++++++++++
ruoyi-admin/src/main/resources/db/migration/V26__data_revision_action_query_contract.sql | 3
ruoyi-system/src/main/resources/mapper/system/TTestMapper.xml | 60 ++++++++
ruoyi-system/src/main/java/com/ruoyi/system/domain/TTestDataRevisionAction.java | 22 +++
ruoyi-system/src/main/java/com/ruoyi/system/mapper/TTestMapper.java | 13 +
ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/TTestDataRevisionController.java | 40 +++++
ruoyi-system/src/main/java/com/ruoyi/system/service/impl/TestConsoleDataServiceImpl.java | 94 ++++++++++++-
ruoyi-system/src/main/java/com/ruoyi/system/service/ITestConsoleDataService.java | 6
9 files changed, 366 insertions(+), 13 deletions(-)
diff --git a/ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/TTestDataRevisionController.java b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/TTestDataRevisionController.java
new file mode 100644
index 0000000..3476f52
--- /dev/null
+++ b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/TTestDataRevisionController.java
@@ -0,0 +1,40 @@
+package com.ruoyi.web.controller.system;
+
+import java.util.List;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.security.access.prepost.PreAuthorize;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.PathVariable;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+import com.ruoyi.common.core.controller.BaseController;
+import com.ruoyi.common.core.domain.AjaxResult;
+import com.ruoyi.common.core.page.TableDataInfo;
+import com.ruoyi.system.domain.TTestDataRevisionAction;
+import com.ruoyi.system.service.ITestConsoleDataService;
+
+/** 数据修订行为查询接口;只读返回一次用户行为及其摘要。 */
+@RestController
+@RequestMapping("/system/data-revision")
+public class TTestDataRevisionController extends BaseController
+{
+ @Autowired
+ private ITestConsoleDataService service;
+
+ @PreAuthorize("@ss.hasPermi('system:dataRevision:list')")
+ @GetMapping("/list")
+ public TableDataInfo list(TTestDataRevisionAction query)
+ {
+ startPage();
+ List<TTestDataRevisionAction> rows = service.selectActions(query);
+ return getDataTable(rows);
+ }
+
+ @PreAuthorize("@ss.hasPermi('system:dataRevision:query')")
+ @GetMapping("/{actionId}")
+ public AjaxResult detail(@PathVariable Long actionId)
+ {
+ TTestDataRevisionAction action = service.selectActionById(actionId);
+ return action == null ? error("未找到数据修订行为") : success(action);
+ }
+}
diff --git a/ruoyi-admin/src/main/resources/db/migration/V26__data_revision_action_query_contract.sql b/ruoyi-admin/src/main/resources/db/migration/V26__data_revision_action_query_contract.sql
new file mode 100644
index 0000000..517c854
--- /dev/null
+++ b/ruoyi-admin/src/main/resources/db/migration/V26__data_revision_action_query_contract.sql
@@ -0,0 +1,3 @@
+-- Ticket26:数据修订行为查询使用现有一次行为表,不复制按单元格记录。
+CREATE INDEX idx_data_revision_query_time
+ ON t_test_data_revision_action (data_type, operation_type, created_at_utc, action_id);
diff --git a/ruoyi-admin/src/test/java/com/ruoyi/config/Ticket26MigrationContractTest.java b/ruoyi-admin/src/test/java/com/ruoyi/config/Ticket26MigrationContractTest.java
new file mode 100644
index 0000000..14cb970
--- /dev/null
+++ b/ruoyi-admin/src/test/java/com/ruoyi/config/Ticket26MigrationContractTest.java
@@ -0,0 +1,25 @@
+package com.ruoyi.config;
+
+import static org.junit.jupiter.api.Assertions.assertFalse;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+import java.io.InputStream;
+import java.nio.charset.StandardCharsets;
+import org.junit.jupiter.api.Test;
+
+/** Ticket26 迁移只增加行为查询索引,不建立按行或按格修订表。 */
+class Ticket26MigrationContractTest
+{
+ @Test
+ void addsActionQueryIndexWithoutReplacingAuditFacts() throws Exception
+ {
+ try (InputStream stream = getClass().getClassLoader().getResourceAsStream(
+ "db/migration/V26__data_revision_action_query_contract.sql"))
+ {
+ if (stream == null) throw new AssertionError("缺少 Ticket26 迁移");
+ String sql = new String(stream.readAllBytes(), StandardCharsets.UTF_8);
+ assertTrue(sql.contains("idx_data_revision_query_time"));
+ assertTrue(sql.contains("t_test_data_revision_action"));
+ assertFalse(sql.matches("(?s).*\\b(DROP|DELETE|UPDATE)\\b.*"));
+ }
+ }
+}
diff --git a/ruoyi-admin/src/test/java/com/ruoyi/system/service/impl/TestConsoleDataRevisionQueryServiceTest.java b/ruoyi-admin/src/test/java/com/ruoyi/system/service/impl/TestConsoleDataRevisionQueryServiceTest.java
new file mode 100644
index 0000000..c884534
--- /dev/null
+++ b/ruoyi-admin/src/test/java/com/ruoyi/system/service/impl/TestConsoleDataRevisionQueryServiceTest.java
@@ -0,0 +1,116 @@
+package com.ruoyi.system.service.impl;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertThrows;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+import java.util.List;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.extension.ExtendWith;
+import org.mockito.InjectMocks;
+import org.mockito.Mock;
+import org.mockito.junit.jupiter.MockitoExtension;
+import com.ruoyi.common.exception.ServiceException;
+import com.ruoyi.system.domain.TTestDataRevisionAction;
+import com.ruoyi.system.domain.TTestDataOverride;
+import com.ruoyi.system.mapper.TTestMapper;
+
+/** Ticket26:修订行为按一次提交查询,且三类数据与三类操作均受服务端约束。 */
+@ExtendWith(MockitoExtension.class)
+class TestConsoleDataRevisionQueryServiceTest
+{
+ @Mock
+ private TTestMapper mapper;
+ @InjectMocks
+ private TestConsoleDataServiceImpl service;
+ private TTestDataRevisionAction query;
+
+ @BeforeEach
+ void setUp()
+ {
+ query = new TTestDataRevisionAction();
+ query.setTestId(26L);
+ query.setDataType("STEP");
+ query.setOperationType("EDIT");
+ }
+
+ @Test
+ void delegatesOneActionQueryWithFilters()
+ {
+ TTestDataRevisionAction action = new TTestDataRevisionAction();
+ action.setActionId(101L);
+ when(mapper.selectDataRevisionActions(query)).thenReturn(List.of(action));
+
+ assertEquals(101L, service.selectActions(query).get(0).getActionId());
+ verify(mapper).selectDataRevisionActions(query);
+ }
+
+ @Test
+ void rejectsUnknownDataTypeAndOperation()
+ {
+ query.setDataType("CELL");
+ assertThrows(ServiceException.class, () -> service.selectActions(query));
+ query.setDataType("CYCLE");
+ query.setOperationType("RESTORE");
+ assertThrows(ServiceException.class, () -> service.selectActions(query));
+ }
+
+ @Test
+ void returnsReadOnlyActionDetail()
+ {
+ TTestDataRevisionAction action = new TTestDataRevisionAction();
+ action.setActionId(99L);
+ action.setOperationType("DELETE");
+ when(mapper.selectDataRevisionActionById(99L)).thenReturn(action);
+
+ assertEquals("DELETE", service.selectActionById(99L).getOperationType());
+ assertThrows(ServiceException.class, () -> service.selectActionById(0L));
+ }
+
+ @Test
+ void rejectsIdentitySummaryThatDoesNotMatchOverrides()
+ {
+ TTestDataRevisionAction action = new TTestDataRevisionAction();
+ action.setTestId(26L); action.setDataType("REALTIME"); action.setOperationType("DELETE");
+ action.setScopeSummary("删除一条实时数据"); action.setIdentitySummary("[\"record-1\"]");
+ action.setReason("异常点"); action.setOperatorName("tester");
+ TTestDataOverride override = new TTestDataOverride();
+ override.setStableIdentity("record-2"); override.setDeleted(true);
+
+ assertThrows(ServiceException.class,
+ () -> service.submitAction(action, List.of(override), List.of(), List.of()));
+ }
+
+ @Test
+ void rejectsIdentitySummaryWithExtraIdentity()
+ {
+ TTestDataRevisionAction action = new TTestDataRevisionAction();
+ action.setTestId(26L); action.setDataType("STEP"); action.setOperationType("DELETE");
+ action.setScopeSummary("删除一条工步数据"); action.setIdentitySummary("[\"step:1:2:3:4\",\"step:1:2:3:5\"]");
+ action.setReason("异常工步"); action.setOperatorName("tester");
+ TTestDataOverride override = new TTestDataOverride();
+ override.setStableIdentity("step:1:2:3:4"); override.setDeleted(true);
+
+ assertThrows(ServiceException.class,
+ () -> service.submitAction(action, List.of(override), List.of(), List.of()));
+ }
+
+ @Test
+ void physicallyDeletesSamplesBehindStepAggregate()
+ {
+ TTestDataRevisionAction action = new TTestDataRevisionAction();
+ action.setTestId(26L); action.setDataType("STEP"); action.setOperationType("DELETE");
+ action.setScopeSummary("删除一条工步数据"); action.setIdentitySummary("[\"step:1:2:3:4\"]");
+ action.setReason("异常工步"); action.setOperatorName("tester");
+ TTestDataOverride override = new TTestDataOverride();
+ override.setStableIdentity("step:1:2:3:4"); override.setDeleted(true);
+ when(mapper.selectBtsSampleIdsByDeviceChannelStep(26L, 1L, 2L, 3, 4))
+ .thenReturn(List.of(101L, 102L));
+
+ service.submitAction(action, List.of(override), List.of(), List.of());
+
+ verify(mapper).deleteBtsMeasurementsBySampleIds(List.of(101L, 102L));
+ verify(mapper).deleteBtsSamplesByIds(26L, List.of(101L, 102L));
+ }
+}
diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/domain/TTestDataRevisionAction.java b/ruoyi-system/src/main/java/com/ruoyi/system/domain/TTestDataRevisionAction.java
index 1e5d79f..89497cb 100644
--- a/ruoyi-system/src/main/java/com/ruoyi/system/domain/TTestDataRevisionAction.java
+++ b/ruoyi-system/src/main/java/com/ruoyi/system/domain/TTestDataRevisionAction.java
@@ -2,6 +2,9 @@
import java.io.Serializable;
import java.util.Date;
+import org.springframework.format.annotation.DateTimeFormat;
+import com.fasterxml.jackson.annotation.JsonIgnore;
+import com.fasterxml.jackson.annotation.JsonFormat;
/** 一次控制台数据编辑、导入或删除行为。 */
public class TTestDataRevisionAction implements Serializable
@@ -17,7 +20,18 @@
private String reason;
private Long operatorId;
private String operatorName;
+ @JsonFormat(pattern = "yyyy-MM-dd'T'HH:mm:ss.SSSXXX", timezone = "UTC")
private Date createdAtUtc;
+ /** 查询展示字段:来源测试名称。 */
+ private String testName;
+ /** 返回测试控制台时使用的后端接收状态。 */
+ private String testReceptionStatus;
+ @JsonIgnore
+ @DateTimeFormat(iso = DateTimeFormat.ISO.DATE_TIME)
+ private Date beginCreatedAt;
+ @JsonIgnore
+ @DateTimeFormat(iso = DateTimeFormat.ISO.DATE_TIME)
+ private Date endCreatedAt;
public Long getActionId() { return actionId; }
public void setActionId(Long value) { actionId = value; }
@@ -41,4 +55,12 @@
public void setOperatorName(String value) { operatorName = value; }
public Date getCreatedAtUtc() { return createdAtUtc; }
public void setCreatedAtUtc(Date value) { createdAtUtc = value; }
+ public String getTestName() { return testName; }
+ public void setTestName(String value) { testName = value; }
+ public String getTestReceptionStatus() { return testReceptionStatus; }
+ public void setTestReceptionStatus(String value) { testReceptionStatus = value; }
+ public Date getBeginCreatedAt() { return beginCreatedAt; }
+ public void setBeginCreatedAt(Date value) { beginCreatedAt = value; }
+ public Date getEndCreatedAt() { return endCreatedAt; }
+ public void setEndCreatedAt(Date value) { endCreatedAt = value; }
}
diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/mapper/TTestMapper.java b/ruoyi-system/src/main/java/com/ruoyi/system/mapper/TTestMapper.java
index 33224d9..c000e5c 100644
--- a/ruoyi-system/src/main/java/com/ruoyi/system/mapper/TTestMapper.java
+++ b/ruoyi-system/src/main/java/com/ruoyi/system/mapper/TTestMapper.java
@@ -192,14 +192,23 @@
int countOpenExceptions(Long testId);
int insertDataRevisionAction(TTestDataRevisionAction action);
+ List<TTestDataRevisionAction> selectDataRevisionActions(TTestDataRevisionAction query);
+ TTestDataRevisionAction selectDataRevisionActionById(Long actionId);
int upsertDataOverride(TTestDataOverride override);
List<TTestDataOverride> selectDataOverrides(@Param("testId") Long testId,
@Param("dataType") String dataType);
int deleteBtsSamplesByIds(@Param("testId") Long testId, @Param("sampleIds") List<Long> sampleIds);
int deleteBtsMeasurementsBySampleIds(@Param("sampleIds") List<Long> sampleIds);
int deleteCollectorSamplesByIds(@Param("testId") Long testId, @Param("sampleIds") List<Long> sampleIds);
- Long selectBtsSampleIdByChannelSequence(@Param("testId") Long testId,
- @Param("channelId") Long channelId, @Param("sequenceId") Long sequenceId);
+ Long selectBtsSampleIdByDeviceChannelSequence(@Param("testId") Long testId,
+ @Param("deviceId") Long deviceId, @Param("channelNo") Long channelNo,
+ @Param("sequenceId") Long sequenceId);
+ List<Long> selectBtsSampleIdsByDeviceChannelStep(@Param("testId") Long testId,
+ @Param("deviceId") Long deviceId, @Param("channelNo") Long channelNo,
+ @Param("cycleNo") Integer cycleNo, @Param("stepNo") Integer stepNo);
+ List<Long> selectBtsSampleIdsByDeviceChannelCycle(@Param("testId") Long testId,
+ @Param("deviceId") Long deviceId, @Param("channelNo") Long channelNo,
+ @Param("cycleNo") Integer cycleNo);
int insertConsoleImportRecord(TTestConsoleImportRecord record);
int countTestBatteryNo(@Param("testId") Long testId, @Param("batteryNo") String batteryNo);
}
diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/service/ITestConsoleDataService.java b/ruoyi-system/src/main/java/com/ruoyi/system/service/ITestConsoleDataService.java
index ef91987..48bc903 100644
--- a/ruoyi-system/src/main/java/com/ruoyi/system/service/ITestConsoleDataService.java
+++ b/ruoyi-system/src/main/java/com/ruoyi/system/service/ITestConsoleDataService.java
@@ -7,6 +7,12 @@
/** 控制台三类数据的修订、导入和物理删除服务。 */
public interface ITestConsoleDataService
{
+ /** 按测试、数据类型、操作类型和时间查询一次用户行为。 */
+ List<TTestDataRevisionAction> selectActions(TTestDataRevisionAction query);
+
+ /** 返回一条只读修订行为,不恢复被删除的数据。 */
+ TTestDataRevisionAction selectActionById(Long actionId);
+
List<TTestDataOverride> selectOverrides(Long testId, String dataType);
/** 在一个事务中写入一次行为、覆盖状态并执行请求的物理删除。 */
diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/TestConsoleDataServiceImpl.java b/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/TestConsoleDataServiceImpl.java
index d557873..4655e0d 100644
--- a/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/TestConsoleDataServiceImpl.java
+++ b/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/TestConsoleDataServiceImpl.java
@@ -28,6 +28,24 @@
private TTestMapper mapper;
@Override
+ public List<TTestDataRevisionAction> selectActions(TTestDataRevisionAction query)
+ {
+ if (query == null) query = new TTestDataRevisionAction();
+ if (query.getDataType() != null && !query.getDataType().isBlank()
+ && !DATA_TYPES.contains(query.getDataType())) throw new ServiceException("控制台数据类型无效");
+ if (query.getOperationType() != null && !query.getOperationType().isBlank()
+ && !OPERATIONS.contains(query.getOperationType())) throw new ServiceException("数据操作类型无效");
+ return mapper.selectDataRevisionActions(query);
+ }
+
+ @Override
+ public TTestDataRevisionAction selectActionById(Long actionId)
+ {
+ if (actionId == null || actionId < 1) throw new ServiceException("修订行为ID无效");
+ return mapper.selectDataRevisionActionById(actionId);
+ }
+
+ @Override
public List<TTestDataOverride> selectOverrides(Long testId, String dataType)
{
validateType(testId, dataType);
@@ -50,6 +68,7 @@
}
if ("EDIT".equals(action.getOperationType())) validateEditableFields(action);
if (action.getReason() == null || action.getReason().trim().isEmpty()) throw new ServiceException("数据操作原因不能为空");
+ validateActionSummaries(action, overrides);
if (action.getOperatorName() == null || action.getOperatorName().trim().isEmpty()) action.setOperatorName("未知用户");
action.setReason(action.getReason().trim());
action.setCreatedAtUtc(new Date());
@@ -95,18 +114,31 @@
mapper.upsertDataOverride(item);
}
}
- if ("DELETE".equals(action.getOperationType()) && "REALTIME".equals(action.getDataType()) && overrides != null)
+ if ("DELETE".equals(action.getOperationType()) && overrides != null)
{
List<Long> resolvedIds = new ArrayList<>();
for (TTestDataOverride item : overrides)
{
- Long[] identity = parseRealtimeIdentity(item.getStableIdentity());
- if (identity == null) continue;
- Long sampleId = mapper.selectBtsSampleIdByChannelSequence(action.getTestId(), identity[0], identity[1]);
- if (sampleId != null) resolvedIds.add(sampleId);
+ Long[] identity = parseDeleteIdentity(item.getStableIdentity(), action.getDataType());
+ if (identity == null) throw new ServiceException("删除数据稳定身份无效");
+ switch (action.getDataType())
+ {
+ case "REALTIME" -> {
+ Long sampleId = mapper.selectBtsSampleIdByDeviceChannelSequence(action.getTestId(),
+ identity[0], identity[1], identity[2]);
+ if (sampleId != null) resolvedIds.add(sampleId);
+ }
+ case "STEP" -> resolvedIds.addAll(mapper.selectBtsSampleIdsByDeviceChannelStep(action.getTestId(),
+ identity[0], identity[1], identity[2].intValue(), identity[3].intValue()));
+ case "CYCLE" -> resolvedIds.addAll(mapper.selectBtsSampleIdsByDeviceChannelCycle(action.getTestId(),
+ identity[0], identity[1], identity[2].intValue()));
+ default -> throw new ServiceException("控制台数据类型无效");
+ }
}
if (!resolvedIds.isEmpty())
{
+ resolvedIds = new ArrayList<>(new HashSet<>(resolvedIds));
+ // 工步和循环是采样聚合视图,物理删除需在同一事务内清理对应底层采样。
mapper.deleteBtsMeasurementsBySampleIds(resolvedIds);
mapper.deleteBtsSamplesByIds(action.getTestId(), resolvedIds);
}
@@ -175,6 +207,43 @@
catch (Exception exception) { throw new ServiceException("修改字段格式无效"); }
}
+ /** 防止客户端提交与实际覆盖身份不一致的伪行为摘要。 */
+ private void validateActionSummaries(TTestDataRevisionAction action, List<TTestDataOverride> overrides)
+ {
+ if (action.getScopeSummary() == null || action.getScopeSummary().trim().isEmpty())
+ throw new ServiceException("数据操作范围不能为空");
+ Set<String> summaryIdentities = new HashSet<>();
+ try
+ {
+ Object parsed = JSON.parse(action.getIdentitySummary());
+ if (!(parsed instanceof List<?> values)) throw new ServiceException("身份摘要格式无效");
+ for (Object value : values)
+ if (value == null || !summaryIdentities.add(String.valueOf(value)))
+ throw new ServiceException("身份摘要存在重复或空值");
+ }
+ catch (ServiceException exception) { throw exception; }
+ catch (Exception exception) { throw new ServiceException("身份摘要格式无效"); }
+ if (overrides == null) return;
+ Set<String> overrideIdentities = new HashSet<>();
+ for (TTestDataOverride item : overrides)
+ if (item == null || !overrideIdentities.add(item.getStableIdentity())
+ || !summaryIdentities.contains(item.getStableIdentity()))
+ throw new ServiceException("身份摘要与数据覆盖明细不一致");
+ if (!summaryIdentities.equals(overrideIdentities))
+ throw new ServiceException("身份摘要与数据覆盖明细不一致");
+ if ("EDIT".equals(action.getOperationType()))
+ {
+ try
+ {
+ Object parsed = JSON.parse(action.getChangesSummary());
+ if (!(parsed instanceof List<?> changes) || changes.size() < overrides.size())
+ throw new ServiceException("字段变化摘要与数据覆盖明细不一致");
+ }
+ catch (ServiceException exception) { throw exception; }
+ catch (Exception exception) { throw new ServiceException("字段变化摘要格式无效"); }
+ }
+ }
+
private Set<String> editableFields(String dataType)
{
return switch (dataType)
@@ -188,11 +257,20 @@
};
}
- private Long[] parseRealtimeIdentity(String value)
+ private Long[] parseDeleteIdentity(String value, String dataType)
{
String[] parts = value.split(":", -1);
- if (parts.length != 3) return null;
- try { return new Long[] { Long.valueOf(parts[0]), Long.valueOf(parts[2]) }; }
+ int expectedLength = "STEP".equals(dataType) ? 5 : "CYCLE".equals(dataType) ? 4 : 3;
+ if (parts.length != expectedLength) return null;
+ int offset = "REALTIME".equals(dataType) ? 0 : 1;
+ try
+ {
+ if ("STEP".equals(dataType))
+ return new Long[] { Long.valueOf(parts[offset]), Long.valueOf(parts[offset + 1]),
+ Long.valueOf(parts[offset + 2]), Long.valueOf(parts[offset + 3]) };
+ return new Long[] { Long.valueOf(parts[offset]), Long.valueOf(parts[offset + 1]),
+ Long.valueOf(parts[offset + 2]) };
+ }
catch (NumberFormatException exception) { return null; }
}
diff --git a/ruoyi-system/src/main/resources/mapper/system/TTestMapper.xml b/ruoyi-system/src/main/resources/mapper/system/TTestMapper.xml
index 7f26929..1f0e210 100644
--- a/ruoyi-system/src/main/resources/mapper/system/TTestMapper.xml
+++ b/ruoyi-system/src/main/resources/mapper/system/TTestMapper.xml
@@ -227,6 +227,42 @@
(#{testName}, #{creatorId}, #{principalId}, #{testTypeId}, #{testPurpose}, #{testStatus}, #{receptionStatus},
#{monitorTimeoutMinutes}, 0, #{createBy}, #{createTime}, #{remark})
</insert>
+ <resultMap id="TTestDataRevisionActionResultMap" type="com.ruoyi.system.domain.TTestDataRevisionAction">
+ <id property="actionId" column="action_id"/>
+ <result property="testId" column="test_id"/><result property="testName" column="test_name"/>
+ <result property="testReceptionStatus" column="reception_status"/>
+ <result property="dataType" column="data_type"/><result property="operationType" column="operation_type"/>
+ <result property="scopeSummary" column="scope_summary"/><result property="identitySummary" column="identity_summary"/>
+ <result property="changesSummary" column="changes_summary"/><result property="reason" column="reason"/>
+ <result property="operatorId" column="operator_id"/><result property="operatorName" column="operator_name"/>
+ <result property="createdAtUtc" column="created_at_utc"/>
+ </resultMap>
+ <select id="selectDataRevisionActions" parameterType="com.ruoyi.system.domain.TTestDataRevisionAction" resultMap="TTestDataRevisionActionResultMap">
+ select a.action_id, a.test_id, t.test_name, t.reception_status,
+ a.data_type, a.operation_type, a.scope_summary,
+ cast(a.identity_summary as char) identity_summary,
+ cast(a.changes_summary as char) changes_summary, a.reason,
+ a.operator_id, a.operator_name, a.created_at_utc
+ from t_test_data_revision_action a join t_test t on t.test_id = a.test_id
+ <where>
+ <if test="testId != null">and a.test_id = #{testId}</if>
+ <if test="testName != null and testName != ''">and t.test_name like concat('%', #{testName}, '%')</if>
+ <if test="dataType != null and dataType != ''">and a.data_type = #{dataType}</if>
+ <if test="operationType != null and operationType != ''">and a.operation_type = #{operationType}</if>
+ <if test="beginCreatedAt != null">and a.created_at_utc >= #{beginCreatedAt}</if>
+ <if test="endCreatedAt != null">and a.created_at_utc < #{endCreatedAt}</if>
+ </where>
+ order by a.created_at_utc desc, a.action_id desc
+ </select>
+ <select id="selectDataRevisionActionById" parameterType="long" resultMap="TTestDataRevisionActionResultMap">
+ select a.action_id, a.test_id, t.test_name, t.reception_status,
+ a.data_type, a.operation_type, a.scope_summary,
+ cast(a.identity_summary as char) identity_summary,
+ cast(a.changes_summary as char) changes_summary, a.reason,
+ a.operator_id, a.operator_name, a.created_at_utc
+ from t_test_data_revision_action a join t_test t on t.test_id = a.test_id
+ where a.action_id = #{actionId}
+ </select>
<update id="updateTest" parameterType="TTest">
update t_test
@@ -822,11 +858,29 @@
delete from t_test_collector_sample where test_id = #{testId} and sample_id in
<foreach collection="sampleIds" item="id" open="(" separator="," close=")">#{id}</foreach>
</delete>
- <select id="selectBtsSampleIdByChannelSequence" resultType="long">
- select sample_id from t_test_sample
- where test_id = #{testId} and channel_id = #{channelId} and seq_id = #{sequenceId}
+ <select id="selectBtsSampleIdByDeviceChannelSequence" resultType="long">
+ select sample.sample_id
+ from t_test_sample sample
+ join t_detection_channel channel_fact on channel_fact.channel_id = sample.channel_id
+ where sample.test_id = #{testId} and channel_fact.devid = #{deviceId}
+ and channel_fact.chlid = #{channelNo} and sample.seq_id = #{sequenceId}
limit 1
</select>
+ <select id="selectBtsSampleIdsByDeviceChannelStep" resultType="long">
+ select sample.sample_id
+ from t_test_sample sample
+ join t_detection_channel channel_fact on channel_fact.channel_id = sample.channel_id
+ where sample.test_id = #{testId} and channel_fact.devid = #{deviceId}
+ and channel_fact.chlid = #{channelNo} and sample.cycle_no = #{cycleNo}
+ and sample.step_no = #{stepNo}
+ </select>
+ <select id="selectBtsSampleIdsByDeviceChannelCycle" resultType="long">
+ select sample.sample_id
+ from t_test_sample sample
+ join t_detection_channel channel_fact on channel_fact.channel_id = sample.channel_id
+ where sample.test_id = #{testId} and channel_fact.devid = #{deviceId}
+ and channel_fact.chlid = #{channelNo} and sample.cycle_no = #{cycleNo}
+ </select>
<insert id="insertConsoleImportRecord" parameterType="com.ruoyi.system.domain.TTestConsoleImportRecord"
useGeneratedKeys="true" keyProperty="importRecordId">
insert into t_test_console_import_record
--
Gitblit v1.7.1