feat(system-ops): 新增系统运维模块及稳态数据视图优化

- 添加 system-ops 模块及其子模块 dbms 和 deploy
- 实现数据库监控和系统部署的基础接口和服务
- 更新项目依赖配置和文档说明
- 优化稳态数据视图中线电压相位显示逻辑
- 完善线电压指标的相位解析和测试验证
This commit is contained in:
2026-05-21 14:08:15 +08:00
parent 89efc55119
commit 9a9614a9e5
21 changed files with 481 additions and 6 deletions

View File

@@ -15,6 +15,7 @@ CN_Tool 是一个基于 Spring Boot 的多模块后端聚合工程,当前仓
- `entrance`
- `system`
- `systemmonitor`
- `system-ops`
- `user`
- `detection`
- `tools`
@@ -23,6 +24,11 @@ CN_Tool 是一个基于 Spring Boot 的多模块后端聚合工程,当前仓
- `disk-monitor`
其中 `system-ops` 当前包含:
- `dbms`
- `deploy`
其中 `tools` 当前包含:
- `activate-tool`
@@ -37,7 +43,7 @@ CN_Tool 是一个基于 Spring Boot 的多模块后端聚合工程,当前仓
- `entrance/src/main/java/com/njcn/gather/EntranceApplication.java`
`entrance` 模块聚合了 `system``disk-monitor``user``detection``activate-tool``add-data``add-ledger``wave-tool``mms-mapping`,是当前运行时主入口。
`entrance` 模块聚合了 `system``disk-monitor``dbms``deploy``user``detection``activate-tool``add-data``add-ledger``wave-tool``mms-mapping`,是当前运行时主入口。
## 技术基线
@@ -80,6 +86,10 @@ P0 已补齐基线文档,建议按以下顺序阅读:
- 负责字典、日志、系统配置、注册资源相关能力
- `systemmonitor/disk-monitor`
- 负责磁盘监控相关能力的独立扩展实现
- `system-ops/dbms`
- 负责系统运维下数据库监控基础入口
- `system-ops/deploy`
- 负责系统运维下系统部署基础入口
- `detection`
- 当前以通信基础设施为主,包含 WebSocket / Netty 相关组件
- `tools/activate-tool`

View File

@@ -21,6 +21,16 @@
<artifactId>disk-monitor</artifactId>
<version>1.0.0</version>
</dependency>
<dependency>
<groupId>com.njcn.gather</groupId>
<artifactId>dbms</artifactId>
<version>1.0.0</version>
</dependency>
<dependency>
<groupId>com.njcn.gather</groupId>
<artifactId>deploy</artifactId>
<version>1.0.0</version>
</dependency>
<dependency>
<groupId>com.njcn.gather</groupId>
<artifactId>detection</artifactId>

View File

@@ -13,6 +13,7 @@
<module>entrance</module>
<module>system</module>
<module>systemmonitor</module>
<module>system-ops</module>
<module>user</module>
<module>detection</module>
<module>tools</module>

View File

