1、新增降噪日志数据健康监测告警

2、IP联动封禁功能完善
This commit is contained in:
2026-05-06 17:54:59 +08:00
parent 5e73c1c8f6
commit 19c563b3f3
23 changed files with 2953 additions and 2 deletions
@@ -0,0 +1,85 @@
package com.common.entity;
import java.time.OffsetDateTime;
/**
* 联动设备表实体类(防火墙设备信息)
* 对应表: device_interlocking
*/
public class DeviceInterlocking {
private Long id;
private String deviceName; // 联动安全设备名称(防火墙)
private String vendor; // 厂商
private String deptId; // 所属组织机构(部门ID
private Integer banLimit; // 封禁上限
private String ip; // IP地址
private String apiUrl; // API地址
private String tenantId;
private Long createDept;
private Long createBy;
private OffsetDateTime createTime;
private Long updateBy;
private OffsetDateTime updateTime;
private String remark;
private String authUsername; // 用户名
private String authPassword; // 密码
// Getter and Setter
public Long getId() { return id; }
public void setId(Long id) { this.id = id; }
public String getDeviceName() { return deviceName; }
public void setDeviceName(String deviceName) { this.deviceName = deviceName; }
public String getVendor() { return vendor; }
public void setVendor(String vendor) { this.vendor = vendor; }
public String getDeptId() { return deptId; }
public void setDeptId(String deptId) { this.deptId = deptId; }
public Integer getBanLimit() { return banLimit; }
public void setBanLimit(Integer banLimit) { this.banLimit = banLimit; }
public String getIp() { return ip; }
public void setIp(String ip) { this.ip = ip; }
public String getApiUrl() { return apiUrl; }
public void setApiUrl(String apiUrl) { this.apiUrl = apiUrl; }
public String getTenantId() { return tenantId; }
public void setTenantId(String tenantId) { this.tenantId = tenantId; }
public Long getCreateDept() { return createDept; }
public void setCreateDept(Long createDept) { this.createDept = createDept; }
public Long getCreateBy() { return createBy; }
public void setCreateBy(Long createBy) { this.createBy = createBy; }
public OffsetDateTime getCreateTime() { return createTime; }
public void setCreateTime(OffsetDateTime createTime) { this.createTime = createTime; }
public Long getUpdateBy() { return updateBy; }
public void setUpdateBy(Long updateBy) { this.updateBy = updateBy; }
public OffsetDateTime getUpdateTime() { return updateTime; }
public void setUpdateTime(OffsetDateTime updateTime) { this.updateTime = updateTime; }
public String getRemark() { return remark; }
public void setRemark(String remark) { this.remark = remark; }
public String getAuthUsername() { return authUsername; }
public void setAuthUsername(String authUsername) { this.authUsername = authUsername; }
public String getAuthPassword() { return authPassword; }
public void setAuthPassword(String authPassword) { this.authPassword = authPassword; }
@Override
public String toString() {
return "DeviceInterlocking{" +
"id=" + id +
", deviceName='" + deviceName + '\'' +
", vendor='" + vendor + '\'' +
", ip='" + ip + '\'' +
'}';
}
}
@@ -0,0 +1,147 @@
package com.common.entity;
import com.Modules.etl.handler.ArrayIntegerTypeHandler;
import com.Modules.etl.handler.ArrayStringTypeHandler;
import org.apache.ibatis.type.JdbcType;
import org.apache.ibatis.type.TypeHandler;
import org.apache.ibatis.type.ArrayTypeHandler;
import java.time.OffsetDateTime;
import java.util.Arrays;
import java.util.List;
/**
* 封禁指令表实体类
* 对应表: device_interlocking_cmd
*/
public class DeviceInterlockingCmd {
private Long id;
private Long probeId; // 探针ID
private String probeIp; // 探针IP
private Integer[] deviceInterlockingId; // 联动设备ID(数组)
private String[] deviceInterlockingIp; // 联动设备IP(数组)
private String[] banIps; // 封禁IP(数组)
private String banMethod; // 封禁方式(0:手工、1:自动)
private String banType; // 封禁类型(1:白名单、0:黑名单)
private String cmdStatus; // 指令状态(0:未执行、1:已完成、2:执行中)
private Integer banDuration; // 封禁时长(秒,-1表示永久)
private OffsetDateTime createTime;
private OffsetDateTime updateTime;
private String tenantId;
private Long createDept;
private Long createBy;
private Long updateBy;
private String remark;
private Integer banOperationType; // 封禁操作类型(0:新增、1:删除)
// Getter and Setter
public Long getId() { return id; }
public void setId(Long id) { this.id = id; }
public Long getProbeId() { return probeId; }
public void setProbeId(Long probeId) { this.probeId = probeId; }
public String getProbeIp() { return probeIp; }
public void setProbeIp(String probeIp) { this.probeIp = probeIp; }
public Integer[] getDeviceInterlockingId() { return deviceInterlockingId; }
public void setDeviceInterlockingId(Integer[] deviceInterlockingId) { this.deviceInterlockingId = deviceInterlockingId; }
public String[] getDeviceInterlockingIp() { return deviceInterlockingIp; }
public void setDeviceInterlockingIp(String[] deviceInterlockingIp) { this.deviceInterlockingIp = deviceInterlockingIp; }
public String[] getBanIps() { return banIps; }
public void setBanIps(String[] banIps) { this.banIps = banIps; }
public String getBanMethod() { return banMethod; }
public void setBanMethod(String banMethod) { this.banMethod = banMethod; }
public String getBanType() { return banType; }
public void setBanType(String banType) { this.banType = banType; }
public String getCmdStatus() { return cmdStatus; }
public void setCmdStatus(String cmdStatus) { this.cmdStatus = cmdStatus; }
public Integer getBanDuration() { return banDuration; }
public void setBanDuration(Integer banDuration) { this.banDuration = banDuration; }
public OffsetDateTime getCreateTime() { return createTime; }
public void setCreateTime(OffsetDateTime createTime) { this.createTime = createTime; }
public OffsetDateTime getUpdateTime() { return updateTime; }
public void setUpdateTime(OffsetDateTime updateTime) { this.updateTime = updateTime; }
public String getTenantId() { return tenantId; }
public void setTenantId(String tenantId) { this.tenantId = tenantId; }
public Long getCreateDept() { return createDept; }
public void setCreateDept(Long createDept) { this.createDept = createDept; }
public Long getCreateBy() { return createBy; }
public void setCreateBy(Long createBy) { this.createBy = createBy; }
public Long getUpdateBy() { return updateBy; }
public void setUpdateBy(Long updateBy) { this.updateBy = updateBy; }
public String getRemark() { return remark; }
public void setRemark(String remark) { this.remark = remark; }
public Integer getBanOperationType() { return banOperationType; }
public void setBanOperationType(Integer banOperationType) { this.banOperationType = banOperationType; }
// ========== 便利方法:数组与List互转 ==========
/**
* 获取设备联动ID列表
*/
public List<Integer> getDeviceInterlockingIdList() {
return deviceInterlockingId != null ? Arrays.asList(deviceInterlockingId) : null;
}
/**
* 设置设备联动ID列表
*/
public void setDeviceInterlockingIdList(List<Integer> list) {
this.deviceInterlockingId = list != null ? list.toArray(new Integer[0]) : null;
}
/**
* 获取设备联动IP列表
*/
public List<String> getDeviceInterlockingIpList() {
return deviceInterlockingIp != null ? Arrays.asList(deviceInterlockingIp) : null;
}
/**
* 设置设备联动IP列表
*/
public void setDeviceInterlockingIpList(List<String> list) {
this.deviceInterlockingIp = list != null ? list.toArray(new String[0]) : null;
}
/**
* 获取封禁IP列表
*/
public List<String> getBanIpsList() {
return banIps != null ? Arrays.asList(banIps) : null;
}
/**
* 设置封禁IP列表
*/
public void setBanIpsList(List<String> list) {
this.banIps = list != null ? list.toArray(new String[0]) : null;
}
@Override
public String toString() {
return "DeviceInterlockingCmd{" +
"id=" + id +
", probeId=" + probeId +
", probeIp='" + probeIp + '\'' +
", banType='" + banType + '\'' +
", cmdStatus='" + cmdStatus + '\'' +
", banOperationType=" + banOperationType +
'}';
}
}
@@ -0,0 +1,90 @@
package com.common.entity;
import java.time.OffsetDateTime;
/**
* 封禁记录表实体类
* 对应表: device_interlocking_log
*/
public class DeviceInterlockingLog {
private Long id;
private Long deviceInterlockingCmdId; // 封禁指令ID
private Long deviceInterlockingId; // 封禁设备ID
private String banIp; // 封禁IP地址
private String deviceName; // 封禁设备名称
private OffsetDateTime banTime; // 封禁时间
private String banMethod; // 封禁方式(0.人工、1.自动化封禁)
private Integer banResult; // 联动结果(成功:1、失败:0
private String tenantId;
private Long createDept;
private Long createBy;
private OffsetDateTime createTime;
private Long updateBy;
private OffsetDateTime updateTime;
private String remark;
private String respBody; // 响应body
private String reqBody; // 请求body
// Getter and Setter
public Long getId() { return id; }
public void setId(Long id) { this.id = id; }
public Long getDeviceInterlockingCmdId() { return deviceInterlockingCmdId; }
public void setDeviceInterlockingCmdId(Long deviceInterlockingCmdId) { this.deviceInterlockingCmdId = deviceInterlockingCmdId; }
public Long getDeviceInterlockingId() { return deviceInterlockingId; }
public void setDeviceInterlockingId(Long deviceInterlockingId) { this.deviceInterlockingId = deviceInterlockingId; }
public String getBanIp() { return banIp; }
public void setBanIp(String banIp) { this.banIp = banIp; }
public String getDeviceName() { return deviceName; }
public void setDeviceName(String deviceName) { this.deviceName = deviceName; }
public OffsetDateTime getBanTime() { return banTime; }
public void setBanTime(OffsetDateTime banTime) { this.banTime = banTime; }
public String getBanMethod() { return banMethod; }
public void setBanMethod(String banMethod) { this.banMethod = banMethod; }
public Integer getBanResult() { return banResult; }
public void setBanResult(Integer banResult) { this.banResult = banResult; }
public String getTenantId() { return tenantId; }
public void setTenantId(String tenantId) { this.tenantId = tenantId; }
public Long getCreateDept() { return createDept; }
public void setCreateDept(Long createDept) { this.createDept = createDept; }
public Long getCreateBy() { return createBy; }
public void setCreateBy(Long createBy) { this.createBy = createBy; }
public OffsetDateTime getCreateTime() { return createTime; }
public void setCreateTime(OffsetDateTime createTime) { this.createTime = createTime; }
public Long getUpdateBy() { return updateBy; }
public void setUpdateBy(Long updateBy) { this.updateBy = updateBy; }
public OffsetDateTime getUpdateTime() { return updateTime; }
public void setUpdateTime(OffsetDateTime updateTime) { this.updateTime = updateTime; }
public String getRemark() { return remark; }
public void setRemark(String remark) { this.remark = remark; }
public String getRespBody() { return respBody; }
public void setRespBody(String respBody) { this.respBody = respBody; }
public String getReqBody() { return reqBody; }
public void setReqBody(String reqBody) { this.reqBody = reqBody; }
@Override
public String toString() {
return "DeviceInterlockingLog{" +
"id=" + id +
", deviceInterlockingCmdId=" + deviceInterlockingCmdId +
", banIp='" + banIp + '\'' +
", deviceName='" + deviceName + '\'' +
", banResult=" + banResult +
'}';
}
}
@@ -0,0 +1,74 @@
package com.common.entity;
import lombok.Data;
import java.time.LocalDateTime;
/**
* 微信通知实体类
* 对应表: wecom_notification
*/
@Data
public class WecomNotification {
/** 企微通知id */
private Long wecomNotificationId;
/** 用户信息 */
private String userId;
/** 通知名称 */
private String wecomNotificationName;
/** 通知IP */
private String wecomNotificationIp;
/** 通知类型 */
private String wecomNotificationType;
/** 通知等级 */
private String wecomNotificationLevel;
/** 通知内容 */
private String wecomNotificationContent;
/** 告警通知时间 */
private LocalDateTime wecomNotificationTime;
/** 租户编号 */
private String tenantId;
/** 创建部门 */
private Long createDept;
/** 创建者 */
private Long createBy;
/** 创建时间 */
private LocalDateTime createTime;
/** 更新者 */
private Long updateBy;
/** 更新时间 */
private LocalDateTime updateTime;
/** 备注 */
private String remark;
/** 通知状态(0:已发送, 1:未发送) */
private String wecomNotificationStatus;
public WecomNotification() {
}
public WecomNotification(String wecomNotificationName, String wecomNotificationType,
String wecomNotificationLevel, String wecomNotificationContent) {
this.wecomNotificationName = wecomNotificationName;
this.wecomNotificationType = wecomNotificationType;
this.wecomNotificationLevel = wecomNotificationLevel;
this.wecomNotificationContent = wecomNotificationContent;
this.wecomNotificationTime = LocalDateTime.now();
this.wecomNotificationStatus = "1"; // 默认未发送
this.createTime = LocalDateTime.now();
}
}
@@ -0,0 +1,129 @@
package com.common.mapper;
import com.Modules.etl.handler.ArrayIntegerTypeHandler;
import com.Modules.etl.handler.ArrayStringTypeHandler;
import com.common.entity.DeviceInterlockingCmd;
import org.apache.ibatis.annotations.*;
import org.apache.ibatis.type.JdbcType;
import java.util.List;
@Mapper
public interface DeviceInterlockingCmdMapper {
/**
* 根据ID查询
*/
@Select("SELECT * FROM device_interlocking_cmd WHERE id = #{id}")
@Results({
@Result(column = "device_interlocking_id", property = "deviceInterlockingId",
typeHandler = ArrayIntegerTypeHandler.class),
@Result(column = "device_interlocking_ip", property = "deviceInterlockingIp",
typeHandler = ArrayStringTypeHandler.class),
@Result(column = "ban_ips", property = "banIps",
typeHandler = ArrayStringTypeHandler.class)
})
DeviceInterlockingCmd selectById(Long id);
/**
* 查询待执行的指令
* @param probeId 探针ID
* @return 待执行指令列表
*/
@Select("SELECT * FROM device_interlocking_cmd WHERE probe_id = #{probeId} AND cmd_status = '0' ORDER BY create_time ASC")
@Results({
@Result(column = "device_interlocking_id", property = "deviceInterlockingId",
typeHandler = ArrayIntegerTypeHandler.class),
@Result(column = "device_interlocking_ip", property = "deviceInterlockingIp",
typeHandler = ArrayStringTypeHandler.class),
@Result(column = "ban_ips", property = "banIps",
typeHandler = ArrayStringTypeHandler.class)
})
List<DeviceInterlockingCmd> selectPendingCommands(@Param("probeId") Long probeId);
/**
* 根据探针ID和状态查询
*/
@Select("SELECT * FROM device_interlocking_cmd WHERE probe_id = #{probeId} AND cmd_status = #{cmdStatus}")
@Results({
@Result(column = "device_interlocking_id", property = "deviceInterlockingId",
typeHandler = ArrayIntegerTypeHandler.class),
@Result(column = "device_interlocking_ip", property = "deviceInterlockingIp",
typeHandler = ArrayStringTypeHandler.class),
@Result(column = "ban_ips", property = "banIps",
typeHandler = ArrayStringTypeHandler.class)
})
List<DeviceInterlockingCmd> selectByProbeIdAndStatus(@Param("probeId") Long probeId, @Param("cmdStatus") String cmdStatus);
/**
* 插入指令
*/
@Insert("INSERT INTO device_interlocking_cmd (probe_id, probe_ip, device_interlocking_id, device_interlocking_ip, " +
"ban_ips, ban_method, ban_type, cmd_status, ban_duration, create_time, update_time, " +
"tenant_id, create_dept, create_by, remark, ban_operation_type) " +
"VALUES (#{probeId}, #{probeIp}, ARRAY[:ids], ARRAY[:ips], ARRAY[:banIps], " +
"#{banMethod}, #{banType}, #{cmdStatus}, #{banDuration}, NOW(), NOW(), " +
"#{tenantId}, #{createDept}, #{createBy}, #{remark}, #{banOperationType})")
@Options(useGeneratedKeys = true, keyProperty = "id")
int insert(DeviceInterlockingCmd cmd);
/**
* 更新指令状态
* @param id 指令ID
* @param cmdStatus 新状态
* @return 影响行数
*/
@Update("UPDATE device_interlocking_cmd SET cmd_status = #{cmdStatus}, update_time = NOW() WHERE id = #{id}")
int updateStatus(@Param("id") Long id, @Param("cmdStatus") String cmdStatus);
/**
* 更新指令状态为执行中
*/
@Update("UPDATE device_interlocking_cmd SET cmd_status = '2', update_time = NOW() WHERE id = #{id}")
int updateStatusToExecuting(@Param("id") Long id);
/**
* 更新指令状态为执行完成
*/
@Update("UPDATE device_interlocking_cmd SET cmd_status = '1', update_time = NOW() WHERE id = #{id}")
int updateStatusToCompleted(@Param("id") Long id);
/**
* 更新指令状态为执行失败
*/
@Update("UPDATE device_interlocking_cmd SET cmd_status = '3', update_time = NOW() WHERE id = #{id}")
int updateStatusToFailed(@Param("id") Long id);
/**
* 根据多个ID查询
*/
@Select("<script>" +
"SELECT * FROM device_interlocking_cmd WHERE id IN " +
"<foreach collection='ids' item='id' open='(' separator=',' close=')'>" +
"#{id}" +
"</foreach>" +
"</script>")
@Results({
@Result(column = "device_interlocking_id", property = "deviceInterlockingId",
typeHandler = ArrayIntegerTypeHandler.class),
@Result(column = "device_interlocking_ip", property = "deviceInterlockingIp",
typeHandler = ArrayStringTypeHandler.class),
@Result(column = "ban_ips", property = "banIps",
typeHandler = ArrayStringTypeHandler.class)
})
List<DeviceInterlockingCmd> selectByIds(@Param("ids") List<Long> ids);
/**
* 查询所有指令
*/
@Select("SELECT * FROM device_interlocking_cmd ORDER BY create_time DESC")
@Results({
@Result(column = "device_interlocking_id", property = "deviceInterlockingId",
typeHandler = ArrayIntegerTypeHandler.class),
@Result(column = "device_interlocking_ip", property = "deviceInterlockingIp",
typeHandler = ArrayStringTypeHandler.class),
@Result(column = "ban_ips", property = "banIps",
typeHandler = ArrayStringTypeHandler.class)
})
List<DeviceInterlockingCmd> selectAll();
}
@@ -0,0 +1,62 @@
package com.common.mapper;
import com.common.entity.DeviceInterlockingLog;
import org.apache.ibatis.annotations.*;
import java.util.List;
@Mapper
public interface DeviceInterlockingLogMapper {
/**
* 根据ID查询
*/
@Select("SELECT * FROM device_interlocking_log WHERE id = #{id}")
DeviceInterlockingLog selectById(Long id);
/**
* 根据指令ID查询
*/
@Select("SELECT * FROM device_interlocking_log WHERE device_interlocking_cmd_id = #{cmdId}")
List<DeviceInterlockingLog> selectByCmdId(@Param("cmdId") Long cmdId);
/**
* 插入记录
*/
@Insert("INSERT INTO device_interlocking_log (device_interlocking_cmd_id, device_interlocking_id, ban_ip, " +
"device_name, ban_time, ban_method, ban_result, tenant_id, create_dept, create_by, " +
"create_time, remark, resp_body, req_body) " +
"VALUES (#{deviceInterlockingCmdId}, #{deviceInterlockingId}, #{banIp}, #{deviceName}, " +
"#{banTime}, #{banMethod}, #{banResult}, #{tenantId}, #{createDept}, #{createBy}, " +
"NOW(), #{remark}, #{respBody}, #{reqBody})")
@Options(useGeneratedKeys = true, keyProperty = "id")
int insert(DeviceInterlockingLog log);
/**
* 批量插入记录
*/
@Insert("<script>" +
"INSERT INTO device_interlocking_log (device_interlocking_cmd_id, device_interlocking_id, ban_ip, " +
"device_name, ban_time, ban_method, ban_result, tenant_id, create_dept, create_by, " +
"create_time, remark, resp_body, req_body) VALUES " +
"<foreach collection='logs' item='item' separator=','>" +
"(#{item.deviceInterlockingCmdId}, #{item.deviceInterlockingId}, #{item.banIp}, " +
"#{item.deviceName}, #{item.banTime}, #{item.banMethod}, #{item.banResult}, " +
"#{item.tenantId}, #{item.createDept}, #{item.createBy}, NOW(), " +
"#{item.remark}, #{item.respBody}, #{item.reqBody})" +
"</foreach>" +
"</script>")
int batchInsert(@Param("logs") List<DeviceInterlockingLog> logs);
/**
* 查询所有记录
*/
@Select("SELECT * FROM device_interlocking_log ORDER BY create_time DESC")
List<DeviceInterlockingLog> selectAll();
/**
* 统计某指令的成功/失败数量
*/
@Select("SELECT ban_result, COUNT(*) as count FROM device_interlocking_log " +
"WHERE device_interlocking_cmd_id = #{cmdId} GROUP BY ban_result")
List<java.util.Map<String, Object>> countByCmdId(@Param("cmdId") Long cmdId);
}
@@ -0,0 +1,52 @@
package com.common.mapper;
import com.common.entity.DeviceInterlocking;
import org.apache.ibatis.annotations.*;
import java.util.List;
@Mapper
public interface DeviceInterlockingMapper {
/**
* 根据ID查询
*/
@Select("SELECT * FROM device_interlocking WHERE id = #{id}")
DeviceInterlocking selectById(Long id);
/**
* 根据部门ID查询联动设备
*/
@Select("SELECT * FROM device_interlocking WHERE dept_id = #{deptId}")
List<DeviceInterlocking> selectByDeptId(@Param("deptId") String deptId);
/**
* 根据厂商查询
*/
@Select("SELECT * FROM device_interlocking WHERE vendor = #{vendor}")
List<DeviceInterlocking> selectByVendor(@Param("vendor") String vendor);
/**
* 插入记录
*/
@Insert("INSERT INTO device_interlocking (device_name, vendor, dept_id, ban_limit, ip, api_url, " +
"tenant_id, create_dept, create_by, create_time, update_time, remark, auth_username, auth_password) " +
"VALUES (#{deviceName}, #{vendor}, #{deptId}, #{banLimit}, #{ip}, #{apiUrl}, " +
"#{tenantId}, #{createDept}, #{createBy}, NOW(), NOW(), #{remark}, #{authUsername}, #{authPassword})")
@Options(useGeneratedKeys = true, keyProperty = "id")
int insert(DeviceInterlocking device);
/**
* 更新记录
*/
@Update("UPDATE device_interlocking SET device_name = #{deviceName}, vendor = #{vendor}, " +
"dept_id = #{deptId}, ban_limit = #{banLimit}, ip = #{ip}, api_url = #{apiUrl}, " +
"update_time = NOW(), remark = #{remark}, auth_username = #{authUsername}, " +
"auth_password = #{authPassword} WHERE id = #{id}")
int update(DeviceInterlocking device);
/**
* 查询所有记录
*/
@Select("SELECT * FROM device_interlocking ORDER BY create_time DESC")
List<DeviceInterlocking> selectAll();
}
@@ -0,0 +1,47 @@
package com.common.mapper;
import com.common.entity.WecomNotification;
import org.apache.ibatis.annotations.*;
/**
* 微信通知 Mapper 接口
*/
@Mapper
public interface WecomNotificationMapper {
/**
* 插入单条记录(使用序列生成ID)
*/
@Insert("INSERT INTO wecom_notification (" +
"wecom_notification_id, user_id, wecom_notification_name, wecom_notification_ip, " +
"wecom_notification_type, wecom_notification_level, wecom_notification_content, " +
"wecom_notification_time, tenant_id, create_dept, create_by, create_time, " +
"update_by, update_time, remark, wecom_notification_status" +
") VALUES (" +
"nextval('seq_wecom_notification'), #{userId}, #{wecomNotificationName}, #{wecomNotificationIp}, " +
"#{wecomNotificationType}, #{wecomNotificationLevel}, #{wecomNotificationContent}, " +
"#{wecomNotificationTime}, #{tenantId}, #{createDept}, #{createBy}, #{createTime}, " +
"#{updateBy}, #{updateTime}, #{remark}, #{wecomNotificationStatus}" +
")")
@SelectKey(statement = "SELECT currval('seq_wecom_notification')", keyProperty = "wecomNotificationId", resultType = Long.class, before = false)
int insert(WecomNotification notification);
/**
* 根据通知ID查询
*/
@Select("SELECT * FROM wecom_notification WHERE wecom_notification_id = #{wecomNotificationId}")
WecomNotification selectById(@Param("wecomNotificationId") Long wecomNotificationId);
/**
* 查询未发送的通知列表
*/
@Select("SELECT * FROM wecom_notification WHERE wecom_notification_status = '1' ORDER BY create_time DESC")
java.util.List<WecomNotification> selectUnsentNotifications();
/**
* 更新通知状态
*/
@Update("UPDATE wecom_notification SET wecom_notification_status = #{status}, update_time = NOW() " +
"WHERE wecom_notification_id = #{wecomNotificationId}")
int updateStatus(@Param("wecomNotificationId") Long wecomNotificationId, @Param("status") String status);
}
@@ -0,0 +1,56 @@
package com.common.schedule;
import com.common.service.AlarmHealthCheckService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
/**
* 告警健康检查定时任务
* 每5分钟巡检告警表和告警日志表
*/
@Component
public class AlarmHealthCheckScheduler {
private static final Logger logger = LoggerFactory.getLogger(AlarmHealthCheckScheduler.class);
@Autowired
private AlarmHealthCheckService alarmHealthCheckService;
/**
* 每5分钟执行一次告警健康检查
* 巡检告警表 alarm 和告警日志表 alarm_visit
*/
@Scheduled(cron = "0 */5 * * * ?")
public void scheduledHealthCheck() {
logger.info("========== 开始执行告警健康检查 ==========");
long startTime = System.currentTimeMillis();
try {
boolean hasAlarm = alarmHealthCheckService.performHealthCheck();
long elapsedTime = System.currentTimeMillis() - startTime;
if (hasAlarm) {
logger.warn("告警健康检查完成, 发现异常数据, 耗时: {}ms", elapsedTime);
} else {
logger.info("告警健康检查完成, 所有表数据正常, 耗时: {}ms", elapsedTime);
}
} catch (Exception e) {
logger.error("告警健康检查执行异常: {}", e.getMessage(), e);
}
logger.info("========== 告警健康检查任务结束 ==========");
}
/**
* 手动触发健康检查(供其他服务调用)
* @return 是否有异常
*/
public boolean manualHealthCheck() {
logger.info("手动触发告警健康检查");
return alarmHealthCheckService.performHealthCheck();
}
}
@@ -0,0 +1,167 @@
package com.common.service;
import com.common.entity.WecomNotification;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Service;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
/**
* 告警健康检查服务
* 巡检告警表和告警日志表是否有数据
*/
@Service
public class AlarmHealthCheckService {
private static final Logger logger = LoggerFactory.getLogger(AlarmHealthCheckService.class);
@Autowired
private JdbcTemplate jdbcTemplate;
@Autowired
private WecomNotificationService wecomNotificationService;
@Value("${alarm.health-check.alarm-hours:2}")
private int alarmHoursThreshold;
@Value("${alarm.health-check.alarm-visit-hours:4}")
private int alarmVisitHoursThreshold;
private static final DateTimeFormatter DATE_FORMATTER = DateTimeFormatter.ofPattern("yyyyMMdd");
/**
* 执行告警健康检查
* @return 是否有异常
*/
public boolean performHealthCheck() {
boolean hasAlarm = false;
// 1. 检查告警表 alarm
boolean alarmTableNormal = checkAlarmTable();
if (!alarmTableNormal) {
hasAlarm = true;
generateAlarmNotification("alarm", alarmHoursThreshold);
}
// 2. 检查告警日志表 alarm_visit
boolean alarmVisitTableNormal = checkAlarmVisitTable();
if (!alarmVisitTableNormal) {
hasAlarm = true;
generateAlarmNotification("alarm_visit", alarmVisitHoursThreshold);
}
return hasAlarm;
}
/**
* 检查告警表 alarm_yyyyMMdd 最近是否无数据
* @return true=正常有数据, false=异常无数据
*/
public boolean checkAlarmTable() {
String partitionDate = LocalDateTime.now().format(DATE_FORMATTER);
String tableName = "alarm_" + partitionDate;
String sql = "SELECT COUNT(*) FROM " + tableName + " WHERE created_at >= NOW() - INTERVAL '" + alarmHoursThreshold + " hours'";
try {
Long count = jdbcTemplate.queryForObject(sql, Long.class);
boolean hasData = count != null && count > 0;
logger.info("告警表 {} 健康检查: {}小时内数据量={}, 状态={}",
tableName, alarmHoursThreshold, count, hasData ? "正常" : "异常");
return hasData;
} catch (Exception e) {
logger.error("检查告警表 {} 失败: {}", tableName, e.getMessage());
// 表不存在或查询失败,认为异常
return false;
}
}
/**
* 检查告警日志表 alarm_visit_yyyyMMdd 最近是否无数据
* @return true=正常有数据, false=异常无数据
*/
public boolean checkAlarmVisitTable() {
String partitionDate = LocalDateTime.now().format(DATE_FORMATTER);
String tableName = "alarm_visit_" + partitionDate;
String sql = "SELECT COUNT(*) FROM " + tableName + " WHERE created_at >= NOW() - INTERVAL '" + alarmVisitHoursThreshold + " hours'";
try {
Long count = jdbcTemplate.queryForObject(sql, Long.class);
boolean hasData = count != null && count > 0;
logger.info("告警日志表 {} 健康检查: {}小时内数据量={}, 状态={}",
tableName, alarmVisitHoursThreshold, count, hasData ? "正常" : "异常");
return hasData;
} catch (Exception e) {
logger.error("检查告警日志表 {} 失败: {}", tableName, e.getMessage());
// 表不存在或查询失败,认为异常
return false;
}
}
/**
* 生成告警通知并插入微信通知表
*
* @param tableType 表类型(alarm 或 alarm_visit
* @param hoursThreshold 小时阈值
*/
public void generateAlarmNotification(String tableType, int hoursThreshold) {
String tableName = tableType + "_" + LocalDateTime.now().format(DATE_FORMATTER);
String content = String.format(
"【数据巡检告警】%n" +
"表名: %s%n" +
"告警时间: %s%n" +
"告警描述: 最近%d小时内无新数据%n" +
"建议: 请检查数据采集服务是否正常运行%n" +
"状态: 需要人工介入检查",
tableName,
LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")),
hoursThreshold
);
WecomNotification notification = wecomNotificationService.sendAlert(
"数据巡检告警-" + tableName,
"alarm_health_check",
"3", // 高危
content,
null
);
logger.warn("生成告警通知: 表={}, 通知ID={}", tableName, notification.getWecomNotificationId());
}
/**
* 微信通知告警数据插入函数方法
* 提供给其他模块在运行有异常的情况下调用
*
* @param alertName 告警名称
* @param alertType 告警类型
* @param alertLevel 告警等级(1:低, 2:中, 3:高, 4:紧急)
* @param alertContent 告警内容
* @return 通知实体
*/
public WecomNotification insertWecomAlert(String alertName, String alertType,
String alertLevel, String alertContent) {
return wecomNotificationService.sendAlert(alertName, alertType, alertLevel, alertContent, null);
}
/**
* 快速插入告警通知(简化版)
*
* @param alertType 告警类型
* @param alertContent 告警内容
* @return 通知实体
*/
public WecomNotification insertWecomAlert(String alertType, String alertContent) {
return wecomNotificationService.sendAlert(alertType, alertContent);
}
}
@@ -0,0 +1,84 @@
package com.common.service;
import com.common.entity.DeviceInterlockingCmd;
import com.common.mapper.DeviceInterlockingCmdMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.List;
@Service
public class DeviceInterlockingCmdService {
@Autowired
private DeviceInterlockingCmdMapper cmdMapper;
/**
* 根据ID查询
*/
public DeviceInterlockingCmd selectById(Long id) {
return cmdMapper.selectById(id);
}
/**
* 查询待执行的指令
*/
public List<DeviceInterlockingCmd> selectPendingCommands(Long probeId) {
return cmdMapper.selectPendingCommands(probeId);
}
/**
* 根据探针ID和状态查询
*/
public List<DeviceInterlockingCmd> selectByProbeIdAndStatus(Long probeId, String cmdStatus) {
return cmdMapper.selectByProbeIdAndStatus(probeId, cmdStatus);
}
/**
* 插入指令
*/
public int insert(DeviceInterlockingCmd cmd) {
return cmdMapper.insert(cmd);
}
/**
* 更新指令状态
*/
public int updateStatus(Long id, String cmdStatus) {
return cmdMapper.updateStatus(id, cmdStatus);
}
/**
* 更新指令状态为执行中
*/
public int updateStatusToExecuting(Long id) {
return cmdMapper.updateStatusToExecuting(id);
}
/**
* 更新指令状态为执行完成
*/
public int updateStatusToCompleted(Long id) {
return cmdMapper.updateStatusToCompleted(id);
}
/**
* 更新指令状态为执行失败
*/
public int updateStatusToFailed(Long id) {
return cmdMapper.updateStatusToFailed(id);
}
/**
* 查询所有指令
*/
public List<DeviceInterlockingCmd> selectAll() {
return cmdMapper.selectAll();
}
/**
* 根据多个ID查询
*/
public List<DeviceInterlockingCmd> selectByIds(List<Long> ids) {
return cmdMapper.selectByIds(ids);
}
}
@@ -0,0 +1,67 @@
package com.common.service;
import com.common.entity.DeviceInterlockingLog;
import com.common.mapper.DeviceInterlockingLogMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.time.OffsetDateTime;
import java.util.List;
@Service
public class DeviceInterlockingLogService {
@Autowired
private DeviceInterlockingLogMapper logMapper;
/**
* 根据ID查询
*/
public DeviceInterlockingLog selectById(Long id) {
return logMapper.selectById(id);
}
/**
* 根据指令ID查询
*/
public List<DeviceInterlockingLog> selectByCmdId(Long cmdId) {
return logMapper.selectByCmdId(cmdId);
}
/**
* 插入记录
*/
public int insert(DeviceInterlockingLog log) {
if (log.getBanTime() == null) {
log.setBanTime(OffsetDateTime.now());
}
return logMapper.insert(log);
}
/**
* 批量插入记录
*/
public int batchInsert(List<DeviceInterlockingLog> logs) {
if (logs != null && !logs.isEmpty()) {
for (DeviceInterlockingLog log : logs) {
if (log.getBanTime() == null) {
log.setBanTime(OffsetDateTime.now());
}
}
}
return logMapper.batchInsert(logs);
}
/**
* 查询所有记录
*/
public List<DeviceInterlockingLog> selectAll() {
return logMapper.selectAll();
}
/**
* 统计某指令的成功/失败数量
*/
public List<java.util.Map<String, Object>> countByCmdId(Long cmdId) {
return logMapper.countByCmdId(cmdId);
}
}
@@ -0,0 +1,56 @@
package com.common.service;
import com.common.entity.DeviceInterlocking;
import com.common.mapper.DeviceInterlockingMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.List;
@Service
public class DeviceInterlockingService {
@Autowired
private DeviceInterlockingMapper interlockingMapper;
/**
* 根据ID查询
*/
public DeviceInterlocking selectById(Long id) {
return interlockingMapper.selectById(id);
}
/**
* 根据部门ID查询联动设备
*/
public List<DeviceInterlocking> selectByDeptId(String deptId) {
return interlockingMapper.selectByDeptId(deptId);
}
/**
* 根据厂商查询
*/
public List<DeviceInterlocking> selectByVendor(String vendor) {
return interlockingMapper.selectByVendor(vendor);
}
/**
* 插入记录
*/
public int insert(DeviceInterlocking device) {
return interlockingMapper.insert(device);
}
/**
* 更新记录
*/
public int update(DeviceInterlocking device) {
return interlockingMapper.update(device);
}
/**
* 查询所有记录
*/
public List<DeviceInterlocking> selectAll() {
return interlockingMapper.selectAll();
}
}
@@ -0,0 +1,121 @@
package com.common.service;
import com.common.entity.WecomNotification;
import com.common.mapper.WecomNotificationMapper;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.time.LocalDateTime;
/**
* 微信通知服务类
*/
@Service
public class WecomNotificationService {
private static final Logger logger = LoggerFactory.getLogger(WecomNotificationService.class);
@Autowired
private WecomNotificationMapper wecomNotificationMapper;
/**
* 插入微信通知
*
* @param notification 通知实体
* @return 影响的行数
*/
public int insert(WecomNotification notification) {
try {
if (notification.getCreateTime() == null) {
notification.setCreateTime(LocalDateTime.now());
}
if (notification.getWecomNotificationTime() == null) {
notification.setWecomNotificationTime(LocalDateTime.now());
}
if (notification.getWecomNotificationStatus() == null) {
notification.setWecomNotificationStatus("1"); // 默认未发送
}
if (notification.getTenantId() == null) {
notification.setTenantId("000000");
}
int rows = wecomNotificationMapper.insert(notification);
logger.info("插入微信通知成功, ID: {}, 类型: {}, 内容: {}",
notification.getWecomNotificationId(),
notification.getWecomNotificationType(),
notification.getWecomNotificationName());
return rows;
} catch (Exception e) {
logger.error("插入微信通知失败: {}", e.getMessage(), e);
throw e;
}
}
/**
* 根据ID查询
*/
public WecomNotification selectById(Long id) {
return wecomNotificationMapper.selectById(id);
}
/**
* 查询未发送的通知列表
*/
public java.util.List<WecomNotification> selectUnsentNotifications() {
return wecomNotificationMapper.selectUnsentNotifications();
}
/**
* 更新通知状态
*
* @param id 通知ID
* @param status 状态(0:已发送, 1:未发送)
* @return 影响的行数
*/
public int updateStatus(Long id, String status) {
return wecomNotificationMapper.updateStatus(id, status);
}
/**
* 发送微信通知告警
* 提供给其他模块在运行异常时调用
*
* @param name 通知名称
* @param type 通知类型(如:alarm_health_check
* @param level 通知等级(1:低, 2:中, 3:高, 4:紧急)
* @param content 通知内容
* @param ip 关联IP(可选)
* @return 通知实体
*/
public WecomNotification sendAlert(String name, String type, String level, String content, String ip) {
WecomNotification notification = new WecomNotification();
notification.setWecomNotificationName(name);
notification.setWecomNotificationType(type);
notification.setWecomNotificationLevel(level);
notification.setWecomNotificationContent(content);
notification.setWecomNotificationIp(ip);
notification.setWecomNotificationTime(LocalDateTime.now());
notification.setWecomNotificationStatus("1"); // 未发送
notification.setTenantId("000000");
notification.setCreateTime(LocalDateTime.now());
insert(notification);
logger.warn("发送微信告警通知 - 名称: {}, 类型: {}, 等级: {}, 内容: {}",
name, type, level, content);
return notification;
}
/**
* 发送告警通知(简化版本)
*
* @param alertType 告警类型
* @param alertContent 告警内容
* @return 通知实体
*/
public WecomNotification sendAlert(String alertType, String alertContent) {
return sendAlert(alertType, alertType, "3", alertContent, null);
}
}
@@ -0,0 +1,49 @@
package com.haobang.config;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import org.springframework.web.servlet.HandlerInterceptor;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
/**
* API-KEY认证拦截器
*/
@Component
public class ApiKeyInterceptor implements HandlerInterceptor {
@Value("${interlocking.api-key:}")
private String configuredApiKey;
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
// 放行CORS预检请求
if ("OPTIONS".equalsIgnoreCase(request.getMethod())) {
return true;
}
String requestApiKey = request.getHeader("X-API-KEY");
// 如果配置了API-KEY,则进行校验
if (configuredApiKey != null && !configuredApiKey.isEmpty()) {
if (requestApiKey == null || requestApiKey.isEmpty()) {
sendUnauthorized(response, "API-KEY header is missing");
return false;
}
if (!configuredApiKey.equals(requestApiKey)) {
sendUnauthorized(response, "Invalid API-KEY");
return false;
}
}
return true;
}
private void sendUnauthorized(HttpServletResponse response, String message) throws Exception {
response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
response.setContentType("application/json;charset=UTF-8");
response.getWriter().write("{\"code\":401,\"message\":\"" + message + "\"}");
}
}
@@ -0,0 +1,24 @@
package com.haobang.config;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
/**
* Web MVC配置类
*/
@Configuration
public class WebMvcConfig implements WebMvcConfigurer {
@Autowired
private ApiKeyInterceptor apiKeyInterceptor;
@Override
public void addInterceptors(InterceptorRegistry registry) {
// 配置API-KEY拦截器,只拦截联动相关的接口
registry.addInterceptor(apiKeyInterceptor)
.addPathPatterns("/interlocking/**")
.excludePathPatterns("/interlocking/health");
}
}
@@ -0,0 +1,417 @@
package com.haobang.controller;
import com.common.entity.DeviceInterlockingCmd;
import com.common.entity.DeviceInterlockingLog;
import com.common.entity.DeviceInterlocking;
import com.common.service.DeviceInterlockingCmdService;
import com.common.service.DeviceInterlockingLogService;
import com.common.service.DeviceInterlockingService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
/**
* 探针联动控制器
* 提供REST API接口给syslog-serve模块调用
* API-KEY认证机制
*/
@RestController
@RequestMapping("/interlocking")
public class InterlockingController {
@Autowired
private DeviceInterlockingCmdService cmdService;
@Autowired
private DeviceInterlockingLogService logService;
@Autowired
private DeviceInterlockingService interlockingService;
/**
* 健康检查接口(不需要API-KEY认证)
*/
@GetMapping("/health")
public ResponseEntity<Map<String, Object>> health() {
Map<String, Object> result = new HashMap<>();
result.put("code", 200);
result.put("message", "OK");
result.put("service", "interlocking-api");
return ResponseEntity.ok(result);
}
// ==================== 封禁指令接口 ====================
/**
* 1.1 获取待执行的封禁指令记录
* GET /interlocking/cmd/pending?probeId=1
*/
@GetMapping("/cmd/pending")
public ResponseEntity<Map<String, Object>> getPendingCommands(@RequestParam Long probeId) {
Map<String, Object> result = new HashMap<>();
try {
List<DeviceInterlockingCmd> commands = cmdService.selectPendingCommands(probeId);
result.put("code", 200);
result.put("message", "success");
result.put("data", commands);
result.put("total", commands.size());
return ResponseEntity.ok(result);
} catch (Exception e) {
result.put("code", 500);
result.put("message", "获取待执行指令失败: " + e.getMessage());
return ResponseEntity.status(500).body(result);
}
}
/**
* 1.2 获取指定状态的封禁指令记录
* GET /interlocking/cmd?probeId=1&cmdStatus=0
*/
@GetMapping("/cmd")
public ResponseEntity<Map<String, Object>> getCommands(
@RequestParam Long probeId,
@RequestParam(required = false) String cmdStatus) {
Map<String, Object> result = new HashMap<>();
try {
List<DeviceInterlockingCmd> commands;
if (cmdStatus != null && !cmdStatus.isEmpty()) {
commands = cmdService.selectByProbeIdAndStatus(probeId, cmdStatus);
} else {
commands = cmdService.selectPendingCommands(probeId);
}
result.put("code", 200);
result.put("message", "success");
result.put("data", commands);
result.put("total", commands.size());
return ResponseEntity.ok(result);
} catch (Exception e) {
result.put("code", 500);
result.put("message", "获取指令失败: " + e.getMessage());
return ResponseEntity.status(500).body(result);
}
}
/**
* 1.3 获取单个指令详情
* GET /interlocking/cmd/{id}
*/
@GetMapping("/cmd/{id}")
public ResponseEntity<Map<String, Object>> getCommandById(@PathVariable Long id) {
Map<String, Object> result = new HashMap<>();
try {
DeviceInterlockingCmd command = cmdService.selectById(id);
if (command == null) {
result.put("code", 404);
result.put("message", "指令不存在");
return ResponseEntity.status(404).body(result);
}
result.put("code", 200);
result.put("message", "success");
result.put("data", command);
return ResponseEntity.ok(result);
} catch (Exception e) {
result.put("code", 500);
result.put("message", "获取指令详情失败: " + e.getMessage());
return ResponseEntity.status(500).body(result);
}
}
/**
* 1.4 创建新的封禁指令
* POST /interlocking/cmd
*/
@PostMapping("/cmd")
public ResponseEntity<Map<String, Object>> createCommand(@RequestBody DeviceInterlockingCmd cmd) {
Map<String, Object> result = new HashMap<>();
try {
// 设置默认状态为待执行
if (cmd.getCmdStatus() == null || cmd.getCmdStatus().isEmpty()) {
cmd.setCmdStatus("0");
}
int rows = cmdService.insert(cmd);
result.put("code", 200);
result.put("message", "指令创建成功");
result.put("data", rows);
return ResponseEntity.ok(result);
} catch (Exception e) {
result.put("code", 500);
result.put("message", "创建指令失败: " + e.getMessage());
return ResponseEntity.status(500).body(result);
}
}
// ==================== 指令状态更新接口 ====================
/**
* 2.1 更新封禁指令状态为执行中
* PUT /interlocking/cmd/{id}/status/executing
*/
@PutMapping("/cmd/{id}/status/executing")
public ResponseEntity<Map<String, Object>> updateStatusToExecuting(@PathVariable Long id) {
Map<String, Object> result = new HashMap<>();
try {
int rows = cmdService.updateStatusToExecuting(id);
if (rows > 0) {
result.put("code", 200);
result.put("message", "状态已更新为执行中");
result.put("data", rows);
} else {
result.put("code", 404);
result.put("message", "指令不存在");
}
return ResponseEntity.ok(result);
} catch (Exception e) {
result.put("code", 500);
result.put("message", "更新状态失败: " + e.getMessage());
return ResponseEntity.status(500).body(result);
}
}
/**
* 2.2 更新封禁指令状态为执行完成
* PUT /interlocking/cmd/{id}/status/completed
*/
@PutMapping("/cmd/{id}/status/completed")
public ResponseEntity<Map<String, Object>> updateStatusToCompleted(@PathVariable Long id) {
Map<String, Object> result = new HashMap<>();
try {
int rows = cmdService.updateStatusToCompleted(id);
if (rows > 0) {
result.put("code", 200);
result.put("message", "状态已更新为执行完成");
result.put("data", rows);
} else {
result.put("code", 404);
result.put("message", "指令不存在");
}
return ResponseEntity.ok(result);
} catch (Exception e) {
result.put("code", 500);
result.put("message", "更新状态失败: " + e.getMessage());
return ResponseEntity.status(500).body(result);
}
}
/**
* 2.3 更新封禁指令状态为执行失败
* PUT /interlocking/cmd/{id}/status/failed
*/
@PutMapping("/cmd/{id}/status/failed")
public ResponseEntity<Map<String, Object>> updateStatusToFailed(@PathVariable Long id) {
Map<String, Object> result = new HashMap<>();
try {
int rows = cmdService.updateStatusToFailed(id);
if (rows > 0) {
result.put("code", 200);
result.put("message", "状态已更新为执行失败");
result.put("data", rows);
} else {
result.put("code", 404);
result.put("message", "指令不存在");
}
return ResponseEntity.ok(result);
} catch (Exception e) {
result.put("code", 500);
result.put("message", "更新状态失败: " + e.getMessage());
return ResponseEntity.status(500).body(result);
}
}
/**
* 2.4 批量更新封禁指令状态
* PUT /interlocking/cmd/status
*/
@PutMapping("/cmd/status")
public ResponseEntity<Map<String, Object>> batchUpdateStatus(@RequestBody Map<String, Object> request) {
Map<String, Object> result = new HashMap<>();
try {
@SuppressWarnings("unchecked")
List<Long> ids = (List<Long>) request.get("ids");
String cmdStatus = (String) request.get("cmdStatus");
if (ids == null || ids.isEmpty()) {
result.put("code", 400);
result.put("message", "指令ID列表不能为空");
return ResponseEntity.badRequest().body(result);
}
int total = 0;
for (Long id : ids) {
total += cmdService.updateStatus(id, cmdStatus);
}
result.put("code", 200);
result.put("message", "批量更新成功");
result.put("data", total);
return ResponseEntity.ok(result);
} catch (Exception e) {
result.put("code", 500);
result.put("message", "批量更新状态失败: " + e.getMessage());
return ResponseEntity.status(500).body(result);
}
}
// ==================== 封禁记录接口 ====================
/**
* 3.1 批量插入封禁记录
* POST /interlocking/log/batch
*/
@PostMapping("/log/batch")
public ResponseEntity<Map<String, Object>> batchInsertLog(@RequestBody Map<String, Object> request) {
Map<String, Object> result = new HashMap<>();
try {
// Spring无法直接将List<LinkedHashMap>转为List<DeviceInterlockingLog>
// 需要手动转换
Object logsObj = request.get("logs");
List<DeviceInterlockingLog> logs;
if (logsObj instanceof List) {
logs = ((List<?>) logsObj).stream()
.map(item -> convertToDeviceInterlockingLog(item))
.collect(Collectors.toList());
} else {
result.put("code", 400);
result.put("message", "logs字段格式错误,应为数组");
return ResponseEntity.badRequest().body(result);
}
if (logs == null || logs.isEmpty()) {
result.put("code", 400);
result.put("message", "封禁记录列表不能为空");
return ResponseEntity.badRequest().body(result);
}
int rows = logService.batchInsert(logs);
result.put("code", 200);
result.put("message", "批量插入成功");
result.put("data", rows);
result.put("total", logs.size());
return ResponseEntity.ok(result);
} catch (Exception e) {
result.put("code", 500);
result.put("message", "批量插入记录失败: " + e.getMessage());
return ResponseEntity.status(500).body(result);
}
}
/**
* 将Map转换为DeviceInterlockingLog实体
*/
private DeviceInterlockingLog convertToDeviceInterlockingLog(Object item) {
DeviceInterlockingLog log = new DeviceInterlockingLog();
if (item instanceof Map) {
@SuppressWarnings("unchecked")
Map<String, Object> map = (Map<String, Object>) item;
if (map.get("id") != null) log.setId(((Number) map.get("id")).longValue());
if (map.get("deviceInterlockingCmdId") != null) log.setDeviceInterlockingCmdId(((Number) map.get("deviceInterlockingCmdId")).longValue());
if (map.get("deviceInterlockingId") != null) log.setDeviceInterlockingId(((Number) map.get("deviceInterlockingId")).longValue());
if (map.get("banIp") != null) log.setBanIp(String.valueOf(map.get("banIp")));
if (map.get("deviceName") != null) log.setDeviceName(String.valueOf(map.get("deviceName")));
if (map.get("banMethod") != null) log.setBanMethod(String.valueOf(map.get("banMethod")));
if (map.get("banResult") != null) {
Object banResult = map.get("banResult");
if (banResult instanceof Number) {
log.setBanResult(((Number) banResult).intValue());
} else {
log.setBanResult(Integer.parseInt(String.valueOf(banResult)));
}
}
if (map.get("tenantId") != null) log.setTenantId(String.valueOf(map.get("tenantId")));
if (map.get("createDept") != null) log.setCreateDept(((Number) map.get("createDept")).longValue());
if (map.get("createBy") != null) log.setCreateBy(((Number) map.get("createBy")).longValue());
if (map.get("remark") != null) log.setRemark(String.valueOf(map.get("remark")));
if (map.get("respBody") != null) log.setRespBody(String.valueOf(map.get("respBody")));
if (map.get("reqBody") != null) log.setReqBody(String.valueOf(map.get("reqBody")));
}
return log;
}
/**
* 3.2 获取封禁记录列表
* GET /interlocking/log?cmdId=1
*/
@GetMapping("/log")
public ResponseEntity<Map<String, Object>> getLogs(@RequestParam(required = false) Long cmdId) {
Map<String, Object> result = new HashMap<>();
try {
List<DeviceInterlockingLog> logs;
if (cmdId != null) {
logs = logService.selectByCmdId(cmdId);
} else {
logs = logService.selectAll();
}
result.put("code", 200);
result.put("message", "success");
result.put("data", logs);
result.put("total", logs.size());
return ResponseEntity.ok(result);
} catch (Exception e) {
result.put("code", 500);
result.put("message", "获取记录失败: " + e.getMessage());
return ResponseEntity.status(500).body(result);
}
}
// ==================== 联动设备接口 ====================
/**
* 获取联动设备列表
* GET /interlocking/device
*/
@GetMapping("/device")
public ResponseEntity<Map<String, Object>> getDevices(
@RequestParam(required = false) String deptId,
@RequestParam(required = false) String vendor) {
Map<String, Object> result = new HashMap<>();
try {
List<DeviceInterlocking> devices;
if (deptId != null && !deptId.isEmpty()) {
devices = interlockingService.selectByDeptId(deptId);
} else if (vendor != null && !vendor.isEmpty()) {
devices = interlockingService.selectByVendor(vendor);
} else {
devices = interlockingService.selectAll();
}
result.put("code", 200);
result.put("message", "success");
result.put("data", devices);
result.put("total", devices.size());
return ResponseEntity.ok(result);
} catch (Exception e) {
result.put("code", 500);
result.put("message", "获取设备失败: " + e.getMessage());
return ResponseEntity.status(500).body(result);
}
}
/**
* 获取单个联动设备详情
* GET /interlocking/device/{id}
*/
@GetMapping("/device/{id}")
public ResponseEntity<Map<String, Object>> getDeviceById(@PathVariable Long id) {
Map<String, Object> result = new HashMap<>();
try {
DeviceInterlocking device = interlockingService.selectById(id);
if (device == null) {
result.put("code", 404);
result.put("message", "设备不存在");
return ResponseEntity.status(404).body(result);
}
result.put("code", 200);
result.put("message", "success");
result.put("data", device);
return ResponseEntity.ok(result);
} catch (Exception e) {
result.put("code", 500);
result.put("message", "获取设备详情失败: " + e.getMessage());
return ResponseEntity.status(500).body(result);
}
}
}