46 Commits

Author SHA1 Message Date
gaoyutao
bd65b27605 优化监控看板、初始化mtr模块 2025-11-17 18:06:37 +08:00
gaoyutao
68e042d9fc 优化告警日志 2025-11-14 18:50:58 +08:00
gaoyutao
1adc72032a 优化执行结果根据失败关键字筛选
优化告警日志
监控看板概览功能
2025-11-14 18:48:27 +08:00
gaoyutao
d9bd70860c 脚本管理页面增加字段、执行结果根据失败关键字筛选
优化菜单点击方法、优化心跳处理
2025-11-13 18:08:05 +08:00
gaoyutao
50d817091e 优化告警日志、消息推送 2025-11-13 13:02:58 +08:00
gaoyutao
2910280746 优化交换机监控策略、交换机管理分页查询 2025-11-13 10:28:17 +08:00
gaoyutao
4da0c86ca4 告警日志、推送消息接口、图形监控排序优化
监控看板相关接口、单点击计数接口开发
2025-11-12 18:05:09 +08:00
gaoyutao
70e943269a 设计消息推送数据表、开发消息推送相关逻辑方法。 2025-11-11 18:03:50 +08:00
gaoyutao
5c3b6df591 优化实时95值计算流量科学计数法、服务器底层流量所有业务网卡流量求和 2025-11-11 10:55:21 +08:00
gaoyutao
80533dc1a3 导出优化、告警日志方法增加 2025-11-10 18:17:59 +08:00
gaoyutao
4137028deb agent更新按最后一次更新时间排序、服务器管理多条件分页查询优化、服务器底层流量科学计数法优化 2025-11-10 12:00:50 +08:00
gaoyutao
4d1503e988 底层bit流量不保留小数、服务器监控策略clientId换行分割 2025-11-07 18:19:51 +08:00
gaoyutao
a5b304c809 补0变为补null、单位最小Kb、服务器在线状态优化 2025-11-07 15:27:37 +08:00
gaoyutao
ce95462d74 监控项详情展示优化 2025-11-07 10:21:44 +08:00
gaoyutao
7190df25f7 挂载点详情优化。 2025-11-06 18:39:41 +08:00
gaoyutao
c4b380437f 优化图形分析根据可选时间补0逻辑、优化流量图形单位可选功能。 2025-11-06 18:09:29 +08:00
gaoyutao
5e5330a924 增加计算服务器平均流量方法、优化95值自动计算方法 2025-11-06 13:47:29 +08:00
gaoyutao
b0868dfe2d 优化常用单位、交换机心跳上报优化、agent更新列表优化 2025-11-05 18:04:06 +08:00
gaoyutao
d0ac03ffbf 优化常用单位、用户自定义列保存优化、业务流量库优化 2025-11-05 14:48:02 +08:00
gaoyutao
e9970b94a9 优化图形分析单位、服务器流量业务表逻辑 2025-11-05 13:02:51 +08:00
gaoyutao
1dc32ec24e 单位换算保留两位小数 2025-11-04 19:27:17 +08:00
gaoyutao
84e003893d 增加计算单位可选方法.
优化图形分析根据可选时间补0逻辑,完成度70%。
优化业务自定义95值计算功能修改相关数据方法。
2025-11-04 19:11:07 +08:00
gaoyutao
fe1763386a 优化95值计算单位、实际流量保留两位小数 2025-11-04 13:46:05 +08:00
gaoyutao
b38cd83ee1 优化心跳监测 2025-11-04 10:31:44 +08:00
gaoyutao
d1db8a5865 增加日志控制、优化金山95值自动计算方法 2025-11-03 18:51:00 +08:00
gaoyutao
841dd84a99 优化交换机心跳监测功能 2025-11-03 14:26:14 +08:00
gaoyutao
07baaf07b0 增加交换机心跳、优化用户自定义列表功能 2025-11-03 13:29:47 +08:00
gaoyutao
01c51b39fe 优化实时95值计算功能、服务器收益功能、用户自定义列展示、交换机基础数据采集 2025-10-31 21:46:17 +08:00
gaoyutao
c0f057d7ed 优化实时95值计算功能、服务器收益功能、用户自定义列展示 2025-10-30 21:20:46 +08:00
gaoyutao
15ecd5caaf 实时95值计算功能、优化服务器收益功能 2025-10-29 18:35:44 +08:00
gaoyutao
8c439013e1 交换机收益图形分析、服务器注册优化 2025-10-28 18:51:08 +08:00
gaoyutao
46bf4c4114 获取最新策略增加路由信息方法、交换机带宽收益 2025-10-27 18:16:47 +08:00
gaoyutao
36362e2236 优化交换机数据采集、脚本策略、agent更新优化、注册增加路由信息 2025-10-24 18:55:21 +08:00
gaoyutao
37eff51e48 服务器注册 agent更新 2025-10-24 09:34:32 +08:00
gaoyutao
31d8114c05 增加agent联调,获取最新策略应答功能 2025-10-22 17:54:46 +08:00
gaoyutao
4fdaadee65 服务器自动注册 2025-10-21 18:28:18 +08:00
gaoyutao
52728eba49 snmp采集工具优化,采集数据入库优化。 2025-10-20 18:17:44 +08:00
gaoyutao
b0e63880fc 服务器注册接口、snmp采集工具优化、其他bug修复 2025-10-17 18:56:32 +08:00
gaoyutao
b3f16d2c8f 交换机监控策略bug修复 2025-10-16 19:05:46 +08:00
gaoyutao
c6937eb44b 交换机监控策略、snmp工具 2025-10-16 18:37:33 +08:00
gaoyutao
3019f65515 服务器注册图形监控监控项接口开发 2025-10-15 18:22:16 +08:00
gaoyutao
87824abb77 拓扑管理字段新增,交换机管理接口优化、网卡信息接口新增 2025-10-14 18:17:31 +08:00
gaoyutao
7da5e19cfa 业务脚本管理、业务下发管理、相关数据分页优化 2025-10-13 18:43:04 +08:00
gaoyutao
054b0f1272 交换机管理,图形监控,策略 2025-10-11 17:54:17 +08:00
gaoyutao
6ffdf8d355 金山云服务API调用并入库,交换机管理功能新增 2025-10-10 18:17:53 +08:00
gaoyutao
7b5c782079 底层流量数据改为bit,测试金山云服务器API,准备1.1分支 2025-10-09 17:38:24 +08:00
330 changed files with 24462 additions and 1938 deletions

View File

@@ -7,9 +7,7 @@ import com.ruoyi.common.core.web.page.TableDataInfo;
import com.ruoyi.system.api.domain.*;
import com.ruoyi.system.api.factory.RemoteRevenueConfigFallbackFactory;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestHeader;
import org.springframework.web.bind.annotation.*;
import java.util.List;
@@ -89,4 +87,50 @@ public interface RemoteRevenueConfigService
@PostMapping("/registration/getListByHardwareSn")
public R<RmResourceRegistrationRemote> getListByHardwareSn(@RequestBody RmResourceRegistrationRemote rmResourceRegistrationRemote, @RequestHeader(SecurityConstants.FROM_SOURCE) String source);
/**
* 根据clientId获取交换机名称信息
* @param rmSwitchManagementRemote
* @param source
* @return
*/
@PostMapping("/switchManagement/getSwitchNameByClientId")
public R<List<RmSwitchManagementRemote>> getSwitchNameByClientId(@RequestBody RmSwitchManagementRemote rmSwitchManagementRemote, @RequestHeader(SecurityConstants.FROM_SOURCE) String source);
/**
* 根据clientId修改交换机在线状态
* @param rmSwitchManagementRemote
* @param source
* @return
*/
@PostMapping("/switchManagement/updateSwitchMsgByClientId")
public R<Integer> updateSwitchMsgByClientId(@RequestBody RmSwitchManagementRemote rmSwitchManagementRemote, @RequestHeader(SecurityConstants.FROM_SOURCE) String source);
/**
* 自动注册
* @param rmRegisterMsgRemote
* @param source
* @return
*/
@PostMapping("/registration/innerAddRegist")
public R<Integer> innerAddRegist(@RequestBody RmRegisterMsgRemote rmRegisterMsgRemote, @RequestHeader(SecurityConstants.FROM_SOURCE) String source);
/**
* 添加节点标识
* @param rmResourceRegistrationRemote
* @param source
* @return
*/
@PostMapping("/registration/innerUpdateRegist")
public R<Integer> innerUpdateRegist(@RequestBody RmResourceRegistrationRemote rmResourceRegistrationRemote, @RequestHeader(SecurityConstants.FROM_SOURCE) String source);
/**
* 获取95值列表
* @param epsNodeBandwidthRemote
* @param source
* @return
*/
@PostMapping("/bandwidth/getEpsNodeBandWidthList")
public R<List<EpsNodeBandwidthRemote>> getEpsNodeBandWidthList(@RequestBody EpsNodeBandwidthRemote epsNodeBandwidthRemote, @RequestHeader(SecurityConstants.FROM_SOURCE) String source);
@GetMapping("/businessScript/inner/{id}")
public R<EpsBusinessScriptRemote> getBusinessScriptMsgByScriptId(@PathVariable("id") Long id, @RequestHeader(SecurityConstants.FROM_SOURCE) String source);
}

View File

@@ -4,6 +4,9 @@ import com.ruoyi.common.core.constant.SecurityConstants;
import com.ruoyi.common.core.constant.ServiceNameConstants;
import com.ruoyi.common.core.domain.R;
import com.ruoyi.system.api.domain.RmAlarmRecordRemote;
import com.ruoyi.system.api.domain.RmDeployScriptRemote;
import com.ruoyi.system.api.domain.RmMonitorPolicyRemote;
import com.ruoyi.system.api.domain.RmNetworkInterfaceRemote;
import com.ruoyi.system.api.factory.RemoteRocketMqFallbackFactory;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.*;
@@ -42,4 +45,57 @@ public interface RemoteRocketMqService {
*/
@GetMapping("/alarmRecord/alarmHandlingStatus")
public R<Map> alarmHandlingStatus(@RequestHeader(SecurityConstants.FROM_SOURCE) String source);
/**
* 获取网卡接口列表
* @param rmNetworkInterfaceRemote
* @param source
* @return
*/
@PostMapping("/networkInterface/getNetworkInterfaceList")
public R<List<RmNetworkInterfaceRemote>> getNetworkInterfaceList(@RequestBody RmNetworkInterfaceRemote rmNetworkInterfaceRemote, @RequestHeader(SecurityConstants.FROM_SOURCE) String source);
/**
* 获取网卡接口列表
* @param rmNetworkInterfaceRemote
* @param source
* @return
*/
@PostMapping("/networkInterface/bindPublicIp")
public R<Integer> bindPublicIp(@RequestBody RmNetworkInterfaceRemote rmNetworkInterfaceRemote, @RequestHeader(SecurityConstants.FROM_SOURCE) String source);
/**
* 下发策略
* @param id
* @param source
* @return
*/
@GetMapping("/monitorPolicy/innerIssueSwitchPolicy")
public R<String> innerIssueSwitchPolicy(Long id, @RequestHeader(SecurityConstants.FROM_SOURCE) String source);
/**
* 查询策略信息
* @param rmMonitorPolicyRemote
* @param source
* @return
*/
@PostMapping("/monitorPolicy/getPolicyMsgInner")
public R<List<RmMonitorPolicyRemote>> getPolicyMsgInner(@RequestBody RmMonitorPolicyRemote rmMonitorPolicyRemote, @RequestHeader(SecurityConstants.FROM_SOURCE) String source);
/**
* 策略添加新设备
* @param rmMonitorPolicyRemote
* @param source
* @return
*/
@PostMapping("/monitorPolicy/updatePolicyMsgInner")
public R<Integer> updatePolicyMsgInner(@RequestBody RmMonitorPolicyRemote rmMonitorPolicyRemote, @RequestHeader(SecurityConstants.FROM_SOURCE) String source);
/**
* 下发优先级为0的策略
* @param clientId
* @param source
* @return
*/
@GetMapping("/monitorPolicy/issueDefaultPolicyByClientId")
public R<Integer> issueDefaultPolicyByClientId(String clientId, @RequestHeader(SecurityConstants.FROM_SOURCE) String source);
@PostMapping("policy/addDeployScript")
R<Integer> addDeployScript(@RequestBody RmDeployScriptRemote addData, @RequestHeader(SecurityConstants.FROM_SOURCE) String source);
}

View File

@@ -0,0 +1,35 @@
package com.ruoyi.system.api.domain;
import com.ruoyi.common.core.annotation.Excel;
import com.ruoyi.common.core.web.domain.BaseEntity;
import lombok.Data;
/**
* 业务脚本管理对象 eps_business_script
*
* @author gyt
* @date 2025-10-13
*/
@Data
public class EpsBusinessScriptRemote extends BaseEntity
{
private static final long serialVersionUID = 1L;
/** 主键ID */
private Long id;
/** 脚本名称 */
@Excel(name = "脚本名称")
private String scriptName;
/** 脚本文件地址 */
@Excel(name = "脚本文件地址")
private String scriptPath;
/** 脚本默认参数 */
@Excel(name = "脚本默认参数")
private String defaultParams;
/** 结果失败判断关键字 */
@Excel(name = "结果失败判断关键字")
private String failedKeywords;
}

View File

@@ -0,0 +1,136 @@
package com.ruoyi.system.api.domain;
import com.fasterxml.jackson.annotation.JsonFormat;
import com.ruoyi.common.core.annotation.Excel;
import com.ruoyi.common.core.web.domain.BaseEntity;
import lombok.Data;
import java.math.BigDecimal;
import java.util.Date;
import java.util.List;
@Data
public class EpsNodeBandwidthRemote extends BaseEntity {
/** id */
private Long id;
/** 节点名称 */
@Excel(name = "节点名称")
private String nodeName;
/** 硬件SN */
@Excel(name = "硬件SN")
private String hardwareSn;
/** 带宽值类型
* 1-95带宽值Mbps/日
* 2-95带宽值Mbps/月
* 3-包端带宽值Mbps/日
* 4-月均日95值Mbps
* 5-有效-95带宽值Mbps/日
* 6-有效-95带宽值Mbps/月
* 7-有效-月均日95值
* */
private String bandwidthType;
/** 带宽值结果 */
private BigDecimal bandwidthResult;
/** 95带宽值Mbps/日 */
@Excel(name = "95带宽值Mbps/日")
private BigDecimal bandwidth95Daily;
/** 95带宽值Mbps/月 */
@Excel(name = "95带宽值Mbps/月")
private BigDecimal bandwidth95Monthly;
/** 月均日95值 */
@Excel(name = "月均日95值")
private BigDecimal avgMonthlyBandwidth95;
/** 包端带宽值Mbps/日 */
@Excel(name = "包端带宽值Mbps/日")
private BigDecimal packageBandwidthDaily;
/** 有效-95带宽值Mbps/日 */
@Excel(name = "有效-95带宽值Mbps/日")
private BigDecimal effectiveBandwidth95Daily;
/** 有效-95带宽值Mbps/月 */
@Excel(name = "有效-95带宽值Mbps/月")
private BigDecimal effectiveBandwidth95Monthly;
/** 有效-月均95值 */
@Excel(name = "有效-月均95值")
private BigDecimal effectiveAvgMonthlyBandwidth95;
/** 金山流量Mbps/日 */
private BigDecimal machineFlow;
/** 设备业务客户id */
@Excel(name = "设备业务客户id")
private String customerId;
/** 设备业务客户名称 */
@Excel(name = "设备业务客户名称")
private String customerName;
/** 业务号 */
@Excel(name = "业务号")
private String serviceNumber;
/** 上联交换机 */
@Excel(name = "上联交换机")
private String uplinkSwitch;
/** 创建人id */
@Excel(name = "创建人id")
private Long creatorId;
/** 创建人名称 */
@Excel(name = "创建人名称")
private String creatorName;
/** 交换机sn */
@Excel(name = "交换机sn")
private String switchSn;
/** 接口名称 */
@Excel(name = "接口名称")
private String interfaceName;
/** 资源类型(1服务器,2交换机) */
@Excel(name = "资源类型")
private String resourceType;
/** 接口连接设备类型(1服务器2机房出口) */
@Excel(name = "接口连接设备类型")
private String interfaceLinkDeviceType;
/** 业务名称 */
@Excel(name = "业务名称")
private String businessName;
/** 业务代码 */
@Excel(name = "业务代码")
private String businessId;
/** 创建时间 */
@JsonFormat(pattern = "yyyy-MM-dd")
private Date createTime;
/** 开始时间 */
private String startTime;
/** 结束时间 */
private String endTime;
/** 月份 */
private String monthTime;
/** 备注 */
private String remark1;
/** 创建时间 */
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
private Date createDatetime;
private List<String> nodeNames;
private List<String> switchNames;
/** 计算方式 */
private String calculationMode;
/** 客户端id */
private String clientId;
}

View File

@@ -0,0 +1,34 @@
package com.ruoyi.system.api.domain;
import com.fasterxml.jackson.annotation.JsonProperty;
import lombok.Data;
@Data
public class NetworkInfo {
// 运营商
@JsonProperty("carrier")
private String carrier;
// 市
@JsonProperty("city")
private String city;
// 网关
@JsonProperty("gateway")
private String gateway;
// IPv4 地址
@JsonProperty("ipv4")
private String ipv4;
// MAC 地址
@JsonProperty("mac")
private String mac;
// 接口名称eth0, enp3s0
@JsonProperty("name")
private String name;
// 省
@JsonProperty("province")
private String province;
// 公网 IP
@JsonProperty("publicIp")
private String publicIp;
@JsonProperty("type")
private String type;
}

View File

@@ -0,0 +1,84 @@
package com.ruoyi.system.api.domain;
import com.fasterxml.jackson.annotation.JsonFormat;
import com.ruoyi.common.core.annotation.Excel;
import lombok.Data;
import java.util.Date;
@Data
public class RmDeployScriptRemote {
/** 策略ID */
private Long id;
/** 策略名称 */
@Excel(name = "策略名称")
private String policyName;
/** 策略描述 */
@Excel(name = "策略描述")
private String description;
/** 关联资源组ID */
@Excel(name = "关联资源组ID")
private Long resourceGroupId;
/** 包含的设备ID列表逗号分隔 */
private String includedDevicesId;
/** 包含设备 */
@Excel(name = "包含设备")
private String includedDevicesName;
/** 源文件地址格式 */
@Excel(name = "源文件地址格式")
private String sourceFilePathType;
/** 源文件路径 */
@Excel(name = "源文件路径")
private String sourceFilePath;
/** 目标目录 */
@Excel(name = "目标目录")
private String targetDirectory;
/** 命令执行内容 */
@Excel(name = "命令执行内容")
private String commandContent;
/** 0=立即执行,1=定时执行 */
@Excel(name = "执行方式", readConverterExp = "0=立即执行,1=定时执行")
private Integer executionMethod;
/** 定时执行时间 */
@Excel(name = "定时执行时间")
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
private Date scheduledTime;
/** 定时执行时间(时间戳秒) */
private Long policyTime;
/** 策略状态0-未下发1-已下发 */
@Excel(name = "策略状态0-未下发1-已下发")
private String policyStatus;
/** 策略下发时间 */
@JsonFormat(pattern = "yyyy-MM-dd")
@Excel(name = "策略下发时间", width = 30, dateFormat = "yyyy-MM-dd")
private Date deployTime;
/** 脚本类型 */
@Excel(name = "脚本类型")
private String scriptType;
/** 资源组名称 */
private String resourceGroupName;
/** 资源组置空 */
private Boolean resourceGroupIdNull;
/** 部署设备 */
private String deployDevice;
/** 业务脚本名称 */
private String scriptName;
/** 业务脚本文件地址 */
private String scriptPath;
/** 业务脚本参数 */
private String defaultParams;
/** 业务下发名称 */
private String taskName;
}

View File

@@ -0,0 +1,61 @@
package com.ruoyi.system.api.domain;
import com.fasterxml.jackson.annotation.JsonFormat;
import com.ruoyi.common.core.annotation.Excel;
import com.ruoyi.common.core.web.domain.BaseEntity;
import lombok.Data;
import java.util.Date;
@Data
public class RmMonitorPolicyRemote extends BaseEntity {
/** 主键ID */
private Long id;
/** 策略名称 */
@Excel(name = "策略名称")
private String policyName;
/** 描述 */
@Excel(name = "描述")
private String description;
/** 资源组ID */
private Long resourceGroupId;
/** 资源组名称 */
@Excel(name = "关联资源组")
private String resourceGroupName;
/** 模板ID */
private Long templateId;
/** 模板名称 */
@Excel(name = "关联监控模板")
private String templateName;
/** 状态0-待下发1-已下发 */
@Excel(name = "策略状态", readConverterExp = "0=待下发,1=已下发")
private String status;
/** 下发策略时间 */
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
@Excel(name = "下发策略时间", width = 30, dateFormat = "yyyy-MM-dd HH:mm:ss")
private Date deployTime;
/** 资源类型linux switch */
private String resourceType;
/** 查询条件名称 */
private String queryName;
/** 创建时间 */
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
@Excel(name = "创建时间")
private Date createTime;
/** 修改时间 */
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
@Excel(name = "修改时间")
private Date updateTime;
/** 交换机类型 */
private String switchType;
/** 部署设备 */
private String deployDevice;
/** 优先级 */
private String priority;
}

View File

@@ -0,0 +1,55 @@
package com.ruoyi.system.api.domain;
import com.ruoyi.common.core.annotation.Excel;
import com.ruoyi.common.core.web.domain.BaseEntity;
import lombok.Data;
@Data
public class RmNetworkInterfaceRemote extends BaseEntity {
/** 主键ID */
private Long id;
/** 客户端ID */
@Excel(name = "客户端ID")
private String clientId;
/** 运营商 */
@Excel(name = "运营商")
private String isp;
/** 省 */
@Excel(name = "")
private String province;
/** 市 */
@Excel(name = "")
private String city;
/** 公网IP */
@Excel(name = "公网IP")
private String publicIp;
/** 接口名称 */
@Excel(name = "接口名称")
private String interfaceName;
/** MAC地址 */
@Excel(name = "MAC地址")
private String macAddress;
/** 接口类型 */
@Excel(name = "接口类型")
private String interfaceType;
/** IPv4地址 */
@Excel(name = "IPv4地址")
private String ipv4Address;
/** 网关 */
@Excel(name = "网关")
private String gateway;
/** 绑定ip 1业务IP2管理ip */
private String bindIp;
/** 新旧标识 */
private Integer newFlag;
}

View File

@@ -0,0 +1,23 @@
package com.ruoyi.system.api.domain;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.fasterxml.jackson.annotation.JsonProperty;
import lombok.Data;
import java.util.List;
@Data
@JsonIgnoreProperties(ignoreUnknown = true)
public class RmRegisterMsgRemote {
@JsonProperty("clientId")
private String clientId;
@JsonProperty("sn")
private String sn;
@JsonProperty("networkInfo")
private List<NetworkInfo> networkInfo;
@JsonProperty("timestamp")
private long timestamp;
}

View File

@@ -1,9 +1,12 @@
package com.ruoyi.system.api.domain;
import com.fasterxml.jackson.annotation.JsonFormat;
import com.ruoyi.common.core.annotation.Excel;
import com.ruoyi.common.core.web.domain.BaseEntity;
import lombok.Data;
import java.util.Date;
/**
* 资源注册对象 rm_resource_registration
*
@@ -127,5 +130,53 @@ public class RmResourceRegistrationRemote extends BaseEntity
private String monitorItems;
/** 自动发现项 */
private String discoveryRules;
/**
* 客户端ID
*/
private String clientId;
/**
* 运营商
*/
private String operator;
/**
* 省
*/
private String province;
/**
* 公网IP
*/
private String publicIp;
/**
* 业务名称
*/
private String businessName;
/**
* 逻辑节点标识
*/
private String logicalNodeId;
/**
* 多公网IP状态
*/
private String multiPublicIpStatus;
/**
* 心跳次数
*/
private Integer heartbeatCount;
/**
* 心跳周期(单位:秒)
*/
private Integer heartbeatInterval;
/** 上机时间 */
@Excel(name = "上机时间")
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
private Date onboardTime;
}

View File

@@ -0,0 +1,74 @@
package com.ruoyi.system.api.domain;
import com.ruoyi.common.core.annotation.Excel;
import lombok.Data;
import java.util.Date;
@Data
public class RmSwitchManagementRemote {
/** 主键ID */
private Long id;
/** 交换机名称 */
@Excel(name = "交换机名称")
private String switchName;
/** 硬件SN序列号 */
@Excel(name = "硬件SN序列号")
private String hardwareSn;
/** SNMP采集地址 */
@Excel(name = "SNMP采集地址")
private String snmpAddress;
/** SNMP采集端口 */
@Excel(name = "SNMP采集端口")
private Long snmpPort;
/** 在线状态(0-离线,1-在线) */
@Excel(name = "在线状态(0-离线,1-在线)")
private String onlineStatus;
/** 上机时间 */
private Date upTime;
/** 心跳监测次数 */
@Excel(name = "心跳监测次数")
private String heartbeatCount;
/** 心跳监测周期(秒) */
@Excel(name = "心跳监测周期(秒)")
private String heartbeatInterval;
/** 心跳检测OID */
@Excel(name = "心跳检测OID")
private String heartbeatOid;
/** SNMP版本(v1/v2c/v3) */
@Excel(name = "SNMP版本(v1/v2c/v3)")
private String snmpVersion;
/** 读写权限 */
@Excel(name = "读写权限")
private String readWritePermission;
/** 安全级别 */
@Excel(name = "安全级别")
private String securityLevel;
/** 加密方式 */
@Excel(name = "加密方式")
private String encryptionMethod;
/** 团体名称 */
@Excel(name = "团体名称")
private String communityName;
/** 密码 */
@Excel(name = "密码")
private String switchPassword;
/** 交换机类型 */
private String switchType;
/** 用户名 */
private String switchUser;
/** 自动生成客户端id(uuid) */
private String clientId;
}

View File

@@ -0,0 +1,12 @@
package com.ruoyi.system.api.domain;
import lombok.Data;
@Data
public class RouteMsg {
/** 网卡名称 */
private String name;
/** 网关地址 */
private String gateway;
}

View File

@@ -59,12 +59,42 @@ public class RemoteRevenueConfigFallbackFactory implements FallbackFactory<Remot
@Override
public R<TableDataInfo> getRegistrationList(RmResourceRegistrationRemote rmResourceRegistrationRemote, String source) {
return R.fail("获取资源注册列表信息失败" + throwable.getMessage());
return R.fail("获取资源注册列表信息失败" + throwable.getMessage());
}
@Override
public R<RmResourceRegistrationRemote> getListByHardwareSn(RmResourceRegistrationRemote rmResourceRegistrationRemote, String source) {
return R.fail("根据SN获取资源注册列表信息失败" + throwable.getMessage());
return R.fail("根据SN获取资源注册列表信息失败" + throwable.getMessage());
}
@Override
public R<List<RmSwitchManagementRemote>> getSwitchNameByClientId(RmSwitchManagementRemote rmSwitchManagementRemote, String source) {
return R.fail("根据clientId获取交换机信息失败" + throwable.getMessage());
}
@Override
public R<Integer> updateSwitchMsgByClientId(RmSwitchManagementRemote rmSwitchManagementRemote, String source) {
return R.fail("根据clientId修改交换机信息失败" + throwable.getMessage());
}
@Override
public R<Integer> innerAddRegist(RmRegisterMsgRemote rmRegisterMsgRemote, String source) {
return R.fail("自动注册失败:" + throwable.getMessage());
}
@Override
public R<Integer> innerUpdateRegist(RmResourceRegistrationRemote rmResourceRegistrationRemote, String source) {
return R.fail("修改服务器注册信息失败:" + throwable.getMessage());
}
@Override
public R<List<EpsNodeBandwidthRemote>> getEpsNodeBandWidthList(EpsNodeBandwidthRemote epsNodeBandwidthRemote, String source) {
return R.fail("获取95值列表失败" + throwable.getMessage());
}
@Override
public R<EpsBusinessScriptRemote> getBusinessScriptMsgByScriptId(Long id, String source) {
return R.fail("获取错误关键词失败:" + throwable.getMessage());
}
};
}

View File

@@ -3,6 +3,9 @@ package com.ruoyi.system.api.factory;
import com.ruoyi.common.core.domain.R;
import com.ruoyi.system.api.RemoteRocketMqService;
import com.ruoyi.system.api.domain.RmAlarmRecordRemote;
import com.ruoyi.system.api.domain.RmDeployScriptRemote;
import com.ruoyi.system.api.domain.RmMonitorPolicyRemote;
import com.ruoyi.system.api.domain.RmNetworkInterfaceRemote;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.cloud.openfeign.FallbackFactory;
@@ -45,6 +48,41 @@ public class RemoteRocketMqFallbackFactory implements FallbackFactory<RemoteRock
public R<Map> alarmHandlingStatus(String source) {
return R.fail(throwable.getMessage());
}
@Override
public R<List<RmNetworkInterfaceRemote>> getNetworkInterfaceList(RmNetworkInterfaceRemote rmNetworkInterfaceRemote, String source) {
return R.fail(throwable.getMessage());
}
@Override
public R<Integer> bindPublicIp(RmNetworkInterfaceRemote rmNetworkInterfaceRemote, String source) {
return R.fail(throwable.getMessage());
}
@Override
public R<String> innerIssueSwitchPolicy(Long id, String source) {
return R.fail(throwable.getMessage());
}
@Override
public R<List<RmMonitorPolicyRemote>> getPolicyMsgInner(RmMonitorPolicyRemote rmMonitorPolicyRemote, String source) {
return R.fail(throwable.getMessage());
}
@Override
public R<Integer> updatePolicyMsgInner(RmMonitorPolicyRemote rmMonitorPolicyRemote, String source) {
return R.fail(throwable.getMessage());
}
@Override
public R<Integer> issueDefaultPolicyByClientId(String clientId, String source) {
return R.fail(throwable.getMessage());
}
@Override
public R<Integer> addDeployScript(RmDeployScriptRemote addData, String source) {
return R.fail(throwable.getMessage());
}
};
}
}

View File

