diff --git a/haobang-security-xdr/syslog-consumer/pom.xml b/haobang-security-xdr/syslog-consumer/pom.xml
index 16a502f..ff7b6cb 100644
--- a/haobang-security-xdr/syslog-consumer/pom.xml
+++ b/haobang-security-xdr/syslog-consumer/pom.xml
@@ -197,7 +197,12 @@
DmJdbcDriver18
8.1.2.141
-
+
+
+ org.bouncycastle
+ bcprov-jdk15to18
+ 1.78
+
diff --git a/haobang-security-xdr/syslog-consumer/src/main/java/com/common/entity/DeviceInterlocking.java b/haobang-security-xdr/syslog-consumer/src/main/java/com/common/entity/DeviceInterlocking.java
new file mode 100644
index 0000000..6ce07ee
--- /dev/null
+++ b/haobang-security-xdr/syslog-consumer/src/main/java/com/common/entity/DeviceInterlocking.java
@@ -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 + '\'' +
+ '}';
+ }
+}
diff --git a/haobang-security-xdr/syslog-consumer/src/main/java/com/common/entity/DeviceInterlockingCmd.java b/haobang-security-xdr/syslog-consumer/src/main/java/com/common/entity/DeviceInterlockingCmd.java
new file mode 100644
index 0000000..29343a0
--- /dev/null
+++ b/haobang-security-xdr/syslog-consumer/src/main/java/com/common/entity/DeviceInterlockingCmd.java
@@ -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 getDeviceInterlockingIdList() {
+ return deviceInterlockingId != null ? Arrays.asList(deviceInterlockingId) : null;
+ }
+
+ /**
+ * 设置设备联动ID列表
+ */
+ public void setDeviceInterlockingIdList(List list) {
+ this.deviceInterlockingId = list != null ? list.toArray(new Integer[0]) : null;
+ }
+
+ /**
+ * 获取设备联动IP列表
+ */
+ public List getDeviceInterlockingIpList() {
+ return deviceInterlockingIp != null ? Arrays.asList(deviceInterlockingIp) : null;
+ }
+
+ /**
+ * 设置设备联动IP列表
+ */
+ public void setDeviceInterlockingIpList(List list) {
+ this.deviceInterlockingIp = list != null ? list.toArray(new String[0]) : null;
+ }
+
+ /**
+ * 获取封禁IP列表
+ */
+ public List getBanIpsList() {
+ return banIps != null ? Arrays.asList(banIps) : null;
+ }
+
+ /**
+ * 设置封禁IP列表
+ */
+ public void setBanIpsList(List 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 +
+ '}';
+ }
+}
diff --git a/haobang-security-xdr/syslog-consumer/src/main/java/com/common/entity/DeviceInterlockingLog.java b/haobang-security-xdr/syslog-consumer/src/main/java/com/common/entity/DeviceInterlockingLog.java
new file mode 100644
index 0000000..516c829
--- /dev/null
+++ b/haobang-security-xdr/syslog-consumer/src/main/java/com/common/entity/DeviceInterlockingLog.java
@@ -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 +
+ '}';
+ }
+}
diff --git a/haobang-security-xdr/syslog-consumer/src/main/java/com/common/entity/WecomNotification.java b/haobang-security-xdr/syslog-consumer/src/main/java/com/common/entity/WecomNotification.java
new file mode 100644
index 0000000..4167c88
--- /dev/null
+++ b/haobang-security-xdr/syslog-consumer/src/main/java/com/common/entity/WecomNotification.java
@@ -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();
+ }
+}
diff --git a/haobang-security-xdr/syslog-consumer/src/main/java/com/common/mapper/DeviceInterlockingCmdMapper.java b/haobang-security-xdr/syslog-consumer/src/main/java/com/common/mapper/DeviceInterlockingCmdMapper.java
new file mode 100644
index 0000000..57bfe7e
--- /dev/null
+++ b/haobang-security-xdr/syslog-consumer/src/main/java/com/common/mapper/DeviceInterlockingCmdMapper.java
@@ -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 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 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("")
+ @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 selectByIds(@Param("ids") List 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 selectAll();
+}
diff --git a/haobang-security-xdr/syslog-consumer/src/main/java/com/common/mapper/DeviceInterlockingLogMapper.java b/haobang-security-xdr/syslog-consumer/src/main/java/com/common/mapper/DeviceInterlockingLogMapper.java
new file mode 100644
index 0000000..ceedf13
--- /dev/null
+++ b/haobang-security-xdr/syslog-consumer/src/main/java/com/common/mapper/DeviceInterlockingLogMapper.java
@@ -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 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("")
+ int batchInsert(@Param("logs") List logs);
+
+ /**
+ * 查询所有记录
+ */
+ @Select("SELECT * FROM device_interlocking_log ORDER BY create_time DESC")
+ List selectAll();
+
+ /**
+ * 统计某指令的成功/失败数量
+ */
+ @Select("SELECT ban_result, COUNT(*) as count FROM device_interlocking_log " +
+ "WHERE device_interlocking_cmd_id = #{cmdId} GROUP BY ban_result")
+ List> countByCmdId(@Param("cmdId") Long cmdId);
+}
diff --git a/haobang-security-xdr/syslog-consumer/src/main/java/com/common/mapper/DeviceInterlockingMapper.java b/haobang-security-xdr/syslog-consumer/src/main/java/com/common/mapper/DeviceInterlockingMapper.java
new file mode 100644
index 0000000..a5beb84
--- /dev/null
+++ b/haobang-security-xdr/syslog-consumer/src/main/java/com/common/mapper/DeviceInterlockingMapper.java
@@ -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 selectByDeptId(@Param("deptId") String deptId);
+
+ /**
+ * 根据厂商查询
+ */
+ @Select("SELECT * FROM device_interlocking WHERE vendor = #{vendor}")
+ List 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 selectAll();
+}
diff --git a/haobang-security-xdr/syslog-consumer/src/main/java/com/common/mapper/WecomNotificationMapper.java b/haobang-security-xdr/syslog-consumer/src/main/java/com/common/mapper/WecomNotificationMapper.java
new file mode 100644
index 0000000..abd6f61
--- /dev/null
+++ b/haobang-security-xdr/syslog-consumer/src/main/java/com/common/mapper/WecomNotificationMapper.java
@@ -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 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);
+}
diff --git a/haobang-security-xdr/syslog-consumer/src/main/java/com/common/schedule/AlarmHealthCheckScheduler.java b/haobang-security-xdr/syslog-consumer/src/main/java/com/common/schedule/AlarmHealthCheckScheduler.java
new file mode 100644
index 0000000..0d80291
--- /dev/null
+++ b/haobang-security-xdr/syslog-consumer/src/main/java/com/common/schedule/AlarmHealthCheckScheduler.java
@@ -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();
+ }
+}
diff --git a/haobang-security-xdr/syslog-consumer/src/main/java/com/common/service/AlarmHealthCheckService.java b/haobang-security-xdr/syslog-consumer/src/main/java/com/common/service/AlarmHealthCheckService.java
new file mode 100644
index 0000000..8bd999a
--- /dev/null
+++ b/haobang-security-xdr/syslog-consumer/src/main/java/com/common/service/AlarmHealthCheckService.java
@@ -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);
+ }
+}
diff --git a/haobang-security-xdr/syslog-consumer/src/main/java/com/common/service/DeviceInterlockingCmdService.java b/haobang-security-xdr/syslog-consumer/src/main/java/com/common/service/DeviceInterlockingCmdService.java
new file mode 100644
index 0000000..48e117d
--- /dev/null
+++ b/haobang-security-xdr/syslog-consumer/src/main/java/com/common/service/DeviceInterlockingCmdService.java
@@ -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 selectPendingCommands(Long probeId) {
+ return cmdMapper.selectPendingCommands(probeId);
+ }
+
+ /**
+ * 根据探针ID和状态查询
+ */
+ public List 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 selectAll() {
+ return cmdMapper.selectAll();
+ }
+
+ /**
+ * 根据多个ID查询
+ */
+ public List selectByIds(List ids) {
+ return cmdMapper.selectByIds(ids);
+ }
+}
diff --git a/haobang-security-xdr/syslog-consumer/src/main/java/com/common/service/DeviceInterlockingLogService.java b/haobang-security-xdr/syslog-consumer/src/main/java/com/common/service/DeviceInterlockingLogService.java
new file mode 100644
index 0000000..b251092
--- /dev/null
+++ b/haobang-security-xdr/syslog-consumer/src/main/java/com/common/service/DeviceInterlockingLogService.java
@@ -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 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 logs) {
+ if (logs != null && !logs.isEmpty()) {
+ for (DeviceInterlockingLog log : logs) {
+ if (log.getBanTime() == null) {
+ log.setBanTime(OffsetDateTime.now());
+ }
+ }
+ }
+ return logMapper.batchInsert(logs);
+ }
+
+ /**
+ * 查询所有记录
+ */
+ public List selectAll() {
+ return logMapper.selectAll();
+ }
+
+ /**
+ * 统计某指令的成功/失败数量
+ */
+ public List> countByCmdId(Long cmdId) {
+ return logMapper.countByCmdId(cmdId);
+ }
+}
diff --git a/haobang-security-xdr/syslog-consumer/src/main/java/com/common/service/DeviceInterlockingService.java b/haobang-security-xdr/syslog-consumer/src/main/java/com/common/service/DeviceInterlockingService.java
new file mode 100644
index 0000000..b6183c2
--- /dev/null
+++ b/haobang-security-xdr/syslog-consumer/src/main/java/com/common/service/DeviceInterlockingService.java
@@ -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 selectByDeptId(String deptId) {
+ return interlockingMapper.selectByDeptId(deptId);
+ }
+
+ /**
+ * 根据厂商查询
+ */
+ public List 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 selectAll() {
+ return interlockingMapper.selectAll();
+ }
+}
diff --git a/haobang-security-xdr/syslog-consumer/src/main/java/com/common/service/WecomNotificationService.java b/haobang-security-xdr/syslog-consumer/src/main/java/com/common/service/WecomNotificationService.java
new file mode 100644
index 0000000..8ab3ae0
--- /dev/null
+++ b/haobang-security-xdr/syslog-consumer/src/main/java/com/common/service/WecomNotificationService.java
@@ -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 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);
+ }
+}
\ No newline at end of file
diff --git a/haobang-security-xdr/syslog-consumer/src/main/java/com/haobang/config/ApiKeyInterceptor.java b/haobang-security-xdr/syslog-consumer/src/main/java/com/haobang/config/ApiKeyInterceptor.java
new file mode 100644
index 0000000..f5886e0
--- /dev/null
+++ b/haobang-security-xdr/syslog-consumer/src/main/java/com/haobang/config/ApiKeyInterceptor.java
@@ -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 + "\"}");
+ }
+}
diff --git a/haobang-security-xdr/syslog-consumer/src/main/java/com/haobang/config/WebMvcConfig.java b/haobang-security-xdr/syslog-consumer/src/main/java/com/haobang/config/WebMvcConfig.java
new file mode 100644
index 0000000..d97b1a9
--- /dev/null
+++ b/haobang-security-xdr/syslog-consumer/src/main/java/com/haobang/config/WebMvcConfig.java
@@ -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");
+ }
+}
diff --git a/haobang-security-xdr/syslog-consumer/src/main/java/com/haobang/controller/InterlockingController.java b/haobang-security-xdr/syslog-consumer/src/main/java/com/haobang/controller/InterlockingController.java
new file mode 100644
index 0000000..50f57d8
--- /dev/null
+++ b/haobang-security-xdr/syslog-consumer/src/main/java/com/haobang/controller/InterlockingController.java
@@ -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