@@ -29,7 +29,7 @@ public class SteadyTrendIndicatorCatalog {
List<SteadyTrendIndicatorDefinitionBO> result = new ArrayList<SteadyTrendIndicatorDefinitionBO>();
result.add(indicator("V_RMS", "相电压有效值", "VOLTAGE", "电压趋势", "data_v", ABC_PHASES,
fields(field("rms", "相电压有效值")), FULL_STATS, "V"));
result.add(indicator("V_LINE_RMS", "线电压有效值", "VOLTAGE", "电压趋势", "data_v", T_PHASE,
result.add(indicator("V_LINE_RMS", "线电压有效值", "VOLTAGE", "电压趋势", "data_v", ABC_PHASES,
fields(field("rms_lvr", "线电压有效值")),
FULL_STATS, "V"));
result.add(indicator("FREQ", "频率", "FREQUENCY", "频率趋势", "data_v", T_PHASE,

View File

@@ -33,6 +33,7 @@ import java.util.Map;
public class SteadyDataViewTrendServiceImpl implements SteadyDataViewTrendService {
private static final String EMPTY_TEXT = "-";
private static final String LINE_VOLTAGE_RMS_INDICATOR = "V_LINE_RMS";
private final SteadyTrendFieldResolver fieldResolver;
private final SteadyInfluxQueryComponent influxQueryComponent;
@@ -91,13 +92,29 @@ public class SteadyDataViewTrendServiceImpl implements SteadyDataViewTrendServic
series.setIndicatorCode(field.getIndicatorCode());
series.setIndicatorName(field.getIndicatorName());
series.setSeriesName(field.getSeriesName());
series.setPhase(field.getPhase());
series.setPhase(resolveDisplayPhase(field));
series.setStatType(field.getStatType());
series.setUnit(field.getUnit());
series.setPoints(points);
return series;
}
private String resolveDisplayPhase(SteadyTrendResolvedFieldBO field) {
if (!LINE_VOLTAGE_RMS_INDICATOR.equals(field.getIndicatorCode())) {
return field.getPhase();
}
if ("A".equals(field.getPhase())) {
return "AB";
}
if ("B".equals(field.getPhase())) {
return "BC";
}
if ("C".equals(field.getPhase())) {
return "CA";
}
return field.getPhase();
}
private void enrichLineNames(List<SteadyTrendResolvedFieldBO> fields) {
List<String> lineIds = new ArrayList<String>();
for (SteadyTrendResolvedFieldBO field : fields) {

View File

@@ -54,7 +54,7 @@ class SteadyTrendFieldResolverTest {
}
@Test
void shouldExpandTotalPhaseIndicatorWithoutRequestPhaseFilter() {
void shouldExpandLineVoltageIndicatorWithQueryPhases() {
SteadyTrendQueryParam param = new SteadyTrendQueryParam();
param.setLineIds(Arrays.asList("line-001"));
param.setIndicatorCodes(Arrays.asList("V_LINE_RMS"));
@@ -63,9 +63,9 @@ class SteadyTrendFieldResolverTest {
param.setTimeEnd("2026-05-01 01:00:00");
List<SteadyTrendResolvedFieldBO> fields = resolver.resolveFields(param);
List<String> phases = fields.stream().map(SteadyTrendResolvedFieldBO::getPhase).collect(Collectors.toList());
Assertions.assertEquals(1, fields.size());
Assertions.assertEquals("T", fields.get(0).getPhase());
Assertions.assertEquals(Arrays.asList("A", "B", "C"), phases);
Assertions.assertEquals("rms_lvr", fields.get(0).getField());
}

View File

@@ -0,0 +1,54 @@
package com.njcn.gather.steady.datavie.service.impl;
import com.njcn.gather.steady.datavie.component.SteadyInfluxQueryComponent;
import com.njcn.gather.steady.datavie.component.SteadyTrendFieldResolver;
import com.njcn.gather.steady.datavie.component.SteadyTrendIndicatorCatalog;
import com.njcn.gather.steady.datavie.pojo.bo.SteadyTrendResolvedFieldBO;
import com.njcn.gather.steady.datavie.pojo.param.SteadyTrendQueryParam;
import com.njcn.gather.steady.datavie.pojo.vo.SteadyTrendQueryVO;
import com.njcn.gather.tool.addledger.service.AddLedgerService;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;
import java.time.LocalDateTime;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.stream.Collectors;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
/**
* 稳态趋势查询服务测试。
*/
class SteadyDataViewTrendServiceImplTest {
@Test
void shouldDisplayLineVoltagePhasesAsLinePairs() {
SteadyInfluxQueryComponent influxQueryComponent = mock(SteadyInfluxQueryComponent.class);
AddLedgerService addLedgerService = mock(AddLedgerService.class);
SteadyDataViewTrendServiceImpl service = new SteadyDataViewTrendServiceImpl(
new SteadyTrendFieldResolver(new SteadyTrendIndicatorCatalog()), influxQueryComponent, addLedgerService);
when(addLedgerService.listLinePathByLineIds(eq(Collections.singletonList("line-001"))))
.thenReturn(Collections.emptyMap());
when(influxQueryComponent.queryTrendPoints(any(SteadyTrendResolvedFieldBO.class),
any(LocalDateTime.class), any(LocalDateTime.class), eq(0))).thenReturn(Collections.emptyList());
SteadyTrendQueryParam param = new SteadyTrendQueryParam();
param.setLineIds(Collections.singletonList("line-001"));
param.setIndicatorCodes(Collections.singletonList("V_LINE_RMS"));
param.setStatTypes(Collections.singletonList("AVG"));
param.setTimeStart("2026-05-01 00:00:00");
param.setTimeEnd("2026-05-01 01:00:00");
param.setQualityFlag(0);
SteadyTrendQueryVO result = service.queryTrend(param);
List<String> phases = result.getSeries().stream()
.map(series -> series.getPhase())
.collect(Collectors.toList());
Assertions.assertEquals(Arrays.asList("AB", "BC", "CA"), phases);
}
}

34
system-ops/README.md Normal file
View File

@@ -0,0 +1,34 @@
# system-ops 模块说明
## 模块定位
`system-ops` 是根工程下的系统运维聚合模块,当前按菜单职责拆分为数据库监控和系统部署两个子模块。
当前包含:
- `dbms`:数据库监控基础入口
- `deploy`:系统部署基础入口
- 系统运维菜单初始化 SQL
## 当前结构
```text
system-ops/
├── pom.xml
├── README.md
├── dbms/
└── deploy/
```
## 当前接口
- `GET /database/overview`
- 查询数据库监控基础信息。
- `GET /deploy/overview`
- 查询系统部署基础信息。
## 当前限制
- 当前只完成后端基础入口,不包含真实数据库探测逻辑。
- 当前只完成后端基础入口,不包含真实系统部署执行逻辑。
- SQL 脚本不自动执行,需要按部署流程手动执行或纳入目标环境初始化流程。

14
system-ops/dbms/README.md Normal file
View File

@@ -0,0 +1,14 @@
# dbms 模块说明
## 模块定位
`dbms``system-ops` 下的数据库监控模块,当前先提供数据库监控菜单对应的后端基础入口。
## 当前接口
- `GET /database/overview`
- 查询数据库监控基础信息。
## 当前限制
- 当前只完成后端基础入口,不包含真实数据库连接状态、容量或性能指标探测逻辑。

30
system-ops/dbms/pom.xml Normal file
View File

@@ -0,0 +1,30 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>com.njcn.gather</groupId>
<artifactId>system-ops</artifactId>
<version>1.0.0</version>
</parent>
<artifactId>dbms</artifactId>
<packaging>jar</packaging>
<name>dbms</name>
<dependencies>
<dependency>
<groupId>com.njcn</groupId>
<artifactId>njcn-common</artifactId>
<version>0.0.1</version>
</dependency>
<dependency>
<groupId>com.njcn</groupId>
<artifactId>spingboot2.3.12</artifactId>
<version>2.3.12</version>
</dependency>
</dependencies>
</project>

View File

@@ -0,0 +1,41 @@
package com.njcn.gather.systemops.database.controller;
import com.njcn.common.pojo.annotation.OperateInfo;
import com.njcn.common.pojo.enums.common.LogEnum;
import com.njcn.common.pojo.enums.response.CommonResponseEnum;
import com.njcn.common.pojo.response.HttpResult;
import com.njcn.common.utils.LogUtil;
import com.njcn.gather.systemops.database.pojo.vo.DatabaseOverviewVO;
import com.njcn.gather.systemops.database.service.DatabaseService;
import com.njcn.web.controller.BaseController;
import com.njcn.web.utils.HttpResultUtil;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
/**
* 数据库监控基础接口。
*/
@Slf4j
@Api(tags = "数据库监控")
@RestController
@RequestMapping("/database")
@RequiredArgsConstructor
public class DatabaseController extends BaseController {
private final DatabaseService databaseService;
@OperateInfo(info = LogEnum.BUSINESS_COMMON)
@ApiOperation("查询数据库监控基础信息")
@GetMapping("/overview")
public HttpResult<DatabaseOverviewVO> overview() {
String methodDescribe = getMethodDescribe("overview");
LogUtil.njcnDebug(log, "{},开始查询数据库监控基础信息", methodDescribe);
DatabaseOverviewVO result = databaseService.overview();
return HttpResultUtil.assembleCommonResponseResult(CommonResponseEnum.SUCCESS, result, methodDescribe);
}
}

View File

@@ -0,0 +1,38 @@
package com.njcn.gather.systemops.database.pojo.vo;
import lombok.Data;
import java.io.Serializable;
/**
* 数据库监控基础信息。
*/
@Data
public class DatabaseOverviewVO implements Serializable {
private static final long serialVersionUID = -6645576505607222597L;
/**
* 菜单名称。
*/
private String menuName;
/**
* 菜单编码。
*/
private String menuCode;
/**
* 菜单路径。
*/
private String path;
/**
* 基础功能状态。
*/
private String status;
/**
* 功能说明。
*/
private String description;
}

View File

@@ -0,0 +1,16 @@
package com.njcn.gather.systemops.database.service;
import com.njcn.gather.systemops.database.pojo.vo.DatabaseOverviewVO;
/**
* 数据库监控基础服务。
*/
public interface DatabaseService {
/**
* 查询数据库监控基础信息。
*
* @return 数据库监控基础信息
*/
DatabaseOverviewVO overview();
}

View File

@@ -0,0 +1,25 @@
package com.njcn.gather.systemops.database.service.impl;
import com.njcn.gather.systemops.database.pojo.vo.DatabaseOverviewVO;
import com.njcn.gather.systemops.database.service.DatabaseService;
import org.springframework.stereotype.Service;
/**
* 数据库监控基础服务实现。
*/
@Service
public class DatabaseServiceImpl implements DatabaseService {
private static final String STATUS_READY = "READY";
@Override
public DatabaseOverviewVO overview() {
DatabaseOverviewVO result = new DatabaseOverviewVO();
result.setMenuName("数据库监控");
result.setMenuCode("database");
result.setPath("/systemOps/database");
result.setStatus(STATUS_READY);
result.setDescription("数据库监控基础入口已接入,后续可在此扩展连接状态、容量和性能指标。");
return result;
}
}

View File

@@ -0,0 +1,14 @@
# deploy 模块说明
## 模块定位
`deploy``system-ops` 下的系统部署模块,当前先提供系统部署菜单对应的后端基础入口。
## 当前接口
- `GET /deploy/overview`
- 查询系统部署基础信息。
## 当前限制
- 当前只完成后端基础入口,不包含真实部署包、环境、执行记录或部署执行逻辑。

30
system-ops/deploy/pom.xml Normal file
View File

@@ -0,0 +1,30 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>com.njcn.gather</groupId>
<artifactId>system-ops</artifactId>
<version>1.0.0</version>
</parent>
<artifactId>deploy</artifactId>
<packaging>jar</packaging>
<name>deploy</name>
<dependencies>
<dependency>
<groupId>com.njcn</groupId>
<artifactId>njcn-common</artifactId>
<version>0.0.1</version>
</dependency>
<dependency>
<groupId>com.njcn</groupId>
<artifactId>spingboot2.3.12</artifactId>
<version>2.3.12</version>
</dependency>
</dependencies>
</project>

View File

@@ -0,0 +1,41 @@
package com.njcn.gather.systemops.deploy.controller;
import com.njcn.common.pojo.annotation.OperateInfo;
import com.njcn.common.pojo.enums.common.LogEnum;
import com.njcn.common.pojo.enums.response.CommonResponseEnum;
import com.njcn.common.pojo.response.HttpResult;
import com.njcn.common.utils.LogUtil;
import com.njcn.gather.systemops.deploy.pojo.vo.DeployOverviewVO;
import com.njcn.gather.systemops.deploy.service.DeployService;
import com.njcn.web.controller.BaseController;
import com.njcn.web.utils.HttpResultUtil;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
/**
* 系统部署基础接口。
*/
@Slf4j
@Api(tags = "系统部署")
@RestController
@RequestMapping("/deploy")
@RequiredArgsConstructor
public class DeployController extends BaseController {
private final DeployService deployService;
@OperateInfo(info = LogEnum.BUSINESS_COMMON)
@ApiOperation("查询系统部署基础信息")
@GetMapping("/overview")
public HttpResult<DeployOverviewVO> overview() {
String methodDescribe = getMethodDescribe("overview");
LogUtil.njcnDebug(log, "{},开始查询系统部署基础信息", methodDescribe);
DeployOverviewVO result = deployService.overview();
return HttpResultUtil.assembleCommonResponseResult(CommonResponseEnum.SUCCESS, result, methodDescribe);
}
}

View File

@@ -0,0 +1,38 @@
package com.njcn.gather.systemops.deploy.pojo.vo;
import lombok.Data;
import java.io.Serializable;
/**
* 系统部署基础信息。
*/
@Data
public class DeployOverviewVO implements Serializable {
private static final long serialVersionUID = 5544653311667074541L;
/**
* 菜单名称。
*/
private String menuName;
/**
* 菜单编码。
*/
private String menuCode;
/**
* 菜单路径。
*/
private String path;
/**
* 基础功能状态。
*/
private String status;
/**
* 功能说明。
*/
private String description;
}

View File

@@ -0,0 +1,16 @@
package com.njcn.gather.systemops.deploy.service;
import com.njcn.gather.systemops.deploy.pojo.vo.DeployOverviewVO;
/**
* 系统部署基础服务。
*/
public interface DeployService {
/**
* 查询系统部署基础信息。
*
* @return 系统部署基础信息
*/
DeployOverviewVO overview();
}

View File

@@ -0,0 +1,25 @@
package com.njcn.gather.systemops.deploy.service.impl;
import com.njcn.gather.systemops.deploy.pojo.vo.DeployOverviewVO;
import com.njcn.gather.systemops.deploy.service.DeployService;
import org.springframework.stereotype.Service;
/**
* 系统部署基础服务实现。
*/
@Service
public class DeployServiceImpl implements DeployService {
private static final String STATUS_READY = "READY";
@Override
public DeployOverviewVO overview() {
DeployOverviewVO result = new DeployOverviewVO();
result.setMenuName("系统部署");
result.setMenuCode("deploy");
result.setPath("/systemOps/deploy");
result.setStatus(STATUS_READY);
result.setDescription("系统部署基础入口已接入,后续可在此扩展部署包、环境和执行记录。");
return result;
}
}

21
system-ops/pom.xml Normal file
View File

@@ -0,0 +1,21 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>com.njcn.gather</groupId>
<artifactId>CN_Tool</artifactId>
<version>1.0.0</version>
</parent>
<artifactId>system-ops</artifactId>
<packaging>pom</packaging>
<name>system-ops</name>
<modules>
<module>dbms</module>
<module>deploy</module>
</modules>
</project>