@@ -13,6 +13,12 @@ import lombok.NoArgsConstructor;
@NoArgsConstructor
public enum MsgEnum {
多公网IP探测("NETWORK_DETECT"),
获取最新策略("GET_POLICY"),
获取最新策略应答("GET_POLICY_RSP"),
注册("REGISTER"),
注册应答("REGISTER_RSP"),

View File

@@ -0,0 +1,240 @@
package com.ruoyi.common.core.utils;
public class ConvertOtherTypeUtil {
/**
* 根据接口类型代码获取对应的类型名称
* @param typeCode 接口类型代码 (1, 2, 3...)
* @return 接口类型名称,如果未找到返回 "unknown"
*/
public static String getInterfaceTypeName(int typeCode) {
switch (typeCode) {
case 1: return "other";
case 2: return "regular1822";
case 3: return "hdh1822";
case 4: return "ddnX25";
case 5: return "rfc877x25";
case 6: return "ethernetCsmacd";
case 7: return "iso88023Csmacd";
case 8: return "iso88024TokenBus";
case 9: return "iso88025TokenRing";
case 10: return "iso88026Man";
case 11: return "starLan";
case 12: return "proteon10Mbit";
case 13: return "proteon80Mbit";
case 14: return "hyperchannel";
case 15: return "fddi";
case 16: return "lapb";
case 17: return "sdlc";
case 18: return "ds1";
case 19: return "e1";
case 20: return "basicISDN";
case 21: return "primaryISDN";
case 22: return "propPointToPointSerial";
case 23: return "ppp";
case 24: return "softwareLoopback";
case 25: return "eon";
case 26: return "ethernet3Mbit";
case 27: return "nsip";
case 28: return "slip";
case 29: return "ultra";
case 30: return "ds3";
case 31: return "sip";
case 32: return "frameRelay";
case 33: return "rs232";
case 34: return "para";
case 35: return "arcnet";
case 36: return "arcnetPlus";
case 37: return "atm";
case 38: return "miox25";
case 39: return "sonet";
case 40: return "x25ple";
case 41: return "iso88022llc";
case 42: return "localTalk";
case 43: return "smdsDxi";
case 44: return "frameRelayService";
case 45: return "v35";
case 46: return "hssi";
case 47: return "hippi";
case 48: return "modem";
case 49: return "aal5";
case 50: return "sonetPath";
case 51: return "sonetVT";
case 52: return "smdsIcip";
case 53: return "propVirtual";
case 54: return "propMultiplexor";
case 55: return "ieee80212";
case 56: return "fibreChannel";
case 57: return "hippiInterface";
case 58: return "frameRelayInterconnect";
case 59: return "aflane8023";
case 60: return "aflane8025";
case 61: return "cctEmul";
case 62: return "fastEther";
case 63: return "isdn";
case 64: return "v11";
case 65: return "v36";
case 66: return "g703at64k";
case 67: return "g703at2mb";
case 68: return "qllc";
case 69: return "fastEtherFX";
case 70: return "channel";
case 71: return "ieee80211";
case 72: return "ibm370parChan";
case 73: return "escon";
case 74: return "dlsw";
case 75: return "isdns";
case 76: return "isdnu";
case 77: return "lapd";
case 78: return "ipSwitch";
case 79: return "rsrb";
case 80: return "atmLogical";
case 81: return "ds0";
case 82: return "ds0Bundle";
case 83: return "bsc";
case 84: return "async";
case 85: return "cnr";
case 86: return "iso88025Dtr";
case 87: return "eplrs";
case 88: return "arap";
case 89: return "propCnls";
case 90: return "hostPad";
case 91: return "termPad";
case 92: return "frameRelayMPI";
case 93: return "x213";
case 94: return "adsl";
case 95: return "radsl";
case 96: return "sdsl";
case 97: return "vdsl";
case 98: return "iso88025CRFPInt";
case 99: return "myrinet";
case 100: return "voiceEM";
case 101: return "voiceFXO";
case 102: return "voiceFXS";
case 103: return "voiceEncap";
case 104: return "voiceOverIp";
case 105: return "atmDxi";
case 106: return "atmFuni";
case 107: return "atmIma";
case 108: return "pppMultilinkBundle";
case 109: return "ipOverCdlc";
case 110: return "ipOverClaw";
case 111: return "stackToStack";
case 112: return "virtualIpAddress";
case 113: return "mpc";
case 114: return "ipOverAtm";
case 115: return "iso88025Fiber";
case 116: return "tdlc";
case 117: return "gigabitEthernet";
case 118: return "hdlc";
case 119: return "lapf";
case 120: return "v37";
case 121: return "x25mlp";
case 122: return "x25huntGroup";
case 123: return "trasnpHdlc";
case 124: return "interleave";
case 125: return "fast";
case 126: return "ip";
case 127: return "docsCableMaclayer";
case 128: return "docsCableDownstream";
case 129: return "docsCableUpstream";
case 130: return "a12MppSwitch";
case 131: return "tunnel";
case 132: return "coffee";
case 133: return "ces";
case 134: return "atmSubInterface";
case 135: return "l2vlan";
case 136: return "l3ipvlan";
case 137: return "l3ipxvlan";
case 138: return "digitalPowerline";
case 139: return "mediaMailOverIp";
case 140: return "dtm";
case 141: return "dcn";
case 142: return "ipForward";
case 143: return "msdsl";
case 144: return "ieee1394";
case 145: return "if-gsn";
case 146: return "dvbRccMacLayer";
case 147: return "dvbRccDownstream";
case 148: return "dvbRccUpstream";
case 149: return "atmVirtual";
case 150: return "mplsTunnel";
case 151: return "srp";
case 152: return "voiceOverAtm";
case 153: return "voiceOverFrameRelay";
case 154: return "idsl";
case 155: return "compositeLink";
case 156: return "ss7SigLink";
case 157: return "propWirelessP2P";
case 158: return "frForward";
case 159: return "rfc1483";
case 160: return "usb";
case 161: return "ieee8023adLag";
case 162: return "bgppolicyaccounting";
case 163: return "frf16MfrBundle";
case 164: return "h323Gatekeeper";
case 165: return "h323Proxy";
case 166: return "mpls";
case 167: return "mfSigLink";
case 168: return "hdsl2";
case 169: return "shdsl";
case 170: return "ds1FDL";
case 171: return "pos";
case 172: return "dvbAsiIn";
case 173: return "dvbAsiOut";
case 174: return "plc";
case 175: return "nfas";
case 176: return "tr008";
case 177: return "gr303RDT";
case 178: return "gr303IDT";
case 179: return "isup";
case 180: return "propDocsWirelessMaclayer";
case 181: return "propDocsWirelessDownstream";
case 182: return "propDocsWirelessUpstream";
case 183: return "hiperlan2";
case 184: return "propBWAp2Mp";
case 185: return "sonetOverheadChannel";
case 186: return "digitalWrapperOverheadChannel";
case 187: return "aal2";
case 188: return "radioMAC";
case 189: return "atmRadio";
case 190: return "imt";
case 191: return "mvl";
case 192: return "reachDSL";
case 193: return "frDlciEndPt";
case 194: return "atmVciEndPt";
case 195: return "opticalChannel";
case 196: return "opticalTransport";
case 197: return "propAtm";
case 198: return "voiceOverCable";
case 199: return "infiniband";
case 200: return "teLink";
case 201: return "q2931";
case 202: return "virtualTg";
case 203: return "sipTg";
case 204: return "sipSig";
case 205: return "docsCableUpstreamChannel";
case 206: return "econet";
case 207: return "pon155";
case 208: return "pon622";
case 209: return "bridge";
case 210: return "linegroup";
case 211: return "voiceEMFGD";
case 212: return "voiceFGDEANA";
case 213: return "voiceDID";
case 214: return "mpegTransport";
case 215: return "sixToFour";
case 216: return "gtp";
case 217: return "pdnEtherLoop1";
case 218: return "pdnEtherLoop2";
case 219: return "opticalChannelGroup";
case 220: return "homepna";
case 221: return "gfp";
case 222: return "ciscoISLvlan";
case 223: return "actelisMetaLOOP";
case 224: return "fcipLink";
case 225: return "rpr";
case 226: return "qam";
default: return "unknown";
}
}
}

View File

@@ -0,0 +1,416 @@
package com.ruoyi.common.core.utils;
import java.math.BigDecimal;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;
public class EchartsDataUtils {
/**
* 构建ECharts图表数据
* @param list 原始数据列表
* @param timeExtractor 时间字段提取函数
* @param dataExtractors 数据提取器Map (key: 数据名称, value: 数据提取函数)
* @param <T> 数据类型泛型
* @return 包含xData和yData的Map
*/
public static <T> Map<String, Object> buildEchartsData(
List<T> list,
Function<T, Date> timeExtractor,
Map<String, Function<T, ?>> dataExtractors) {
// 按时间排序
List<T> sortedList = list.stream()
.sorted(Comparator.comparing(timeExtractor))
.collect(Collectors.toList());
// 准备X轴数据
List<String> xAxisData = sortedList.stream()
.map(item -> DateUtils.parseDateToStr("yyyy-MM-dd HH:mm:ss", timeExtractor.apply(item)))
.collect(Collectors.toList());
// 准备Y轴数据
Map<String, Object> yData = new LinkedHashMap<>();
dataExtractors.forEach((name, extractor) -> {
yData.put(name, sortedList.stream().map(extractor).collect(Collectors.toList()));
});
// 构建返回结果
Map<String, Object> result = new HashMap<>();
result.put("xData", xAxisData);
result.put("yData", yData);
return result;
}
/**
* 微秒转秒
*/
public static double convertMicrosecondsToSeconds(long microseconds) {
return Math.round(microseconds / 1_000_000.0 * 100.0) / 100.0;
}
/**
* 构建ECharts图表数据带时间补全和特殊值处理
* @param list 原始数据列表
* @param timeExtractor 时间字段提取函数
* @param dataExtractors 数据提取器Map
* @param startTime 开始时间字符串格式yyyy-MM-dd HH:mm:ss
* @param endTime 结束时间字符串格式yyyy-MM-dd HH:mm:ss
* @param <T> 数据类型泛型
* @return 包含xData和yData的Map
*/
public static <T> Map<String, Object> buildEchartsDataAutoPadding(
List<T> list,
Function<T, Date> timeExtractor,
Map<String, Function<T, ?>> dataExtractors,
String startTime,
String endTime) {
try {
// 解析时间字符串
Date startDate = parseStringToDate(startTime);
Date endDate = parseStringToDate(endTime);
if (startDate == null || endDate == null) {
throw new IllegalArgumentException("开始时间或结束时间格式错误");
}
if (startDate.after(endDate)) {
throw new IllegalArgumentException("开始时间不能晚于结束时间");
}
if (list == null || list.isEmpty()) {
return createEmptyResult(dataExtractors.keySet(), startTime, endTime);
}
// 按时间排序
List<T> sortedList = list.stream()
.sorted(Comparator.comparing(timeExtractor))
.collect(Collectors.toList());
// 自动检测时间间隔
long timeInterval = detectTimeInterval(sortedList, timeExtractor);
// 生成完整的时间序列
List<Date> fullTimeSeries = generateTimeSeries(startDate, endDate, timeInterval);
// 创建时间到数据的映射(考虑时间精度)
Map<Long, T> timeDataMap = sortedList.stream()
.collect(Collectors.toMap(
item -> normalizeTime(timeExtractor.apply(item), timeInterval),
Function.identity(),
(a, b) -> a
));
// 准备X轴和Y轴数据
List<String> xAxisData = new ArrayList<>();
Map<String, Object> yData = new LinkedHashMap<>();
// 初始化Y轴数据结构
dataExtractors.keySet().forEach(name ->
yData.put(name, new ArrayList<>()));
// 特殊处理查找percentile95的固定值
Object fixedPercentile95Value = findFixedValueForPercentile95(sortedList, dataExtractors);
// 检测整个数据集中是否有真实数据
boolean hasRealData = checkHasRealData(sortedList, dataExtractors);
// 记录当前处理的时间点索引
int timeIndex = 0;
for (Date time : fullTimeSeries) {
// X轴数据
xAxisData.add(parseDateToStr(time));
// Y轴数据
Long normalizedTime = normalizeTime(time, timeInterval);
T item = timeDataMap.get(normalizedTime);
for (Map.Entry<String, Function<T, ?>> entry : dataExtractors.entrySet()) {
String name = entry.getKey();
Function<T, ?> extractor = entry.getValue();
@SuppressWarnings("unchecked")
List<Object> seriesData = (List<Object>) yData.get(name);
if (item != null) {
Object value = extractor.apply(item);
seriesData.add(value != null ? value : getDefaultValue(name, fixedPercentile95Value, timeIndex, hasRealData));
} else {
// 智能数据补全
seriesData.add(getDefaultValue(name, fixedPercentile95Value, timeIndex, hasRealData));
}
}
timeIndex++;
}
Map<String, Object> result = new HashMap<>();
result.put("xData", xAxisData);
result.put("yData", yData);
return result;
} catch (Exception e) {
// 记录日志
System.err.println("构建图表数据失败: " + e.getMessage());
return createEmptyResult(dataExtractors.keySet(), startTime, endTime);
}
}
/**
* 检测整个数据集中是否有真实数据非null
*/
private static <T> boolean checkHasRealData(List<T> list, Map<String, Function<T, ?>> dataExtractors) {
for (T item : list) {
for (Map.Entry<String, Function<T, ?>> entry : dataExtractors.entrySet()) {
String name = entry.getKey();
Function<T, ?> extractor = entry.getValue();
Object value = extractor.apply(item);
if (value != null) {
return true; // 发现至少一个真实数据
}
}
}
return false; // 没有发现任何真实数据
}
/**
* 判断值是否为0支持多种数值类型
*/
private static boolean isZeroValue(Object value) {
if (value == null) return true;
if (value instanceof Number) {
return ((Number) value).doubleValue() == 0.0;
}
if (value instanceof BigDecimal) {
return ((BigDecimal) value).compareTo(BigDecimal.ZERO) == 0;
}
if (value instanceof String) {
try {
return new BigDecimal(value.toString()).compareTo(BigDecimal.ZERO) == 0;
} catch (Exception e) {
return false;
}
}
return false;
}
/**
* 智能获取默认值
* 策略:
* 1. 如果整个数据集有真实数据所有缺失点都补null
* 2. 如果整个数据集没有真实数据第一个点补0其他点补null
* 3. percentile95特殊处理使用固定值
*/
private static Object getDefaultValue(String metricName, Object fixedPercentile95Value,
int timeIndex, boolean hasRealData) {
// percentile95特殊处理
if ("percentile95".equals(metricName) && !fixedPercentile95Value.equals(0)) {
return fixedPercentile95Value;
}
// deployDevice特殊处理
if ("deployDevice".equals(metricName)) {
return fixedPercentile95Value;
}
// 智能补全策略
if (hasRealData) {
// 数据集中有真实数据所有缺失点都补null
return null;
} else {
// 数据集中没有真实数据第一个点补0其他点补null
if (timeIndex == 0) {
return 0;
} else {
return null;
}
}
}
/**
* 创建空结果(智能补全策略)
*/
private static Map<String, Object> createEmptyResult(Set<String> dataNames, String startTime, String endTime) {
Map<String, Object> result = new HashMap<>();
try {
// 解析时间范围
Date startDate = parseStringToDate(startTime);
Date endDate = parseStringToDate(endTime);
if (startDate != null && endDate != null && !startDate.after(endDate)) {
// 使用默认时间间隔生成完整时间序列
long defaultInterval = 300000L; // 5分钟
List<Date> fullTimeSeries = generateTimeSeries(startDate, endDate, defaultInterval);
// 构建x轴数据
List<String> xAxisData = new ArrayList<>();
for (Date date : fullTimeSeries) {
xAxisData.add(parseDateToStr(date));
}
result.put("xData", xAxisData);
// 构建y轴数据空数据集第一个点补0其他点补null
Map<String, Object> yData = new LinkedHashMap<>();
int dataSize = xAxisData.size();
dataNames.forEach(name -> {
List<Object> seriesData = new ArrayList<>();
for (int i = 0; i < dataSize; i++) {
// deployDevice特殊处理始终补空字符串
if ("deployDevice".equals(name)) {
seriesData.add("");
}
else if (i == 0) {
// 第一个点补0
seriesData.add(0);
} else {
// 其他点补null
seriesData.add(null);
}
}
yData.put(name, seriesData);
});
result.put("yData", yData);
} else {
// 时间解析失败时返回空数据
result.put("xData", new ArrayList<>());
Map<String, Object> yData = new LinkedHashMap<>();
dataNames.forEach(name -> yData.put(name, new ArrayList<>()));
result.put("yData", yData);
}
} catch (Exception e) {
// 异常时返回空数据
result.put("xData", new ArrayList<>());
Map<String, Object> yData = new LinkedHashMap<>();
dataNames.forEach(name -> yData.put(name, new ArrayList<>()));
result.put("yData", yData);
}
return result;
}
/**
* 查找特殊字段的固定值
* percentile95: 第一个非零值
* deployDevice: 第一个非空值,没值填充空字符串
*/
private static <T> Object findFixedValueForPercentile95(List<T> list, Map<String, Function<T, ?>> dataExtractors) {
// 处理percentile95字段
if (dataExtractors.containsKey("percentile95")) {
Function<T, ?> extractor = dataExtractors.get("percentile95");
for (T item : list) {
Object value = extractor.apply(item);
if (value != null && !isZeroValue(value)) {
return value;
}
}
}
// 处理deployDevice字段
if (dataExtractors.containsKey("deployDevice")) {
Function<T, ?> extractor = dataExtractors.get("deployDevice");
for (T item : list) {
Object value = extractor.apply(item);
if (value != null) {
return value;
}
}
return ""; // deployDevice没值返回空字符串
}
return 0; // 默认返回0
}
/**
* 字符串转日期
*/
private static Date parseStringToDate(String dateStr) {
if (dateStr == null || dateStr.trim().isEmpty()) {
return null;
}
try {
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
sdf.setLenient(false); // 严格模式
return sdf.parse(dateStr);
} catch (ParseException e) {
System.err.println("日期解析失败: " + dateStr);
return null;
}
}
/**
* 日期转字符串
*/
private static String parseDateToStr(Date date) {
if (date == null) {
return "";
}
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
return sdf.format(date);
}
/**
* 生成完整的时间序列
*/
private static List<Date> generateTimeSeries(Date start, Date end, long interval) {
List<Date> timeSeries = new ArrayList<>();
Calendar calendar = Calendar.getInstance();
calendar.setTime(start);
// 确保开始时间对齐到时间间隔
long startMillis = normalizeTime(start, interval);
calendar.setTimeInMillis(startMillis);
while (!calendar.getTime().after(end)) {
timeSeries.add(calendar.getTime());
calendar.setTimeInMillis(calendar.getTimeInMillis() + interval);
}
return timeSeries;
}
/**
* 自动检测时间间隔
*/
private static <T> long detectTimeInterval(List<T> list, Function<T, Date> timeExtractor) {
if (list.size() < 2) {
return 300000; // 默认5分钟
}
// 计算时间间隔的众数
Map<Long, Integer> intervalCount = new HashMap<>();
for (int i = 1; i < list.size(); i++) {
long interval = timeExtractor.apply(list.get(i)).getTime() -
timeExtractor.apply(list.get(i - 1)).getTime();
if (interval > 0) {
intervalCount.merge(interval, 1, Integer::sum);
}
}
// 如果没有有效间隔,使用默认值
if (intervalCount.isEmpty()) {
return 300000L;
}
return intervalCount.entrySet().stream()
.max(Map.Entry.comparingByValue())
.map(Map.Entry::getKey)
.orElse(300000L);
}
/**
* 时间标准化(对齐到时间间隔)
*/
private static long normalizeTime(Date time, long interval) {
long timeMillis = time.getTime();
return (timeMillis / interval) * interval;
}
}

View File

@@ -0,0 +1,387 @@
package com.ruoyi.common.core.utils;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.List;
public class SpeedUtils {
public static class SpeedResult {
private BigDecimal avgInSpeedGb; // 平均输入速度 (Gb)
private BigDecimal avgOutSpeedGb; // 平均输出速度 (Gb)
private BigDecimal maxInSpeedGb; // 最大输入速度 (Gb)
private BigDecimal maxOutSpeedGb; // 最大输出速度 (Gb)
private BigDecimal lastInSpeedGb; // 最后一个输入速度 (Gb)
private BigDecimal lastOutSpeedGb;// 最后一个输出速度 (Gb)
private String recommendedUnit; // 基于平均值推荐的单位
public SpeedResult(BigDecimal avgInSpeedGb, BigDecimal avgOutSpeedGb,
BigDecimal maxInSpeedGb, BigDecimal maxOutSpeedGb,
BigDecimal lastInSpeedGb, BigDecimal lastOutSpeedGb,
String recommendedUnit) {
this.avgInSpeedGb = avgInSpeedGb;
this.avgOutSpeedGb = avgOutSpeedGb;
this.maxInSpeedGb = maxInSpeedGb;
this.maxOutSpeedGb = maxOutSpeedGb;
this.lastInSpeedGb = lastInSpeedGb;
this.lastOutSpeedGb = lastOutSpeedGb;
this.recommendedUnit = recommendedUnit;
}
// Getters
public BigDecimal getAvgInSpeedGb() { return avgInSpeedGb; }
public BigDecimal getAvgOutSpeedGb() { return avgOutSpeedGb; }
public BigDecimal getMaxInSpeedGb() { return maxInSpeedGb; }
public BigDecimal getMaxOutSpeedGb() { return maxOutSpeedGb; }
public BigDecimal getLastInSpeedGb() { return lastInSpeedGb; }
public BigDecimal getLastOutSpeedGb() { return lastOutSpeedGb; }
public String getRecommendedUnit() { return recommendedUnit; }
public void setRecommendedUnit(String recommendedUnit) {
this.recommendedUnit = recommendedUnit;
}
@Override
public String toString() {
return String.format(
"平均输入速度: %s Gb, 平均输出速度: %s Gb\n" +
"最大输入速度: %s Gb, 最大输出速度: %s Gb\n" +
"最后输入速度: %s Gb, 最后输出速度: %s Gb\n" +
"推荐单位(基于平均值): %s",
avgInSpeedGb.setScale(2, RoundingMode.HALF_UP),
avgOutSpeedGb.setScale(2, RoundingMode.HALF_UP),
maxInSpeedGb.setScale(2, RoundingMode.HALF_UP),
maxOutSpeedGb.setScale(2, RoundingMode.HALF_UP),
lastInSpeedGb.setScale(2, RoundingMode.HALF_UP),
lastOutSpeedGb.setScale(2, RoundingMode.HALF_UP),
recommendedUnit
);
}
}
public static SpeedResult calculateWithAverageBasedUnit(List<?> list,
String inSpeedField, String outSpeedField)
throws NoSuchFieldException, IllegalAccessException {
if (list == null || list.isEmpty()) {
return new SpeedResult(
BigDecimal.ZERO, BigDecimal.ZERO,
BigDecimal.ZERO, BigDecimal.ZERO,
BigDecimal.ZERO, BigDecimal.ZERO,
"Kb"
);
}
BigDecimal totalInSpeedBit = BigDecimal.ZERO;
BigDecimal totalOutSpeedBit = BigDecimal.ZERO;
BigDecimal maxInSpeedGb = BigDecimal.ZERO;
BigDecimal maxOutSpeedGb = BigDecimal.ZERO;
BigDecimal lastInSpeedGb = BigDecimal.ZERO;
BigDecimal lastOutSpeedGb = BigDecimal.ZERO;
final BigDecimal GB_DIVISOR = new BigDecimal("1000000000");
// 计算总和(bit)和Gb值
for (Object obj : list) {
try {
java.lang.reflect.Field inField = obj.getClass().getDeclaredField(inSpeedField);
java.lang.reflect.Field outField = obj.getClass().getDeclaredField(outSpeedField);
inField.setAccessible(true);
outField.setAccessible(true);
BigDecimal inSpeedBit = (BigDecimal) inField.get(obj) == null ? BigDecimal.ZERO : (BigDecimal) inField.get(obj);
BigDecimal outSpeedBit = (BigDecimal) outField.get(obj) == null ? BigDecimal.ZERO : (BigDecimal) outField.get(obj);
// 累加bit值(用于计算平均值)
totalInSpeedBit = totalInSpeedBit.add(inSpeedBit);
totalOutSpeedBit = totalOutSpeedBit.add(outSpeedBit);
// 转换为Gb并更新最大值
BigDecimal inSpeedGb = inSpeedBit.divide(GB_DIVISOR, 2, RoundingMode.HALF_UP);
BigDecimal outSpeedGb = outSpeedBit.divide(GB_DIVISOR, 2, RoundingMode.HALF_UP);
maxInSpeedGb = maxInSpeedGb.max(inSpeedGb);
maxOutSpeedGb = maxOutSpeedGb.max(outSpeedGb);
// 记录最后一个值
lastInSpeedGb = inSpeedGb;
lastOutSpeedGb = outSpeedGb;
} catch (Exception e) {
throw new RuntimeException("无法获取速度字段值", e);
}
}
// 计算Gb平均值
BigDecimal size = new BigDecimal(list.size());
BigDecimal avgInSpeedGb = totalInSpeedBit.divide(GB_DIVISOR, 2, RoundingMode.HALF_UP)
.divide(size, 2, RoundingMode.HALF_UP);
BigDecimal avgOutSpeedGb = totalOutSpeedBit.divide(GB_DIVISOR, 2, RoundingMode.HALF_UP)
.divide(size, 2, RoundingMode.HALF_UP);
// 基于平均值的较大值确定推荐单位
BigDecimal maxAvgBit = avgInSpeedGb.compareTo(avgOutSpeedGb) > 0 ?
avgInSpeedGb.multiply(GB_DIVISOR) :
avgOutSpeedGb.multiply(GB_DIVISOR);
String recommendedUnit;
if (maxAvgBit.compareTo(new BigDecimal("1000000000")) >= 0) {
recommendedUnit = "Gb";
} else if (maxAvgBit.compareTo(new BigDecimal("1000000")) >= 0) {
recommendedUnit = "Mb";
} else{
recommendedUnit = "Kb";
}
return new SpeedResult(
avgInSpeedGb, avgOutSpeedGb,
maxInSpeedGb, maxOutSpeedGb,
lastInSpeedGb, lastOutSpeedGb,
recommendedUnit
);
}
// 工具方法:获取单位换算除数
public static BigDecimal getDivisor(String unit) {
switch (unit) {
case "Gb": return new BigDecimal("1000000000");
case "Mb": return new BigDecimal("1000000");
case "Kb": return new BigDecimal("1000");
default: return BigDecimal.ONE; // bit
}
}
public static String calculateUnit(List<?> list,
String inSpeedField, String outSpeedField)
throws NoSuchFieldException, IllegalAccessException {
if (list == null || list.isEmpty()) {
return "Kb";
}
BigDecimal totalInSpeedBit = BigDecimal.ZERO;
BigDecimal totalOutSpeedBit = BigDecimal.ZERO;
BigDecimal maxInSpeedGb = BigDecimal.ZERO;
BigDecimal maxOutSpeedGb = BigDecimal.ZERO;
BigDecimal lastInSpeedGb = BigDecimal.ZERO;
BigDecimal lastOutSpeedGb = BigDecimal.ZERO;
final BigDecimal GB_DIVISOR = new BigDecimal("1000000000");
// 计算总和(bit)和Gb值
for (Object obj : list) {
try {
java.lang.reflect.Field inField = obj.getClass().getDeclaredField(inSpeedField);
java.lang.reflect.Field outField = obj.getClass().getDeclaredField(outSpeedField);
inField.setAccessible(true);
outField.setAccessible(true);
BigDecimal inSpeedBit = (BigDecimal) inField.get(obj) == null ? BigDecimal.ZERO : (BigDecimal) inField.get(obj);
BigDecimal outSpeedBit = (BigDecimal) outField.get(obj) == null ? BigDecimal.ZERO : (BigDecimal) outField.get(obj);
// 累加bit值(用于计算平均值)
totalInSpeedBit = totalInSpeedBit.add(inSpeedBit);
totalOutSpeedBit = totalOutSpeedBit.add(outSpeedBit);
} catch (Exception e) {
throw new RuntimeException("无法获取速度字段值", e);
}
}
// 计算Gb平均值
BigDecimal size = new BigDecimal(list.size());
BigDecimal avgInSpeedGb = totalInSpeedBit.divide(size, 2, RoundingMode.HALF_UP);
BigDecimal avgOutSpeedGb = totalOutSpeedBit.divide(size, 2, RoundingMode.HALF_UP);
// 基于平均值的较大值确定推荐单位
BigDecimal maxAvgBit = avgInSpeedGb.compareTo(avgOutSpeedGb) > 0 ?
avgInSpeedGb : avgOutSpeedGb;
String recommendedUnit;
if (maxAvgBit.compareTo(new BigDecimal("1000000000")) >= 0) {
recommendedUnit = "Gb";
} else if (maxAvgBit.compareTo(new BigDecimal("1000000")) >= 0) {
recommendedUnit = "Mb";
} else{
recommendedUnit = "Kb";
}
return recommendedUnit;
}
/**
* 计算String类型存储数字的速度统计结果
* @param list 数据列表
* @param inSpeedField 输入速度字段名
* @param outSpeedField 输出速度字段名
* @return SpeedResult 速度统计结果
*/
public static SpeedResult calculateWithStringTraffic(List<?> list,
String inSpeedField, String outSpeedField)
throws NoSuchFieldException, IllegalAccessException {
if (list == null || list.isEmpty()) {
return new SpeedResult(
BigDecimal.ZERO, BigDecimal.ZERO,
BigDecimal.ZERO, BigDecimal.ZERO,
BigDecimal.ZERO, BigDecimal.ZERO,
"bit"
);
}
BigDecimal totalInSpeedBit = BigDecimal.ZERO;
BigDecimal totalOutSpeedBit = BigDecimal.ZERO;
BigDecimal maxInSpeedGb = BigDecimal.ZERO;
BigDecimal maxOutSpeedGb = BigDecimal.ZERO;
BigDecimal lastInSpeedGb = BigDecimal.ZERO;
BigDecimal lastOutSpeedGb = BigDecimal.ZERO;
final BigDecimal GB_DIVISOR = new BigDecimal("1000000000");
// 计算总和(bit)和Gb值
for (Object obj : list) {
try {
java.lang.reflect.Field inField = obj.getClass().getDeclaredField(inSpeedField);
java.lang.reflect.Field outField = obj.getClass().getDeclaredField(outSpeedField);
inField.setAccessible(true);
outField.setAccessible(true);
// 处理String类型的数字值
String inSpeedStr = (String) inField.get(obj);
String outSpeedStr = (String) outField.get(obj);
BigDecimal inSpeedBit = convertStringToBigDecimal(inSpeedStr);
BigDecimal outSpeedBit = convertStringToBigDecimal(outSpeedStr);
// 累加bit值(用于计算平均值)
totalInSpeedBit = totalInSpeedBit.add(inSpeedBit);
totalOutSpeedBit = totalOutSpeedBit.add(outSpeedBit);
// 转换为Gb并更新最大值
BigDecimal inSpeedGb = inSpeedBit.divide(GB_DIVISOR, 2, RoundingMode.HALF_UP);
BigDecimal outSpeedGb = outSpeedBit.divide(GB_DIVISOR, 2, RoundingMode.HALF_UP);
maxInSpeedGb = maxInSpeedGb.max(inSpeedGb);
maxOutSpeedGb = maxOutSpeedGb.max(outSpeedGb);
// 记录最后一个值
lastInSpeedGb = inSpeedGb;
lastOutSpeedGb = outSpeedGb;
} catch (Exception e) {
throw new RuntimeException("无法获取或转换速度字段值", e);
}
}
// 计算Gb平均值
BigDecimal size = new BigDecimal(list.size());
BigDecimal avgInSpeedGb = totalInSpeedBit.divide(GB_DIVISOR, 2, RoundingMode.HALF_UP)
.divide(size, 2, RoundingMode.HALF_UP);
BigDecimal avgOutSpeedGb = totalOutSpeedBit.divide(GB_DIVISOR, 2, RoundingMode.HALF_UP)
.divide(size, 2, RoundingMode.HALF_UP);
// 基于平均值的较大值确定推荐单位
BigDecimal maxAvgBit = avgInSpeedGb.compareTo(avgOutSpeedGb) > 0 ?
avgInSpeedGb.multiply(GB_DIVISOR) :
avgOutSpeedGb.multiply(GB_DIVISOR);
String recommendedUnit;
if (maxAvgBit.compareTo(new BigDecimal("1000000000")) >= 0) {
recommendedUnit = "Gb";
} else if (maxAvgBit.compareTo(new BigDecimal("1000000")) >= 0) {
recommendedUnit = "Mb";
} else {
recommendedUnit = "Kb";
}
return new SpeedResult(
avgInSpeedGb, avgOutSpeedGb,
maxInSpeedGb, maxOutSpeedGb,
lastInSpeedGb, lastOutSpeedGb,
recommendedUnit
);
}
/**
* 将String类型的数字转换为BigDecimal
* @param numberStr 数字字符串
* @return BigDecimal值转换失败返回0
*/
private static BigDecimal convertStringToBigDecimal(String numberStr) {
if (numberStr == null || numberStr.trim().isEmpty()) {
return BigDecimal.ZERO;
}
try {
return new BigDecimal(numberStr.trim());
} catch (Exception e) {
return BigDecimal.ZERO;
}
}
/**
* 仅计算String类型存储数字的推荐单位
* @param list 数据列表
* @param inSpeedField 输入速度字段名
* @param outSpeedField 输出速度字段名
* @return 推荐单位
*/
public static String calculateUnitWithStringTraffic(List<?> list,
String inSpeedField, String outSpeedField)
throws NoSuchFieldException, IllegalAccessException {
if (list == null || list.isEmpty()) {
return "Kb";
}
BigDecimal totalInSpeedBit = BigDecimal.ZERO;
BigDecimal totalOutSpeedBit = BigDecimal.ZERO;
// 计算总和(bit)
for (Object obj : list) {
try {
java.lang.reflect.Field inField = obj.getClass().getDeclaredField(inSpeedField);
java.lang.reflect.Field outField = obj.getClass().getDeclaredField(outSpeedField);
inField.setAccessible(true);
outField.setAccessible(true);
// 处理String类型的数字值
String inSpeedStr = (String) inField.get(obj);
String outSpeedStr = (String) outField.get(obj);
BigDecimal inSpeedBit = convertStringToBigDecimal(inSpeedStr);
BigDecimal outSpeedBit = convertStringToBigDecimal(outSpeedStr);
totalInSpeedBit = totalInSpeedBit.add(inSpeedBit);
totalOutSpeedBit = totalOutSpeedBit.add(outSpeedBit);
} catch (Exception e) {
throw new RuntimeException("无法获取或转换速度字段值", e);
}
}
// 计算平均值
BigDecimal size = new BigDecimal(list.size());
BigDecimal avgInSpeedBit = totalInSpeedBit.divide(size, 2, RoundingMode.HALF_UP);
BigDecimal avgOutSpeedBit = totalOutSpeedBit.divide(size, 2, RoundingMode.HALF_UP);
// 基于平均值的较大值确定推荐单位
BigDecimal maxAvgBit = avgInSpeedBit.compareTo(avgOutSpeedBit) > 0 ?
avgInSpeedBit : avgOutSpeedBit;
String recommendedUnit;
if (maxAvgBit.compareTo(new BigDecimal("1000000000")) >= 0) {
recommendedUnit = "Gb";
} else if (maxAvgBit.compareTo(new BigDecimal("1000000")) >= 0) {
recommendedUnit = "Mb";
} else {
recommendedUnit = "Kb";
}
return recommendedUnit;
}
// Mbit 转 Bit 换算1 Mbit = 1,000,000 Bit
public static BigDecimal mbitToBit(BigDecimal mbitValue) {
if (mbitValue == null) return BigDecimal.ZERO;
return mbitValue.multiply(new BigDecimal("1000000"));
}
}

View File

@@ -0,0 +1,171 @@
package com.ruoyi.common.core.utils;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.concurrent.TimeUnit;
public class UnitChangeUtil {
private static final double GB = 1024.0 * 1024.0 * 1024.0;
/**
* long类型字节转化为Gb
* @param bytes
* @return
*/
public static double bytesToGb(long bytes) {
double gb = bytes / GB;
BigDecimal bd = new BigDecimal(gb);
bd = bd.setScale(2, RoundingMode.HALF_UP);
return bd.doubleValue();
}
/**
* String类型字节转化为Gb
* @param bytes
* @return
*/
public static BigDecimal bytesToGb(String bytes) {
// 参数校验
if (bytes == null || bytes.trim().isEmpty()) {
return BigDecimal.ZERO;
}
BigDecimal bytesValue = new BigDecimal(bytes);
BigDecimal bd = bytesValue.divide(BigDecimal.valueOf(GB), 2, RoundingMode.HALF_UP);
return bd;
}
/**
* Kb转化为Gb
* @param kbValue
* @return
*/
public static double convertKbToGb(String kbValue) {
if (kbValue == null || kbValue.trim().isEmpty()) {
throw new IllegalArgumentException("KB值不能为空");
}
double kb = Double.parseDouble(kbValue.trim());
double gb = kb / (1024.0 * 1024.0);
BigDecimal bd = new BigDecimal(gb);
bd = bd.setScale(2, RoundingMode.HALF_UP);
return bd.doubleValue();
}
/**
* 工具方法:将毫秒值转换为运行时长
* @param uptimeMillis
* @return
*/
public static String formatUptime(long uptimeMillis) {
if (uptimeMillis <= 0) {
return "0秒";
}
long days = TimeUnit.MILLISECONDS.toDays(uptimeMillis);
long hours = TimeUnit.MILLISECONDS.toHours(uptimeMillis) % 24;
long minutes = TimeUnit.MILLISECONDS.toMinutes(uptimeMillis) % 60;
long seconds = TimeUnit.MILLISECONDS.toSeconds(uptimeMillis) % 60;
long months = days / 30;
days = days % 30;
return String.format("%d个月%d天%d小时%d分%d秒", months, days, hours, minutes, seconds);
}
/**
* 工具方法- 将秒值转换为运行时长
* @param uptimeSeconds
* @return
*/
public static String formatUptimeSeconds(long uptimeSeconds) {
if (uptimeSeconds <= 0) {
return "0秒";
}
long days = TimeUnit.SECONDS.toDays(uptimeSeconds);
long hours = TimeUnit.SECONDS.toHours(uptimeSeconds) % 24;
long minutes = TimeUnit.SECONDS.toMinutes(uptimeSeconds) % 60;
long seconds = uptimeSeconds % 60;
long months = days / 30;
days = days % 30;
return String.format("%d个月%d天%d小时%d分%d秒", months, days, hours, minutes, seconds);
}
/**
* 将字符串小数值格式化为保留两位小数(高精度)
* @param numberStr 数字字符串
* @return 保留两位小数的字符串,如果转换失败返回原字符串
*/
public static String formatDecimal(String numberStr) {
if (numberStr == null || numberStr.trim().isEmpty()) {
return numberStr;
}
try {
if("NaN".equals(numberStr)){
numberStr = "0";
}
BigDecimal number = new BigDecimal(numberStr);
return number.setScale(1, RoundingMode.HALF_UP).toString();
} catch (NumberFormatException e) {
return numberStr; // 转换失败返回原字符串
}
}
/**
* 次数单位换算
* @param count
* @return
*/
public static String formatWithUnit(long count) {
String[] units = {"", "", "百万", "亿"};
double[] divisors = {1, 10_000.0, 1_000_000.0, 100_000_000.0};
int unitIndex = 0;
double value = count;
for (int i = divisors.length - 1; i >= 0; i--) {
if (count >= divisors[i]) {
unitIndex = i;
value = count / divisors[i];
break;
}
}
// 根据数值大小决定小数位数
String formatPattern = (value >= 100 || unitIndex == 0) ? "%.0f %s次" : "%.1f %s次";
return String.format(formatPattern, value, units[unitIndex]).trim();
}
/**
* 简洁版本所有值都显示为KB及以上单位
*/
public static String formatWithKbMin(long bytes) {
if (bytes == 0) {
return "0.00 KB";
}
final String[] units = {"KB", "MB", "GB", "TB"};
double value = bytes / 1024.0;
int unitIndex = 0;
while (value >= 1024 && unitIndex < units.length - 1) {
value /= 1024;
unitIndex++;
}
// 四舍五入到两位小数
double roundedValue = Math.round(value * 100.0) / 100.0;
// 处理四舍五入后可能出现的情况
if (roundedValue == 0.0 && value > 0) {
roundedValue = 0.01; // 最小值显示为0.01而不是0.00
}
return String.format("%.2f %s", roundedValue, units[unitIndex]);
}
}

View File

@@ -13,6 +13,7 @@
<module>ruoyi-gen</module>
<module>ruoyi-job</module>
<module>ruoyi-file</module>
<module>ruoyi-mtragent</module>
</modules>
<artifactId>ruoyi-modules</artifactId>

View File

@@ -0,0 +1,100 @@
<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.ruoyi</groupId>
<artifactId>ruoyi-modules</artifactId>
<version>3.6.6</version>
</parent>
<artifactId>ruoyi-modules-mtragent</artifactId>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>3.8.1</version>
<scope>test</scope>
</dependency>
<!--rocketmq消息队列-->
<dependency>
<groupId>org.apache.rocketmq</groupId>
<artifactId>rocketmq-client</artifactId>
<version> 4.9.0</version>
</dependency>
<!-- SpringCloud Alibaba Nacos -->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>
<!-- SpringCloud Alibaba Nacos Config -->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
</dependency>
<dependency>
<groupId>com.alibaba.nacos</groupId>
<artifactId>nacos-client</artifactId>
</dependency>
<!-- SpringCloud Alibaba Sentinel -->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
</dependency>
<!-- SpringBoot Actuator -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<!-- Mysql驱动包 -->
<dependency>
<groupId>com.mysql</groupId>
<artifactId>mysql-connector-j</artifactId>
</dependency>
<!-- RuoYi Common Log -->
<dependency>
<groupId>com.ruoyi</groupId>
<artifactId>ruoyi-common-log</artifactId>
</dependency>
<!-- RuoYi Common Swagger-->
<dependency>
<groupId>com.ruoyi</groupId>
<artifactId>ruoyi-common-swagger</artifactId>
</dependency>
<dependency>
<groupId>com.ruoyi</groupId>
<artifactId>ruoyi-common-security</artifactId>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</dependency>
<!-- yml调用pom变量 -->
<dependency>
<groupId>org.yaml</groupId>
<artifactId>snakeyaml</artifactId>
<version>1.28</version>
</dependency>
<!-- SpringBoot Web -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
</dependencies>
</project>

View File

@@ -1,4 +1,4 @@
package com.ruoyi.testrocketmq;
package com.ruoyi.mtragent;
import com.ruoyi.common.security.annotation.EnableCustomConfig;
import com.ruoyi.common.security.annotation.EnableRyFeignClients;
@@ -15,11 +15,11 @@ import org.springframework.scheduling.annotation.EnableAsync;
@EnableRyFeignClients
@SpringBootApplication
@EnableAsync
public class RocketMQApplication
public class RuoYiMtragentApplication
{
public static void main(String[] args)
{
SpringApplication.run(RocketMQApplication.class, args);
System.out.println("(♥◠‿◠)ノ゙ RocketMQ模块启动成功 ლ(´ڡ`ლ)゙");
SpringApplication.run(RuoYiMtragentApplication.class, args);
System.out.println("(♥◠‿◠)ノ゙ RuoYiMtragent模块启动成功 ლ(´ڡ`ლ)゙");
}
}

View File

@@ -1,8 +1,8 @@
package com.ruoyi.testrocketmq.config;
package com.ruoyi.mtragent.config;
import com.ruoyi.testrocketmq.consumer.RocketMsgListener;
import com.ruoyi.testrocketmq.enums.MessageCodeEnum;
import com.ruoyi.testrocketmq.model.ConsumerMode;
import com.ruoyi.mtragent.consumer.RocketMsgListener;
import com.ruoyi.mtragent.enums.MessageTopic;
import com.ruoyi.mtragent.model.ConsumerMode;
import lombok.extern.slf4j.Slf4j;
import org.apache.rocketmq.client.consumer.DefaultMQPushConsumer;
import org.apache.rocketmq.client.exception.MQClientException;
@@ -12,6 +12,8 @@ import org.springframework.cloud.context.config.annotation.RefreshScope;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import java.util.List;
/**
* 消费者配置
*/
@@ -19,17 +21,22 @@ import org.springframework.context.annotation.Configuration;
@Configuration
@Slf4j
public class ConsumerConfig {
@Autowired
private ConsumerMode consumerMode;
@Autowired
private RocketMsgListener rocketMsgListener;
@Bean
public DefaultMQPushConsumer getRocketMQConsumer() throws MQClientException {
// ConsumerMode consumerMode = new ConsumerMode();
DefaultMQPushConsumer consumer = new DefaultMQPushConsumer(consumerMode.getGroupName());
public DefaultMQPushConsumer getRocketMQConsumer() {
//构建客户端连接
DefaultMQPushConsumer consumer = new DefaultMQPushConsumer(consumerMode.getAgentGroup());
//
consumer.setNamesrvAddr(consumerMode.getNamesrvAddr());
consumer.setConsumeThreadMin(consumerMode.getConsumeThreadMin());
consumer.setConsumeThreadMax(consumerMode.getConsumeThreadMax());
consumer.registerMessageListener(new RocketMsgListener());
consumer.registerMessageListener(rocketMsgListener);
/**
* 1. CONSUME_FROM_LAST_OFFSET第一次启动从队列最后位置消费后续再启动接着上次消费的进度开始消费
* 2. CONSUME_FROM_FIRST_OFFSET第一次启动从队列初始位置消费后续再启动接着上次消费的进度开始消费
@@ -41,7 +48,7 @@ public class ConsumerConfig {
* CLUSTERING (集群模式) 默认模式同一个ConsumerGroup(groupName相同)每个consumer只消费所订阅消息的一部分内容同一个ConsumerGroup里所有的Consumer消息加起来才是所
* 订阅topic整体从而达到负载均衡的目的
* BROADCASTING (广播模式) 同一个ConsumerGroup每个consumer都消费到所订阅topic所有消息也就是一个消费会被多次分发被多个consumer消费
*
* 需要注意的是在广播模式下每个Consumer都会独立地处理相同的消息副本这可能会导致一些潜在的问题例如消息重复处理或者资源浪费因此在使用广播模式时请确保消息的处理逻辑是幂等的并仔细考虑系统资源的消耗
*/
// consumer.setMessageModel(MessageModel.BROADCASTING);
@@ -50,11 +57,17 @@ public class ConsumerConfig {
try {
/**
* 订阅topic可以对指定消息进行过滤例如"TopicTest","tagl||tag2||tag3",*或null表示topic所有消息
* 由于官方并没有给直接订阅全部消息示例 所以使用list列表循环订阅所有topic
*/
consumer.subscribe(MessageCodeEnum.ORDER_MESSAGE.getCode(),"*");
consumer.subscribe(MessageCodeEnum.USER_MESSAGE.getCode(),"*");
// 获取所有topic列表
MessageTopic messageTopic = new MessageTopic();
List<String> allTopics = messageTopic.RocketMQTopicList();
//订阅所有topic
for (String topic : allTopics) {
consumer.subscribe(topic,"*");
}
consumer.start();
log.info("消费者初始化成功:{}", consumer.toString());
log.info("消费者初始化成功:{}", consumer);
} catch (MQClientException e) {
e.printStackTrace();
log.error("消费者初始化失败:{}",e.getMessage());

View File

@@ -1,6 +1,6 @@
package com.ruoyi.testrocketmq.config;
package com.ruoyi.mtragent.config;
import com.ruoyi.testrocketmq.model.ProducerMode;
import com.ruoyi.mtragent.model.ProducerMode;
import lombok.extern.slf4j.Slf4j;
import org.apache.rocketmq.client.exception.MQClientException;
import org.apache.rocketmq.client.producer.DefaultMQProducer;
@@ -9,20 +9,28 @@ import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
/**
* mq搭建地址连接
* 生产者初者连接信息 具体看nacos配置
*/
@Configuration
@Slf4j
public class ProducerConfig {
/**
* 远程调用连接信息
*/
public static DefaultMQProducer producer;
/**
* 连接客户端信息配置 具体看nacos配置
*/
@Autowired
private ProducerMode producerMode;
@Bean
public DefaultMQProducer getRocketMQProducer() {
producer = new DefaultMQProducer(producerMode.getGroupName());
producer = new DefaultMQProducer(producerMode.getAgentGroup());
producer.setNamesrvAddr(producerMode.getNamesrvAddr());
//如果需要同一个jvm中不同的producer往不同的mq集群发送消息需要设置不同的instanceName
if(producerMode.getMaxMessageSize()!=null){

View File

@@ -0,0 +1,94 @@
package com.ruoyi.mtragent.consumer;
import com.alibaba.fastjson.JSON;
import com.ruoyi.mtragent.domain.DeviceMessage;
import com.ruoyi.mtragent.enums.MessageCodeEnum;
import com.ruoyi.mtragent.handler.MessageHandler;
import com.ruoyi.mtragent.producer.ConsumeException;
import lombok.extern.slf4j.Slf4j;
import org.apache.rocketmq.client.consumer.listener.ConsumeConcurrentlyContext;
import org.apache.rocketmq.client.consumer.listener.ConsumeConcurrentlyStatus;
import org.apache.rocketmq.client.consumer.listener.MessageListenerConcurrently;
import org.apache.rocketmq.common.message.MessageExt;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils;
import java.io.UnsupportedEncodingException;
import java.util.List;
/**
* 消息监听
*/
@Slf4j
@Component
public class RocketMsgListener implements MessageListenerConcurrently {
@Autowired
private MessageHandler messageHandler;
/**
* 消费消息
* @param list msgs.size() >= 1
* DefaultMQPushConsumer.consumeMessageBatchMaxSize=1you can modify here
* 这里只设置为1当设置为多个时list中只要有一条消息消费失败就会整体重试
* @param consumeConcurrentlyContext 上下文信息
* @return 消费状态 成功CONSUME_SUCCESS或者 重试 (RECONSUME_LATER)
*/
@Override
public ConsumeConcurrentlyStatus consumeMessage(List<MessageExt> list, ConsumeConcurrentlyContext consumeConcurrentlyContext) {
try{
//消息不等于空情况
if (!CollectionUtils.isEmpty(list)) {
//获取topic
for (MessageExt messageExt : list) {
// 解析消息内容
String body = new String(messageExt.getBody());
log.info("接受到的消息为:{}", body);
String tags = messageExt.getTags();
String topic = messageExt.getTopic();
String msgId = messageExt.getMsgId();
String keys = messageExt.getKeys();
int reConsume = messageExt.getReconsumeTimes();
// 消息已经重试了3次如果不需要再次消费则返回成功
if (reConsume == 3) {
// TODO 补偿信息
log.error("消息消费三次失败,消息内容:{}", body);
return ConsumeConcurrentlyStatus.CONSUME_SUCCESS;//根据业务返回是否正常
}
if(MessageCodeEnum.TR_AGENT_UP.getCode().equals(topic)){
// 拿到信息
DeviceMessage message = JSON.parseObject(body, DeviceMessage.class);
// 处理消息
messageHandler.handleMessage(message);
return ConsumeConcurrentlyStatus.CONSUME_SUCCESS;//业务处理成功
}
// 根据不同的topic处理不同的业务 这里以订单消息为例子
}
}
// 消息消费失败
//broker会根据设置的messageDelayLevel发起重试默认16次
return ConsumeConcurrentlyStatus.RECONSUME_LATER;
} catch (Exception e) {
// 调用 handleException 方法处理异常并返回处理结果
return handleException(e);
}
}
/**
* 异常处理
*
* @param e 捕获的异常
* @return 消息消费结果
*/
private static ConsumeConcurrentlyStatus handleException(final Exception e) {
Class exceptionClass = e.getClass();
if (exceptionClass.equals(UnsupportedEncodingException.class)) {
log.error(e.getMessage());
} else if (exceptionClass.equals(ConsumeException.class)) {
log.error(e.getMessage());
} else{
log.error(e.getMessage());
}
return ConsumeConcurrentlyStatus.RECONSUME_LATER;
}
}

View File

@@ -0,0 +1,30 @@
package com.ruoyi.mtragent.consumer;
import org.apache.rocketmq.client.producer.LocalTransactionState;
import org.apache.rocketmq.client.producer.TransactionListener;
import org.apache.rocketmq.common.message.Message;
import org.apache.rocketmq.common.message.MessageExt;
/**
* 事物消息监听
*/
public class RocketMsgTransactionListenerImpl implements TransactionListener {
@Override
public LocalTransactionState executeLocalTransaction(Message msg, Object arg) {
// 在这里执行本地事务,比如数据库操作等
// 如果本地事务执行成功,返回 COMMIT_MESSAGE
// 如果本地事务执行失败,返回 ROLLBACK_MESSAGE
// 如果本地事务执行中,可以返回 UNKNOWRocketMQ 将会检查事务状态,并根据状态处理消息
return LocalTransactionState.COMMIT_MESSAGE; // 根据实际情况返回对应的状态
}
@Override
public LocalTransactionState checkLocalTransaction(MessageExt msg) {
// 检查本地事务状态,如果本地事务执行成功,返回 COMMIT_MESSAGE
// 如果本地事务执行失败,返回 ROLLBACK_MESSAGE
// 如果本地事务仍在执行中,返回 UNKNOWRocketMQ 将会继续检查事务状态
return LocalTransactionState.COMMIT_MESSAGE; // 根据实际情况返回对应的状态
}
}

View File

@@ -0,0 +1,139 @@
package com.ruoyi.mtragent.controller;
import com.ruoyi.common.security.annotation.InnerAuth;
import com.ruoyi.mtragent.producer.MessageProducer;
import org.apache.rocketmq.client.producer.SendResult;
import org.apache.rocketmq.common.message.Message;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
* 消息测试类Controller
*/
@RestController
@RequestMapping("/api/rocketMessage")
public class RocketMqController {
/**
* 发送同步消息
*/
@PostMapping("/sendSynchronizeMessage")
private Map sendSynchronizeMessage(){
MessageProducer messageProducer = new MessageProducer();
//调用MessageProducer配置好的消息方法
SendResult sendResult = messageProducer.sendSynchronizeMessage("order-message","order_message_tag","title","content");
Map<String,Object> result = new HashMap<>();
result.put("data",sendResult);
return result;
}
/**
* 发送单向消息
*/
@PostMapping("/sendOnewayMessage")
private Map sendOnewayMessage(@RequestParam("topic") String topic,@RequestParam("tag") String tag,@RequestParam("key") String key,@RequestParam("value") String value){
MessageProducer messageProducer = new MessageProducer();
//调用MessageProducer配置好的消息方法 topic需要你根据你们业务定制相应的
messageProducer.sendOnewayMessage("order-message","order_timeout_tag","title","content");
Map<String,Object> result = new HashMap<>();
result.put("msg","发送成功");
result.put("code",200);
return result;
}
/**
* 批量发送消息
*/
@PostMapping("/sendBatchMessage")
private Map sendBatchMessage(){
// 根据实际需求创建消息列表并返回
List<Message> messages = new ArrayList<>();
// 添加消息到列表
messages.add(new Message("order-message", "order_timeout_tag", "Message 1".getBytes()));
messages.add(new Message("order-message", "order_timeout_tag", "Message 2".getBytes()));
messages.add(new Message("order-message", "order_timeout_tag", "Message 3".getBytes()));
MessageProducer messageProducer = new MessageProducer();
//调用MessageProducer配置好的消息方法 topic需要你根据你们业务定制相应的
SendResult sendResult = messageProducer.sendBatchMessage(messages);
Map<String,Object> result = new HashMap<>();
result.put("data",sendResult);
return result;
}
/**
* 发送事物消息
*/
@PostMapping("/sendThingMessage")
private Map sendThingMessage(@RequestParam("topic") String topic,@RequestParam("tag") String tag,@RequestParam("key") String key,@RequestParam("value") String value){
MessageProducer messageProducer = new MessageProducer();
//调用MessageProducer配置好的消息方法 topic需要你根据你们业务定制相应的
SendResult sendResult = messageProducer.sendThingMessage("order-message","order_timeout_tag","title","content");
Map<String,Object> result = new HashMap<>();
result.put("data",sendResult);
return result;
}
/**
* 发送有序的消息
*/
@PostMapping("/sendOrderlyMessage")
private Map sendOrderlyMessage(){
// 根据实际需求创建消息列表并返回
List<Message> messages = new ArrayList<>();
// 添加消息到列表
messages.add(new Message("order-message", "order_timeout_tag", "Message 1".getBytes()));
messages.add(new Message("order-message", "order_timeout_tag", "Message 2".getBytes()));
messages.add(new Message("order-message", "order_timeout_tag", "Message 3".getBytes()));
Integer messageQueueNumber = 3;
MessageProducer messageProducer = new MessageProducer();
//调用MessageProducer配置好的消息方法 topic需要你根据你们业务定制相应的
SendResult sendResult = messageProducer.sendOrderlyMessage(messages,messageQueueNumber);
Map<String,Object> result = new HashMap<>();
result.put("data",sendResult);
return result;
}
/**
* 发送延迟消息
*/
@PostMapping("/sendDelayMessage")
private Map sendDelayMessage(@RequestParam("topic") String topic,@RequestParam("tag") String tag,@RequestParam("key") String key,@RequestParam("value") String value){
MessageProducer messageProducer = new MessageProducer();
//调用MessageProducer配置好的消息方法 topic需要你根据你们业务定制相应的
SendResult sendResult = messageProducer.sendDelayMessage("order-message","order_timeout_tag","title","content",4);
Map<String,Object> result = new HashMap<>();
result.put("data",sendResult);
return result;
}
/**
* 发送异步的消息
*/
@InnerAuth
@PostMapping("/sendAsyncProducerMessage")
private Map sendAsyncProducerMessage(@RequestParam("topic") String topic,@RequestParam("tag") String tag,@RequestParam("key") String key,@RequestParam("value") String value){
MessageProducer messageProducer = new MessageProducer();
//调用MessageProducer配置好的消息方法 topic需要你根据你们业务定制相应的
SendResult sendResult = messageProducer.sendAsyncProducerMessage(topic,tag,key,value);
Map<String,Object> result = new HashMap<>();
result.put("data",sendResult);
return result;
}
}

View File

@@ -0,0 +1,10 @@
package com.ruoyi.mtragent.domain;
import lombok.Data;
@Data
public class DeviceMessage {
private String clientId;
private String dataType;
private String data;
}

View File

@@ -0,0 +1,37 @@
package com.ruoyi.mtragent.domain;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.ruoyi.common.core.annotation.Excel;
import com.ruoyi.common.core.web.domain.BaseEntity;
import lombok.Data;
/**
* 心跳信息对象 initial_heartbeat_listen
*
* @author gyt
* @date 2025-09-08
*/
@Data
@JsonIgnoreProperties(ignoreUnknown = true)
public class InitialHeartbeatListen extends BaseEntity
{
private static final long serialVersionUID = 1L;
/** 客户端ID */
private String clientId;
/** 节点 */
private String logicalNode;
/** sn */
private String sn;
/** 强度值 */
@Excel(name = "强度值")
private Long strength;
/** 服务名称 */
private String name;
/** 版本 */
private String version;
/** 服务启动时间 */
private Long startupTime;
}

View File

@@ -0,0 +1,86 @@
package com.ruoyi.mtragent.domain;
import com.fasterxml.jackson.annotation.JsonFormat;
import com.ruoyi.common.core.annotation.Excel;
import com.ruoyi.common.core.web.domain.BaseEntity;
import lombok.Data;
import java.util.Date;
/**
* Agent管理对象 rm_agent_management
*
* @author gyt
* @date 2025-09-15
*/
@Data
public class RmAgentManagement extends BaseEntity
{
private static final long serialVersionUID = 1L;
/** 主键ID */
private Long id;
/** 硬件SN码 */
@Excel(name = "硬件SN码")
private String hardwareSn;
/** 资源名称 */
@Excel(name = "资源名称")
private String resourceName;
/** 内网IP地址 */
@Excel(name = "内网IP地址")
private String internalIp;
/** Agent状态0-离线1-在线2-异常 */
@Excel(name = "Agent状态0-离线1-在线2-异常")
private String status;
/** Agent版本号 */
@Excel(name = "Agent版本号")
private String agentVersion;
/** 执行方式 */
@Excel(name = "执行方式")
private Integer method;
/** 定时更新时间cron表达式 */
@Excel(name = "定时更新时间")
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
private Date scheduledUpdateTime;
/** 文件地址格式 */
@Excel(name = "文件地址格式")
private Long fileUrlType;
/** 文件地址 */
@Excel(name = "文件地址")
private String fileUrl;
/** 文件目录 */
@Excel(name = "文件目录")
private String fileDirectory;
/** 最后一次更新结果success/failure */
@Excel(name = "最后一次更新结果", readConverterExp = "s=uccess/failure")
private String lastUpdateResult;
/** 最后一次更新时间 */
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
@Excel(name = "最后一次更新时间", width = 30, dateFormat = "yyyy-MM-dd HH:mm:ss")
private Date lastUpdateTime;
/** 生效服务器id */
private String includeIds;
/** 生效服务器名称 */
private String includeNames;
/** 查询条件名称 */
private String queryName;
/** 文件MD5 */
private String fileMd5;
/** 客户端id */
private String clientId;
/** 部署设备 */
private String deployDevice;
/** 管理网公网Ip */
private String managePublicIp;
}

View File

@@ -0,0 +1,15 @@
package com.ruoyi.mtragent.domain.vo;
import lombok.Data;
@Data
public class AgentUpdateMsgVo {
/**文件地址外网HTTPS地址 */
private String fileUrl;
/** 文件MD5 */
private String fileMd5;
/** 执行方式0、立即执行1、定时执行 */
private Integer method;
/** 定时时间执行方式为1、定时执行时该字段必传 */
private long policyTime;
}

View File

@@ -0,0 +1,20 @@
package com.ruoyi.mtragent.domain.vo;
import lombok.Data;
import java.time.Instant;
@Data
public class PolicyTypeVo {
/** 服务器监控策略信息 */
private String monitors;
/** 服务器脚本策略信息 */
private String scripts;
/** agent更新信息 */
private String versions;
/** 路由信息 */
private String routes;
/** 时间戳 */
private Long timestamp = Instant.now().getEpochSecond();
}

View File

@@ -0,0 +1,14 @@
package com.ruoyi.mtragent.domain.vo;
import lombok.Data;
import java.time.Instant;
import java.util.List;
@Data
public class PolicyVo<T> {
/** 更新时间戳 */
private Long upTime = Instant.now().getEpochSecond();
/** 更新内容 */
private List<T> contents;
}

View File

@@ -0,0 +1,29 @@
package com.ruoyi.mtragent.domain.vo;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import lombok.Data;
import java.time.Instant;
@Data
@JsonIgnoreProperties(ignoreUnknown = true)
public class RspVo {
/**
* 状态码0、失败1、成功
*/
private Integer resCode;
/**
* 描述
*/
private String resMag;
/**
* 描述
*/
private String resMsg;
private String result;
/**
* 时间戳
*/
private Long timestamp = Instant.now().getEpochSecond();
}

View File

@@ -0,0 +1,15 @@
package com.ruoyi.mtragent.enums;
import lombok.Getter;
@Getter
public enum AlarmTypeEnum {
服务器下线("1", "服务器下线"),
交换机下线("2", "交换机下线");
private final String code;
private final String msg;
AlarmTypeEnum(String code, String msg){
this.code = code;
this.msg = msg;
}
}

View File

@@ -0,0 +1,65 @@
package com.ruoyi.mtragent.enums;
import lombok.Getter;
/**
* 用于传递topic和 tag
* 也用于接收消息后判断不同的消息处理不同的业务
*/
@Getter
public enum MessageCodeEnum {
/**
* agent数据采集的信息
*/
AGENT_MESSAGE_TOPIC("agent_up","agent数据采集的信息topic"),
TONGRAN_AGENT_UP("tongran_agent_up","agent数据采集的信息topic"),
TR_AGENT_UP("tr_agent_up","agent数据采集的信息topic v1.1"),
/**
* 系统消息
*/
NOTE_MESSAGE_TOPIC("system-message","系统消息服务模块topic名称"),
/**
* 用户消息
*/
USER_MESSAGE_TOPIC("user-message","用户消息服务模块topic名称"),
/**
* 订单消息
*/
ORDER_MESSAGE_TOPIC("order-message","订单消息服务模块topic名称"),
/**
* 用户消息tag
*/
USER_MESSAGE_TAG("user_message_tag","用户消息推送"),
/**
* 系统消息tag
*/
NOTE_MESSAGE_TAG("system_message_tag","系统消息推送"),
/**
* 订单消息
*/
ORDER_MESSAGE_TAG("order_message_tag","订单消息推送"),
/**
* 订单处理编号
*/
ORDER_TIMEOUT_TAG("order_timeout_tag","订单超时处理");
private final String code;
private final String msg;
MessageCodeEnum(String code, String msg){
this.code = code;
this.msg = msg;
}
}

View File

@@ -0,0 +1,21 @@
package com.ruoyi.mtragent.enums;
import java.util.ArrayList;
import java.util.List;
/**
* 定义topic列表
*/
public class MessageTopic {
//在这里添加topic 用于批量订阅
public List<String> RocketMQTopicList(){
List<String> getTopicLists=new ArrayList<>();
// agent采集消息
// getTopicLists.add("agent_up");
getTopicLists.add("tr_mtragent_up");
return getTopicLists;
}
}

View File

@@ -0,0 +1,14 @@
package com.ruoyi.mtragent.enums;
import lombok.Getter;
@Getter
public enum PushMethodEnum {
企业微信("1", "企业微信");
private final String code;
private final String msg;
PushMethodEnum(String code, String msg){
this.code = code;
this.msg = msg;
}
}

View File

@@ -0,0 +1,21 @@
package com.ruoyi.mtragent.enums;
import lombok.Getter;
@Getter
public enum ServerLogoEnum {
交换卷文件的可用空间("systemSwapSizeFreeCollect", "交换卷/文件的可用空间(字节)"),
内存利用率("memoryUtilizationCollect", "内存利用率"),
可用交换空间百分比("systemSwapSizePercentCollect", "可用交换空间百分比"),
可用内存("memorySizeAvailableCollect", "可用内存"),
可用内存百分比("memorySizePercentCollect", "可用内存百分比"),
正在运行的进程数("procNumRunCollect", "正在运行的进程数"),
登录用户数("systemUsersNumCollect", "登录用户数"),
进程数("procNumCollect", "进程数");
private final String code;
private final String msg;
ServerLogoEnum(String code, String msg){
this.code = code;
this.msg = msg;
}
}

View File

@@ -0,0 +1,17 @@
package com.ruoyi.mtragent.enums;
import lombok.Getter;
@Getter
public enum SwitchLogo {
设备CPU使用率("hwEntityCpuUsage", "设备CPU使用率"),
设备内存使用率("hwEntityMemUsage", "设备内存使用率(%)"),
系统平均功率("hwAveragePower", "系统平均功率(%)"),
系统实时功率("hwCurrentPower", "系统实时功率(%)");
private final String code;
private final String msg;
SwitchLogo(String code, String msg){
this.code = code;
this.msg = msg;
}
}

View File

@@ -0,0 +1,92 @@
package com.ruoyi.mtragent.handler;
import com.ruoyi.common.core.enums.MsgEnum;
import com.ruoyi.mtragent.domain.DeviceMessage;
import com.ruoyi.mtragent.domain.vo.RspVo;
import com.ruoyi.mtragent.service.IRmAgentManagementService;
import com.ruoyi.mtragent.utils.JsonDataParser;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.scheduling.annotation.EnableScheduling;
import org.springframework.stereotype.Component;
import javax.annotation.PostConstruct;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.function.Consumer;
/**
* 设备消息处理器
*/
@Slf4j
@Component
@EnableScheduling
public class MessageHandler {
private final Map<String, Consumer<DeviceMessage>> messageHandlers = new HashMap<>();
// 心跳状态
private static final String HEARTBEAT_STATUS_PREFIX = "heartbeat:status:";
// 心跳时间
private static final String HEARTBEAT_TIME_PREFIX = "heartbeat:time:";
// 心跳告警
private static final String HEARTBEAT_ALERT_PREFIX = "heartbeat:alert:";
String HEARTBEAT_RECOVERY_COUNT_PREFIX = "heartbeat:recovery:count:";
String HEARTBEAT_COUNT_PREFIX = "heartbeat:count:";
private static final long HEARTBEAT_TIMEOUT = 30000; // 3分钟超时
@Autowired
private RedisTemplate<String, String> redisTemplate;
@Autowired
private IRmAgentManagementService rmAgentManagementService;
/**
* 初始化处理器映射
*/
@PostConstruct
public void init() {
registerHandler(MsgEnum.Agent版本更新应答.getValue(), this::handleAgentUpdateRspMessage);
// 其他类型消息可以单独注册处理器
registerHandler(MsgEnum.注册.getValue(), this::handleRegisterMessage);
}
private void handleRegisterMessage(DeviceMessage message) {
}
/**
* agent更新响应
* @param message
*/
private void handleAgentUpdateRspMessage(DeviceMessage message) {
List<RspVo> rspVoList = JsonDataParser.parseJsonData(message.getData(), RspVo.class);
}
/**
* 注册消息处理器
*/
private void registerHandler(String dataType, Consumer<DeviceMessage> handler) {
messageHandlers.put(dataType, handler);
}
/**
* 处理设备消息(对外暴露的主方法)
*/
public void handleMessage(DeviceMessage message) {
String dataType = message.getDataType();
Consumer<DeviceMessage> handler = messageHandlers.get(dataType);
if (handler != null) {
handler.accept(message);
} else {
log.warn("未知数据类型:{}", dataType);
}
}
// ========== 具体的消息处理方法 ==========
}

View File

@@ -0,0 +1,65 @@
package com.ruoyi.mtragent.mapper;
import com.ruoyi.mtragent.domain.RmAgentManagement;
import java.util.List;
/**
* Agent管理Mapper接口
*
* @author gyt
* @date 2025-09-15
*/
public interface RmAgentManagementMapper
{
/**
* 查询Agent管理
*
* @param id Agent管理主键
* @return Agent管理
*/
public RmAgentManagement selectRmAgentManagementById(Long id);
/**
* 查询Agent管理列表
*
* @param rmAgentManagement Agent管理
* @return Agent管理集合
*/
public List<RmAgentManagement> selectRmAgentManagementList(RmAgentManagement rmAgentManagement);
/**
* 新增Agent管理
*
* @param rmAgentManagement Agent管理
* @return 结果
*/
public int insertRmAgentManagement(RmAgentManagement rmAgentManagement);
/**
* 修改Agent管理
*
* @param rmAgentManagement Agent管理
* @return 结果
*/
public int updateRmAgentManagement(RmAgentManagement rmAgentManagement);
/**
* 删除Agent管理
*
* @param id Agent管理主键
* @return 结果
*/
public int deleteRmAgentManagementById(Long id);
/**
* 批量删除Agent管理
*
* @param ids 需要删除的数据主键集合
* @return 结果
*/
public int deleteRmAgentManagementByIds(Long[] ids);
void updateRmAgentManagementBySn(RmAgentManagement rmAgentManagement);
}

View File

@@ -1,10 +1,14 @@
package com.ruoyi.testrocketmq.model;
package com.ruoyi.mtragent.model;
import lombok.Data;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Configuration;
import org.springframework.stereotype.Component;
/**
* 消费者初始化
* 消费者连接信息 具体看nacos配置
*/
@Data
@Configuration
@Component
@@ -19,4 +23,8 @@ public class ConsumerMode {
private int consumeThreadMax;
@Value("${suning.rocketmq.conumer.consumeMessageBatchMaxSize}")
private int consumeMessageBatchMaxSize;
@Value("${suning.rocketmq.conumer.agentTopic}")
private String agentTopic;
@Value("${suning.rocketmq.conumer.agentGroup}")
private String agentGroup;
}

View File

@@ -1,4 +1,4 @@
package com.ruoyi.testrocketmq.model;
package com.ruoyi.mtragent.model;
import lombok.Data;
import org.springframework.beans.factory.annotation.Value;
@@ -14,6 +14,10 @@ import org.springframework.context.annotation.Configuration;
public class ProducerMode {
@Value("${suning.rocketmq.producer.groupName}")
private String groupName;
@Value("${suning.rocketmq.producer.agentTopic}")
private String agentTopic;
@Value("${suning.rocketmq.producer.agentGroup}")
private String agentGroup;
@Value("${suning.rocketmq.namesrvAddr}")
private String namesrvAddr;
@Value("${suning.rocketmq.producer.maxMessageSize}")

View File

@@ -1,7 +1,10 @@
package com.ruoyi.testrocketmq.producer;
package com.ruoyi.mtragent.producer;
/**
* @author 影子
* 用于捕捉异常非受检异常unchecked exception
* RuntimeException 和其子类的异常在编译时不需要进行强制性的异常处理可以选择在运行时进行捕获和处理
* 可选择使用
*/
public class ConsumeException extends RuntimeException{
private static final long serialVersionUID = 4093867789628938836L;

View File

@@ -0,0 +1,225 @@
package com.ruoyi.mtragent.producer;
import com.alibaba.fastjson.JSON;
import com.ruoyi.mtragent.consumer.RocketMsgTransactionListenerImpl;
import lombok.extern.slf4j.Slf4j;
import org.apache.rocketmq.client.exception.MQBrokerException;
import org.apache.rocketmq.client.exception.MQClientException;
import org.apache.rocketmq.client.producer.SendCallback;
import org.apache.rocketmq.client.producer.SendResult;
import org.apache.rocketmq.client.producer.TransactionMQProducer;
import org.apache.rocketmq.client.producer.TransactionSendResult;
import org.apache.rocketmq.common.message.Message;
import org.apache.rocketmq.remoting.common.RemotingHelper;
import org.apache.rocketmq.remoting.exception.RemotingException;
import java.io.UnsupportedEncodingException;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List;
import static com.ruoyi.mtragent.config.ProducerConfig.producer;
/**
* 消息发送
*/
@Slf4j
public class MessageProducer {
/**
* 同步发送消息
* @param topic 主题
* @param tag 标签
* @param key 自定义的key根据业务来定
* @param value 消息的内容
* 通过调用 send() 方法发送消息,阻塞等待服务器响应。
*/
public SendResult sendSynchronizeMessage(String topic, String tag, String key, String value){
String body = "topic"+topic+"】, tag"+tag+"】, key"+key+"】, value"+value+"";
try {
Message msg = new Message(topic,tag,key, value.getBytes(RemotingHelper.DEFAULT_CHARSET));
System.out.println("生产者发送消息:"+ JSON.toJSONString(value));
SendResult result = producer.send(msg);
return result;
} catch (UnsupportedEncodingException e) {
log.error("消息初始化失败body{}",body);
} catch (MQClientException | InterruptedException | RemotingException | MQBrokerException e) {
log.error("消息发送失败! body{}",body);
}
return null;
}
/**
* 单向发送消息
* @param topic 主题
* @param tag 标签
* @param key 自定义的key根据业务来定
* @param value 消息的内容
* 单向发送:通过调用 sendOneway() 方法发送消息,不关心发送结果,适用于对可靠性要求不高的场景。
*/
public void sendOnewayMessage(String topic, String tag, String key, String value){
String body = "topic"+topic+"】, tag"+tag+"】, key"+key+"】, value"+value+"";
try {
Message msg = new Message(topic,tag,key, value.getBytes(RemotingHelper.DEFAULT_CHARSET));
System.out.println("生产者发送消息:"+ JSON.toJSONString(value));
producer.sendOneway(msg);
} catch (UnsupportedEncodingException e) {
log.error("消息初始化失败body{}",body);
} catch (MQClientException | InterruptedException | RemotingException e) {
log.error("消息发送失败! body{}",body);
}
}
/**
* 批量发送消息
* @param messages 消息列表
* 批量发送:通过调用 send() 方法并传入多条消息,实现批量发送消息。
*/
public SendResult sendBatchMessage(List<Message> messages){
String body = messages.toString();
try {
System.out.println("生产者发送消息:"+ messages);
// 发送批量消息
SendResult sendResult = producer.send(messages);
return sendResult;
} catch (MQClientException | InterruptedException | RemotingException e) {
log.error("消息发送失败! body{}",body);
} catch (MQBrokerException e) {
throw new RuntimeException(e);
}
return null;
}
/**
* 事务消息发送
* @param topic 主题
* @param tag 标签
* @param key 自定义的key根据业务来定
* @param value 消息的内容
* 事务消息发送:通过使用事务监听器实现本地事务执行和消息发送的一致性。
*/
public SendResult sendThingMessage(String topic, String tag, String key, String value){
String body = "topic"+topic+"】, tag"+tag+"】, key"+key+"】, value"+value+"";
try {
// 实例化事务生产者
TransactionMQProducer transactionMQProducer = new TransactionMQProducer(producer.getProducerGroup());
transactionMQProducer.setNamesrvAddr(producer.getNamesrvAddr());
// 设置事务监听器
transactionMQProducer.setTransactionListener(new RocketMsgTransactionListenerImpl());
Message msg = new Message(topic,tag,key, value.getBytes(RemotingHelper.DEFAULT_CHARSET));
System.out.println("生产者发送消息:"+ JSON.toJSONString(value));
// 发送事务消息
TransactionSendResult sendResult = transactionMQProducer.sendMessageInTransaction(msg, null);
return sendResult;
} catch (UnsupportedEncodingException e) {
log.error("消息初始化失败body{}",body);
} catch (MQClientException e) {
log.error("消息发送失败! body{}",body);
}
return null;
}
/**
* 发送有序的消息
* @param messagesList Message集合
* @param messageQueueNumber 消息队列数量,根据实际情况设定
* 顺序发送: messageQueueNumber 表示消息的业务标识,可以根据具体需求进行设置来保证消息按顺序发送。
*/
public SendResult sendOrderlyMessage(List<Message> messagesList, Integer messageQueueNumber) {
SendResult result = null;
for (Message message : messagesList) {
try {
result = producer.send(message, (list, msg, arg) -> {
Integer queueNumber = (Integer) arg;
//int queueIndex = queueNumber % list.size();
return list.get(queueNumber);
}, messageQueueNumber);//根据编号取模,选择消息队列
} catch (MQClientException | RemotingException | MQBrokerException | InterruptedException e) {
log.error("发送有序消息失败");
return result;
}
}
return result;
}
/**
* 发送延迟消息
* @param topic 主题
* @param tag 标签
* @param key 自定义的key根据业务来定
* @param value 消息的内容
* 延迟发送:通过设置延迟级别来实现延迟发送消息。
*/
public SendResult sendDelayMessage(String topic, String tag, String key, String value, Integer level)
{
SendResult result = null;
try
{
Message msg = new Message(topic,tag,key, value.getBytes(RemotingHelper.DEFAULT_CHARSET));
System.out.println("生产者发送消息:"+ JSON.toJSONString(value));
//设置消息延迟级别我这里设置5对应就是延时一分钟
// "1s 5s 10s 30s 1m 2m 3m 4m 5m 6m 7m 8m 9m 10m 20m 30m 1h 2h"
msg.setDelayTimeLevel(level);
// 发送消息到一个Broker
result = producer.send(msg);
// 通过sendResult返回消息是否成功送达
log.info("发送延迟消息结果:======sendResult{}", result);
DateFormat format =new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
log.info("发送时间:{}", format.format(new Date()));
return result;
}
catch (Exception e)
{
e.printStackTrace();
log.error("延迟消息队列推送消息异常:{},推送内容:{}", e.getMessage(), result);
}
return result;
}
/**
* 发送异步的消息
* @param topic 主题
* @param tag 标签
* @param key 自定义的key根据业务来定
* @param value 消息的内容
* 通过调用 send() 方法,并传入一个 SendCallback 对象,在发送消息的同时可以继续处理其他逻辑,消息发送结果通过回调函数通知。
*/
public SendResult sendAsyncProducerMessage(String topic, String tag, String key, String value){
try {
//创建一个消息实例,指定主题、标签和消息体。
Message msg = new Message(topic,tag,key, value.getBytes(RemotingHelper.DEFAULT_CHARSET));
System.out.println("生产者发送消息:"+ JSON.toJSONString(value));
producer.send(msg,new SendCallback() {
// 异步回调的处理
@Override
public void onSuccess(SendResult sendResult) {
System.out.printf("%-10d 异步发送消息成功 %s %n", msg, sendResult.getMsgId());
}
@Override
public void onException(Throwable e) {
System.out.printf("%-10d 异步发送消息失败 %s %n", msg, e);
e.printStackTrace();
}
});
} catch (MQClientException e) {
e.printStackTrace();
} catch (RemotingException e) {
e.printStackTrace();
} catch (InterruptedException e) {
e.printStackTrace();
} catch (UnsupportedEncodingException e) {
throw new RuntimeException(e);
}
return null;
}
}

View File

@@ -0,0 +1,56 @@
package com.ruoyi.mtragent.service;
import com.ruoyi.mtragent.domain.RmAgentManagement;
import java.util.List;
/**
* Agent管理Service接口
*
* @author gyt
* @date 2025-09-15
*/
public interface IRmAgentManagementService
{
/**
* 查询Agent管理
*
* @param id Agent管理主键
* @return Agent管理
*/
public RmAgentManagement selectRmAgentManagementById(Long id);
/**
* 查询Agent管理列表
*
* @param rmAgentManagement Agent管理
* @return Agent管理集合
*/
public List<RmAgentManagement> selectRmAgentManagementList(RmAgentManagement rmAgentManagement);
/**
* 保存最后更新结果
*
* @param rmAgentManagement Agent管理
* @return 结果
*/
public void updateRmAgentManagementByHardwareSn(RmAgentManagement rmAgentManagement);
/**
* 手动立即更新agent
* @param rmAgentManagement
* @return
*/
int updateAgentNow(RmAgentManagement rmAgentManagement);
/**
* 配置更新策略
* @param rmAgentManagement
* @return
*/
int addUpdatePolicy(RmAgentManagement rmAgentManagement);
}

View File

@@ -0,0 +1,202 @@
package com.ruoyi.mtragent.service.impl;
import com.alibaba.fastjson.JSONObject;
import com.ruoyi.common.core.constant.SecurityConstants;
import com.ruoyi.common.core.domain.R;
import com.ruoyi.common.core.enums.MsgEnum;
import com.ruoyi.common.core.utils.DateUtils;
import com.ruoyi.mtragent.domain.DeviceMessage;
import com.ruoyi.mtragent.domain.RmAgentManagement;
import com.ruoyi.mtragent.domain.vo.AgentUpdateMsgVo;
import com.ruoyi.mtragent.domain.vo.PolicyTypeVo;
import com.ruoyi.mtragent.domain.vo.PolicyVo;
import com.ruoyi.mtragent.mapper.RmAgentManagementMapper;
import com.ruoyi.mtragent.model.ProducerMode;
import com.ruoyi.mtragent.producer.MessageProducer;
import com.ruoyi.mtragent.service.IRmAgentManagementService;
import com.ruoyi.system.api.RemoteRevenueConfigService;
import com.ruoyi.system.api.domain.RmResourceRegistrationRemote;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
/**
* Agent管理Service业务层处理
*
* @author gyt
* @date 2025-09-15
*/
@Service
@Slf4j
public class RmAgentManagementServiceImpl implements IRmAgentManagementService
{
@Autowired
private RmAgentManagementMapper rmAgentManagementMapper;
@Autowired
private RemoteRevenueConfigService remoteRevenueConfigService;
@Autowired
private ProducerMode producerMode;
/**
* 查询Agent管理
*
* @param id Agent管理主键
* @return Agent管理
*/
@Override
public RmAgentManagement selectRmAgentManagementById(Long id)
{
RmAgentManagement agentManagement = rmAgentManagementMapper.selectRmAgentManagementById(id);
if(agentManagement != null){
if(agentManagement.getClientId() != null){
// 赋其他值
setPropties(agentManagement);
}
}
return agentManagement;
}
/**
* 查询Agent管理列表
*
* @param rmAgentManagement Agent管理
* @return Agent管理
*/
@Override
public List<RmAgentManagement> selectRmAgentManagementList(RmAgentManagement rmAgentManagement)
{
List<RmAgentManagement> managementList = rmAgentManagementMapper.selectRmAgentManagementList(rmAgentManagement);
for (RmAgentManagement agentManagement : managementList) {
if(agentManagement.getClientId()!=null){
// 查询注册表信息赋值
setPropties(agentManagement);
}
}
return managementList;
}
/**
* 根据注册表赋值
* @param agentManagement
*/
public void setPropties(RmAgentManagement agentManagement){
String clientId = agentManagement.getClientId();
// 设置其他信息
RmResourceRegistrationRemote queryRegist = new RmResourceRegistrationRemote();
queryRegist.setClientId(clientId);
R<RmResourceRegistrationRemote> registMsgR = remoteRevenueConfigService.getListByHardwareSn(queryRegist, SecurityConstants.INNER);
if(registMsgR != null && registMsgR.getData() != null){
RmResourceRegistrationRemote registMsg = registMsgR.getData();
agentManagement.setStatus(registMsg.getOnlineStatus());
agentManagement.setHardwareSn(registMsg.getHardwareSn());
}
}
/**
* 保存最后更新结果
*
* @param rmAgentManagement Agent管理
* @return 结果
*/
public void updateRmAgentManagementByHardwareSn(RmAgentManagement rmAgentManagement){
rmAgentManagementMapper.updateRmAgentManagementBySn(rmAgentManagement);
}
/**
* 配置更新策略v1.1
* @param rmAgentManagement
* @return
*/
@Override
public int addUpdatePolicy(RmAgentManagement rmAgentManagement) {
processAgentData(rmAgentManagement);
return 1;
}
/**
* 手动立即更新
* @param rmAgentManagement 更新信息
* @return
*/
@Override
public int updateAgentNow(RmAgentManagement rmAgentManagement) {
processAgentData(rmAgentManagement);
return 1;
}
/**
* 处理agen更新数据
* @param rmAgentManagement
*/
public void processAgentData(RmAgentManagement rmAgentManagement){
String clientIds = rmAgentManagement.getDeployDevice();
String[] clientIdArr = clientIds.split("\n");
for (String clientId : clientIdArr) {
// 创建新的对象,避免污染原始数据
RmAgentManagement currentAgent = new RmAgentManagement();
// 复制原始对象的属性
BeanUtils.copyProperties(rmAgentManagement, currentAgent);
// 设置当前循环的 clientId
currentAgent.setClientId(clientId);
currentAgent.setDeployDevice(clientId);
// 查询该资源是否已经配置
RmAgentManagement agentQueryParam = new RmAgentManagement();
agentQueryParam.setClientId(clientId);
List<RmAgentManagement> agentManagements = rmAgentManagementMapper.selectRmAgentManagementList(agentQueryParam);
if(!agentManagements.isEmpty()){
// 如果存在,修改
currentAgent.setLastUpdateTime(DateUtils.getNowDate());
if("0".equals(rmAgentManagement.getMethod())){
currentAgent.setScheduledUpdateTime(null);
}
rmAgentManagementMapper.updateRmAgentManagement(currentAgent);
}else{
// 如果不存在,添加
currentAgent.setLastUpdateTime(DateUtils.getNowDate());
if("0".equals(rmAgentManagement.getMethod())){
currentAgent.setScheduledUpdateTime(null);
}
rmAgentManagementMapper.insertRmAgentManagement(currentAgent);
}
// 构建更新策略
AgentUpdateMsgVo agentUpdateMsgVo = new AgentUpdateMsgVo();
agentUpdateMsgVo.setFileUrl(rmAgentManagement.getFileUrl());
agentUpdateMsgVo.setFileMd5(rmAgentManagement.getFileMd5());
agentUpdateMsgVo.setMethod(rmAgentManagement.getMethod());
if(rmAgentManagement.getMethod() == 1){
Date scheduledUpdateTime = rmAgentManagement.getScheduledUpdateTime();
long scheduledTime = scheduledUpdateTime.toInstant().getEpochSecond();
agentUpdateMsgVo.setPolicyTime(scheduledTime);
}
try {
PolicyVo<AgentUpdateMsgVo> policyVo = new PolicyVo();
List<AgentUpdateMsgVo> list = new ArrayList<>();
list.add(agentUpdateMsgVo);
policyVo.setContents(list);
String policyVoStr = JSONObject.toJSONString(policyVo);
PolicyTypeVo policyTypeVo = new PolicyTypeVo();
policyTypeVo.setVersions(policyVoStr);
String configJson = JSONObject.toJSONString(policyTypeVo);
DeviceMessage deviceMessage = new DeviceMessage();
deviceMessage.setClientId(clientId);
deviceMessage.setDataType(MsgEnum.获取最新策略应答.getValue());
deviceMessage.setData(configJson);
MessageProducer messageProducer = new MessageProducer();
messageProducer.sendAsyncProducerMessage(
producerMode.getAgentTopic(),
"",
"",
JSONObject.toJSONString(deviceMessage)
);
} catch (Exception e) {
log.error("发送设备配置失败deviceId: {}", rmAgentManagement.getHardwareSn(), e);
}
}
}
}

View File

@@ -0,0 +1,41 @@
package com.ruoyi.mtragent.utils;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.springframework.util.StringUtils;
import java.util.ArrayList;
import java.util.List;
public class JsonDataParser {
private static final ObjectMapper objectMapper = new ObjectMapper();
/**
* 通用JSON解析方法兼容对象和数组
* @param jsonStr JSON字符串
* @param valueType 目标实体类类型
* @return 实体类List集合
*/
public static <T> List<T> parseJsonData(String jsonStr, Class<T> valueType) {
if (!StringUtils.hasText(jsonStr)) {
return new ArrayList<>();
}
try {
JsonNode rootNode = objectMapper.readTree(jsonStr);
if (rootNode.isArray()) {
// 处理数组格式JSON
return objectMapper.readValue(jsonStr,
objectMapper.getTypeFactory().constructCollectionType(List.class, valueType));
} else {
// 处理单个对象格式JSON
List<T> result = new ArrayList<>(1);
result.add(objectMapper.readValue(jsonStr, valueType));
return result;
}
} catch (Exception e) {
throw new RuntimeException("JSON解析失败: " + e.getMessage(), e);
}
}
}

View File

@@ -0,0 +1,149 @@
package com.ruoyi.mtragent.utils;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.node.ArrayNode;
import com.fasterxml.jackson.databind.node.ObjectNode;
import org.springframework.util.StringUtils;
import java.util.ArrayList;
import java.util.List;
public class SwitchJsonDataParser {
private static final ObjectMapper objectMapper = new ObjectMapper();
/**
* 通用JSON解析方法兼容对象和数组
* @param jsonStr JSON字符串
* @param valueType 目标实体类类型
* @return 实体类List集合
*/
public static <T> List<T> parseJsonData(String jsonStr, Class<T> valueType) {
if (!StringUtils.hasText(jsonStr)) {
return new ArrayList<>();
}
try {
JsonNode rootNode = objectMapper.readTree(jsonStr);
if (rootNode.isArray()) {
// 处理数组格式JSON
if (isStringArrayContainingJsonObjects((ArrayNode) rootNode)) {
// 处理包含JSON对象字符串的数组 - 转换为真正的对象数组
ArrayNode processedArray = processStringJsonArrayToObjectArray((ArrayNode) rootNode);
return convertJsonArrayToList(processedArray, valueType);
} else {
// 处理普通JSON数组
processJsonArray((ArrayNode) rootNode);
return convertJsonArrayToList((ArrayNode) rootNode, valueType);
}
} else {
// 处理单个对象格式JSON
if (rootNode.isObject()) {
processJsonObject((ObjectNode) rootNode);
}
List<T> result = new ArrayList<>(1);
result.add(objectMapper.treeToValue(rootNode, valueType));
return result;
}
} catch (Exception e) {
throw new RuntimeException("JSON解析失败: " + e.getMessage(), e);
}
}
/**
* 将JsonArray转换为List<T>
*/
private static <T> List<T> convertJsonArrayToList(ArrayNode arrayNode, Class<T> valueType) throws Exception {
List<T> result = new ArrayList<>();
for (int i = 0; i < arrayNode.size(); i++) {
JsonNode element = arrayNode.get(i);
result.add(objectMapper.treeToValue(element, valueType));
}
return result;
}
/**
* 判断是否是包含JSON对象字符串的字符串数组
*/
private static boolean isStringArrayContainingJsonObjects(ArrayNode arrayNode) {
if (arrayNode.size() == 0) return false;
JsonNode firstElement = arrayNode.get(0);
if (firstElement.isTextual()) {
try {
String strValue = firstElement.textValue();
// 检查是否是JSON对象格式的字符串
if (strValue.startsWith("{") && strValue.endsWith("}")) {
objectMapper.readTree(strValue);
return true;
}
} catch (Exception e) {
return false;
}
}
return false;
}
/**
* 处理包含JSON对象字符串的字符串数组转换为真正的对象数组
*/
private static ArrayNode processStringJsonArrayToObjectArray(ArrayNode arrayNode) {
ArrayNode resultArray = objectMapper.createArrayNode();
for (int i = 0; i < arrayNode.size(); i++) {
JsonNode element = arrayNode.get(i);
if (element.isTextual()) {
try {
String jsonString = element.textValue();
JsonNode jsonNode = objectMapper.readTree(jsonString);
if (jsonNode.isObject()) {
// 处理JSON对象中的 noSuchInstance
processJsonObject((ObjectNode) jsonNode);
resultArray.add(jsonNode);
} else {
resultArray.add(element);
}
} catch (Exception e) {
// 如果解析失败,保持原样
resultArray.add(element);
}
} else {
resultArray.add(element);
}
}
return resultArray;
}
/**
* 处理JSON数组
*/
private static void processJsonArray(ArrayNode arrayNode) {
for (int i = 0; i < arrayNode.size(); i++) {
JsonNode element = arrayNode.get(i);
if (element.isObject()) {
processJsonObject((ObjectNode) element);
} else if (element.isArray()) {
processJsonArray((ArrayNode) element);
}
}
}
/**
* 处理JSON对象
*/
private static void processJsonObject(ObjectNode objectNode) {
objectNode.fields().forEachRemaining(entry -> {
JsonNode value = entry.getValue();
if (value.isTextual() && "noSuchInstance".equals(value.textValue())) {
objectNode.putNull(entry.getKey());
} else if (value.isObject()) {
processJsonObject((ObjectNode) value);
} else if (value.isArray()) {
processJsonArray((ArrayNode) value);
}
});
}
}

View File

@@ -0,0 +1,99 @@
package com.ruoyi.mtragent.utils;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.LinkedHashSet;
import java.util.Set;
public class TableRouterUtil {
// 日期格式
private static final DateTimeFormatter YEAR_MONTH_FORMAT =
DateTimeFormatter.ofPattern("yyyy_MM");
private static final DateTimeFormatter DATE_TIME_FORMATTER =
DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
// 表名前缀
private static final String TABLE_PREFIX = "eps_initial_traffic";
// 表名前缀
private static final String TABLE_PREFIX_INITIAL = "initial_bandwidth_traffic";
/**
* 根据创建时间获取表名
* @param createTime 记录创建时间
* @return 对应的分表名称
* @throws IllegalArgumentException 如果createTime为null
*
* 示例:
* 2023-08-05 14:30:00 → eps_initial_traffic_2023_08_1_10
* 2023-08-15 09:15:00 → eps_initial_traffic_2023_08_11_20
* 2023-08-25 18:45:00 → eps_initial_traffic_2023_08_21_31
*/
public static String getTableName(LocalDateTime createTime) {
if (createTime == null) {
throw new IllegalArgumentException("创建时间不能为null");
}
String yearMonth = createTime.format(YEAR_MONTH_FORMAT);
int day = createTime.getDayOfMonth();
return String.format("%s_%s_%s",
TABLE_PREFIX_INITIAL,
yearMonth,
getDayRange(day));
}
/**
* 获取时间范围内涉及的所有表名
* @param startTime 开始时间 (格式: "yyyy-MM-dd HH:mm:ss")
* @param endTime 结束时间 (格式: "yyyy-MM-dd HH:mm:ss")
* @return 按时间顺序排列的表名集合
*/
public static Set<String> getTableNamesBetween(String startTime, String endTime) {
LocalDateTime start = parseDateTime(startTime);
LocalDateTime end = parseDateTime(endTime);
validateTimeRange(start, end);
Set<String> tableNames = new LinkedHashSet<>();
LocalDateTime current = start.withHour(0).withMinute(0).withSecond(0);
while (!current.isAfter(end)) {
tableNames.add(getTableName(current));
current = current.plusDays(1);
}
return tableNames;
}
// 解析字符串为LocalDateTime
private static LocalDateTime parseDateTime(String dateTimeStr) {
if (dateTimeStr == null || dateTimeStr.trim().isEmpty()) {
throw new IllegalArgumentException("时间字符串不能为空");
}
try {
return LocalDateTime.parse(dateTimeStr, DATE_TIME_FORMATTER);
} catch (Exception e) {
throw new IllegalArgumentException("时间格式必须为: yyyy-MM-dd HH:mm:ss", e);
}
}
// 获取日期区间
private static String getDayRange(int day) {
if (day < 1 || day > 31) {
throw new IllegalArgumentException("日期必须在1-31之间");
}
if (day <= 10) return "1_10";
if (day <= 20) return "11_20";
return "21_31";
}
// 验证时间范围
private static void validateTimeRange(LocalDateTime start, LocalDateTime end) {
if (start == null || end == null) {
throw new IllegalArgumentException("时间范围参数不能为null");
}
if (start.isAfter(end)) {
throw new IllegalArgumentException("开始时间不能晚于结束时间");
}
}
}

View File

@@ -0,0 +1,285 @@
package com.ruoyi.mtragent.utils;
import com.fasterxml.jackson.databind.ObjectMapper;
import java.io.OutputStream;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.HashMap;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class WeChatWorkBot {
private static final ObjectMapper mapper = new ObjectMapper();
/**
* 发送基于模板的文本消息
* @param webhookUrl webhook地址
* @param template 消息模板,例如:"项目[项目名称]在[时间]发生[事件类型]"
* @param fieldValues 字段值的映射key为中文字段名value为实际值支持String、Number、Boolean等
* @return 是否发送成功
*/
public static boolean sendTemplateMessage(String webhookUrl, String template,
Map<String, Object> fieldValues) {
return sendTemplateMessage(webhookUrl, template, fieldValues, null, null, false);
}
/**
* 发送基于模板的文本消息(支持@功能)
* @param webhookUrl webhook地址
* @param template 消息模板
* @param fieldValues 字段值的映射
* @param mentionedMobiles 被@的用户列表(手机号)
* @param mentionedAll 是否@所有人
* @return 是否发送成功
*/
public static boolean sendTemplateMessage(String webhookUrl, String template,
Map<String, Object> fieldValues,
String[] mentionedMobiles, boolean mentionedAll) {
return sendTemplateMessage(webhookUrl, template, fieldValues, null, mentionedMobiles, mentionedAll);
}
/**
* 发送基于模板的文本消息(完整参数)
* @param webhookUrl webhook地址
* @param template 消息模板
* @param fieldValues 字段值的映射
* @param defaultValue 未找到字段时的默认值
* @param mentionedMobiles 被@的用户列表(手机号)
* @param mentionedAll 是否@所有人
* @return 是否发送成功
*/
public static boolean sendTemplateMessage(String webhookUrl, String template,
Map<String, Object> fieldValues, Object defaultValue,
String[] mentionedMobiles, boolean mentionedAll) {
try {
String actualContent = processTemplate(template, fieldValues, defaultValue);
return sendTextMessage(webhookUrl, actualContent, mentionedMobiles, mentionedAll);
} catch (Exception e) {
e.printStackTrace();
return false;
}
}
/**
* 处理模板,替换字段占位符
* @param template 消息模板
* @param fieldValues 字段值映射
* @param defaultValue 默认值
* @return 处理后的消息内容
*/
public static String processTemplate(String template, Map<String, Object> fieldValues,
Object defaultValue) {
if (template == null) return "";
if (fieldValues == null || fieldValues.isEmpty()) {
return template;
}
Pattern pattern = Pattern.compile("\\[(.*?)\\]");
Matcher matcher = pattern.matcher(template);
StringBuffer result = new StringBuffer();
while (matcher.find()) {
String fieldName = matcher.group(1);
Object fieldValueObj = fieldValues.get(fieldName);
String fieldValue = convertToString(fieldValueObj);
// 如果字段值为空,使用默认值或保留原占位符
if (fieldValue == null || fieldValue.trim().isEmpty()) {
fieldValue = convertToString(defaultValue);
if (fieldValue == null) {
fieldValue = "[" + fieldName + "]";
}
}
// 对替换值进行转义,防止正则表达式特殊字符问题
matcher.appendReplacement(result, Matcher.quoteReplacement(fieldValue));
}
matcher.appendTail(result);
return result.toString();
}
/**
* 将对象转换为字符串
* @param obj 要转换的对象
* @return 字符串表示
*/
private static String convertToString(Object obj) {
if (obj == null) {
return null;
}
if (obj instanceof String) {
return (String) obj;
} else if (obj instanceof Number || obj instanceof Boolean) {
return String.valueOf(obj);
} else if (obj instanceof java.util.Date) {
return new java.text.SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format((java.util.Date) obj);
} else {
return obj.toString();
}
}
/**
* 验证模板中的字段是否都有对应的值
* @param template 消息模板
* @param fieldValues 字段值映射
* @return 是否所有字段都有值
*/
public static boolean validateTemplate(String template, Map<String, Object> fieldValues) {
if (template == null || fieldValues == null) {
return false;
}
Pattern pattern = Pattern.compile("\\[(.*?)\\]");
Matcher matcher = pattern.matcher(template);
while (matcher.find()) {
String fieldName = matcher.group(1);
Object fieldValue = fieldValues.get(fieldName);
String strValue = convertToString(fieldValue);
if (!fieldValues.containsKey(fieldName) ||
strValue == null ||
strValue.trim().isEmpty()) {
return false;
}
}
return true;
}
/**
* 获取模板中的所有字段名
* @param template 消息模板
* @return 字段名列表
*/
public static java.util.List<String> getTemplateFields(String template) {
java.util.List<String> fields = new java.util.ArrayList<>();
if (template == null) {
return fields;
}
Pattern pattern = Pattern.compile("\\[(.*?)\\]");
Matcher matcher = pattern.matcher(template);
while (matcher.find()) {
fields.add(matcher.group(1));
}
return fields;
}
/**
* 发送Markdown模板消息
* @param webhookUrl webhook地址
* @param template Markdown模板
* @param fieldValues 字段值映射
* @return 是否发送成功
*/
public static boolean sendMarkdownTemplateMessage(String webhookUrl, String template,
Map<String, Object> fieldValues) {
return sendMarkdownTemplateMessage(webhookUrl, template, fieldValues, null);
}
/**
* 发送Markdown模板消息
* @param webhookUrl webhook地址
* @param template Markdown模板
* @param fieldValues 字段值映射
* @param defaultValue 默认值
* @return 是否发送成功
*/
public static boolean sendMarkdownTemplateMessage(String webhookUrl, String template,
Map<String, Object> fieldValues,
Object defaultValue) {
try {
String actualContent = processTemplate(template, fieldValues, defaultValue);
return sendMarkdownMessage(webhookUrl, actualContent);
} catch (Exception e) {
e.printStackTrace();
return false;
}
}
/**
* 发送文本消息
*/
public static boolean sendTextMessage(String webhookUrl, String content) {
return sendTextMessage(webhookUrl, content, null, false);
}
/**
* 发送文本消息(支持@功能)
*/
public static boolean sendTextMessage(String webhookUrl, String content,
String[] mentionedMobiles, boolean mentionedAll) {
try {
Map<String, Object> message = new HashMap<>();
message.put("msgtype", "text");
Map<String, Object> textContent = new HashMap<>();
textContent.put("content", content);
if (mentionedAll) {
textContent.put("mentioned_mobile_list", new String[]{"@all"});
} else if (mentionedMobiles != null && mentionedMobiles.length > 0) {
textContent.put("mentioned_mobile_list", mentionedMobiles);
}
message.put("text", textContent);
return sendMessage(webhookUrl, mapper.writeValueAsString(message));
} catch (Exception e) {
e.printStackTrace();
return false;
}
}
/**
* 发送Markdown消息
*/
public static boolean sendMarkdownMessage(String webhookUrl, String content) {
try {
Map<String, Object> message = new HashMap<>();
message.put("msgtype", "markdown");
Map<String, Object> markdownContent = new HashMap<>();
markdownContent.put("content", content);
message.put("markdown", markdownContent);
return sendMessage(webhookUrl, mapper.writeValueAsString(message));
} catch (Exception e) {
e.printStackTrace();
return false;
}
}
private static boolean sendMessage(String webhookUrl, String jsonBody) {
try {
URL url = new URL(webhookUrl);
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
connection.setRequestMethod("POST");
connection.setRequestProperty("Content-Type", "application/json");
connection.setDoOutput(true);
connection.setConnectTimeout(5000);
connection.setReadTimeout(10000);
try (OutputStream os = connection.getOutputStream()) {
byte[] input = jsonBody.getBytes("UTF-8");
os.write(input, 0, input.length);
}
int responseCode = connection.getResponseCode();
return responseCode == 200;
} catch (Exception e) {
e.printStackTrace();
return false;
}
}
}

View File

@@ -0,0 +1,41 @@
# Tomcat
server:
port: 9208
# Spring
spring:
application:
# 应用名称
name: ruoyi-mtragent
profiles:
# 环境配置
active: dev
cloud:
nacos:
discovery:
# 服务注册地址
server-addr: 127.0.0.1:8848
# server-addr: 172.16.15.103:8848
# username: ${spring.cloud.nacos.config.username}
# password: ${spring.cloud.nacos.config.password}
config:
# 配置中心地址
server-addr: 127.0.0.1:8848
# server-addr: 172.16.15.103:8848
# username: nacos
# password: nacos
# 配置文件格式
file-extension: yml
# 共享配置
shared-configs:
- application-${spring.profiles.active}.${spring.cloud.nacos.config.file-extension}
redisson:
singleServerConfig:
address: redis://localhost:6379
logging:
level:
com.ruoyi.app.mapper: DEBUG

View File

@@ -0,0 +1,72 @@
<?xml version="1.0" encoding="UTF-8"?>
<configuration scan="true" scanPeriod="60 seconds" debug="false">
<!-- 日志存放路径 -->
<property name="log.path" value="logs/ruoyi-mtragent" />
<!-- 日志输出格式 -->
<property name="log.pattern" value="%d{HH:mm:ss.SSS} [%thread] %-5level %logger{20} - [%method,%line] - %msg%n" />
<!-- 控制台输出 -->
<appender name="console" class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<pattern>${log.pattern}</pattern>
</encoder>
</appender>
<!-- 业务日志输出 -->
<appender name="file_info" class="ch.qos.logback.core.rolling.RollingFileAppender">
<file>${log.path}/info.log</file>
<!-- 循环政策:基于时间创建日志文件 -->
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<!-- 日志文件名格式 -->
<fileNamePattern>${log.path}/info.%d{yyyy-MM-dd}.log</fileNamePattern>
<!-- 日志最大的历史 60天 -->
<maxHistory>60</maxHistory>
</rollingPolicy>
<encoder>
<pattern>${log.pattern}</pattern>
</encoder>
<filter class="ch.qos.logback.classic.filter.LevelFilter">
<!-- 过滤的级别 -->
<level>INFO</level>
<!-- 匹配时的操作:接收(记录) -->
<onMatch>ACCEPT</onMatch>
<!-- 不匹配时的操作:拒绝(不记录) -->
<onMismatch>DENY</onMismatch>
</filter>
</appender>
<!-- 错误日志输出 -->
<appender name="file_error" class="ch.qos.logback.core.rolling.RollingFileAppender">
<file>${log.path}/error.log</file>
<!-- 循环政策:基于时间创建日志文件 -->
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<!-- 日志文件名格式 -->
<fileNamePattern>${log.path}/error.%d{yyyy-MM-dd}.log</fileNamePattern>
<!-- 日志最大的历史 60天 -->
<maxHistory>60</maxHistory>
</rollingPolicy>
<encoder>
<pattern>${log.pattern}</pattern>
</encoder>
<filter class="ch.qos.logback.classic.filter.LevelFilter">
<!-- 过滤的级别 -->
<level>ERROR</level>
<!-- 匹配时的操作:接收(记录) -->
<onMatch>ACCEPT</onMatch>
<!-- 不匹配时的操作:拒绝(不记录) -->
<onMismatch>DENY</onMismatch>
</filter>
</appender>
<!-- MTR Agent模块日志级别控制 -->
<logger name="com.ruoyi.mtragent" level="info" additivity="false">
<appender-ref ref="console" /> <!-- 显式添加控制台 -->
<appender-ref ref="file_info" />
<appender-ref ref="file_error" />
</logger>
<!-- 根日志配置 -->
<root level="info">
<appender-ref ref="console" />
</root>
</configuration>

View File

@@ -0,0 +1,192 @@
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.ruoyi.mtragent.mapper.RmAgentManagementMapper">
<resultMap type="RmAgentManagement" id="RmAgentManagementResult">
<result property="id" column="id" />
<result property="hardwareSn" column="hardware_sn" />
<result property="resourceName" column="resource_name" />
<result property="internalIp" column="internal_ip" />
<result property="status" column="status" />
<result property="agentVersion" column="agent_version" />
<result property="method" column="method" />
<result property="scheduledUpdateTime" column="scheduled_update_time" />
<result property="fileUrlType" column="file_url_type" />
<result property="fileUrl" column="file_url" />
<result property="fileDirectory" column="file_directory" />
<result property="lastUpdateResult" column="last_update_result" />
<result property="lastUpdateTime" column="last_update_time" />
<result property="createTime" column="create_time" />
<result property="updateTime" column="update_time" />
<result property="createBy" column="create_by" />
<result property="updateBy" column="update_by" />
<result property="fileMd5" column="file_md5" />
<result property="clientId" column="client_id" />
<result property="deployDevice" column="deploy_device" />
</resultMap>
<sql id="selectRmAgentManagementVo">
select id, hardware_sn, resource_name, internal_ip, status, agent_version, method, scheduled_update_time, file_url_type, file_url, file_directory, last_update_result, last_update_time, create_time, update_time, create_by, update_by, file_md5, client_id, deploy_device from rm_agent_management
</sql>
<select id="selectRmAgentManagementList" parameterType="RmAgentManagement" resultMap="RmAgentManagementResult">
<include refid="selectRmAgentManagementVo"/>
<where>
<if test="hardwareSn != null and hardwareSn != ''"> and hardware_sn = #{hardwareSn}</if>
<if test="resourceName != null and resourceName != ''"> and resource_name like concat('%', #{resourceName}, '%')</if>
<if test="internalIp != null and internalIp != ''"> and internal_ip = #{internalIp}</if>
<if test="status != null and status != ''"> and status = #{status}</if>
<if test="agentVersion != null and agentVersion != ''"> and agent_version = #{agentVersion}</if>
<if test="method != null "> and method = #{method}</if>
<if test="scheduledUpdateTime != null and scheduledUpdateTime != ''"> and scheduled_update_time = #{scheduledUpdateTime}</if>
<if test="fileUrlType != null "> and file_url_type = #{fileUrlType}</if>
<if test="fileUrl != null and fileUrl != ''"> and file_url = #{fileUrl}</if>
<if test="fileDirectory != null and fileDirectory != ''"> and file_directory = #{fileDirectory}</if>
<if test="lastUpdateResult != null and lastUpdateResult != ''"> and last_update_result = #{lastUpdateResult}</if>
<if test="lastUpdateTime != null "> and last_update_time = #{lastUpdateTime}</if>
<if test="fileMd5 != null and fileMd5 != ''"> and file_md5 = #{fileMd5}</if>
<if test="clientId != null and clientId != ''"> and client_id = #{clientId}</if>
<if test="deployDevice != null and deployDevice != ''"> and deploy_device = #{deployDevice}</if>
<if test="queryName != null and queryName != '' "> and (resource_name like concat('%', #{resourceName}, '%') or internal_ip = #{internalIp})</if>
</where>
order by last_update_time desc
</select>
<select id="selectRmAgentManagementById" parameterType="Long" resultMap="RmAgentManagementResult">
<include refid="selectRmAgentManagementVo"/>
where id = #{id}
</select>
<insert id="insertRmAgentManagement" parameterType="RmAgentManagement" useGeneratedKeys="true" keyProperty="id">
insert into rm_agent_management
<trim prefix="(" suffix=")" suffixOverrides=",">
<if test="hardwareSn != null and hardwareSn != ''">hardware_sn,</if>
<if test="resourceName != null and resourceName != ''">resource_name,</if>
<if test="internalIp != null">internal_ip,</if>
<if test="status != null and status != ''">status,</if>
<if test="agentVersion != null">agent_version,</if>
<if test="method != null">method,</if>
<if test="scheduledUpdateTime != null">scheduled_update_time,</if>
<if test="fileUrlType != null">file_url_type,</if>
<if test="fileUrl != null">file_url,</if>
<if test="fileDirectory != null">file_directory,</if>
<if test="lastUpdateResult != null">last_update_result,</if>
<if test="lastUpdateTime != null">last_update_time,</if>
<if test="createTime != null">create_time,</if>
<if test="updateTime != null">update_time,</if>
<if test="createBy != null">create_by,</if>
<if test="updateBy != null">update_by,</if>
<if test="fileMd5 != null">file_md5,</if>
<if test="clientId != null">client_id,</if>
<if test="deployDevice != null">deploy_device,</if>
</trim>
<trim prefix="values (" suffix=")" suffixOverrides=",">
<if test="hardwareSn != null and hardwareSn != ''">#{hardwareSn},</if>
<if test="resourceName != null and resourceName != ''">#{resourceName},</if>
<if test="internalIp != null">#{internalIp},</if>
<if test="status != null and status != ''">#{status},</if>
<if test="agentVersion != null">#{agentVersion},</if>
<if test="method != null">#{method},</if>
<if test="scheduledUpdateTime != null">#{scheduledUpdateTime},</if>
<if test="fileUrlType != null">#{fileUrlType},</if>
<if test="fileUrl != null">#{fileUrl},</if>
<if test="fileDirectory != null">#{fileDirectory},</if>
<if test="lastUpdateResult != null">#{lastUpdateResult},</if>
<if test="lastUpdateTime != null">#{lastUpdateTime},</if>
<if test="createTime != null">#{createTime},</if>
<if test="updateTime != null">#{updateTime},</if>
<if test="createBy != null">#{createBy},</if>
<if test="updateBy != null">#{updateBy},</if>
<if test="fileMd5 != null">#{fileMd5},</if>
<if test="clientId != null">#{clientId},</if>
<if test="deployDevice != null">#{deployDevice},</if>
</trim>
</insert>
<update id="updateRmAgentManagement" parameterType="RmAgentManagement">
update rm_agent_management
<trim prefix="SET" suffixOverrides=",">
<if test="hardwareSn != null and hardwareSn != ''">hardware_sn = #{hardwareSn},</if>
<if test="resourceName != null and resourceName != ''">resource_name = #{resourceName},</if>
<if test="internalIp != null">internal_ip = #{internalIp},</if>
<if test="status != null and status != ''">status = #{status},</if>
<if test="agentVersion != null">agent_version = #{agentVersion},</if>
<if test="method != null">method = #{method},</if>
<if test="scheduledUpdateTime != null">scheduled_update_time = #{scheduledUpdateTime},</if>
<if test="fileUrlType != null">file_url_type = #{fileUrlType},</if>
<if test="fileUrl != null">file_url = #{fileUrl},</if>
<if test="fileDirectory != null">file_directory = #{fileDirectory},</if>
<if test="lastUpdateResult != null">last_update_result = #{lastUpdateResult},</if>
<if test="lastUpdateTime != null">last_update_time = #{lastUpdateTime},</if>
<if test="createTime != null">create_time = #{createTime},</if>
<if test="updateTime != null">update_time = #{updateTime},</if>
<if test="createBy != null">create_by = #{createBy},</if>
<if test="updateBy != null">update_by = #{updateBy},</if>
<if test="fileMd5 != null">file_md5 = #{fileMd5},</if>
<if test="clientId != null">client_id = #{clientId},</if>
<if test="deployDevice != null">deploy_device = #{deployDevice},</if>
</trim>
<where>
<choose>
<when test="id != null">
and id = #{id}
</when>
<when test="clientId != null and clientId != ''">
and client_id = #{clientId}
</when>
<otherwise>
and 1=0 <!-- 如果没有提供任何条件,则不更新任何记录 -->
</otherwise>
</choose>
</where>
</update>
<delete id="deleteRmAgentManagementById" parameterType="Long">
delete from rm_agent_management where id = #{id}
</delete>
<delete id="deleteRmAgentManagementByIds" parameterType="String">
delete from rm_agent_management where id in
<foreach item="id" collection="array" open="(" separator="," close=")">
#{id}
</foreach>
</delete>
<update id="updateRmAgentManagementBySn" parameterType="RmAgentManagement">
update rm_agent_management
<trim prefix="SET" suffixOverrides=",">
<if test="resourceName != null and resourceName != ''">resource_name = #{resourceName},</if>
<if test="internalIp != null">internal_ip = #{internalIp},</if>
<if test="status != null and status != ''">status = #{status},</if>
<if test="agentVersion != null">agent_version = #{agentVersion},</if>
<if test="method != null">method = #{method},</if>
<if test="scheduledUpdateTime != null">scheduled_update_time = #{scheduledUpdateTime},</if>
<if test="fileUrlType != null">file_url_type = #{fileUrlType},</if>
<if test="fileUrl != null">file_url = #{fileUrl},</if>
<if test="fileDirectory != null">file_directory = #{fileDirectory},</if>
<if test="lastUpdateResult != null">last_update_result = #{lastUpdateResult},</if>
<if test="lastUpdateTime != null">last_update_time = #{lastUpdateTime},</if>
<if test="createTime != null">create_time = #{createTime},</if>
<if test="updateTime != null">update_time = #{updateTime},</if>
<if test="createBy != null">create_by = #{createBy},</if>
<if test="updateBy != null">update_by = #{updateBy},</if>
</trim>
<where>
<choose>
<when test="id != null">
and id = #{id}
</when>
<when test="clientId != null and clientId != ''">
and client_id = #{clientId}
</when>
<when test="hardwareSn != null and hardwareSn != ''">
and hardware_sn = #{hardwareSn}
</when>
<otherwise>
and 1=0 <!-- 如果没有提供任何条件,则不更新任何记录 -->
</otherwise>
</choose>
</where>
</update>
</mapper>

View File

@@ -0,0 +1,38 @@
package com.ruoyi.mtragent;
import junit.framework.Test;
import junit.framework.TestCase;
import junit.framework.TestSuite;
/**
* Unit test for simple App.
*/
public class AppTest
extends TestCase
{
/**
* Create the test case
*
* @param testName name of the test case
*/
public AppTest( String testName )
{
super( testName );
}
/**
* @return the suite of tests being tested
*/
public static Test suite()
{
return new TestSuite( AppTest.class );
}
/**
* Rigourous Test :-)
*/
public void testApp()
{
assertTrue( true );
}
}

View File

@@ -0,0 +1,259 @@
package com.ruoyi.system.config;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.ruoyi.common.core.utils.DateUtils;
import com.ruoyi.system.domain.EpsInitialTrafficData;
import com.ruoyi.system.domain.RmRegistrationMachine;
import com.ruoyi.system.service.EpsInitialTrafficDataService;
import com.ruoyi.system.service.IRmRegistrationMachineService;
import com.ruoyi.system.util.TableRouterUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpMethod;
import org.springframework.http.ResponseEntity;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
import org.springframework.web.client.RestTemplate;
import org.springframework.web.util.UriComponentsBuilder;
import javax.crypto.Mac;
import javax.crypto.SecretKey;
import javax.crypto.spec.SecretKeySpec;
import java.math.BigDecimal;
import java.net.URI;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.List;
import java.util.Map;
import java.util.Optional;
@Component
public class HmacScheduledTask {
private static final String MAC_NAME = "HmacSHA1";
private static final String ENCODING = "UTF-8";
@Autowired
private IRmRegistrationMachineService rmRegistrationMachineService;
@Autowired
private EpsInitialTrafficDataService epsInitialTrafficDataService;
/**
* 每小时执行一次查询4小时前的数据
* 例如9:39执行时查询4:00-5:00的数据
*/
@Scheduled(cron = "0 0 * * * ?") // 每小时整点执行
// 或者每5分钟执行一次@Scheduled(cron = "0 */5 * * * ?")
// @Scheduled(initialDelay = 5000, fixedDelay = Long.MAX_VALUE)
public void executeHourlyTask() {
RestTemplate restTemplate = new RestTemplate();
try {
System.out.println("开始执行定时任务,时间:" + LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")));
// 计算时间范围当前时间往前推4小时的整点时间段
LocalDateTime now = LocalDateTime.now();
// 计算查询的时间段4小时前的整点小时
LocalDateTime queryBaseTime = now.minusHours(4);
LocalDateTime startTime = queryBaseTime.withMinute(0).withSecond(0).withNano(0);
LocalDateTime endTime = startTime.plusHours(1);
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
String startTimeStr = startTime.format(formatter);
String endTimeStr = endTime.format(formatter);
System.out.println("查询时间范围:" + startTimeStr + "" + endTimeStr);
long timestamp = System.currentTimeMillis();
String plainText = "efea5f0218c84a24b9fdab3264de3da5" + timestamp + "/supplier/outer/dev/getFlow";
String secretKey = getHmac(plainText, "91a73fd806ab2c005c13b4dc19130a884e909dea3f72d46e30266fe1a1f588d8");
// 设置请求头
HttpHeaders headers = new HttpHeaders();
headers.set("Content-Type", "application/json");
headers.set("TOKEN", "efea5f0218c84a24b9fdab3264de3da5");
headers.set("secret-key", secretKey);
headers.set("timestamps", String.valueOf(timestamp));
// 查询绑定的machinecode
List<RmRegistrationMachine> machineList = rmRegistrationMachineService.selectRmRegistrationMachineList(new RmRegistrationMachine());
for (RmRegistrationMachine rmRegistrationMachine : machineList) {
// 构建URL
URI uri = UriComponentsBuilder
.fromHttpUrl("https://ecscm-openapi.ksyun.com/supplier/outer/dev/getFlow")
.queryParam("srmChannel", "1000121954")
.queryParam("startTime", startTimeStr)
.queryParam("endTime", endTimeStr)
.queryParam("machineCode", rmRegistrationMachine.getMachineCode())
.build()
.toUri();
HttpEntity<String> entity = new HttpEntity<>(headers);
// GET 请求
ResponseEntity<String> response = restTemplate.exchange(
uri,
HttpMethod.GET,
entity,
String.class
);
String result = response.getBody();
// 保存流量数据
parseAndProcessResponse(result, rmRegistrationMachine.getClientId());
}
System.out.println("定时任务执行完成");
} catch (Exception e) {
System.err.println("定时任务执行失败:" + e.getMessage());
e.printStackTrace();
}
}
/**
* 解析和处理API响应
*/
private void parseAndProcessResponse(String responseBody, String clientId) {
ObjectMapper objectMapper = new ObjectMapper();
try {
Map<String, Object> responseMap = objectMapper.readValue(responseBody, Map.class);
if (responseMap.get("code").equals(200)) {
Map<String, Object> dataMap = (Map<String, Object>) responseMap.get("data");
Integer total = (Integer) dataMap.get("total");
List<Map<String, Object>> dataList = (List<Map<String, Object>>) dataMap.get("data");
System.out.println("成功获取数据,总记录数:" + total);
// 处理每条数据
for (Map<String, Object> item : dataList) {
processFlowData(item, clientId);
}
} else {
System.out.println("API返回错误" + responseMap.get("msg"));
}
} catch (Exception e) {
System.err.println("JSON解析失败" + e.getMessage());
}
}
/**
* 处理单条流量数据
*/
private void processFlowData(Map<String, Object> flowData, String clientId) {
String time = (String) flowData.get("time");
// 科学计数法转换为BigDecimal
BigDecimal flow = Optional.ofNullable(flowData.get("flow"))
.map(Object::toString)
.map(str -> {
try {
return new BigDecimal(str);
} catch (NumberFormatException e) {
return BigDecimal.ZERO;
}
})
.orElse(BigDecimal.ZERO);
// 字节转bit
flow = flow.multiply(new BigDecimal(8));
String flowPlain = flow.toPlainString();
String deviceid = (String) flowData.get("deviceid");
String ip = (String) flowData.get("ip");
String province = (String) flowData.get("province");
System.out.println(String.format("时间:%s, 流量:%.2f, 设备:%s, IP%s, 省份:%s",
time, flow, deviceid, ip, province));
String tableName = TableRouterUtil.getTableName(TableRouterUtil.parseDateTime(time));
EpsInitialTrafficData epsInitialTrafficData = new EpsInitialTrafficData();
epsInitialTrafficData.setTableName(tableName);
epsInitialTrafficData.setCreateTime(DateUtils.parseDate(time));
epsInitialTrafficData.setClientId(clientId);
epsInitialTrafficData.setMachineFlow(flowPlain);
epsInitialTrafficDataService.updateMachineTraffic(epsInitialTrafficData);
}
/**
* 测试方法:手动执行查询指定时间段
*/
public void manualExecuteForTimeRange(LocalDateTime start, LocalDateTime end) {
RestTemplate restTemplate = new RestTemplate();
try {
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
String startTimeStr = start.format(formatter);
String endTimeStr = end.format(formatter);
System.out.println("手动执行查询,时间范围:" + startTimeStr + "" + endTimeStr);
long timestamp = System.currentTimeMillis();
String plainText = "efea5f0218c84a24b9fdab3264de3da5" + timestamp + "/supplier/outer/dev/getFlow";
String secretKey = getHmac(plainText, "91a73fd806ab2c005c13b4dc19130a884e909dea3f72d46e30266fe1a1f588d8");
// 设置请求头
HttpHeaders headers = new HttpHeaders();
headers.set("Content-Type", "application/json");
headers.set("TOKEN", "efea5f0218c84a24b9fdab3264de3da5");
headers.set("secret-key", secretKey);
headers.set("timestamps", String.valueOf(timestamp));
// 构建URL
URI uri = UriComponentsBuilder
.fromHttpUrl("https://ecscm-openapi.ksyun.com/supplier/outer/dev/getFlow")
.queryParam("srmChannel", "1000121954")
.queryParam("startTime", startTimeStr)
.queryParam("endTime", endTimeStr)
.build()
.toUri();
HttpEntity<String> entity = new HttpEntity<>(headers);
// GET 请求
ResponseEntity<String> response = restTemplate.exchange(
uri,
HttpMethod.GET,
entity,
String.class
);
System.out.println("手动执行API响应结果" + response.getBody());
} catch (Exception e) {
System.err.println("手动执行失败:" + e.getMessage());
e.printStackTrace();
}
}
/**
* HMAC加密方法
*/
public static String getHmac(String plainText, String encryptKey) {
try{
byte[] dataKey = encryptKey.getBytes(ENCODING);
byte[] dataValue = plainText.getBytes(ENCODING);
SecretKey secretKey = new SecretKeySpec(dataKey, MAC_NAME);
Mac mac = Mac.getInstance(MAC_NAME);
mac.init(secretKey);
byte[] bytes = mac.doFinal(dataValue);
String rs = encodeHex(bytes, false);
return rs;
} catch (Exception e){
throw new IllegalArgumentException(e.getMessage());
}
}
/**
* 数据转16进制编码
*/
public static String encodeHex(final byte[] data, final boolean toLowerCase) {
final char[] DIGITS_LOWER = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f' };
final char[] DIGITS_UPPER = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' };
final char[] toDigits = toLowerCase ? DIGITS_LOWER : DIGITS_UPPER;
final int l = data.length;
final char[] out = new char[l << 1];
for (int i = 0, j = 0; i < l; i++) {
out[j++] = toDigits[(0xF0 & data[i]) >>> 4];
out[j++] = toDigits[0x0F & data[i]];
}
return new String(out);
}
}

View File

@@ -1,6 +1,5 @@
package com.ruoyi.system.config;
import com.ruoyi.common.core.utils.DateUtils;
import com.ruoyi.system.domain.*;
import com.ruoyi.system.service.*;
import lombok.extern.slf4j.Slf4j;
@@ -35,11 +34,11 @@ public class TableScheduleConfig {
@Autowired
private IAllInterfaceNameService allInterfaceNameService;
@Autowired
private IEpsServerRevenueConfigService epsServerRevenueConfigService;
@Autowired
private IRmEpsTopologyManagementService rmEpsTopologyManagementService;
@Autowired
private IEpsMethodChangeRecordService epsMethodChangeRecordService;
@Autowired
private IRmMonitorConfigService rmMonitorConfigService;
// 每月25号创建下月表
@Scheduled(cron = "0 0 0 25 * ?")
@@ -48,6 +47,14 @@ public class TableScheduleConfig {
epsInitialTrafficDataService.createNextMonthTables();
}
/**
* 每5分钟计算配置好的总流量
*/
@Scheduled(cron = "0 1/5 * * * ?")
public void sumTrafficMyMonitorConfigScheduled() {
rmMonitorConfigService.sumTrafficMyMonitorConfig(null);
}
// 每天0点执行 计算95带宽值/日
@Scheduled(cron = "0 4 0 * * ?", zone = "Asia/Shanghai")
public void calculate95BandwidthDaily() {
@@ -72,6 +79,26 @@ public class TableScheduleConfig {
.thenRun(() -> executeWithLog("交换机带宽1024",
() -> initialSwitchInfoDetailsService.calculateSwitch95BandwidthDaily(initialSwitchInfoDetails, dailyStartTime, dailyEndTime, "1024")));
}
// 每天5点04执行 计算金山95带宽值/日
@Scheduled(cron = "0 4 5 * * ?", zone = "Asia/Shanghai")
public void calculateJinShan95() {
// 获取昨天的日期范围(北京时间)
LocalDate yesterday = LocalDate.now(ZoneId.of("Asia/Shanghai")).minusDays(1);
String dailyStartTime = yesterday.atStartOfDay().format(TIME_FORMAT); // 00:00:00
String dailyEndTime = yesterday.atTime(23, 59, 59).format(TIME_FORMAT); // 23:59:59
// 日
String dayOrMonth = "1";
// 95带宽值/日
EpsInitialTrafficData queryParam = new EpsInitialTrafficData();
queryParam.setDayOrMonth(dayOrMonth);
InitialSwitchInfoDetails initialSwitchInfoDetails = new InitialSwitchInfoDetails();
initialSwitchInfoDetails.setDayOrMonth(dayOrMonth);
// 顺序执行链
CompletableFuture.runAsync(() -> executeWithLog("金山业务带宽1000",
() -> epsInitialTrafficDataService.calculate95ByJinShan(queryParam, dailyStartTime, dailyEndTime, "1000")))
.thenRun(() -> executeWithLog("金山业务带宽1024",
() -> epsInitialTrafficDataService.calculate95ByJinShan(queryParam, dailyStartTime, dailyEndTime, "1024")));
}
// 每月1号0点执行 计算95带宽值/月
@Scheduled(cron = "0 3 0 1 * ?", zone = "Asia/Shanghai")
@@ -168,96 +195,87 @@ public class TableScheduleConfig {
* 处理单个服务器的平均带宽计算
*/
private void processServerAvgBandwidth(EpsNodeBandwidth epsNodeBandwidth, AllInterfaceName allInterfaceName, String calculationMode) {
final String deviceSn = allInterfaceName.getDeviceSn();
final String clientId = allInterfaceName.getClientId();
try {
// 1. 设置基础设备信息
epsNodeBandwidth.setHardwareSn(deviceSn);
epsNodeBandwidth.setClientId(clientId);
// 查询业务变更记录
EpsMethodChangeRecord changeQuery = new EpsMethodChangeRecord();
changeQuery.setClientId(clientId);
changeQuery.setStartTime(epsNodeBandwidth.getStartTime());
changeQuery.setEndTime(epsNodeBandwidth.getEndTime());
// 2. 查询服务器配置
EpsServerRevenueConfig queryConfig = new EpsServerRevenueConfig();
queryConfig.setHardwareSn(deviceSn);
List<EpsServerRevenueConfig> configList = epsServerRevenueConfigService.selectEpsServerRevenueConfigList(queryConfig);
EpsServerRevenueConfig serverConfig = configList.isEmpty() ? new EpsServerRevenueConfig() : configList.get(0);
epsNodeBandwidth.setNodeName(serverConfig.getNodeName());
List<EpsMethodChangeRecord> records = epsMethodChangeRecordService.selectEpsMethodChangeRecordList(changeQuery);
// 3. 检查是否需要处理业务变更
boolean shouldProcessChange = serverConfig.getUpdateTime() != null
&& epsNodeBandwidth.getStartTime() != null
&& epsNodeBandwidth.getStartTime().length() >= 10
&& "1".equals(serverConfig.getChanged())
&& DateUtils.parseDateToStr("yyyy-MM", serverConfig.getUpdateTime())
.equals(epsNodeBandwidth.getStartTime().substring(0, 7));
// 按businessCode分组处理修复null key问题
if (!records.isEmpty()) {
Map<String, List<EpsMethodChangeRecord>> groupedRecords = records.stream()
.filter(record -> record.getBusinessCode() != null) // 过滤掉businessCode为null的记录
.collect(Collectors.groupingBy(EpsMethodChangeRecord::getBusinessCode));
// 4. 处理业务变更情况
if (shouldProcessChange) {
// 查询业务变更记录
EpsMethodChangeRecord changeQuery = new EpsMethodChangeRecord();
changeQuery.setHardwareSn(deviceSn);
changeQuery.setStartTime(epsNodeBandwidth.getStartTime());
changeQuery.setEndTime(epsNodeBandwidth.getEndTime());
// 处理每个业务分组
for (Map.Entry<String, List<EpsMethodChangeRecord>> entry : groupedRecords.entrySet()) {
String businessCode = entry.getKey();
// 取第一个有效业务名称同businessCode的业务名称应该相同
String businessName = entry.getValue().stream()
.filter(r -> r.getBusinessName() != null)
.findFirst()
.map(EpsMethodChangeRecord::getBusinessName)
.orElse("未知业务");
List<EpsMethodChangeRecord> records = epsMethodChangeRecordService.selectEpsMethodChangeRecordList(changeQuery);
// 创建业务带宽对象
EpsNodeBandwidth bandwidthWithBiz = new EpsNodeBandwidth();
bandwidthWithBiz.setClientId(clientId);
bandwidthWithBiz.setCalculationMode(calculationMode);
bandwidthWithBiz.setStartTime(epsNodeBandwidth.getStartTime());
bandwidthWithBiz.setEndTime(epsNodeBandwidth.getEndTime());
bandwidthWithBiz.setBusinessId(businessCode);
bandwidthWithBiz.setBusinessName(businessName);
bandwidthWithBiz.setResourceType("1");
// 按businessCode分组处理修复null key问题
if (!records.isEmpty()) {
Map<String, List<EpsMethodChangeRecord>> groupedRecords = records.stream()
.filter(record -> record.getBusinessCode() != null) // 过滤掉businessCode为null的记录
.collect(Collectors.groupingBy(EpsMethodChangeRecord::getBusinessCode));
// 处理每个业务分组
for (Map.Entry<String, List<EpsMethodChangeRecord>> entry : groupedRecords.entrySet()) {
String businessCode = entry.getKey();
// 取第一个有效业务名称同businessCode的业务名称应该相同
String businessName = entry.getValue().stream()
.filter(r -> r.getBusinessName() != null)
.findFirst()
.map(EpsMethodChangeRecord::getBusinessName)
.orElse("未知业务");
// 创建业务带宽对象
EpsNodeBandwidth bandwidthWithBiz = new EpsNodeBandwidth();
bandwidthWithBiz.setHardwareSn(deviceSn);
bandwidthWithBiz.setCalculationMode(calculationMode);
bandwidthWithBiz.setNodeName(serverConfig.getNodeName());
bandwidthWithBiz.setStartTime(epsNodeBandwidth.getStartTime());
bandwidthWithBiz.setEndTime(epsNodeBandwidth.getEndTime());
bandwidthWithBiz.setBusinessId(businessCode);
bandwidthWithBiz.setBusinessName(businessName);
bandwidthWithBiz.setResourceType("1");
// 执行计算
epsNodeBandwidthService.calculateAvg(bandwidthWithBiz);
}
// 处理businessCode为null的记录如果有
List<EpsMethodChangeRecord> nullBusinessRecords = records.stream()
.filter(record -> record.getBusinessCode() == null)
.collect(Collectors.toList());
if (!nullBusinessRecords.isEmpty()) {
log.warn("服务器 {} 有 {} 条记录的businessCode为null", deviceSn, nullBusinessRecords.size());
// 可以选择记录日志或进行其他处理
}
return; // 业务变更处理完成后直接返回
// 执行计算
epsNodeBandwidthService.calculateAvg(bandwidthWithBiz);
}
}
// 处理businessCode为null的记录如果有
List<EpsMethodChangeRecord> nullBusinessRecords = records.stream()
.filter(record -> record.getBusinessCode() == null)
.collect(Collectors.toList());
if (!nullBusinessRecords.isEmpty()) {
log.warn("服务器 {} 有 {} 条记录的businessCode为null", clientId, nullBusinessRecords.size());
// 可以选择记录日志或进行其他处理
}
return; // 业务变更处理完成后直接返回
}
String businessCode = null;
String businessName = null;
// 查询绑定的业务
EpsMethodChangeRecord queryParam = new EpsMethodChangeRecord();
queryParam.setClientId(clientId);
List<EpsMethodChangeRecord> recordList = epsMethodChangeRecordService.selectEpsMethodChangeRecordList(queryParam);
if(!recordList.isEmpty()){
EpsMethodChangeRecord record = recordList.stream()
.findFirst()
.orElse(null);
businessCode = record.getBusinessCode();
businessName = record.getBusinessName();
}
// 5. 处理正常情况(无业务变更或无需处理变更)
EpsNodeBandwidth normalBandwidth = new EpsNodeBandwidth();
normalBandwidth.setHardwareSn(deviceSn);
normalBandwidth.setClientId(clientId);
normalBandwidth.setCalculationMode(calculationMode);
normalBandwidth.setNodeName(serverConfig.getNodeName());
normalBandwidth.setStartTime(epsNodeBandwidth.getStartTime());
normalBandwidth.setEndTime(epsNodeBandwidth.getEndTime());
normalBandwidth.setBusinessId(serverConfig.getBusinessCode());
normalBandwidth.setBusinessName(serverConfig.getBusinessName());
normalBandwidth.setBusinessId(businessCode);
normalBandwidth.setBusinessName(businessName);
normalBandwidth.setResourceType("1");
epsNodeBandwidthService.calculateAvg(normalBandwidth);
} catch (Exception e) {
log.error("处理服务器 {} 平均带宽失败", deviceSn, e);
log.error("处理服务器 {} 平均带宽失败", clientId, e);
}
}
@@ -285,131 +303,128 @@ public class TableScheduleConfig {
* 处理单个交换机的平均带宽计算
*/
private void processSwitchAvgBandwidth(EpsNodeBandwidth epsNodeBandwidth, AllInterfaceName switchSnMsg, String calculationMode) {
final String switchSn = switchSnMsg.getSwitchSn();
final String clientId = switchSnMsg.getClientId();
try {
// 1. 查询交换机拓扑信息
RmEpsTopologyManagement managementQuery = new RmEpsTopologyManagement();
managementQuery.setSwitchSn(switchSn);
managementQuery.setClientId(clientId);
List<RmEpsTopologyManagement> topologyList = rmEpsTopologyManagementService.selectRmEpsTopologyManagementList(managementQuery);
if(!topologyList.isEmpty()){
for (RmEpsTopologyManagement topology : topologyList) {
epsNodeBandwidth.setClientId(clientId);
epsNodeBandwidth.setInterfaceName(topology.getInterfaceName());
// 2. 设置基础信息
RmEpsTopologyManagement topology = topologyList.isEmpty() ? new RmEpsTopologyManagement() : topologyList.get(0);
epsNodeBandwidth.setSwitchSn(switchSn);
epsNodeBandwidth.setInterfaceName(topology.getInterfaceName());
// 3. 判断连接设备类型
boolean isServerConnected = "1".equals(topology.getConnectedDeviceType());
// 3. 判断连接设备类型
boolean isServerConnected = "1".equals(topology.getConnectedDeviceType());
// 4. 处理服务器连接的情况
if (isServerConnected && topology.getServerClientId() != null) {
String serverClientId = topology.getServerClientId();
String serverSn = topology.getServerSn();
// 查询业务变更记录
EpsMethodChangeRecord changeQuery = new EpsMethodChangeRecord();
changeQuery.setClientId(serverClientId);
changeQuery.setStartTime(epsNodeBandwidth.getStartTime());
changeQuery.setEndTime(epsNodeBandwidth.getEndTime());
List<EpsMethodChangeRecord> records = epsMethodChangeRecordService.selectEpsMethodChangeRecordList(changeQuery);
// 4. 处理服务器连接的情况
if (isServerConnected && topology.getServerSn() != null) {
String serverSn = topology.getServerSn();
epsNodeBandwidth.setHardwareSn(serverSn);
// 查询服务器配置
EpsServerRevenueConfig queryConfig = new EpsServerRevenueConfig();
queryConfig.setHardwareSn(serverSn);
List<EpsServerRevenueConfig> configList = epsServerRevenueConfigService.selectEpsServerRevenueConfigList(queryConfig);
EpsServerRevenueConfig serverConfig = configList.isEmpty() ? new EpsServerRevenueConfig() : configList.get(0);
epsNodeBandwidth.setNodeName(serverConfig.getNodeName());
// 按businessCode分组处理
if (!records.isEmpty()) {
Map<String, List<EpsMethodChangeRecord>> groupedRecords = records.stream()
.filter(record -> record.getBusinessCode() != null) // 过滤掉businessCode为null的记录
.collect(Collectors.groupingBy(EpsMethodChangeRecord::getBusinessCode));
// 检查是否需要处理业务变更
boolean shouldProcessChange = serverConfig.getUpdateTime() != null
&& epsNodeBandwidth.getStartTime() != null
&& epsNodeBandwidth.getStartTime().length() >= 10
&& "1".equals(serverConfig.getChanged())
&& DateUtils.parseDateToStr("yyyy-MM", serverConfig.getUpdateTime())
.equals(epsNodeBandwidth.getStartTime().substring(0, 7));
// 处理每个业务分组
for (Map.Entry<String, List<EpsMethodChangeRecord>> entry : groupedRecords.entrySet()) {
String businessCode = entry.getKey();
List<EpsMethodChangeRecord> businessRecords = entry.getValue();
if(shouldProcessChange){
// 查询业务变更记录
EpsMethodChangeRecord changeQuery = new EpsMethodChangeRecord();
changeQuery.setHardwareSn(serverSn);
changeQuery.setStartTime(epsNodeBandwidth.getStartTime());
changeQuery.setEndTime(epsNodeBandwidth.getEndTime());
// 取第一个有效业务名称
String businessName = businessRecords.stream()
.filter(r -> r.getBusinessName() != null)
.findFirst()
.map(EpsMethodChangeRecord::getBusinessName)
.orElse("未知业务");
List<EpsMethodChangeRecord> records = epsMethodChangeRecordService.selectEpsMethodChangeRecordList(changeQuery);
// 创建业务带宽对象
EpsNodeBandwidth bandwidthWithBiz = new EpsNodeBandwidth();
bandwidthWithBiz.setClientId(clientId);
bandwidthWithBiz.setCalculationMode(calculationMode);
bandwidthWithBiz.setInterfaceName(topology.getInterfaceName());
bandwidthWithBiz.setHardwareSn(serverSn);
bandwidthWithBiz.setUplinkSwitch(topology.getSwitchName());
bandwidthWithBiz.setInterfaceLinkDeviceType(topology.getConnectedDeviceType());
bandwidthWithBiz.setStartTime(epsNodeBandwidth.getStartTime());
bandwidthWithBiz.setEndTime(epsNodeBandwidth.getEndTime());
bandwidthWithBiz.setBusinessId(businessCode);
bandwidthWithBiz.setBusinessName(businessName);
bandwidthWithBiz.setResourceType("2");
bandwidthWithBiz.setServerClientId(serverClientId);
// 执行计算
epsNodeBandwidthService.calculateAvg(bandwidthWithBiz);
}
// businessCode分组处理
if (!records.isEmpty()) {
Map<String, List<EpsMethodChangeRecord>> groupedRecords = records.stream()
.filter(record -> record.getBusinessCode() != null) // 过滤掉businessCode为null的记录
.collect(Collectors.groupingBy(EpsMethodChangeRecord::getBusinessCode));
// 处理businessCode为null的记录如果有
List<EpsMethodChangeRecord> nullBusinessRecords = records.stream()
.filter(record -> record.getBusinessCode() == null)
.collect(Collectors.toList());
// 处理每个业务分组
for (Map.Entry<String, List<EpsMethodChangeRecord>> entry : groupedRecords.entrySet()) {
String businessCode = entry.getKey();
List<EpsMethodChangeRecord> businessRecords = entry.getValue();
if (!nullBusinessRecords.isEmpty()) {
log.warn("交换机 {} 有 {} 条记录的businessCode为null", clientId, nullBusinessRecords.size());
// 可以选择记录日志或进行其他处理
}
// 取第一个有效业务名称
String businessName = businessRecords.stream()
.filter(r -> r.getBusinessName() != null)
.findFirst()
.map(EpsMethodChangeRecord::getBusinessName)
.orElse("未知业务");
// 创建业务带宽对象
EpsNodeBandwidth bandwidthWithBiz = new EpsNodeBandwidth();
bandwidthWithBiz.setSwitchSn(switchSn);
bandwidthWithBiz.setCalculationMode(calculationMode);
bandwidthWithBiz.setInterfaceName(topology.getInterfaceName());
bandwidthWithBiz.setHardwareSn(serverSn);
bandwidthWithBiz.setNodeName(topology.getServerName());
bandwidthWithBiz.setUplinkSwitch(topology.getSwitchName());
bandwidthWithBiz.setInterfaceLinkDeviceType(topology.getConnectedDeviceType());
bandwidthWithBiz.setStartTime(epsNodeBandwidth.getStartTime());
bandwidthWithBiz.setEndTime(epsNodeBandwidth.getEndTime());
bandwidthWithBiz.setBusinessId(businessCode);
bandwidthWithBiz.setBusinessName(businessName);
bandwidthWithBiz.setResourceType("2");
// 执行计算
epsNodeBandwidthService.calculateAvg(bandwidthWithBiz);
return; // 业务变更处理完成后直接返回
}else{
String businessCode = null;
String businessName = null;
// 查询绑定的业务
EpsMethodChangeRecord queryParam = new EpsMethodChangeRecord();
queryParam.setClientId(clientId);
queryParam.setTrafficPort(topology.getServerPort());
List<EpsMethodChangeRecord> recordList = epsMethodChangeRecordService.selectEpsMethodChangeRecordList(queryParam);
if(!recordList.isEmpty()){
EpsMethodChangeRecord record = recordList.stream()
.findFirst()
.orElse(null);
businessCode = record.getBusinessCode();
businessName = record.getBusinessName();
}
// 5. 处理普通情况(无变更记录)
EpsNodeBandwidth normalBandwidth = new EpsNodeBandwidth();
normalBandwidth.setClientId(clientId);
normalBandwidth.setBusinessId(businessCode);
normalBandwidth.setBusinessName(businessName);
normalBandwidth.setCalculationMode(calculationMode);
normalBandwidth.setInterfaceName(topology.getInterfaceName());
normalBandwidth.setHardwareSn(topology.getServerSn());
normalBandwidth.setUplinkSwitch(topology.getSwitchName());
normalBandwidth.setInterfaceLinkDeviceType(topology.getConnectedDeviceType());
normalBandwidth.setStartTime(epsNodeBandwidth.getStartTime());
normalBandwidth.setEndTime(epsNodeBandwidth.getEndTime());
normalBandwidth.setResourceType("2");
normalBandwidth.setServerClientId(serverClientId);
epsNodeBandwidthService.calculateAvg(normalBandwidth);
return;
}
// 处理businessCode为null的记录如果有
List<EpsMethodChangeRecord> nullBusinessRecords = records.stream()
.filter(record -> record.getBusinessCode() == null)
.collect(Collectors.toList());
if (!nullBusinessRecords.isEmpty()) {
log.warn("交换机 {} 有 {} 条记录的businessCode为null", switchSn, nullBusinessRecords.size());
// 可以选择记录日志或进行其他处理
}
return; // 业务变更处理完成后直接返回
}
}else{
// 5. 处理普通情况(无变更记录)
// 5. 处理机房出口情况
EpsNodeBandwidth normalBandwidth = new EpsNodeBandwidth();
normalBandwidth.setSwitchSn(switchSn);
normalBandwidth.setClientId(clientId);
normalBandwidth.setCalculationMode(calculationMode);
normalBandwidth.setInterfaceName(topology.getInterfaceName());
normalBandwidth.setHardwareSn(topology.getServerSn());
normalBandwidth.setNodeName(topology.getServerName());
normalBandwidth.setUplinkSwitch(topology.getSwitchName());
normalBandwidth.setInterfaceLinkDeviceType(topology.getConnectedDeviceType());
normalBandwidth.setStartTime(epsNodeBandwidth.getStartTime());
normalBandwidth.setEndTime(epsNodeBandwidth.getEndTime());
normalBandwidth.setBusinessId(serverConfig.getBusinessCode());
normalBandwidth.setBusinessName(serverConfig.getBusinessName());
normalBandwidth.setResourceType("2");
epsNodeBandwidthService.calculateAvg(normalBandwidth);
}
}else{
log.warn("未检测到拓扑配置交换机clientId{}", clientId);
}
// 5. 处理机房出口情况
EpsNodeBandwidth normalBandwidth = new EpsNodeBandwidth();
normalBandwidth.setSwitchSn(switchSn);
normalBandwidth.setCalculationMode(calculationMode);
normalBandwidth.setInterfaceName(topology.getInterfaceName());
normalBandwidth.setInterfaceLinkDeviceType(topology.getConnectedDeviceType());
normalBandwidth.setStartTime(epsNodeBandwidth.getStartTime());
normalBandwidth.setEndTime(epsNodeBandwidth.getEndTime());
normalBandwidth.setResourceType("2");
epsNodeBandwidthService.calculateAvg(normalBandwidth);
} catch (Exception e) {
log.error("处理交换机 {} 平均带宽失败", switchSn, e);
log.error("处理交换机 {} 平均带宽失败", clientId, e);
}
}
}

View File

@@ -0,0 +1,115 @@
package com.ruoyi.system.controller;
import com.ruoyi.common.core.utils.poi.ExcelUtil;
import com.ruoyi.common.core.web.controller.BaseController;
import com.ruoyi.common.core.web.domain.AjaxResult;
import com.ruoyi.common.core.web.page.PageDomain;
import com.ruoyi.common.core.web.page.TableDataInfo;
import com.ruoyi.common.log.annotation.Log;
import com.ruoyi.common.log.enums.BusinessType;
import com.ruoyi.common.security.annotation.RequiresPermissions;
import com.ruoyi.system.domain.EpsBusinessDeploy;
import com.ruoyi.system.service.IEpsBusinessDeployService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import javax.servlet.http.HttpServletResponse;
import java.util.List;
/**
* 业务下发管理Controller
*
* @author gyt
* @date 2025-10-13
*/
@RestController
@RequestMapping("/businessDeploy")
public class EpsBusinessDeployController extends BaseController
{
@Autowired
private IEpsBusinessDeployService epsBusinessDeployService;
/**
* 查询业务下发管理列表
*/
@RequiresPermissions("system:businessDeploy:list")
@PostMapping("/list")
public TableDataInfo list(@RequestBody EpsBusinessDeploy epsBusinessDeploy)
{
PageDomain pageDomain = new PageDomain();
pageDomain.setPageNum(epsBusinessDeploy.getPageNum());
pageDomain.setPageSize(epsBusinessDeploy.getPageSize());
startPage(pageDomain);
List<EpsBusinessDeploy> list = epsBusinessDeployService.selectEpsBusinessDeployList(epsBusinessDeploy);
return getDataTable(list);
}
/**
* 导出
* @param response
* @param epsBusinessDeploy
*/
@PostMapping("/export")
public void export(HttpServletResponse response, @RequestBody EpsBusinessDeploy epsBusinessDeploy)
{
List<EpsBusinessDeploy> list = epsBusinessDeployService.selectEpsBusinessDeployList(epsBusinessDeploy);
ExcelUtil<EpsBusinessDeploy> util = new ExcelUtil<EpsBusinessDeploy>(EpsBusinessDeploy.class);
util.showColumn(epsBusinessDeploy.getProperties());
util.exportExcel(response, list, "业务下发管理");
}
/**
* 获取业务下发管理详细信息
*/
@RequiresPermissions("system:businessDeploy:query")
@GetMapping(value = "/{id}")
public AjaxResult getInfo(@PathVariable("id") Long id)
{
return success(epsBusinessDeployService.selectEpsBusinessDeployById(id));
}
/**
* 新增业务下发管理
*/
@RequiresPermissions("system:businessDeploy:add")
@Log(title = "业务下发管理", businessType = BusinessType.INSERT)
@PostMapping
public AjaxResult add(@RequestBody EpsBusinessDeploy epsBusinessDeploy)
{
return toAjax(epsBusinessDeployService.insertEpsBusinessDeploy(epsBusinessDeploy));
}
/**
* 修改业务下发管理
*/
@RequiresPermissions("system:businessDeploy:edit")
@Log(title = "业务下发管理", businessType = BusinessType.UPDATE)
@PutMapping
public AjaxResult edit(@RequestBody EpsBusinessDeploy epsBusinessDeploy)
{
return toAjax(epsBusinessDeployService.updateEpsBusinessDeploy(epsBusinessDeploy));
}
/**
* 删除业务下发管理
*/
@RequiresPermissions("system:businessDeploy:remove")
@Log(title = "业务下发管理", businessType = BusinessType.DELETE)
@DeleteMapping("/{ids}")
public AjaxResult remove(@PathVariable Long[] ids)
{
return toAjax(epsBusinessDeployService.deleteEpsBusinessDeployByIds(ids));
}
/**
* 审核
* @param epsBusinessDeploy
* @return
*/
@RequiresPermissions("system:businessDeploy:review")
@PostMapping("/reviewBusiness")
public AjaxResult reviewBusiness(@RequestBody EpsBusinessDeploy epsBusinessDeploy){
return toAjax(epsBusinessDeployService.reviewBusiness(epsBusinessDeploy));
}
}

View File

@@ -0,0 +1,109 @@
package com.ruoyi.system.controller;
import com.ruoyi.common.core.domain.R;
import com.ruoyi.common.core.web.controller.BaseController;
import com.ruoyi.common.core.web.domain.AjaxResult;
import com.ruoyi.common.core.web.page.PageDomain;
import com.ruoyi.common.core.web.page.TableDataInfo;
import com.ruoyi.common.log.annotation.Log;
import com.ruoyi.common.log.enums.BusinessType;
import com.ruoyi.common.security.annotation.InnerAuth;
import com.ruoyi.common.security.annotation.RequiresPermissions;
import com.ruoyi.system.domain.EpsBusinessScript;
import com.ruoyi.system.service.IEpsBusinessScriptService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import java.util.List;
/**
* 业务脚本管理Controller
*
* @author gyt
* @date 2025-10-13
*/
@RestController
@RequestMapping("/businessScript")
public class EpsBusinessScriptController extends BaseController
{
@Autowired
private IEpsBusinessScriptService epsBusinessScriptService;
/**
* 查询业务脚本管理列表
*/
@RequiresPermissions("system:businessScript:list")
@PostMapping("/list")
public TableDataInfo list(@RequestBody EpsBusinessScript epsBusinessScript)
{
PageDomain pageDomain = new PageDomain();
pageDomain.setPageNum(epsBusinessScript.getPageNum());
pageDomain.setPageSize(epsBusinessScript.getPageSize());
startPage(pageDomain);
List<EpsBusinessScript> list = epsBusinessScriptService.selectEpsBusinessScriptList(epsBusinessScript);
return getDataTable(list);
}
/**
* 获取业务脚本管理详细信息
*/
@RequiresPermissions("system:businessScript:query")
@GetMapping(value = "/{id}")
public AjaxResult getInfo(@PathVariable("id") Long id)
{
return success(epsBusinessScriptService.selectEpsBusinessScriptById(id));
}
/**
* 获取业务脚本管理详细信息
*/
@GetMapping(value = "/inner/{id}")
@InnerAuth
public R<EpsBusinessScript> innerGetInfo(@PathVariable("id") Long id)
{
return R.ok(epsBusinessScriptService.selectEpsBusinessScriptById(id));
}
/**
* 新增业务脚本管理
*/
@RequiresPermissions("system:businessScript:add")
@Log(title = "业务脚本管理", businessType = BusinessType.INSERT)
@PostMapping
public AjaxResult add(@RequestBody EpsBusinessScript epsBusinessScript)
{
return toAjax(epsBusinessScriptService.insertEpsBusinessScript(epsBusinessScript));
}
/**
* 修改业务脚本管理
*/
@RequiresPermissions("system:businessScript:edit")
@Log(title = "业务脚本管理", businessType = BusinessType.UPDATE)
@PutMapping
public AjaxResult edit(@RequestBody EpsBusinessScript epsBusinessScript)
{
return toAjax(epsBusinessScriptService.updateEpsBusinessScript(epsBusinessScript));
}
/**
* 删除业务脚本管理
*/
@RequiresPermissions("system:businessScript:remove")
@Log(title = "业务脚本管理", businessType = BusinessType.DELETE)
@DeleteMapping("/{ids}")
public AjaxResult remove(@PathVariable Long[] ids)
{
return toAjax(epsBusinessScriptService.deleteEpsBusinessScriptByIds(ids));
}
/**
* 获取所有业务脚本名称
* @return
*/
@RequiresPermissions("system:businessScript:list")
@GetMapping("/getAllScriptName")
public AjaxResult getAllScriptName(){
List<EpsBusinessScript> list = epsBusinessScriptService.selectEpsBusinessScriptList(new EpsBusinessScript());
return success(list);
}
}

View File

@@ -1,5 +1,7 @@
package com.ruoyi.system.controller;
import com.ruoyi.common.core.web.domain.AjaxResult;
import com.ruoyi.common.security.annotation.RequiresPermissions;
import com.ruoyi.system.domain.EpsInitialTrafficData;
import com.ruoyi.system.service.EpsInitialTrafficDataService;
import lombok.RequiredArgsConstructor;
@@ -10,13 +12,16 @@ import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import java.util.List;
import java.util.Map;
import static com.ruoyi.common.core.web.domain.AjaxResult.success;
/**
* EPS初始流量数据控制器
* 提供流量数据的REST接口
*/
@RestController
@RequestMapping("/eps-traffic-data")
@RequestMapping("/epsTrafficData")
@RequiredArgsConstructor
public class EpsInitialTrafficDataController {
@@ -53,4 +58,35 @@ public class EpsInitialTrafficDataController {
List<EpsInitialTrafficData> result = epsInitialTrafficDataService.query(queryParam);
return ResponseEntity.ok(result);
}
/**
* 图形分析 - 95值/日
* @return
*/
@RequiresPermissions("system:bandwidth:list")
@PostMapping("/getServerGraphicalAnalysisDaily")
public AjaxResult getServerGraphicalAnalysisDaily(@RequestBody EpsInitialTrafficData queryParam){
List<Map<String, Object>> echartsData = epsInitialTrafficDataService.getServerGraphicalAnalysisDaily(queryParam);
return success(echartsData);
}
/**
* 图形分析 - 95值/日
* @return
*/
@RequiresPermissions("system:bandwidth:list")
@PostMapping("/getServerGraphicalAnalysisMonthy")
public AjaxResult getServerGraphicalAnalysisMonthy(@RequestBody EpsInitialTrafficData queryParam){
List<Map<String, Object>> echartsData = epsInitialTrafficDataService.getServerGraphicalAnalysisMonthy(queryParam);
return success(echartsData);
}
/**
* 监控看板-详情视图 出入流量
*/
// @RequiresPermissions("system:bandwidth:list")
// @PostMapping("/getServerTrafficByMonitorView")
// public AjaxResult getServerTrafficByMonitorView(@RequestBody EpsInitialTrafficData queryParam)
// {
// Map<String, Object> echartsData = epsInitialTrafficDataService.getServerTrafficByMonitorView(queryParam);
// return success(echartsData);
// }
}

View File

@@ -1,6 +1,7 @@
package com.ruoyi.system.controller;
import com.github.pagehelper.PageInfo;
import com.ruoyi.common.core.domain.R;
import com.ruoyi.common.core.exception.ServiceException;
import com.ruoyi.common.core.utils.DateUtils;
import com.ruoyi.common.core.utils.poi.ExcelUtil;
@@ -10,6 +11,7 @@ import com.ruoyi.common.core.web.page.PageDomain;
import com.ruoyi.common.core.web.page.TableDataInfo;
import com.ruoyi.common.log.annotation.Log;
import com.ruoyi.common.log.enums.BusinessType;
import com.ruoyi.common.security.annotation.InnerAuth;
import com.ruoyi.common.security.annotation.RequiresPermissions;
import com.ruoyi.system.domain.EpsInitialTrafficData;
import com.ruoyi.system.domain.EpsNodeBandwidth;
@@ -154,16 +156,13 @@ public class EpsNodeBandwidthController extends BaseController
}
/**
* 相关数据
*/
@RequiresPermissions("system:bandwidth:query")
@GetMapping(value = "relatedData/traffic")
/**
* 根据ID获取相关数据
* @param id 资源ID
* @return 表格数据信息
*/
@RequiresPermissions("system:bandwidth:query")
@GetMapping(value = "relatedData/traffic")
public TableDataInfo relatedData(Long id,Integer pageNum,Integer pageSize) {
// 1. 参数校验
if (id == null || id <= 0) {
@@ -319,4 +318,32 @@ public class EpsNodeBandwidthController extends BaseController
List<Map> list = epsNodeBandwidthService.graphicalAnalysis(epsNodeBandwidth, "7", ChronoUnit.MONTHS);
return success(list);
}
/**
* 查询节点带宽信息列表
*/
@PostMapping("/getEpsNodeBandWidthList")
@InnerAuth
public R<List<EpsNodeBandwidth>> getEpsNodeBandWidthList(@RequestBody EpsNodeBandwidth epsNodeBandwidth)
{
List<EpsNodeBandwidth> list = epsNodeBandwidthService.selectEpsNodeBandwidthList(epsNodeBandwidth);
return R.ok(list);
}
/**
* 监控看板-详情视图 95值列表
* @param epsNodeBandwidth
* @return
*/
@RequiresPermissions("system:bandwidth:list")
@PostMapping("/getListByMonitorView")
public TableDataInfo getListByMonitorView(@RequestBody EpsNodeBandwidth epsNodeBandwidth)
{
PageDomain pageDomain = new PageDomain();
pageDomain.setPageNum(epsNodeBandwidth.getPageNum());
pageDomain.setPageSize(epsNodeBandwidth.getPageSize());
startPage(pageDomain);
List<EpsNodeBandwidth> list = epsNodeBandwidthService.getListByMonitorView(epsNodeBandwidth);
return getDataTable(list);
}
}

View File

@@ -0,0 +1,160 @@
package com.ruoyi.system.controller;
import com.github.pagehelper.PageInfo;
import com.ruoyi.common.core.utils.poi.ExcelUtil;
import com.ruoyi.common.core.web.controller.BaseController;
import com.ruoyi.common.core.web.domain.AjaxResult;
import com.ruoyi.common.core.web.page.PageDomain;
import com.ruoyi.common.core.web.page.TableDataInfo;
import com.ruoyi.common.log.annotation.Log;
import com.ruoyi.common.log.enums.BusinessType;
import com.ruoyi.common.security.annotation.RequiresPermissions;
import com.ruoyi.system.domain.EpsTaskStatistics;
import com.ruoyi.system.service.IEpsTaskStatisticsService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import javax.servlet.http.HttpServletResponse;
import java.util.List;
import java.util.Map;
/**
* 业务95值计算任务Controller
*
* @author gyt
* @date 2025-10-29
*/
@RestController
@RequestMapping("/taskStatistics")
public class EpsTaskStatisticsController extends BaseController
{
@Autowired
private IEpsTaskStatisticsService epsTaskStatisticsService;
/**
* 查询业务95值计算任务列表
*/
@RequiresPermissions("system:taskStatistics:list")
@PostMapping("/list")
public TableDataInfo list(@RequestBody EpsTaskStatistics epsTaskStatistics)
{
PageDomain pageDomain = new PageDomain();
pageDomain.setPageNum(epsTaskStatistics.getPageNum());
pageDomain.setPageSize(epsTaskStatistics.getPageSize());
startPage(pageDomain);
List<EpsTaskStatistics> list = epsTaskStatisticsService.selectEpsTaskStatisticsList(epsTaskStatistics);
return getDataTable(list);
}
/**
* 导出业务95值计算任务列表
*/
@RequiresPermissions("system:taskStatistics:export")
@Log(title = "业务95值计算任务", businessType = BusinessType.EXPORT)
@PostMapping("/export")
public void export(HttpServletResponse response, @RequestBody EpsTaskStatistics epsTaskStatistics)
{
List<EpsTaskStatistics> list = epsTaskStatisticsService.selectEpsTaskStatisticsList(epsTaskStatistics);
ExcelUtil<EpsTaskStatistics> util = new ExcelUtil<EpsTaskStatistics>(EpsTaskStatistics.class);
util.showColumn(epsTaskStatistics.getProperties());
util.exportExcel(response, list, "业务95值计算任务数据");
}
/**
* 获取业务95值计算任务详细信息
*/
@RequiresPermissions("system:taskStatistics:query")
@GetMapping(value = "/{id}")
public AjaxResult getInfo(@PathVariable("id") Long id)
{
return success(epsTaskStatisticsService.selectEpsTaskStatisticsById(id));
}
/**
* 新增业务95值计算任务
*/
@RequiresPermissions("system:taskStatistics:add")
@Log(title = "业务95值计算任务", businessType = BusinessType.INSERT)
@PostMapping
public AjaxResult add(@RequestBody EpsTaskStatistics epsTaskStatistics)
{
return toAjax(epsTaskStatisticsService.insertEpsTaskStatistics(epsTaskStatistics));
}
/**
* 修改业务95值计算任务
*/
@RequiresPermissions("system:taskStatistics:edit")
@Log(title = "业务95值计算任务", businessType = BusinessType.UPDATE)
@PutMapping
public AjaxResult edit(@RequestBody EpsTaskStatistics epsTaskStatistics)
{
return toAjax(epsTaskStatisticsService.updateEpsTaskStatistics(epsTaskStatistics));
}
/**
* 删除业务95值计算任务
*/
@RequiresPermissions("system:taskStatistics:remove")
@Log(title = "业务95值计算任务", businessType = BusinessType.DELETE)
@DeleteMapping("/{ids}")
public AjaxResult remove(@PathVariable Long[] ids)
{
return toAjax(epsTaskStatisticsService.deleteEpsTaskStatisticsByIds(ids));
}
/**
* 相关数据查询
*/
@RequiresPermissions("system:taskStatistics:list")
@PostMapping("/getRelateData")
public TableDataInfo getRelateData(@RequestBody EpsTaskStatistics epsTaskStatistics)
{
PageInfo<?> list = epsTaskStatisticsService.getRelateData(epsTaskStatistics);
return getDataTable(list.getList(), list.getTotal());
}
/**
* 修改相关数据
* @param epsTaskStatistics
* @return
*/
@RequiresPermissions("system:taskStatistics:edit")
@PostMapping("/updateRelateData")
public AjaxResult updateRelateData(@RequestBody EpsTaskStatistics epsTaskStatistics)
{
int rows = epsTaskStatisticsService.updateRelateData(epsTaskStatistics);
return toAjax(rows);
}
/**
* 重新计算
*/
@RequiresPermissions("system:taskStatistics:list")
@PostMapping("/recaculate")
public AjaxResult recaculate(@RequestBody EpsTaskStatistics epsTaskStatistics)
{
int rows = epsTaskStatisticsService.recaculate(epsTaskStatistics);
return toAjax(rows);
}
/**
* 图形查看
*/
@RequiresPermissions("system:taskStatistics:list")
@PostMapping("/getRraphicalMsg")
public AjaxResult getRraphicalMsg(@RequestBody EpsTaskStatistics epsTaskStatistics)
{
Map echartsMap = epsTaskStatisticsService.getRraphicalMsg(epsTaskStatistics);
return success(echartsMap);
}
/**
* 获取月均日95值的日列表
* @param epsTaskStatistics
* @return
*/
@RequiresPermissions("system:taskStatistics:list")
@PostMapping("/getAvgTimeList")
public AjaxResult getAvgTimeList(@RequestBody EpsTaskStatistics epsTaskStatistics)
{
List<String> avgTimeList = epsTaskStatisticsService.getAvgTimeList(epsTaskStatistics);
return success(avgTimeList);
}
}

View File

@@ -16,6 +16,7 @@ import org.springframework.web.bind.annotation.*;
import javax.servlet.http.HttpServletResponse;
import java.util.List;
import java.util.Map;
/**
* 交换机监控信息Controller
@@ -105,4 +106,45 @@ public class InitialSwitchInfoDetailsController extends BaseController
{
return initialSwitchInfoDetailsService.autoSaveSwitchTraffic(initialSwitchInfoDetails);
}
/**
* 图形分析-95带宽值mbps/日 v1.1
*/
@RequiresPermissions("system:bandwidth:list")
@PostMapping("/getGraphicalAnalysisDaily")
public AjaxResult getGraphicalAnalysisDaily(@RequestBody InitialSwitchInfoDetails initialSwitchInfoDetails)
{
List<Map<String, Object>> echartsData = initialSwitchInfoDetailsService.getGraphicalAnalysisDaily(initialSwitchInfoDetails);
return success(echartsData);
}
/**
* 图形分析-95带宽值mbps/月 v1.1
*/
@RequiresPermissions("system:bandwidth:list")
@PostMapping("/getGraphicalAnalysisMonthy")
public AjaxResult getGraphicalAnalysisMonthy(@RequestBody InitialSwitchInfoDetails initialSwitchInfoDetails)
{
List<Map<String, Object>> echartsData = initialSwitchInfoDetailsService.getGraphicalAnalysisMonthy(initialSwitchInfoDetails);
return success(echartsData);
}
/**
* 监控看板-详情视图 出入流量
*/
// @RequiresPermissions("system:bandwidth:list")
// @PostMapping("/getSwitchTrafficByMonitorView")
// public AjaxResult getSwitchTrafficByMonitorView(@RequestBody InitialSwitchInfoDetails initialSwitchInfoDetails)
// {
// Map<String, Object> echartsData = initialSwitchInfoDetailsService.getMonitorViewDetails(initialSwitchInfoDetails);
// return success(echartsData);
// }
/**
* 监控看板-详情视图 出入流量列表
*/
@RequiresPermissions("system:bandwidth:list")
@PostMapping("/geSwitchListByMonitorView")
public TableDataInfo geSwitchListByMonitorView(@RequestBody InitialSwitchInfoDetails initialSwitchInfoDetails)
{
List<InitialSwitchInfoDetails> list = initialSwitchInfoDetailsService.geSwitchListByMonitorView(initialSwitchInfoDetails);
return getDataTable(list);
}
}

View File

@@ -0,0 +1,96 @@
package com.ruoyi.system.controller;
import com.ruoyi.common.core.utils.poi.ExcelUtil;
import com.ruoyi.common.core.web.controller.BaseController;
import com.ruoyi.common.core.web.domain.AjaxResult;
import com.ruoyi.common.log.annotation.Log;
import com.ruoyi.common.log.enums.BusinessType;
import com.ruoyi.common.security.annotation.RequiresPermissions;
import com.ruoyi.system.domain.RmMonitorConfig;
import com.ruoyi.system.service.IRmMonitorConfigService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import javax.servlet.http.HttpServletResponse;
import java.util.List;
/**
* 监控配置Controller
*
* @author gyt
* @date 2025-11-12
*/
@RestController
@RequestMapping("/monitorConfig")
public class RmMonitorConfigController extends BaseController
{
@Autowired
private IRmMonitorConfigService rmMonitorConfigService;
/**
* 查询监控配置列表
*/
@RequiresPermissions("system:monitorConfig:list")
@PostMapping("/list")
public AjaxResult list(@RequestBody RmMonitorConfig rmMonitorConfig)
{
List<RmMonitorConfig> list = rmMonitorConfigService.selectRmMonitorConfigList(rmMonitorConfig);
return success(list);
}
/**
* 导出监控配置列表
*/
@RequiresPermissions("system:monitorConfig:export")
@Log(title = "监控配置", businessType = BusinessType.EXPORT)
@PostMapping("/export")
public void export(HttpServletResponse response, RmMonitorConfig rmMonitorConfig)
{
List<RmMonitorConfig> list = rmMonitorConfigService.selectRmMonitorConfigList(rmMonitorConfig);
ExcelUtil<RmMonitorConfig> util = new ExcelUtil<RmMonitorConfig>(RmMonitorConfig.class);
util.exportExcel(response, list, "监控配置数据");
}
/**
* 获取监控配置详细信息
*/
@RequiresPermissions("system:monitorConfig:query")
@GetMapping(value = "/{id}")
public AjaxResult getInfo(@PathVariable("id") Long id)
{
return success(rmMonitorConfigService.selectRmMonitorConfigById(id));
}
/**
* 新增监控配置
*/
@RequiresPermissions("system:monitorConfig:add")
@Log(title = "监控配置", businessType = BusinessType.INSERT)
@PostMapping
public AjaxResult add(@RequestBody RmMonitorConfig rmMonitorConfig)
{
return toAjax(rmMonitorConfigService.insertRmMonitorConfig(rmMonitorConfig));
}
/**
* 修改监控配置
*/
@RequiresPermissions("system:monitorConfig:edit")
@Log(title = "监控配置", businessType = BusinessType.UPDATE)
@PutMapping
public AjaxResult edit(@RequestBody RmMonitorConfig rmMonitorConfig)
{
return toAjax(rmMonitorConfigService.updateRmMonitorConfig(rmMonitorConfig));
}
/**
* 删除监控配置
*/
@RequiresPermissions("system:monitorConfig:remove")
@Log(title = "监控配置", businessType = BusinessType.DELETE)
@DeleteMapping("/{ids}")
public AjaxResult remove(@PathVariable Long[] ids)
{
return toAjax(rmMonitorConfigService.deleteRmMonitorConfigByIds(ids));
}
}

View File

@@ -0,0 +1,40 @@
package com.ruoyi.system.controller;
import com.ruoyi.common.core.web.controller.BaseController;
import com.ruoyi.common.core.web.domain.AjaxResult;
import com.ruoyi.common.security.annotation.RequiresPermissions;
import com.ruoyi.system.domain.RmMonitorConfigDetails;
import com.ruoyi.system.service.IRmMonitorConfigDetailsService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import java.util.List;
import java.util.Map;
/**
* 监控看板详情Controller
*
* @author gyt
* @date 2025-11-14
*/
@RestController
@RequestMapping("/monitorConfigDetails")
public class RmMonitorConfigDetailsController extends BaseController
{
@Autowired
private IRmMonitorConfigDetailsService rmMonitorConfigDetailsService;
/**
* 监控看板-详情视图 出入流量
*/
@RequiresPermissions("system:bandwidth:list")
@PostMapping("/getTrafficByMonitorView")
public AjaxResult getTrafficByMonitorView(@RequestBody RmMonitorConfigDetails queryParam)
{
List<Map<String, Object>> echartsData = rmMonitorConfigDetailsService.getTrafficByMonitorView(queryParam);
return success(echartsData);
}
}

View File

@@ -0,0 +1,105 @@
package com.ruoyi.system.controller;
import java.util.List;
import java.io.IOException;
import javax.servlet.http.HttpServletResponse;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import com.ruoyi.common.log.annotation.Log;
import com.ruoyi.common.log.enums.BusinessType;
import com.ruoyi.common.security.annotation.RequiresPermissions;
import com.ruoyi.system.domain.RmRegistrationMachine;
import com.ruoyi.system.service.IRmRegistrationMachineService;
import com.ruoyi.common.core.web.controller.BaseController;
import com.ruoyi.common.core.web.domain.AjaxResult;
import com.ruoyi.common.core.utils.poi.ExcelUtil;
import com.ruoyi.common.core.web.page.TableDataInfo;
/**
* 绑定金山machinecodeController
*
* @author gyt
* @date 2025-10-10
*/
@RestController
@RequestMapping("/machine")
public class RmRegistrationMachineController extends BaseController
{
@Autowired
private IRmRegistrationMachineService rmRegistrationMachineService;
/**
* 查询绑定金山machinecode列表
*/
@RequiresPermissions("system:machine:list")
@GetMapping("/list")
public TableDataInfo list(RmRegistrationMachine rmRegistrationMachine)
{
startPage();
List<RmRegistrationMachine> list = rmRegistrationMachineService.selectRmRegistrationMachineList(rmRegistrationMachine);
return getDataTable(list);
}
/**
* 导出绑定金山machinecode列表
*/
@RequiresPermissions("system:machine:export")
@Log(title = "绑定金山machinecode", businessType = BusinessType.EXPORT)
@PostMapping("/export")
public void export(HttpServletResponse response, RmRegistrationMachine rmRegistrationMachine)
{
List<RmRegistrationMachine> list = rmRegistrationMachineService.selectRmRegistrationMachineList(rmRegistrationMachine);
ExcelUtil<RmRegistrationMachine> util = new ExcelUtil<RmRegistrationMachine>(RmRegistrationMachine.class);
util.exportExcel(response, list, "绑定金山machinecode数据");
}
/**
* 获取绑定金山machinecode详细信息
*/
@RequiresPermissions("system:machine:query")
@GetMapping(value = "/{id}")
public AjaxResult getInfo(@PathVariable("id") Long id)
{
return success(rmRegistrationMachineService.selectRmRegistrationMachineById(id));
}
/**
* 新增绑定金山machinecode
*/
@RequiresPermissions("system:machine:add")
@Log(title = "绑定金山machinecode", businessType = BusinessType.INSERT)
@PostMapping
public AjaxResult add(@RequestBody RmRegistrationMachine rmRegistrationMachine)
{
return toAjax(rmRegistrationMachineService.insertRmRegistrationMachine(rmRegistrationMachine));
}
/**
* 修改绑定金山machinecode
*/
@RequiresPermissions("system:machine:edit")
@Log(title = "绑定金山machinecode", businessType = BusinessType.UPDATE)
@PutMapping
public AjaxResult edit(@RequestBody RmRegistrationMachine rmRegistrationMachine)
{
return toAjax(rmRegistrationMachineService.updateRmRegistrationMachine(rmRegistrationMachine));
}
/**
* 删除绑定金山machinecode
*/
@RequiresPermissions("system:machine:remove")
@Log(title = "绑定金山machinecode", businessType = BusinessType.DELETE)
@DeleteMapping("/{ids}")
public AjaxResult remove(@PathVariable Long[] ids)
{
return toAjax(rmRegistrationMachineService.deleteRmRegistrationMachineByIds(ids));
}
}

View File

@@ -4,12 +4,13 @@ import com.ruoyi.common.core.domain.R;
import com.ruoyi.common.core.utils.poi.ExcelUtil;
import com.ruoyi.common.core.web.controller.BaseController;
import com.ruoyi.common.core.web.domain.AjaxResult;
import com.ruoyi.common.core.web.page.PageDomain;
import com.ruoyi.common.core.web.page.TableDataInfo;
import com.ruoyi.common.log.annotation.Log;
import com.ruoyi.common.log.enums.BusinessType;
import com.ruoyi.common.security.annotation.InnerAuth;
import com.ruoyi.common.security.annotation.RequiresPermissions;
import com.ruoyi.system.api.domain.RmRegisterMsgRemote;
import com.ruoyi.system.api.domain.RmResourceRegistrationRemote;
import com.ruoyi.system.domain.RmResourceRegistration;
import com.ruoyi.system.service.IRmResourceRegistrationService;
import org.springframework.beans.factory.annotation.Autowired;
@@ -39,12 +40,11 @@ public class RmResourceRegistrationController extends BaseController
@PostMapping("/list")
public TableDataInfo list(@RequestBody RmResourceRegistration rmResourceRegistration)
{
PageDomain pageDomain = new PageDomain();
pageDomain.setPageNum(rmResourceRegistration.getPageNum());
pageDomain.setPageSize(rmResourceRegistration.getPageSize());
startPage(pageDomain);
List<RmResourceRegistration> list = rmResourceRegistrationService.selectRmResourceRegistrationList(rmResourceRegistration);
return getDataTable(list);
Map<String, Object> resultMap = rmResourceRegistrationService.getRegistrationTableInfoList(rmResourceRegistration);
if(rmResourceRegistration.getQueryParam() != null){
return getDataTable((List<RmResourceRegistration>) resultMap.get("list"), (int) resultMap.get("total"));
}
return getDataTable((List<RmResourceRegistration>) resultMap.get("list"));
}
/**
@@ -163,7 +163,91 @@ public class RmResourceRegistrationController extends BaseController
public R<RmResourceRegistration> getListByHardwareSn(@RequestBody RmResourceRegistration rmResourceRegistration)
{
List<RmResourceRegistration> list = rmResourceRegistrationService.selectRmResourceRegistrationList(rmResourceRegistration);
return R.ok(list.get(0));
if(list != null && !list.isEmpty()){
return R.ok(list.get(0));
}
return R.ok(new RmResourceRegistration());
}
/**
* 查询资源注册列表
*/
@RequiresPermissions("system:registration:list")
@PostMapping("/getRegistList")
public AjaxResult getRegistList(@RequestBody RmResourceRegistration rmResourceRegistration)
{
List<RmResourceRegistration> list = rmResourceRegistrationService.selectRmResourceRegistrationList(rmResourceRegistration);
return success(list);
}
/**
* 自动注册服务器
* @param rmResourceRegistration mq接收的消息
* @return
*/
@PostMapping("/innerAddRegist")
@InnerAuth
public R<Integer> innerAddRegist(@RequestBody RmRegisterMsgRemote rmResourceRegistration)
{
int rows = rmResourceRegistrationService.innerAddRegist(rmResourceRegistration);
return R.ok(rows);
}
/**
* 添加节点标识
* @param rmResourceRegistration mq接收的消息
* @return
*/
@PostMapping("/innerUpdateRegist")
@InnerAuth
public R<Integer> innerUpdateRegist(@RequestBody RmResourceRegistrationRemote rmResourceRegistration)
{
int rows = rmResourceRegistrationService.innerUpdateRegist(rmResourceRegistration);
return R.ok(rows);
}
/**
* 选择公网业务IP
*/
@RequiresPermissions("system:registration:update")
@PostMapping("/bindBusinessPubulicIp")
public AjaxResult bindBusinessPubulicIp(@RequestBody RmResourceRegistration rmResourceRegistration)
{
int rows = rmResourceRegistrationService.bindBusinessPublicIp(rmResourceRegistration);
return toAjax(rows);
}
/**
* 查询所有逻辑标识节点
* @return 资源注册集合
*/
@RequiresPermissions("system:registration:list")
@GetMapping("/getAllLogicalNodeId")
public List<Map> getAllLogicalNodeId()
{
List<Map> list = rmResourceRegistrationService.getAllLogicalNodeId();
return list;
}
/**
* 绑定业务名称
* @return 资源注册集合
*/
@RequiresPermissions("system:registration:list")
@PostMapping("/bindBusinessByClientIds")
public AjaxResult bindBusinessByClientIds(@RequestBody RmResourceRegistration rmResourceRegistration)
{
int rows = rmResourceRegistrationService.bindBusinessByClientIds(rmResourceRegistration);
return toAjax(rows);
}
/**
* 根据clientId查询详情
* @return 资源注册集合
*/
@RequiresPermissions("system:registration:list")
@PostMapping("/getServerMsgByClientId")
public AjaxResult getServerMsgByClientId(@RequestBody RmResourceRegistration rmResourceRegistration)
{
List<RmResourceRegistration> list = rmResourceRegistrationService.selectRmResourceRegistrationList(rmResourceRegistration);
if(list != null && !list.isEmpty()){
return success(list.get(0));
}
return success(list);
}
}

View File

@@ -0,0 +1,105 @@
package com.ruoyi.system.controller;
import java.util.List;
import java.io.IOException;
import javax.servlet.http.HttpServletResponse;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import com.ruoyi.common.log.annotation.Log;
import com.ruoyi.common.log.enums.BusinessType;
import com.ruoyi.common.security.annotation.RequiresPermissions;
import com.ruoyi.system.domain.RmSwitchInterfaceInfo;
import com.ruoyi.system.service.IRmSwitchInterfaceInfoService;
import com.ruoyi.common.core.web.controller.BaseController;
import com.ruoyi.common.core.web.domain.AjaxResult;
import com.ruoyi.common.core.utils.poi.ExcelUtil;
import com.ruoyi.common.core.web.page.TableDataInfo;
/**
* 交换机接口信息Controller
*
* @author gyt
* @date 2025-10-10
*/
@RestController
@RequestMapping("/switchInterfaceInfo")
public class RmSwitchInterfaceInfoController extends BaseController
{
@Autowired
private IRmSwitchInterfaceInfoService rmSwitchInterfaceInfoService;
/**
* 查询交换机接口信息列表
*/
@RequiresPermissions("system:switchInterfaceInfo:list")
@GetMapping("/list")
public TableDataInfo list(RmSwitchInterfaceInfo rmSwitchInterfaceInfo)
{
startPage();
List<RmSwitchInterfaceInfo> list = rmSwitchInterfaceInfoService.selectRmSwitchInterfaceInfoList(rmSwitchInterfaceInfo);
return getDataTable(list);
}
/**
* 导出交换机接口信息列表
*/
@RequiresPermissions("system:switchInterfaceInfo:export")
@Log(title = "交换机接口信息", businessType = BusinessType.EXPORT)
@PostMapping("/export")
public void export(HttpServletResponse response, RmSwitchInterfaceInfo rmSwitchInterfaceInfo)
{
List<RmSwitchInterfaceInfo> list = rmSwitchInterfaceInfoService.selectRmSwitchInterfaceInfoList(rmSwitchInterfaceInfo);
ExcelUtil<RmSwitchInterfaceInfo> util = new ExcelUtil<RmSwitchInterfaceInfo>(RmSwitchInterfaceInfo.class);
util.exportExcel(response, list, "交换机接口信息数据");
}
/**
* 获取交换机接口信息详细信息
*/
@RequiresPermissions("system:switchInterfaceInfo:query")
@GetMapping(value = "/{id}")
public AjaxResult getInfo(@PathVariable("id") Long id)
{
return success(rmSwitchInterfaceInfoService.selectRmSwitchInterfaceInfoById(id));
}
/**
* 新增交换机接口信息
*/
@RequiresPermissions("system:switchInterfaceInfo:add")
@Log(title = "交换机接口信息", businessType = BusinessType.INSERT)
@PostMapping
public AjaxResult add(@RequestBody RmSwitchInterfaceInfo rmSwitchInterfaceInfo)
{
return toAjax(rmSwitchInterfaceInfoService.insertRmSwitchInterfaceInfo(rmSwitchInterfaceInfo));
}
/**
* 修改交换机接口信息
*/
@RequiresPermissions("system:switchInterfaceInfo:edit")
@Log(title = "交换机接口信息", businessType = BusinessType.UPDATE)
@PutMapping
public AjaxResult edit(@RequestBody RmSwitchInterfaceInfo rmSwitchInterfaceInfo)
{
return toAjax(rmSwitchInterfaceInfoService.updateRmSwitchInterfaceInfo(rmSwitchInterfaceInfo));
}
/**
* 删除交换机接口信息
*/
@RequiresPermissions("system:switchInterfaceInfo:remove")
@Log(title = "交换机接口信息", businessType = BusinessType.DELETE)
@DeleteMapping("/{ids}")
public AjaxResult remove(@PathVariable Long[] ids)
{
return toAjax(rmSwitchInterfaceInfoService.deleteRmSwitchInterfaceInfoByIds(ids));
}
}

View File

@@ -0,0 +1,144 @@
package com.ruoyi.system.controller;
import com.ruoyi.common.core.domain.R;
import com.ruoyi.common.core.utils.poi.ExcelUtil;
import com.ruoyi.common.core.web.controller.BaseController;
import com.ruoyi.common.core.web.domain.AjaxResult;
import com.ruoyi.common.core.web.page.PageDomain;
import com.ruoyi.common.core.web.page.TableDataInfo;
import com.ruoyi.common.log.annotation.Log;
import com.ruoyi.common.log.enums.BusinessType;
import com.ruoyi.common.security.annotation.InnerAuth;
import com.ruoyi.common.security.annotation.RequiresPermissions;
import com.ruoyi.system.domain.RmSwitchManagement;
import com.ruoyi.system.service.IRmSwitchManagementService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import javax.servlet.http.HttpServletResponse;
import java.util.List;
/**
* 交换机管理Controller
*
* @author gyt
* @date 2025-10-10
*/
@RestController
@RequestMapping("/switchManagement")
public class RmSwitchManagementController extends BaseController
{
@Autowired
private IRmSwitchManagementService rmSwitchManagementService;
/**
* 查询交换机管理列表
*/
@RequiresPermissions("system:switchManagement:list")
@PostMapping("/list")
public TableDataInfo list(@RequestBody RmSwitchManagement rmSwitchManagement)
{
PageDomain pageDomain = new PageDomain();
pageDomain.setPageNum(rmSwitchManagement.getPageNum());
pageDomain.setPageSize(rmSwitchManagement.getPageSize());
startPage(pageDomain);
List<RmSwitchManagement> list = rmSwitchManagementService.selectRmSwitchManagementList(rmSwitchManagement);
return getDataTable(list);
}
/**
* 导出交换机管理列表
*/
@RequiresPermissions("system:switchManagement:export")
@Log(title = "交换机管理", businessType = BusinessType.EXPORT)
@PostMapping("/export")
public void export(HttpServletResponse response, RmSwitchManagement rmSwitchManagement)
{
List<RmSwitchManagement> list = rmSwitchManagementService.selectRmSwitchManagementList(rmSwitchManagement);
ExcelUtil<RmSwitchManagement> util = new ExcelUtil<RmSwitchManagement>(RmSwitchManagement.class);
util.showColumn(rmSwitchManagement.getProperties());
util.exportExcel(response, list, "交换机管理数据");
}
/**
* 获取交换机管理详细信息
*/
@RequiresPermissions("system:switchManagement:query")
@GetMapping(value = "/{id}")
public AjaxResult getInfo(@PathVariable("id") Long id)
{
return success(rmSwitchManagementService.selectRmSwitchManagementById(id));
}
/**
* 新增交换机管理
*/
@RequiresPermissions("system:switchManagement:add")
@Log(title = "交换机管理", businessType = BusinessType.INSERT)
@PostMapping
public AjaxResult add(@RequestBody RmSwitchManagement rmSwitchManagement)
{
return toAjax(rmSwitchManagementService.insertRmSwitchManagement(rmSwitchManagement));
}
/**
* 修改交换机管理
*/
@RequiresPermissions("system:switchManagement:edit")
@Log(title = "交换机管理", businessType = BusinessType.UPDATE)
@PutMapping
public AjaxResult edit(@RequestBody RmSwitchManagement rmSwitchManagement)
{
return toAjax(rmSwitchManagementService.updateRmSwitchManagement(rmSwitchManagement));
}
/**
* 删除交换机管理
*/
@RequiresPermissions("system:switchManagement:remove")
@Log(title = "交换机管理", businessType = BusinessType.DELETE)
@DeleteMapping("/{ids}")
public AjaxResult remove(@PathVariable Long[] ids)
{
return toAjax(rmSwitchManagementService.deleteRmSwitchManagementByIds(ids));
}
/**
* 查询交换机管理列表
*/
@RequiresPermissions("system:switchManagement:list")
@PostMapping("/getAllSwitchName")
public AjaxResult getAllSwitchName(@RequestBody RmSwitchManagement rmSwitchManagement)
{
List<RmSwitchManagement> list = rmSwitchManagementService.selectRmSwitchManagementList(rmSwitchManagement);
return success(list);
}
/**
* 查询交换机管理列表
*/
@InnerAuth
@PostMapping("/getSwitchNameByClientId")
public R<List<RmSwitchManagement>> getSwitchNameByClientId(@RequestBody RmSwitchManagement rmSwitchManagement)
{
List<RmSwitchManagement> list = rmSwitchManagementService.selectRmSwitchManagementList(rmSwitchManagement);
return R.ok(list);
}
/**
* 查询交换机信息树形接口
*/
@RequiresPermissions("system:switchManagement:list")
@GetMapping("/getAllSwitchNameTree")
public AjaxResult getAllSwitchNameTree()
{
List<RmSwitchManagement> list = rmSwitchManagementService.getAllSwitchNameTree();
return success(list);
}
/**
* 修改交换机管理
*/
@PostMapping("/updateSwitchMsgByClientId")
@InnerAuth
public R<Integer> updateSwitchMsgByClientId(@RequestBody RmSwitchManagement rmSwitchManagement)
{
return R.ok(rmSwitchManagementService.updateRmSwitchManagement(rmSwitchManagement));
}
}

View File

@@ -92,7 +92,11 @@ public class ScreenController extends BaseController
public AjaxResult countDeviceNumTop5()
{
List<Map> maps = epsServerRevenueConfigService.countDeviceNumTop5();
return success(maps);
if(maps.isEmpty()){
return success();
}else{
return success(maps);
}
}
/**

View File

@@ -0,0 +1,48 @@
package com.ruoyi.system.controller;
import com.ruoyi.common.core.web.controller.BaseController;
import com.ruoyi.common.core.web.domain.AjaxResult;
import com.ruoyi.common.log.annotation.Log;
import com.ruoyi.common.log.enums.BusinessType;
import com.ruoyi.common.security.annotation.RequiresPermissions;
import com.ruoyi.system.domain.SysMenuClick;
import com.ruoyi.system.service.ISysMenuClickService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import java.util.List;
/**
* 菜单点击计数Controller
*
* @author gyt
* @date 2025-11-12
*/
@RestController
@RequestMapping("/sysMenuClick")
public class SysMenuClickController extends BaseController
{
@Autowired
private ISysMenuClickService sysMenuClickService;
/**
* 查询菜单点击计数列表
*/
@RequiresPermissions("system:sysMenuClick:list")
@GetMapping("/getMenuListTopEight")
public AjaxResult list()
{
List<SysMenuClick> list = sysMenuClickService.selectSysMenuClickList();
return success(list);
}
/**
* 新增菜单点击计数
*/
@RequiresPermissions("system:sysMenuClick:add")
@Log(title = "菜单点击计数", businessType = BusinessType.INSERT)
@PostMapping
public AjaxResult add(@RequestBody SysMenuClick sysMenuClick)
{
return toAjax(sysMenuClickService.insertSysMenuClick(sysMenuClick));
}
}

View File

@@ -0,0 +1,50 @@
package com.ruoyi.system.controller;
import com.ruoyi.common.core.web.controller.BaseController;
import com.ruoyi.common.core.web.domain.AjaxResult;
import com.ruoyi.common.log.annotation.Log;
import com.ruoyi.common.log.enums.BusinessType;
import com.ruoyi.common.security.annotation.RequiresPermissions;
import com.ruoyi.system.domain.UserTableColumnConfig;
import com.ruoyi.system.service.IUserTableColumnConfigService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
/**
* 用户自定义列配置Controller
*
* @author gyt
* @date 2025-10-30
*/
@RestController
@RequestMapping("/columnConfig")
public class UserTableColumnConfigController extends BaseController
{
@Autowired
private IUserTableColumnConfigService userTableColumnConfigService;
/**
* 根据获取用户id获取自定义列配置详细信息
*/
@RequiresPermissions("system:columnConfig:query")
@PostMapping(value = "/getColumnConfigByUserId")
public AjaxResult getColumnConfigByUserId(@RequestBody UserTableColumnConfig userTableColumnConfig)
{
UserTableColumnConfig columnConfig = userTableColumnConfigService.getColumnConfigByUserId(userTableColumnConfig);
return success(columnConfig);
}
/**
* 新增用户自定义列配置
*/
@RequiresPermissions("system:columnConfig:add")
@Log(title = "用户自定义列配置", businessType = BusinessType.INSERT)
@PostMapping("addColumnConfig")
public AjaxResult add(@RequestBody UserTableColumnConfig userTableColumnConfig)
{
return toAjax(userTableColumnConfigService.insertUserTableColumnConfig(userTableColumnConfig));
}
}

View File

@@ -73,5 +73,13 @@ public class AllInterfaceName extends BaseEntity
/** 服务器ip */
@Excel(name = "服务器ip")
private String serverIp;
/** 交换机接口别名 */
private String otherName;
/** 业务需要 拼接id 交换机clientId,交换机接口名称值 别名 */
private String value;
/** 前端需要 name 别名 */
private String label;
/** 是否需要展开 */
private boolean expand;
}

View File

@@ -0,0 +1,74 @@
package com.ruoyi.system.domain;
import com.fasterxml.jackson.annotation.JsonFormat;
import com.ruoyi.common.core.annotation.Excel;
import com.ruoyi.common.core.web.domain.BaseEntity;
import lombok.Data;
import java.util.Date;
/**
* 业务下发管理对象 eps_business_deploy
*
* @author gyt
* @date 2025-10-13
*/
@Data
public class EpsBusinessDeploy extends BaseEntity
{
private static final long serialVersionUID = 1L;
/** 主键ID */
private Long id;
/** 任务名称 */
@Excel(name = "任务名称")
private String taskName;
/** 业务code */
@Excel(name = "业务code")
private String businessCode;
/** 业务名称 */
@Excel(name = "业务名称")
private String businessName;
/** 脚本名称 */
@Excel(name = "脚本名称")
private String scriptName;
/** 脚本文件地址 */
@Excel(name = "脚本文件地址")
private String scriptPath;
/** 脚本参数 */
@Excel(name = "脚本参数")
private String scriptParams;
/** 部署设备 */
@Excel(name = "部署设备")
private String deployDevice;
/** 提交人 */
@Excel(name = "提交人")
private String submitBy;
/** 审核人 */
@Excel(name = "审核人")
private String reviewBy;
/** 审核状态(0-未提交1-待审核,2-审核通过,3-审核驳回) */
@Excel(name = "审核状态")
private String reviewStatus;
/** 审核时间 */
@JsonFormat(pattern = "yyyy-MM-dd")
@Excel(name = "审核时间", width = 30, dateFormat = "yyyy-MM-dd")
private Date reviewTime;
/** 审核意见 */
@Excel(name = "审核意见")
private String reviewComment;
/** 服务器clientId */
private String clientId;
}

View File

@@ -0,0 +1,35 @@
package com.ruoyi.system.domain;
import com.ruoyi.common.core.annotation.Excel;
import com.ruoyi.common.core.web.domain.BaseEntity;
import lombok.Data;
/**
* 业务脚本管理对象 eps_business_script
*
* @author gyt
* @date 2025-10-13
*/
@Data
public class EpsBusinessScript extends BaseEntity
{
private static final long serialVersionUID = 1L;
/** 主键ID */
private Long id;
/** 脚本名称 */
@Excel(name = "脚本名称")
private String scriptName;
/** 脚本文件地址 */
@Excel(name = "脚本文件地址")
private String scriptPath;
/** 脚本默认参数 */
@Excel(name = "脚本默认参数")
private String defaultParams;
/** 结果失败判断关键字 */
@Excel(name = "结果失败判断关键字")
private String failedKeywords;
}

View File

@@ -110,6 +110,24 @@ public class EpsInitialTrafficData extends BaseEntity {
private String bandwidthType;
/** 日或月 */
private String dayOrMonth;
/** 金山流量 */
private String machineFlow;
/** 包含设备 */
private String clientIds;
/** 是否95值 */
private boolean flag95 = false;
/** 计算方式 */
private String calculationMode;
/** 95值 */
private BigDecimal percentile95;
/** 单位 */
private String unit;
/** 总接收带宽 */
private String totalInSpeed;
/** 总发送带宽 */
private String totalOutSpeed;
/** 监控看板id */
private Long monitorId;
}

View File

@@ -49,6 +49,8 @@ public class EpsMethodChangeRecord extends BaseEntity
/** 业务代码(12位) */
private String businessCode;
/** 客户端id */
private String clientId;
/** 开始时间 */
private String startTime;
/** 结束时间 */

View File

@@ -71,30 +71,13 @@ public class EpsNodeBandwidth extends BaseEntity
/** 有效-月均95值 */
@Excel(name = "有效-月均95值")
private BigDecimal effectiveAvgMonthlyBandwidth95;
/** 设备业务客户id */
@Excel(name = "设备业务客户id")
private String customerId;
/** 设备业务客户名称 */
@Excel(name = "设备业务客户名称")
private String customerName;
/** 业务号 */
@Excel(name = "业务号")
private String serviceNumber;
/** 金山流量Mbps/日 */
private BigDecimal machineFlow;
/** 上联交换机 */
@Excel(name = "上联交换机")
private String uplinkSwitch;
/** 创建人id */
@Excel(name = "创建人id")
private Long creatorId;
/** 创建人名称 */
@Excel(name = "创建人名称")
private String creatorName;
/** 交换机sn */
@Excel(name = "交换机sn")
@@ -127,16 +110,24 @@ public class EpsNodeBandwidth extends BaseEntity
private String endTime;
/** 月份 */
private String monthTime;
/** 备注 */
/** 交换机接口名称别名 */
private String remark1;
/** 创建时间 */
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
private Date createDatetime;
/** 节点名称集合 */
private List<String> nodeNames;
/** 交换机名称集合 */
private List<String> switchNames;
/** 计算方式 */
private String calculationMode;
/** 客户端id */
private String clientId;
/** 交换机连接的服务器客户端id */
private String serverClientId;
/** 监控看板配置id */
private Long monitorId;
/** 服务器id \n 分割 */
private String clientIds;
}

View File

@@ -0,0 +1,79 @@
package com.ruoyi.system.domain;
import com.ruoyi.common.core.annotation.Excel;
import com.ruoyi.common.core.web.domain.BaseEntity;
import lombok.Data;
import java.math.BigDecimal;
/**
* 业务95值计算任务对象 eps_task_statistics
*
* @author gyt
* @date 2025-10-29
*/
@Data
public class EpsTaskStatistics extends BaseEntity
{
private static final long serialVersionUID = 1L;
/** 主键ID */
private Long id;
/** 任务名称 */
@Excel(name = "任务名称")
private String taskName;
/** 业务名称 */
@Excel(name = "业务名称")
private String businessName;
/** 业务代码 */
private String businessCode;
/** 开始时间 */
@Excel(name = "开始时间")
private String startTime;
/** 结束时间 */
@Excel(name = "结束时间")
private String endTime;
/** 95值 */
@Excel(name = "95值")
private BigDecimal percentile95;
/** 月均日95值 */
@Excel(name = "月均日95值")
private BigDecimal monthlyAvgPercentile95;
/** 资源类型 */
@Excel(name = "资源类型")
private String resourceType;
/** 包含资源 */
@Excel(name = "包含资源")
private String includedResources;
/** 计算类型 */
@Excel(name = "计算类型")
private String calculationType;
/** 计算模式 */
@Excel(name = "计算模式")
private String calculationMode;
/** 任务状态(1-计算中,2-计算完成) */
@Excel(name = "任务状态(1-计算中,2-计算完成)")
private String taskStatus;
/** 需要修改的流量值 */
private BigDecimal needSpeed;
/** 需要修改的值对应的时间 */
private String needTime;
/** 月均日相关数据时间 */
private String avgTime;
/** 接口名称s */
private String interfaceNames;
/** 时间段 */
private String timeRange;
}

View File

@@ -25,8 +25,8 @@ public class InitialSwitchInfoDetails extends BaseEntity
@Excel(name = "客户端ID")
private String clientId;
/** 网络接口名称(如eth0、ens33等) */
@Excel(name = "网络接口名称(如eth0、ens33等)")
/** 接口名称 */
@Excel(name = "接口名称")
private String name;
/** 接收流量(字节) */
@@ -41,17 +41,19 @@ public class InitialSwitchInfoDetails extends BaseEntity
@Excel(name = "接口状态(up/down等)")
private String status;
/** 接口类型(ethernet/wireless等) */
@Excel(name = "接口类型(ethernet/wireless等)")
/** 接口类型*/
@Excel(name = "接口类型")
private String type;
/** 接收流量bytes/s */
@Excel(name = "接收流量", readConverterExp = "b=ytes/s")
/** 接收流量bits/s */
@Excel(name = "接收流量")
private BigDecimal inSpeed;
/** 发送流量bytes/s */
@Excel(name = "发送流量", readConverterExp = "b=ytes/s")
/** 发送流量bits/s */
@Excel(name = "发送流量")
private BigDecimal outSpeed;
/** 发送或接收流量的最大值 */
private BigDecimal maxSpeed;
/** 交换机名称 */
@Excel(name = "交换机名称")
@@ -108,4 +110,22 @@ public class InitialSwitchInfoDetails extends BaseEntity
private String ifOutErrors;
/** 端口索引 */
private String ifIndex;
/** 计算方式 */
public String calculationMode;
/** 包含资源 */
public String clientIds;
/** 包含资源-接口名称 */
public String interfaceNames;
/** 是否95值 */
private boolean flag95 = false;
/** 服务器客户端id */
private String serverClientId;
/** 交换机接口别名 */
private String interfaceNameRemark;
/** 95值 */
private BigDecimal percentile95;
/** 单位 */
private String unit;
/** 监控看板概览id */
private Long monitorId;
}

View File

@@ -28,6 +28,8 @@ public class RmEpsTopologyManagement extends BaseEntity
/** 交换机硬件SN */
@Excel(name = "交换机硬件SN")
private String switchSn;
/** 交换机clientId */
private String clientId;
/** 接口名称 */
@Excel(name = "接口名称")
@@ -75,4 +77,19 @@ public class RmEpsTopologyManagement extends BaseEntity
private String switchIpAddress;
/** 资源名称 */
private String resourceName;
/**
* 对端交换机名称
*/
private String peerSwitchName;
/**
* 对端交换机接口
*/
private String peerSwitchInterface;
/**
* 服务器clientId
*/
private String serverClientId;
}

View File

@@ -0,0 +1,44 @@
package com.ruoyi.system.domain;
import com.ruoyi.common.core.annotation.Excel;
import com.ruoyi.common.core.web.domain.BaseEntity;
import lombok.Data;
/**
* 监控配置对象 rm_monitor_config
*
* @author gyt
* @date 2025-11-12
*/
@Data
public class RmMonitorConfig extends BaseEntity
{
private static final long serialVersionUID = 1L;
/** 主键ID */
private Long id;
/** 配置名称 */
@Excel(name = "配置名称")
private String configName;
/** 监控数据开始时间 */
@Excel(name = "监控数据开始时间")
private String monitorStartTime;
/** 资源类型 */
@Excel(name = "资源类型")
private String resourceType;
/** 业务代码 */
@Excel(name = "业务代码")
private String businessCode;
/** 业务名称 */
@Excel(name = "业务名称")
private String businessName;
/** 部署设备 */
@Excel(name = "部署设备")
private String deployDevice;
}

View File

@@ -0,0 +1,53 @@
package com.ruoyi.system.domain;
import com.ruoyi.common.core.annotation.Excel;
import com.ruoyi.common.core.web.domain.BaseEntity;
import lombok.Data;
import java.math.BigDecimal;
/**
* 监控看板详情对象 rm_monitor_config_details
*
* @author gyt
* @date 2025-11-14
*/
@Data
public class RmMonitorConfigDetails extends BaseEntity
{
private static final long serialVersionUID = 1L;
/** 自增主键ID */
private Long id;
/** 监控id */
@Excel(name = "监控id")
private Long monitorId;
/** 包含设备 */
@Excel(name = "包含设备")
private String deployDevice;
/** 接收流量(字节) */
@Excel(name = "接收流量(字节)")
private BigDecimal inBytes;
/** 发送流量(字节) */
@Excel(name = "发送流量(字节)")
private BigDecimal outBytes;
/** 接收流量bit/s */
@Excel(name = "接收流量bit/s")
private BigDecimal inSpeed;
/** 发送流量bit/s */
@Excel(name = "发送流量bit/s")
private BigDecimal outSpeed;
/** 开始时间 */
private String startTime;
/** 结束时间 */
private String endTime;
/** 单位 */
private String unit;
}

View File

@@ -0,0 +1,71 @@
package com.ruoyi.system.domain;
import org.apache.commons.lang3.builder.ToStringBuilder;
import org.apache.commons.lang3.builder.ToStringStyle;
import com.ruoyi.common.core.annotation.Excel;
import com.ruoyi.common.core.web.domain.BaseEntity;
/**
* 绑定金山machinecode对象 rm_registration_machine
*
* @author gyt
* @date 2025-10-10
*/
public class RmRegistrationMachine extends BaseEntity
{
private static final long serialVersionUID = 1L;
/** 主键ID */
private Long id;
/** 客户端ID */
@Excel(name = "客户端ID")
private String clientId;
/** 机器码 */
@Excel(name = "机器码")
private String machineCode;
public void setId(Long id)
{
this.id = id;
}
public Long getId()
{
return id;
}
public void setClientId(String clientId)
{
this.clientId = clientId;
}
public String getClientId()
{
return clientId;
}
public void setMachineCode(String machineCode)
{
this.machineCode = machineCode;
}
public String getMachineCode()
{
return machineCode;
}
@Override
public String toString() {
return new ToStringBuilder(this,ToStringStyle.MULTI_LINE_STYLE)
.append("id", getId())
.append("clientId", getClientId())
.append("machineCode", getMachineCode())
.append("createTime", getCreateTime())
.append("updateTime", getUpdateTime())
.append("createBy", getCreateBy())
.append("updateBy", getUpdateBy())
.toString();
}
}

View File

@@ -1,9 +1,14 @@
package com.ruoyi.system.domain;
import com.fasterxml.jackson.annotation.JsonFormat;
import com.ruoyi.common.core.annotation.Excel;
import com.ruoyi.common.core.web.domain.BaseEntity;
import lombok.Data;
import java.util.Date;
import java.util.List;
import java.util.Map;
/**
* 资源注册对象 rm_resource_registration
*
@@ -18,25 +23,25 @@ public class RmResourceRegistration extends BaseEntity
/** id */
private Long id;
/** clientID */
@Excel(name = "clientID")
private String clientId;
/** 硬件SN */
@Excel(name = "硬件SN")
@Excel(name = "设备SN")
private String hardwareSn;
/** 资源类型
* 1 服务器2 交换机*/
@Excel(name = "资源类型",readConverterExp = "1=服务器,2=交换机")
private String resourceType;
/** 资源名称 */
@Excel(name = "资源名称")
private String resourceName;
/** IP地址 */
@Excel(name = "IP地址")
private String ipAddress;
/** 端口1.162(SNMP),2.其他 */
@Excel(name = "端口")
private String resourcePort;
/**其他端口名称 */
@@ -46,70 +51,58 @@ public class RmResourceRegistration extends BaseEntity
@Excel(name = "agent版本")
private String agentVersion;
/** 协议 1.TCP,2.UDP */
@Excel(name = "协议",readConverterExp = "1=TCP,2=UDP")
private String protocol;
/** SNMP探测 0=否,1=是 */
@Excel(name = "",readConverterExp = "0=否,1=是")
private String snmpDetect;
/** 版本(1.SNMPv2,2.SNMPv3) */
@Excel(name = "SNMP版本",readConverterExp = "1=华为SNMPv2c,2=华为SNMPv3")
private String resourceVersion;
/** 读写权限(1.RW,2.ReadOnly) */
@Excel(name = "读写权限",readConverterExp = "1=只读,2=可读可写")
private String rwPermission;
/** 团体名称 */
@Excel(name = "团体名称")
private String teamName;
/** SNMP采集地址 */
@Excel(name = "SNMP采集地址")
private String snmpCollectAddr;
/** SNMP采集端口 */
@Excel(name = "SNMP采集端口")
private String snmpCollectPort;
/** 安全级别(1.authPriv、2.authNoPriv3.noAuthNoPriv) */
@Excel(name = "安全级别",readConverterExp = "1=authPriv,2=authNoPriv,3=noAuthNoPriv")
private String securityLevel;
/** 加密方式 1.md5,2.SHA */
@Excel(name = "加密方式",readConverterExp = "1=MD5,2=SHA")
private String encryption;
/** 用户名 */
@Excel(name = "用户名")
private String resourceUserName;
/** 密码 */
@Excel(name = "密码")
/** 密码 */
private String resourcePwd;
/** 注册状态 0-未注册1-已注册 */
@Excel(name = "注册状态",readConverterExp = "0=未注册,1=已注册")
private String registrationStatus;
/** 在线状态 0-离线1-在线 */
@Excel(name = "在线状态",readConverterExp = "0=离线,1=在线")
@Excel(name = "在线状态", readConverterExp = "0=离线,1=在线")
private String onlineStatus;
@Excel(name = "交换机在线状态",readConverterExp = "0=离线,1=在线")
private String switchOnlineStatus;
/** 描述 */
@Excel(name = "描述")
private String description;
/** 设备业务客户id */
private Long customerId;
/** 设备业务客户名称 */
@Excel(name = "设备业务客户")
private String customerName;
/** 业务号 */
@Excel(name = "业务号")
private String serviceNumber;
/** 创建人id */
@@ -123,11 +116,196 @@ public class RmResourceRegistration extends BaseEntity
/** 修改人名称 */
private String updaterName;
/** 监控项 */
private String monitorItems;
/** 自动发现项 */
private String discoveryRules;
/** 查询名称 */
private String queryName;
/**
* 运营商
*/
private String operator;
/**
* 省
*/
private String province;
/**
* 公网IP
*/
private String publicIp;
/**
* 业务名称
*/
@Excel(name = "业务名称")
private String businessName;
/** 业务代码 */
private String businessCode;
/**
* 逻辑节点标识
*/
@Excel(name = "逻辑节点标识")
private String logicalNodeId;
/**
* 多公网IP状态
*/
private String multiPublicIpStatus;
/**
* 心跳次数
*/
@Excel(name = "心跳次数")
private Integer heartbeatCount;
/**
* 心跳周期(单位:秒)
*/
@Excel(name = "心跳时间间隔")
private Integer heartbeatInterval;
/** 需要绑定的网卡信息 */
private List<Map> bindNetworkMsg;
// IP1 相关字段
@Excel(name = "IP1-运营商")
private String ip1Isp; // IP1-运营商
@Excel(name = "IP1-省")
private String ip1Province; // IP1-省
@Excel(name = "IP1-市")
private String ip1City; // IP1-市
@Excel(name = "IP1-业务公网")
private String ip1PublicIp; // IP1-业务公网
@Excel(name = "IP1-接口名称")
private String ip1InterfaceName; // IP1-接口名称
@Excel(name = "IP1-mac地址")
private String ip1MacAddress; // IP1-mac地址
@Excel(name = "IP1-接口类型")
private String ip1InterfaceType; // IP1-接口类型
@Excel(name = "IP1-IPv4地址")
private String ip1Ipv4Address; // IP1-IPv4地址
@Excel(name = "IP1-网关")
private String ip1Gateway; // IP1-网关
// IP2 相关字段
@Excel(name = "IP2-运营商")
private String ip2Isp;
@Excel(name = "IP2-省")
private String ip2Province;
@Excel(name = "IP2-市")
private String ip2City;
@Excel(name = "IP2-业务公网")
private String ip2PublicIp;
@Excel(name = "IP2-接口名称")
private String ip2InterfaceName;
@Excel(name = "IP2-mac地址")
private String ip2MacAddress;
@Excel(name = "IP2-接口类型")
private String ip2InterfaceType;
@Excel(name = "IP2-IPv4地址")
private String ip2Ipv4Address;
@Excel(name = "IP2-网关")
private String ip2Gateway;
// IP3 相关字段
@Excel(name = "IP3-运营商")
private String ip3Isp;
@Excel(name = "IP3-省")
private String ip3Province;
@Excel(name = "IP3-市")
private String ip3City;
@Excel(name = "IP3-业务公网")
private String ip3PublicIp;
@Excel(name = "IP3-接口名称")
private String ip3InterfaceName;
@Excel(name = "IP3-mac地址")
private String ip3MacAddress;
@Excel(name = "IP3-接口类型")
private String ip3InterfaceType;
@Excel(name = "IP3-IPv4地址")
private String ip3Ipv4Address;
@Excel(name = "IP3-网关")
private String ip3Gateway;
// 管理网相关字段
@Excel(name = "管理网-运营商")
private String mgmtIsp; // 管理网-运营商
@Excel(name = "管理网-省")
private String mgmtProvince; // 管理网-省
@Excel(name = "管理网-市")
private String mgmtCity; // 管理网-市
@Excel(name = "管理网-公网IP")
private String mgmtPublicIp; // 管理网-公网IP
@Excel(name = "管理网-接口名称")
private String mgmtInterfaceName; // 管理网-接口名称
@Excel(name = "管理网-mac地址")
private String mgmtMacAddress; // 管理网-mac地址
@Excel(name = "管理网-接口类型")
private String mgmtInterfaceType; // 管理网-接口类型
@Excel(name = "管理网-IPv4地址")
private String mgmtIpv4Address; // 管理网-IPv4地址
@Excel(name = "管理网-网关")
private String mgmtGateway; // 管理网-IPv4地址
/** 多条件查询 */
private String queryParam;
/** 金山machineCode */
@Excel(name = "金山machineCode")
private String machineCode;
/** 注册时间 */
@Excel(name = "注册时间")
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
private Date createTime;
/** 上机时间 */
@Excel(name = "上机时间")
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
private Date onboardTime;
/** 服务器列表 */
private String deployDevice;
/** 业务空标识 */
private boolean businessEmpty;
/** 逻辑节点空标识 */
private boolean logicalNodeEmpty;
}

View File

@@ -0,0 +1,38 @@
package com.ruoyi.system.domain;
import com.ruoyi.common.core.annotation.Excel;
import com.ruoyi.common.core.web.domain.BaseEntity;
import lombok.Data;
/**
* 交换机接口信息对象 rm_switch_interface_info
*
* @author gyt
* @date 2025-10-10
*/
@Data
public class RmSwitchInterfaceInfo extends BaseEntity
{
private static final long serialVersionUID = 1L;
/** 主键ID */
private Long id;
/** 硬件SN序列号 */
@Excel(name = "硬件SN序列号")
private String hardwareSn;
/** 交换机名称 */
@Excel(name = "交换机名称")
private String switchName;
/** 交换机接口名称 */
@Excel(name = "交换机接口名称")
private String interfaceName;
/** 接口备注 */
@Excel(name = "接口备注")
private String interfaceRemark;
/** 客户端id */
private String clientId;
}

View File

@@ -0,0 +1,97 @@
package com.ruoyi.system.domain;
import com.ruoyi.common.core.annotation.Excel;
import com.ruoyi.common.core.web.domain.BaseEntity;
import lombok.Data;
import java.util.Date;
import java.util.List;
/**
* 交换机管理对象 rm_switch_management
*
* @author gyt
* @date 2025-10-10
*/
@Data
public class RmSwitchManagement extends BaseEntity
{
private static final long serialVersionUID = 1L;
/** 主键ID */
private Long id;
/** 交换机名称 */
@Excel(name = "交换机名称")
private String switchName;
/** 硬件SN序列号 */
@Excel(name = "硬件SN序列号")
private String hardwareSn;
/** SNMP采集地址 */
@Excel(name = "SNMP采集地址")
private String snmpAddress;
/** SNMP采集端口 */
@Excel(name = "SNMP采集端口")
private Long snmpPort;
/** 在线状态(0-离线,1-在线) */
@Excel(name = "在线状态(0-离线,1-在线)")
private String onlineStatus;
/** 上机时间 */
private Date upTime;
/** 心跳监测次数 */
@Excel(name = "心跳监测次数")
private String heartbeatCount;
/** 心跳监测周期(秒) */
@Excel(name = "心跳监测周期(秒)")
private String heartbeatInterval;
/** 心跳检测OID */
@Excel(name = "心跳检测OID")
private String heartbeatOid;
/** SNMP版本(v1/v2c/v3) */
@Excel(name = "SNMP版本(v1/v2c/v3)")
private String snmpVersion;
/** 读写权限 */
@Excel(name = "读写权限")
private String readWritePermission;
/** 安全级别 */
@Excel(name = "安全级别")
private String securityLevel;
/** 加密方式 */
@Excel(name = "加密方式")
private String encryptionMethod;
/** 团体名称 */
@Excel(name = "团体名称")
private String communityName;
/** 密码 */
@Excel(name = "密码")
private String switchPassword;
/** 交换机类型 */
private String switchType;
/** 用户名 */
private String switchUser;
/** 端口备注列表 */
private List<RmSwitchInterfaceInfo> switchInterfaceInfoList;
/** 自动生成客户端id(uuid) */
private String clientId;
/** 查询条件 */
private String queryName;
/** 接口信息 */
private List<AllInterfaceName> children;
/** 前端需要 id 别名 */
private Long value;
/** 前端需要 name 别名 */
private String label;
}

View File

@@ -0,0 +1,41 @@
package com.ruoyi.system.domain;
import com.fasterxml.jackson.annotation.JsonFormat;
import com.ruoyi.common.core.annotation.Excel;
import com.ruoyi.common.core.web.domain.BaseEntity;
import lombok.Data;
import java.util.Date;
/**
* 菜单点击计数对象 sys_menu_click
*
* @author gyt
* @date 2025-11-12
*/
@Data
public class SysMenuClick extends BaseEntity
{
private static final long serialVersionUID = 1L;
/** 主键ID */
private Long id;
/** 页面路由标识例如system:user:list, business:order:manage */
@Excel(name = "页面路由标识", readConverterExp = "例=如system:user:list,,b=usiness:order:manage")
private String pageRoute;
/** 页面名称 */
@Excel(name = "页面名称")
private String pageName;
/** 点击次数 */
@Excel(name = "点击次数")
private Long clickCount;
/** 最后点击时间 */
@JsonFormat(pattern = "yyyy-MM-dd")
@Excel(name = "最后点击时间", width = 30, dateFormat = "yyyy-MM-dd")
private Date lastClickTime;
}

View File

@@ -0,0 +1,30 @@
package com.ruoyi.system.domain;
import com.ruoyi.common.core.annotation.Excel;
import com.ruoyi.common.core.web.domain.BaseEntity;
import lombok.Data;
/**
* 用户自定义列配置对象 user_table_column_config
*
* @author gyt
* @date 2025-10-30
*/
@Data
public class UserTableColumnConfig extends BaseEntity
{
private static final long serialVersionUID = 1L;
/** 主键ID */
private Long id;
/** 用户ID */
@Excel(name = "用户ID")
private Long userId;
/** 页面路由标识例如system:user:list, business:order:manage */
private String pageRoute;
/** 列配置JSON数组格式 */
private String columnConfig;
}

View File

@@ -0,0 +1,17 @@
package com.ruoyi.system.domain.vo;
import lombok.Data;
import java.time.Instant;
@Data
public class RspVo {
/** 状态码0、失败1、成功*/
private Integer resCode;
/** 描述 */
private String resMag;
/** 路由 */
private String addRoute;
/** 时间戳 */
private long timestamp = Instant.now().getEpochSecond();
}

View File

@@ -0,0 +1,15 @@
package com.ruoyi.system.enums;
import lombok.Getter;
@Getter
public enum ReviewEnum {
未提交("0"),
待审核("1"),
通过("2"),
驳回("3");
private String code;
ReviewEnum(String code){
this.code = code;
}
}

View File

@@ -0,0 +1,61 @@
package com.ruoyi.system.mapper;
import java.util.List;
import com.ruoyi.system.domain.EpsBusinessDeploy;
/**
* 业务下发管理Mapper接口
*
* @author gyt
* @date 2025-10-13
*/
public interface EpsBusinessDeployMapper
{
/**
* 查询业务下发管理
*
* @param id 业务下发管理主键
* @return 业务下发管理
*/
public EpsBusinessDeploy selectEpsBusinessDeployById(Long id);
/**
* 查询业务下发管理列表
*
* @param epsBusinessDeploy 业务下发管理
* @return 业务下发管理集合
*/
public List<EpsBusinessDeploy> selectEpsBusinessDeployList(EpsBusinessDeploy epsBusinessDeploy);
/**
* 新增业务下发管理
*
* @param epsBusinessDeploy 业务下发管理
* @return 结果
*/
public int insertEpsBusinessDeploy(EpsBusinessDeploy epsBusinessDeploy);
/**
* 修改业务下发管理
*
* @param epsBusinessDeploy 业务下发管理
* @return 结果
*/
public int updateEpsBusinessDeploy(EpsBusinessDeploy epsBusinessDeploy);
/**
* 删除业务下发管理
*
* @param id 业务下发管理主键
* @return 结果
*/
public int deleteEpsBusinessDeployById(Long id);
/**
* 批量删除业务下发管理
*
* @param ids 需要删除的数据主键集合
* @return 结果
*/
public int deleteEpsBusinessDeployByIds(Long[] ids);
}

View File

@@ -19,6 +19,13 @@ public interface EpsBusinessMapper
* @return 业务信息
*/
public EpsBusiness selectEpsBusinessById(String id);
/**
* 查询业务代码
*
* @param businessName 业务名称
* @return 业务信息
*/
public EpsBusiness selectEpsBusinessByName(String businessName);
/**
* 查询业务信息列表

View File

@@ -0,0 +1,61 @@
package com.ruoyi.system.mapper;
import java.util.List;
import com.ruoyi.system.domain.EpsBusinessScript;
/**
* 业务脚本管理Mapper接口
*
* @author gyt
* @date 2025-10-13
*/
public interface EpsBusinessScriptMapper
{
/**
* 查询业务脚本管理
*
* @param id 业务脚本管理主键
* @return 业务脚本管理
*/
public EpsBusinessScript selectEpsBusinessScriptById(Long id);
/**
* 查询业务脚本管理列表
*
* @param epsBusinessScript 业务脚本管理
* @return 业务脚本管理集合
*/
public List<EpsBusinessScript> selectEpsBusinessScriptList(EpsBusinessScript epsBusinessScript);
/**
* 新增业务脚本管理
*
* @param epsBusinessScript 业务脚本管理
* @return 结果
*/
public int insertEpsBusinessScript(EpsBusinessScript epsBusinessScript);
/**
* 修改业务脚本管理
*
* @param epsBusinessScript 业务脚本管理
* @return 结果
*/
public int updateEpsBusinessScript(EpsBusinessScript epsBusinessScript);
/**
* 删除业务脚本管理
*
* @param id 业务脚本管理主键
* @return 结果
*/
public int deleteEpsBusinessScriptById(Long id);
/**
* 批量删除业务脚本管理
*
* @param ids 需要删除的数据主键集合
* @return 结果
*/
public int deleteEpsBusinessScriptByIds(Long[] ids);
}

View File

@@ -41,4 +41,12 @@ public interface EpsInitialTrafficDataMapper {
*/
List<EpsInitialTrafficData> getAllTraficMsg(EpsInitialTrafficData condition);
/**
* 保存金山流量信息
* @param epsInitialTrafficData
* @return
*/
int updateMachineTraffic(EpsInitialTrafficData epsInitialTrafficData);
List<EpsInitialTrafficData> getTrafficListByClientIds(EpsInitialTrafficData condition);
}

View File

@@ -85,4 +85,11 @@ public interface EpsNodeBandwidthMapper
int updateEpsNodeBandwidthByServerSn(EpsNodeBandwidth epsNodeBandwidth);
int updateEpsNodeBandwidthBySwitchSn(EpsNodeBandwidth epsNodeBandwidth);
/**
* 监控看板-详情视图 95值列表
* @param epsNodeBandwidth
* @return
*/
List<EpsNodeBandwidth> getListByMonitorView(EpsNodeBandwidth epsNodeBandwidth);
}

View File

@@ -0,0 +1,61 @@
package com.ruoyi.system.mapper;
import java.util.List;
import com.ruoyi.system.domain.EpsTaskStatistics;
/**
* 业务95值计算任务Mapper接口
*
* @author gyt
* @date 2025-10-29
*/
public interface EpsTaskStatisticsMapper
{
/**
* 查询业务95值计算任务
*
* @param id 业务95值计算任务主键
* @return 业务95值计算任务
*/
public EpsTaskStatistics selectEpsTaskStatisticsById(Long id);
/**
* 查询业务95值计算任务列表
*
* @param epsTaskStatistics 业务95值计算任务
* @return 业务95值计算任务集合
*/
public List<EpsTaskStatistics> selectEpsTaskStatisticsList(EpsTaskStatistics epsTaskStatistics);
/**
* 新增业务95值计算任务
*
* @param epsTaskStatistics 业务95值计算任务
* @return 结果
*/
public int insertEpsTaskStatistics(EpsTaskStatistics epsTaskStatistics);
/**
* 修改业务95值计算任务
*
* @param epsTaskStatistics 业务95值计算任务
* @return 结果
*/
public int updateEpsTaskStatistics(EpsTaskStatistics epsTaskStatistics);
/**
* 删除业务95值计算任务
*
* @param id 业务95值计算任务主键
* @return 结果
*/
public int deleteEpsTaskStatisticsById(Long id);
/**
* 批量删除业务95值计算任务
*
* @param ids 需要删除的数据主键集合
* @return 结果
*/
public int deleteEpsTaskStatisticsByIds(Long[] ids);
}

View File

@@ -28,6 +28,8 @@ public interface InitialSwitchInfoDetailsMapper
*/
public List<InitialSwitchInfoDetails> selectInitialSwitchInfoDetailsList(InitialSwitchInfoDetails initialSwitchInfoDetails);
public List<InitialSwitchInfoDetails> getswitchDetailList(InitialSwitchInfoDetails initialSwitchInfoDetails);
/**
* 新增交换机监控信息
*
@@ -73,4 +75,18 @@ public interface InitialSwitchInfoDetailsMapper
* @return
*/
List<InitialSwitchInfoDetails> getAllSwitchInfoMsg(InitialSwitchInfoDetails initialSwitchInfoDetails);
/**
* 计算业务95值
* @param queryParam
* @return
*/
List<InitialSwitchInfoDetails> sumSwitchTrafficByclientIds(InitialSwitchInfoDetails queryParam);
/**
* 监控看板-详情视图 出入流量列表
* @param queryParam
* @return
*/
List<InitialSwitchInfoDetails> geSwitchListByMonitorView(InitialSwitchInfoDetails queryParam);
}

View File

@@ -0,0 +1,68 @@
package com.ruoyi.system.mapper;
import com.ruoyi.system.domain.RmMonitorConfigDetails;
import org.springframework.transaction.annotation.Transactional;
import java.util.List;
/**
* 监控看板详情Mapper接口
*
* @author gyt
* @date 2025-11-14
*/
public interface RmMonitorConfigDetailsMapper
{
/**
* 查询监控看板详情
*
* @param id 监控看板详情主键
* @return 监控看板详情
*/
public RmMonitorConfigDetails selectRmMonitorConfigDetailsById(Long id);
/**
* 查询监控看板详情列表
*
* @param rmMonitorConfigDetails 监控看板详情
* @return 监控看板详情集合
*/
public List<RmMonitorConfigDetails> selectRmMonitorConfigDetailsList(RmMonitorConfigDetails rmMonitorConfigDetails);
/**
* 新增监控看板详情
*
* @param rmMonitorConfigDetails 监控看板详情
* @return 结果
*/
public int insertRmMonitorConfigDetails(RmMonitorConfigDetails rmMonitorConfigDetails);
/**
* 修改监控看板详情
*
* @param rmMonitorConfigDetails 监控看板详情
* @return 结果
*/
public int updateRmMonitorConfigDetails(RmMonitorConfigDetails rmMonitorConfigDetails);
/**
* 删除监控看板详情
*
* @param id 监控看板详情主键
* @return 结果
*/
public int deleteRmMonitorConfigDetailsById(Long id);
public int deleteRmMonitorConfigDetailsByMonitorIds(Long[] monitorId);
/**
* 批量删除监控看板详情
*
* @param ids 需要删除的数据主键集合
* @return 结果
*/
public int deleteRmMonitorConfigDetailsByIds(Long[] ids);
@Transactional(rollbackFor = Exception.class)
int batchInsertRmMonitorConfigDetails(List<RmMonitorConfigDetails> batchInsertList);
}

Some files were not shown because too many files have changed in this diff Show More