kongdeqiang
2025-11-13 ca4d537c4065315be5c5c27cdef733fc383c4b74
fix:新分支
14个文件已添加
6个文件已修改
1555 ■■■■■ 已修改文件
pom.xml 12 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/wgcloud/WgcloudServiceApplication.java 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/wgcloud/controller/OspfInfoController.java 181 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/wgcloud/controller/TuopuController.java 73 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/wgcloud/entity/OspfInfo.java 96 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/wgcloud/entity/vo/OspfInterface.java 16 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/wgcloud/entity/vo/OspfNeighbor.java 15 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/wgcloud/filter/AuthRestFilter.java 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/wgcloud/mapper/OspfInfoMapper.java 39 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/wgcloud/service/OspfInfoService.java 137 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/wgcloud/service/RouterConnectionService.java 98 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/wgcloud/util/OspfInterfaceUtil.java 67 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/wgcloud/util/OspfNeighborUtil.java 66 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/application.yml 7 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/mybatis/mapper/OspfInfoMapper.xml 186 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/static/js/ospfInfo.js 22 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/templates/common/aside.html 11 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/templates/ospfInfo/add.html 103 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/templates/ospfInfo/list.html 120 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/templates/ospfInfo/view.html 300 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
pom.xml
@@ -87,12 +87,6 @@
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
        </dependency>
        <!-- oracle -->
        <dependency>
            <groupId>com.oracle</groupId>
            <artifactId>ojdbc6</artifactId>
            <version>11.2.0.3</version>
        </dependency>
        <!-- mariadb -->
        <dependency>
            <groupId>org.mariadb.jdbc</groupId>
@@ -134,12 +128,6 @@
            <groupId>org.postgresql</groupId>
            <artifactId>postgresql</artifactId>
            <version>42.5.0</version>
        </dependency>
        <!-- SqlServer -->
        <dependency>
            <groupId>com.microsoft.sqlserver</groupId>
            <artifactId>sqljdbc4</artifactId>
            <version>4.0</version>
        </dependency>
        <!-- shell -->
        <dependency>
src/main/java/com/wgcloud/WgcloudServiceApplication.java
@@ -31,7 +31,7 @@
@ServletComponentScan("com.wgcloud.filter")
@ComponentScan(basePackages = "com.wgcloud")
@EnableCaching
@EnableScheduling
//@EnableScheduling
public class WgcloudServiceApplication {
    public static void main(String[] args) {
        SpringApplication.run(WgcloudServiceApplication.class, args);
src/main/java/com/wgcloud/controller/OspfInfoController.java
New file
@@ -0,0 +1,181 @@
package com.wgcloud.controller;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import com.github.pagehelper.PageInfo;
import com.wgcloud.entity.AccountInfo;
import com.wgcloud.entity.OspfInfo;
import com.wgcloud.entity.SnmpInfo;
import com.wgcloud.service.LogInfoService;
import com.wgcloud.service.OspfInfoService;
import com.wgcloud.util.HostUtil;
import com.wgcloud.util.PageUtil;
import com.wgcloud.util.ResDataUtils;
import com.wgcloud.util.TokenUtils;
import com.wgcloud.util.staticvar.StaticKeys;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.snmp4j.mp.SnmpConstants;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.servlet.mvc.support.RedirectAttributes;
import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.util.HashMap;
import java.util.Map;
/**
 * @version v3.3
 * @ClassName:OspfInfoController.java
 * @author: http://www.wgstart.com
 * @date: 2021年1月16日
 * @Description: 系统生成的日志管理
 * @Copyright: 2019-2021 wgcloud. All rights reserved.
 */
@Controller
@RequestMapping("/ospfInfo")
public class OspfInfoController {
    private static final Logger logger = LoggerFactory.getLogger(OspfInfoController.class);
    @Resource
    private OspfInfoService OspfInfoService;
    @Resource
    private LogInfoService logInfoService;
    @Autowired
    private TokenUtils tokenUtils;
    /**
     * 根据条件查询日志信息列表
     *
     * @param model
     * @param request
     * @return
     */
    @RequestMapping(value = "list")
    public String OspfInfoList(OspfInfo OspfInfo, Model model, HttpServletRequest request) {
        Map<String, Object> params = new HashMap<String, Object>();
        try {
            StringBuffer url = new StringBuffer();
            String hostname = null;
            if (!StringUtils.isEmpty(OspfInfo.getHostname())) {
                hostname = OspfInfo.getHostname();
                params.put("hostname", hostname.trim());
                url.append("&hostname=").append(hostname);
            }
            if (!StringUtils.isEmpty(OspfInfo.getState())) {
                params.put("state", OspfInfo.getState());
                url.append("&state=").append(OspfInfo.getState());
            }
            if (OspfInfo.getAreaNum() !=null) {
                params.put("areaNum", OspfInfo.getAreaNum());
                url.append("&areaNum=").append(OspfInfo.getAreaNum());
            }
            PageInfo pageInfo = OspfInfoService.selectByParams(params, OspfInfo.getPage(), OspfInfo.getPageSize());
            PageUtil.initPageNumber(pageInfo, model);
            model.addAttribute("pageUrl", "/ospfInfo/list?1=1" + url.toString());
            model.addAttribute("page", pageInfo);
            model.addAttribute("ospfInfo", OspfInfo);
        } catch (Exception e) {
            logger.error("查询日志列表错误", e);
        }
        return "ospfInfo/list";
    }
    /**
     * 查看日志信息
     *
     * @param model
     * @param request
     * @return
     */
    @RequestMapping(value = "view")
    public String viewOspfInfo(Model model, HttpServletRequest request) {
        String id = request.getParameter("id");
        OspfInfo OspfInfo;
        try {
            OspfInfo = OspfInfoService.selectById(id);
            model.addAttribute("OspfInfo", OspfInfo);
        } catch (Exception e) {
            logger.error("查看日志信息错误", e);
        }
        return "ospfInfo/view";
    }
    /**
     * 保存ospf
     *
     * @param ospfInfo
     * @param model
     * @param request
     * @return
     */
    @RequestMapping(value = "save")
    public String saveOspfInfo(OspfInfo ospfInfo, Model model, HttpServletRequest request) {
        String errorMsg = "保存ospf监测错误";
        try {
            if (StringUtils.isEmpty(ospfInfo.getId())) {
                OspfInfoService.save(ospfInfo);
            } else {
                OspfInfoService.updateById(ospfInfo);
            }
        } catch (Exception e) {
            logger.error(errorMsg, e);
        }
        return "redirect:/ospfInfo/list";
    }
    @RequestMapping(value = "edit")
    public String edit(Model model, HttpServletRequest request) {
        String errorMsg = "编辑ospf设备监测";
        String id = request.getParameter("id");
        OspfInfo ospfInfo = new OspfInfo();
        try {
            if (StringUtils.isEmpty(id)) {
                //添加页面默认值,snmp端口为161,团体名称为public
                ospfInfo.setAreaNum("0");
                model.addAttribute("ospfInfo", ospfInfo);
                return "ospfInfo/add";
            }
            ospfInfo = OspfInfoService.selectById(id);
            model.addAttribute("ospfInfo", ospfInfo);
        } catch (Exception e) {
            logger.error(errorMsg, e);
            logInfoService.save(errorMsg, e.toString(), StaticKeys.LOG_XTCZ);
        }
        return "ospfInfo/add";
    }
    @RequestMapping(value = "del")
    public String delete(Model model, HttpServletRequest request, RedirectAttributes redirectAttributes) {
        String errorMsg = "删除ospf设备监测错误";
        OspfInfo ospfInfo = new OspfInfo();
        try {
            if (!StringUtils.isEmpty(request.getParameter("id"))) {
                String[] ids = request.getParameter("id").split(",");
                for (String id : ids) {
                    ospfInfo = OspfInfoService.selectById(id);
                }
                OspfInfoService.deleteById(ids);
            }
        } catch (Exception e) {
            logger.error(errorMsg, e);
            logInfoService.save(errorMsg, e.toString(), StaticKeys.LOG_XTCZ);
        }
        return "redirect:/ospfInfo/list";
    }
}
src/main/java/com/wgcloud/controller/TuopuController.java
@@ -80,13 +80,15 @@
            HostUtil.addAccountquery(request, params);
            List<SystemInfo> pageInfo = systemInfoService.selectAllByParams(params);
            for (SystemInfo systemInfo : pageInfo) {
                TuopuNodeDto dto = new TuopuNodeDto();
                systemInfoMap.put(systemInfo.getHostname(), systemInfo.getHostname());
                dto.setHostname(systemInfo.getHostname() + HostUtil.addRemark(systemInfo.getHostname()));
                dto.setState(systemInfo.getState());
                dto.setType("1");
                nodeList.add(dto);
            if(pageInfo!=null &&pageInfo.size()>0){
                for (SystemInfo systemInfo : pageInfo) {
                    TuopuNodeDto dto = new TuopuNodeDto();
                    systemInfoMap.put(systemInfo.getHostname(), systemInfo.getHostname());
                    dto.setHostname(systemInfo.getHostname() + HostUtil.addRemark(systemInfo.getHostname()));
                    dto.setState(systemInfo.getState());
                    dto.setType("1");
                    nodeList.add(dto);
                }
            }
            //组装主机 ends
@@ -120,20 +122,22 @@
            HostUtil.addAccountquery(request, params);
            List<DceInfo> pageInfoDce = dceInfoService.selectAllByParams(params);
            for (DceInfo dceInfo : pageInfoDce) {
                TuopuNodeDto dto = new TuopuNodeDto();
                if (!StringUtils.isEmpty(dceInfo.getRemark())) {
                    dto.setHostname(dceInfo.getHostname() + "(" + dceInfo.getRemark() + ")");
                } else {
                    dto.setHostname(dceInfo.getHostname());
            if(pageInfoDce!=null &&pageInfoDce.size()>0){
                for (DceInfo dceInfo : pageInfoDce) {
                    TuopuNodeDto dto = new TuopuNodeDto();
                    if (!StringUtils.isEmpty(dceInfo.getRemark())) {
                        dto.setHostname(dceInfo.getHostname() + "(" + dceInfo.getRemark() + ")");
                    } else {
                        dto.setHostname(dceInfo.getHostname());
                    }
                    if (dceInfo.getResTimes() < 0) {
                        dto.setState(StaticKeys.DOWN_STATE);
                    } else {
                        dto.setState(StaticKeys.ON_STATE);
                    }
                    dto.setType("2");
                    nodeList.add(dto);
                }
                if (dceInfo.getResTimes() < 0) {
                    dto.setState(StaticKeys.DOWN_STATE);
                } else {
                    dto.setState(StaticKeys.ON_STATE);
                }
                dto.setType("2");
                nodeList.add(dto);
            }
            //组装数通PING设备 end
@@ -146,22 +150,25 @@
            HostUtil.addAccountquery(request, params);
            List<SnmpInfo> pageInfoSnmp = snmpInfoService.selectAllByParams(params);
            for (SnmpInfo snmpInfo : pageInfoSnmp) {
                for (SnmpInfo snmpInfoAdded : snmpAddedList) {
                    if (snmpInfo.getHostname().equals(snmpInfoAdded.getHostname())) {
                        continue;
            if(pageInfoSnmp!=null &&pageInfoSnmp.size()>0){
                for (SnmpInfo snmpInfo : pageInfoSnmp) {
                    for (SnmpInfo snmpInfoAdded : snmpAddedList) {
                        if (snmpInfo.getHostname().equals(snmpInfoAdded.getHostname())) {
                            continue;
                        }
                    }
                    TuopuNodeDto dto = new TuopuNodeDto();
                    if (!StringUtils.isEmpty(snmpInfo.getRemark())) {
                        dto.setHostname(snmpInfo.getHostname() + "(" + snmpInfo.getRemark() + ")");
                    } else {
                        dto.setHostname(snmpInfo.getHostname());
                    }
                    dto.setState(snmpInfo.getState());
                    dto.setType("2");
                    nodeList.add(dto);
                }
                TuopuNodeDto dto = new TuopuNodeDto();
                if (!StringUtils.isEmpty(snmpInfo.getRemark())) {
                    dto.setHostname(snmpInfo.getHostname() + "(" + snmpInfo.getRemark() + ")");
                } else {
                    dto.setHostname(snmpInfo.getHostname());
                }
                dto.setState(snmpInfo.getState());
                dto.setType("2");
                nodeList.add(dto);
            }
            //组装数通SNMP设备 end
            //设置节点坐标
src/main/java/com/wgcloud/entity/OspfInfo.java
New file
@@ -0,0 +1,96 @@
package com.wgcloud.entity;
import java.util.Date;
/**
 * @version v3.3
 * @ClassName:ospf.java
 * @author: http://www.wgstart.com
 * @date: 2021年1月16日
 * @Description: 系统日志信息
 * @Copyright: 2019-2021 wgcloud. All rights reserved.
 */
public class OspfInfo extends BaseEntity {
    /**
     *
     */
    private static final long serialVersionUID = 1L;
    /**
     * 标题
     */
    private String hostname;
    /**
     * 描述
     */
    private String infoContent;
    /**
     * 1业务告警,2系统操作
     */
    private String state;
    /**
     * 区域号
     */
    private String areaNum;
    /**
     * 创建时间
     */
    private Date createTime;
    public String getHostname() {
        return hostname;
    }
    public void setHostname(String hostname) {
        this.hostname = hostname;
    }
    public String getInfoContent() {
        return infoContent;
    }
    public void setInfoContent(String infoContent) {
        this.infoContent = infoContent;
    }
    public String getAreaNum() {
        return areaNum;
    }
    public void setAreaNum(String areaNum) {
        this.areaNum = areaNum;
    }
    public String getState() {
        return state;
    }
    public void setState(String state) {
        this.state = state;
    }
    public Date getCreateTime() {
        return createTime;
    }
    public void setCreateTime(Date createTime) {
        this.createTime = createTime;
    }
}
src/main/java/com/wgcloud/entity/vo/OspfInterface.java
New file
@@ -0,0 +1,16 @@
package com.wgcloud.entity.vo;
import lombok.AllArgsConstructor;
import lombok.Data;
@Data
@AllArgsConstructor
public class OspfInterface {
    private String ipAddress;
    private String  type;
    private String state;
    private int cost;
    private int pri;
    private String dr;
    private String bdr;
}
src/main/java/com/wgcloud/entity/vo/OspfNeighbor.java
New file
@@ -0,0 +1,15 @@
package com.wgcloud.entity.vo;
import lombok.AllArgsConstructor;
import lombok.Data;
@Data
@AllArgsConstructor
public class OspfNeighbor {
    private String routerId;
    private String address;
    private int pri;
    private int deadTime;
    private String state;
    private String interfaceName;
}
src/main/java/com/wgcloud/filter/AuthRestFilter.java
@@ -197,6 +197,10 @@
            session.setAttribute("menuActive", "62");
            return;
        }
        if (uri.indexOf("/ospfInfo") > -1) {
            session.setAttribute("menuActive", "63");
            return;
        }
        if (uri.indexOf("/tuopu/tuopuListHost") > -1) {
            session.setAttribute("menuActive", "71");
            return;
src/main/java/com/wgcloud/mapper/OspfInfoMapper.java
New file
@@ -0,0 +1,39 @@
package com.wgcloud.mapper;
import com.wgcloud.entity.LogInfo;
import com.wgcloud.entity.OspfInfo;
import org.springframework.stereotype.Repository;
import java.util.List;
import java.util.Map;
/**
 * @version v3.3
 * @ClassName:LogInfoDao.java
 * @author: http://www.wgstart.com
 * @date: 2021年1月16日
 * @Description: 查看日志信息
 * @Copyright: 2019-2021 wgcloud. All rights reserved.
 */
@Repository
public interface OspfInfoMapper {
    public List<OspfInfo> selectAllByParams(Map<String, Object> map);
    public int countByParams(Map<String, Object> params) throws Exception;
    public List<OspfInfo> selectByParams(Map<String, Object> params) throws Exception;
    public OspfInfo selectById(String id) throws Exception;
    public void save(OspfInfo LogInfo) throws Exception;
    public int deleteById(String[] id) throws Exception;
    public void insertList(List<OspfInfo> recordList) throws Exception;
    public int deleteByDate(Map<String, Object> map) throws Exception;
    public void updateById(OspfInfo ospfInfo);
}
src/main/java/com/wgcloud/service/OspfInfoService.java
New file
@@ -0,0 +1,137 @@
package com.wgcloud.service;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.wgcloud.entity.OspfInfo;
import com.wgcloud.entity.SnmpInfo;
import com.wgcloud.mapper.OspfInfoMapper;
import com.wgcloud.util.DateUtil;
import com.wgcloud.util.UUIDUtil;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
 * @version v3.3
 * @ClassName:OspfInfoService.java
 * @author: http://www.wgstart.com
 * @date: 2021年1月16日
 * @Description: OspfInfoService.java
 * @Copyright: 2019-2021 wgcloud. All rights reserved.
 */
@Service
public class OspfInfoService {
    @Autowired
    private RouterConnectionService routerConnectionService;
    private static final Logger logger = LoggerFactory.getLogger(OspfInfoService.class);
    public PageInfo selectByParams(Map<String, Object> params, int currPage, int pageSize) throws Exception {
        PageHelper.startPage(currPage, pageSize);
        List<OspfInfo> list = OspfInfoMapper.selectByParams(params);
        PageInfo<OspfInfo> pageInfo = new PageInfo<OspfInfo>(list);
        return pageInfo;
    }
    public void saveRecord(List<OspfInfo> recordList) throws Exception {
        if (recordList.size() < 1) {
            return;
        }
        Map<String, Object> map = new HashMap<String, Object>();
        for (OspfInfo as : recordList) {
            as.setId(UUIDUtil.getUUID());
            as.setCreateTime(DateUtil.getNowTime());
        }
        OspfInfoMapper.insertList(recordList);
    }
    public void save(OspfInfo ospfInfo) {
        ospfInfo.setId(UUIDUtil.getUUID());
        ospfInfo.setCreateTime(DateUtil.getNowTime());
        try {
            OspfInfoMapper.save(ospfInfo);
        } catch (Exception e) {
            logger.error("保存日志信息异常:", e);
        }
    }
    public void updateById(OspfInfo ospfInfo)
            throws Exception {
        if (StringUtils.isEmpty(ospfInfo.getHostname())) {
            ospfInfo.setHostname(ospfInfo.getHostname().trim());
        }
        OspfInfoMapper.updateById(ospfInfo);
    }
    public boolean checkOspfStatus() {
        String command = "display ospf brief";
        String output = routerConnectionService.executeCommand(command);
        if (output == null) {
            return false;
        }
        // 检查输出中是否包含OSPF相关信息
        boolean containsRouterId = StringUtils.containsIgnoreCase(output, "Router ID");
        boolean containsArea = StringUtils.containsIgnoreCase(output, "Area");
        boolean containsProcessId = StringUtils.containsIgnoreCase(output, "Process ID");
        // 检查是否有错误信息
        boolean containsError = StringUtils.containsIgnoreCase(output, "Error") ||
                StringUtils.containsIgnoreCase(output, "Fail") ||
                StringUtils.containsIgnoreCase(output, "Invalid");
        return (containsRouterId && containsArea && containsProcessId) && !containsError;
    }
    /**
     * 获取详细的OSPF邻居信息
     */
    public String getDetailedOspfNeighborInfo() {
        String command = "display ospf peer";
        return routerConnectionService.executeCommand(command);
    }
    /**
     * 获取OSPF接口状态
     */
    public String getOspfInterfaceStatus() {
        String command = "display ospf interface";
        return routerConnectionService.executeCommand(command);
    }
    public int countByParams(Map<String, Object> params) throws Exception {
        return OspfInfoMapper.countByParams(params);
    }
    public int deleteById(String[] id) throws Exception {
        return OspfInfoMapper.deleteById(id);
    }
    public OspfInfo selectById(String id) throws Exception {
        return OspfInfoMapper.selectById(id);
    }
    public List<OspfInfo> selectAllByParams(Map<String, Object> params) throws Exception {
        return OspfInfoMapper.selectAllByParams(params);
    }
    public int deleteByDate(Map<String, Object> map) throws Exception{
        return OspfInfoMapper.deleteByDate(map);
    }
    @Autowired
    private OspfInfoMapper OspfInfoMapper;
}
src/main/java/com/wgcloud/service/RouterConnectionService.java
New file
@@ -0,0 +1,98 @@
package com.wgcloud.service;
import com.jcraft.jsch.ChannelExec;
import com.jcraft.jsch.JSch;
import com.jcraft.jsch.JSchException;
import com.jcraft.jsch.Session;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.util.Properties;
@Service
public class RouterConnectionService {
    @Value("${router.host}")
    private String routerHost;
    @Value("${router.username}")
    private String routerUsername;
    @Value("${router.password}")
    private String routerPassword;
    private Session session;
    /**
     * 连接到路由器
     */
    public boolean connect() {
        try {
            JSch jsch = new JSch();
            session = jsch.getSession(routerUsername, routerHost, 22);
            session.setPassword(routerPassword);
            // 设置不进行主机密钥检查
            Properties config = new Properties();
            config.put("StrictHostKeyChecking", "no");
            session.setConfig(config);
            session.connect(5000); // 5秒超时
            return true;
        } catch (JSchException e) {
            System.err.println("连接路由器失败: " + e.getMessage());
            return false;
        }
    }
    /**
     * 断开连接
     */
    public void disconnect() {
        if (session != null && session.isConnected()) {
            session.disconnect();
        }
    }
    /**
     * 执行路由器命令
     */
    public String executeCommand(String command) {
        if (!isConnected()) {
            if (!connect()) {
                return null;
            }
        }
        try {
            ChannelExec channel = (ChannelExec) session.openChannel("exec");
            channel.setCommand(command);
            channel.connect();
            BufferedReader reader = new BufferedReader(new InputStreamReader(channel.getInputStream()));
            StringBuilder output = new StringBuilder();
            String line;
            while ((line = reader.readLine()) != null) {
                output.append(line).append("\n");
            }
            reader.close();
            channel.disconnect();
            return output.toString();
        } catch (Exception e) {
            System.err.println("执行命令失败: " + e.getMessage());
            disconnect(); // 执行失败时断开连接,下次重连
            return null;
        }
    }
    /**
     * 检查连接状态
     */
    public boolean isConnected() {
        return session != null && session.isConnected();
    }
}
src/main/java/com/wgcloud/util/OspfInterfaceUtil.java
New file
@@ -0,0 +1,67 @@
package com.wgcloud.util;
import com.wgcloud.entity.vo.OspfInterface;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Component;
import java.util.ArrayList;
import java.util.List;
/**
 * 解析ospf接口信息工具类
 */
@Component
public class OspfInterfaceUtil {
    public List<OspfInterface> analysisStr(String str){
        List<OspfInterface> ospfInterfaceList = new ArrayList<>();
        String s1 = parseOspfInterface(str);
        String[] lines = s1.split("\n");
        for (String line : lines) {
            if(StringUtils.isNotBlank(line.trim())){
                String[] parts = line.trim().split("\\s+");
                if (parts.length >= 6) {
                    OspfInterface entity = new OspfInterface(
                            parts[0],
                            parts[1],
                            parts[2],
                            Integer.parseInt(parts[3]),
                            Integer.parseInt(parts[4]),
                            parts[5],
                            parts[6]
                    );
                    ospfInterfaceList.add(entity);
                } else {
                    System.out.println("搜索结果不符合要求,无法解析");
                }
            }
        }
        System.out.println(ospfInterfaceList);
        return ospfInterfaceList;
    }
    private  String parseOspfInterface(String s) {
        // 找到 "Router ID" 所在行的位置
        int routerIdLineStart = s.indexOf("Cost  Pri");
        if (routerIdLineStart == -1) {
            System.out.println("未找到包含\"Cost  Pri\"的行");
            return "";
        }
        // 找到 "Router ID" 所在行的下一行的起始位置
        int nextLineStart = s.indexOf("\n", routerIdLineStart) + 1;
        // 找到最后的 "<H3C>" 所在行的位置
        int h3cLineStart = s.lastIndexOf("<H3C>");
        if (h3cLineStart == -1) {
            System.out.println("未找到最后的\"<H3C>\"");
            return "";
        }
        // 找到最后的 "<H3C>" 所在行的上一行的结束位置
        int prevLineEnd = s.lastIndexOf("\n", h3cLineStart - 1) + 1;
        // 截取从 Router ID 的下一行到最后的 <H3C> 上一行的内容
        String result = s.substring(nextLineStart, prevLineEnd);
        System.out.println(result);
        return result;
    }
}
src/main/java/com/wgcloud/util/OspfNeighborUtil.java
New file
@@ -0,0 +1,66 @@
package com.wgcloud.util;
import com.wgcloud.entity.vo.OspfNeighbor;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Component;
import java.util.ArrayList;
import java.util.List;
/**
 * 解析ospf邻居信息实体类
 */
@Component
public class OspfNeighborUtil {
    public List<OspfNeighbor> analysisStr(String str){
        List<OspfNeighbor> ospfNeighborList = new ArrayList<>();
        String s1 = parseOspfNeighbor(str);
        String[] lines = s1.split("\n");
        for (String line : lines) {
            if(StringUtils.isNotBlank(line.trim())){
                String[] parts = line.trim().split("\\s+");
                if (parts.length >= 6) {
                    OspfNeighbor entity = new OspfNeighbor(
                            parts[0],
                            parts[1],
                            Integer.parseInt(parts[2]),
                            Integer.parseInt(parts[3]),
                            parts[4],
                            parts[5]
                    );
                    ospfNeighborList.add(entity);
                } else {
                    System.out.println("搜索结果不符合要求,无法解析");
                }
            }
        }
        System.out.println(ospfNeighborList);
        return ospfNeighborList;
    }
    private  String parseOspfNeighbor(String s) {
        // 找到 "Router ID" 所在行的位置
        int routerIdLineStart = s.indexOf("Pri Dead-Time");
        if (routerIdLineStart == -1) {
            System.out.println("未找到包含\"Pri Dead-Time\"的行");
            return "";
        }
        // 找到 "Router ID" 所在行的下一行的起始位置
        int nextLineStart = s.indexOf("\n", routerIdLineStart) + 1;
        // 找到最后的 "<H3C>" 所在行的位置
        int h3cLineStart = s.lastIndexOf("<H3C>");
        if (h3cLineStart == -1) {
            System.out.println("未找到最后的\"<H3C>\"");
            return "";
        }
        // 找到最后的 "<H3C>" 所在行的上一行的结束位置
        int prevLineEnd = s.lastIndexOf("\n", h3cLineStart - 1) + 1;
        // 截取从 Router ID 的下一行到最后的 <H3C> 上一行的内容
        String result = s.substring(nextLineStart, prevLineEnd);
        System.out.println(result);
        return result;
    }
}
src/main/resources/application.yml
@@ -54,7 +54,7 @@
  #只读账号的密码
  guestAccountPwd: 111111
  #通信token,agent端和此保持一致
  wgToken: wgcloud
  wgToken: tssw
  #每页显示多少条数据,建议不小于10
  pageSize: 20
  #是否开启web ssh客户端,yes开启,no关闭
@@ -207,4 +207,9 @@
  varDatas: /collect/api/realData/varDatas
  alarm: /collect/api/alarm/findByPage
router:
  routerHost: 192.168.1.1
  routerUsername: xxxxx
  routerPassword: xxxxx
src/main/resources/mybatis/mapper/OspfInfoMapper.xml
New file
@@ -0,0 +1,186 @@
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd" >
<mapper namespace="com.wgcloud.mapper.OspfInfoMapper">
    <resultMap id="resultMap" type="com.wgcloud.entity.OspfInfo">
        <id column="ID" property="id" jdbcType="CHAR" />
        <result column="HOST_NAME" property="hostname" jdbcType="CHAR" />
        <result column="INFO_CONTENT" property="infoContent" jdbcType="CHAR" />
        <result column="AREA_NUM" property="areaNum" jdbcType="CHAR" />
        <result column="STATE" property="state" jdbcType="CHAR" />
        <result column="CREATE_TIME" property="createTime" jdbcType="TIMESTAMP" />
    </resultMap>
    <sql id="tableColumnList">
        ID,HOST_NAME, INFO_CONTENT, STATE,AREA_NUM,CREATE_TIME
    </sql>
    <sql id="queryByParams">
        <if test="hostname != null">
            <choose>
                <when test="_databaseId == 'oracle'">
                    <![CDATA[ AND HOST_NAME LIKE  CONCAT(CONCAT('%',#{hostname}),'%') ]]>
                </when>
                <otherwise>
                    <![CDATA[ AND HOST_NAME LIKE  CONCAT('%',#{hostname},'%') ]]>
                </otherwise>
            </choose>
        </if>
        <if test="hostnameNe != null">
            <choose>
                <when test="_databaseId == 'oracle'">
                    <![CDATA[ AND HOST_NAME NOT LIKE  CONCAT(CONCAT('%',#{hostnameNe}),'%') ]]>
                </when>
                <otherwise>
                    <![CDATA[ AND HOST_NAME NOT LIKE  CONCAT('%',#{hostnameNe},'%') ]]>
                </otherwise>
            </choose>
        </if>
        <if test="startTime != null and endTime !=null and startTime !='' and endTime != '' ">
            <if test="_databaseId == 'mysql'">
                <![CDATA[ AND CREATE_TIME >= #{startTime} and CREATE_TIME <=#{endTime}]]>
            </if>
            <if test="_databaseId == 'postgresql'">
                <![CDATA[ AND CREATE_TIME >= cast(#{startTime} as timestamp) and CREATE_TIME <= cast(#{endTime} as timestamp)]]>
            </if>
            <if test="_databaseId == 'oracle'">
                <![CDATA[ AND CREATE_TIME >= to_date(#{startTime},'yyyy-MM-dd hh24:mi:ss') and CREATE_TIME <= to_date(#{endTime},'yyyy-MM-dd hh24:mi:ss')]]>
            </if>
        </if>
        <if test="state != null">
            <![CDATA[ AND STATE = #{state} ]]>
        </if>
        <if test="areaNum != null">
            <![CDATA[ AND AREA_NUM = #{areaNum} ]]>
        </if>
    </sql>
    <select id="selectById" resultMap="resultMap" parameterType="java.lang.String">
        SELECT
        <include refid="tableColumnList" />
        FROM OSPF_INFO WHERE ID=#{id}
    </select>
    <delete id="deleteByPrimaryKey" parameterType="java.lang.String">
        DELETE FROM OSPF_INFO WHERE ID = #{id}
    </delete>
    <delete id="deleteByDate"  parameterType="map">
        DELETE FROM OSPF_INFO WHERE
        <if test="_databaseId == 'mysql'">
            <![CDATA[  CREATE_TIME <=#{endTime}]]>
        </if>
        <if test="_databaseId == 'postgresql'">
            <![CDATA[  CREATE_TIME <= cast(#{endTime} as timestamp)]]>
        </if>
        <if test="_databaseId == 'oracle'">
            <![CDATA[  CREATE_TIME <=  to_date(#{endTime},'yyyy-MM-dd hh24:mi:ss')]]>
        </if>
    </delete>
    <delete id="deleteByAccHname"  parameterType="map">
        DELETE FROM OSPF_INFO WHERE ACCOUNT = #{account} AND HOST_NAME = #{hostname}
    </delete>
    <delete id="deleteById" parameterType="java.lang.String">
        DELETE FROM OSPF_INFO WHERE ID IN
        <foreach item="item" index="index" collection="array" open="(" separator="," close=")">
            #{item}
        </foreach>
    </delete>
    <insert id="insertList" parameterType="java.util.List" >
        <choose>
            <when test="_databaseId == 'oracle'">
                begin
                <foreach collection="list" item="item" index="index">
                    INSERT INTO OSPF_INFO (ID,HOST_NAME,INFO_CONTENT,STATE,AREA_NUM,CREATE_TIME)  VALUES
                    (#{item.id},#{item.hostname},#{item.infoContent},#{item.state},#{item.areaNum},#{item.createTime});
                </foreach>
                end;
            </when>
            <otherwise>
                INSERT INTO OSPF_INFO (ID,HOST_NAME,INFO_CONTENT,STATE,AREA_NUM,CREATE_TIME)  VALUES
                <foreach collection="list" item="item" index="index" separator="," >
                    (#{item.id},#{item.hostname},#{item.infoContent},#{item.state},#{item.areaNum},#{item.createTime})
                </foreach>
            </otherwise>
        </choose>
    </insert>
    <insert id="save" parameterType="com.wgcloud.entity.OspfInfo">
        INSERT INTO OSPF_INFO
        <trim prefix="(" suffix=")" suffixOverrides="," >
              <if test="id != null" >ID,</if>
              <if test="hostname != null" > HOST_NAME,</if>
              <if test="infoContent != null">INFO_CONTENT,</if>
              <if test="state != null" >STATE,</if>
              <if test="areaNum != null" >AREA_NUM,</if>
              <if test="createTime != null" >CREATE_TIME</if>
        </trim>
        <trim prefix="values (" suffix=")" suffixOverrides="," >
              <if test="id != null" >#{id},</if>
              <if test="hostname != null" >#{hostname},</if>
              <if test="infoContent != null" >#{infoContent},</if>
              <if test="state != null" >#{state},</if>
            <if test="areaNum != null" >#{areaNum},</if>
              <if test="createTime != null" >#{createTime}</if>
        </trim>
    </insert>
    <select id="countByParams" parameterType="map" resultType="java.lang.Integer">
        SELECT count(*)  FROM OSPF_INFO t
        <where>
            <include refid="queryByParams" />
        </where>
    </select>
      <select id="selectAllByParams" parameterType="map" resultMap="resultMap">
        SELECT
        <include refid="tableColumnList" />
        FROM OSPF_INFO t
        <where>
            <include refid="queryByParams" />
        </where>
         ORDER BY CREATE_TIME DESC
    </select>
    <select id="selectByParams" parameterType="map" resultMap="resultMap">
        SELECT
        <include refid="tableColumnList" />
        FROM OSPF_INFO
        <where>
            <include refid="queryByParams" />
        </where>
         ORDER BY CREATE_TIME DESC
    </select>
    <update id="updateById" parameterType="com.wgcloud.entity.OspfInfo">
        UPDATE OSPF_INFO
        <set>
            <if test="hostname != null">
                HOST_NAME = #{hostname},
            </if>
            <if test="infoContent != null">
                INFO_CONTENT = #{infoContent},
            </if>
            <if test="areaNum != null">
                AREA_NUM = #{areaNum},
            </if>
            <if test="state != null">
                STATE = #{state},
            </if>
            <if test="createTime != null">
                CREATE_TIME = #{createTime},
            </if>
        </set>
        WHERE ID = #{id}
    </update>
</mapper>
src/main/resources/static/js/ospfInfo.js
New file
@@ -0,0 +1,22 @@
function view(id) {
    window.location.href = "/tssw/ospfInfo/edit?id="+id;
}
function searchByAccount() {
    window.location.href = "/tssw/ospfInfo/list?account="+$("#account").val();
}
function add() {
    window.location.href = "/tssw/ospfInfo/edit";
}
function del(id) {
    if(confirm('你确定要删除吗?同时也将删除对应的ospf数据')) {
        window.location.href = "/tssw/ospfInfo/del?id=" + id;
    }
}
function cancel(){
    history.back();
}
src/main/resources/templates/common/aside.html
@@ -272,6 +272,17 @@
                        <p>SNMP监测</p>
                        </a>
                    </li>
                    <li class="nav-item">
                        <th:block th:if="${session.menuActive eq '63'}">
                            <a th:href="@{'/ospfInfo/list'}" class="nav-link active">
                        </th:block>
                        <th:block th:unless="${session.menuActive eq '63'}">
                            <a th:href="@{'/ospfInfo/list'}" class="nav-link">
                        </th:block>
                        <i class="far fa-circle nav-icon"></i>
                        <p>OSPF监测</p>
                        </a>
                    </li>
                </ul>
                </li>
src/main/resources/templates/ospfInfo/add.html
New file
@@ -0,0 +1,103 @@
<!DOCTYPE html>
<html>
<head>
  <div  th:replace="common/header.html"></div>
</head>
<body th:class="${application.sidebarCollapse}">
<div th:replace="common/chart.html"></div>
<div class="wrapper">
  <div th:replace="common/navbar.html"></div>
  <div th:replace="common/aside.html"></div>
  <!-- Content Wrapper. Contains page content -->
  <div class="content-wrapper"  style="font-size:0.90rem">
    <!-- Content Header (Page header) -->
    <section class="content-header">
      <div class="container-fluid">
        <div class="row mb-2">
          <div class="col-sm-6">
            <h1></h1>
          </div>
            <div class="col-sm-6">
                <ol class="breadcrumb float-sm-right">
                    <li class="breadcrumb-item active"></li>
                </ol>
            </div>
        </div>
      </div><!-- /.container-fluid -->
    </section>
    <!-- Main content -->
    <section class="content">
      <div class="container-fluid">
        <div class="row">
  <div class="col-md-10">
    <div class="card card-primary">
      <div class="card-header">
        <h3 class="card-title">添加OSPF区域信息</h3>
          <div class=" float-sm-right">
              <a href="javascript:history.back()">返回</a>
          </div>
      </div>
      <!-- /.card-header -->
      <!-- form start -->
        <form role="form" id="form1" th:action="@{'/ospfInfo/save'}">
            <input type="hidden" name="id" th:value="${ospfInfo.id}"/>
            <div class="card-body">
                <div class="form-group">
                    <label><font color="red">*</font>设备IP</label>
                    <input type="text" autocomplete="off"  th:value="${ospfInfo.hostname}" class="validate[required,maxSize[50]] form-control" name="hostname" id="hostname" placeholder="输入IP">
                </div>
                <div class="form-group">
                    <label><font color="red">*</font>OSPF区域号</label>
                    <input type="text" autocomplete="off"  th:value="${ospfInfo.areaNum}" class="validate[required,maxSize[50]] form-control" name="areaNum" id="areaNum" placeholder="如0">
                </div>
                <div class="form-group">
                    <label>描述</label>
                    <input type="text" autocomplete="off"  th:value="${ospfInfo.infoContent}" class="validate[maxSize[50]] form-control" name="infoContent" id="infoContent" placeholder="如交换机01">
                </div>
            </div>
            <!-- /.card-body -->
            <div class="card-footer">
                <button type="submit" class="btn btn-primary btn-sm" style="margin-right:10px;">保 存</button>
                <button type="button"  th:onclick="goback()"  class="btn bg-gradient-danger btn-sm">返 回</button>
            </div>
        </form>
      <!-- /.card-body -->
    </div>
    <!-- /.card -->
  </div>
        </div>
      </div>
    </section>
  </div>
  <div th:replace="common/footer.html"></div>
</div>
<!-- ./wrapper -->
<link rel="stylesheet" th:href="@{'/static/js/jQuery/validationEngine.jquery.css'}" type="text/css"/>
<script th:src="@{'/static/js/jQuery/jquery.validationEngine-zh_CN.js'}" type="text/javascript" charset="utf-8"></script>
<script th:src="@{'/static/js/jQuery/jquery.validationEngine.js'}" type="text/javascript" charset="utf-8"></script>
<script th:inline="javascript">
    $(document).ready(function(){
        $("#form1").validationEngine();
    });
    function goback() {
        history.back();
    }
</script>
</body>
</html>
src/main/resources/templates/ospfInfo/list.html
New file
@@ -0,0 +1,120 @@
<!DOCTYPE html>
<html>
<head>
  <div  th:replace="common/header.html"></div>
</head>
<body th:class="${application.sidebarCollapse}">
<div th:replace="common/chart.html"></div>
<div class="wrapper">
  <div th:replace="common/navbar.html"></div>
  <div th:replace="common/aside.html"></div>
  <!-- Content Wrapper. Contains page content -->
  <div class="content-wrapper"  style="font-size:0.90rem">
    <!-- Content Header (Page header) -->
    <section class="content-header" style="height:38px">
      <div class="container-fluid">
        <div class="row mb-2" style="margin-top: -7px;">
          <div class="col-sm-6"></div>
          <div class="col-sm-6">
            <ol class="breadcrumb float-sm-right">
              <li class="breadcrumb-item"><a href="javascript:history.back()">返回上级</a></li>
            </ol>
          </div>
        </div>
      </div><!-- /.container-fluid -->
    </section>
    <!-- Main content -->
    <section class="content">
      <div class="container-fluid">
        <div class="row">
  <div class="col-md-12">
    <div class="card">
      <div class="card-header">
        <h3 class="card-title"><i class="nav-icon fa fa-cloud"></i>&nbsp;OSPF设备监测列表</h3>
        <div class=" float-sm-right">
          <!-- SEARCH FORM -->
          <form class="form-inline ml-3" th:action="@{'/ospfInfo/list'}">
            <th:block th:if="${session.LOGIN_KEY.role != 'guest'}">
              <button type="button" onclick="add()" class="btn btn-primary btn-sm" style="margin-right:5px;">添加</button>
            </th:block>
            <div class="input-group input-group-sm">
              <input class="form-control"  id="hostname" name="hostname" autocomplete="off" th:value="${ospfInfo.hostname}" type="text" placeholder="输入设备IP">
              <div class="input-group-append">
                <button class="btn btn-primary" type="submit">
                  <i class="fas fa-search"></i>
                </button>
              </div>
            </div>
          </form>
        </div>
      </div>
      <!-- /.card-header -->
      <div class="card-body">
        <table class="table table-bordered table-hover">
          <thead>
          <tr>
            <th style="width: 20px"> <input type="checkbox" value="" name="checkall" id="checkall"></th>
            <th style="width: 60px">序号</th>
            <th title="描述">描述</th>
            <th title="设备IP">设备IP</th>
            <th title="区域号">区域号</th>
            </tr>
          </th:block>
          </thead>
          <tbody>
          <th:block th:each="item,iterStat : ${page.list}">
            <tr>
              <td><input type="checkbox" th:value="${item.id}" name="todo2" th:id="${item.id}+'_check'"/></td>
              <td th:text="${iterStat.index+1}">1</td>
              <td th:text="${item.infoContent}"><span   th:text="${#strings.abbreviate(item.infoContent,20)}"></span></td>
              <td th:text="${item.hostname}"></td>
              <td th:text="${item.areaNum}"></td>
              <td>
                <th:block th:if="${session.LOGIN_KEY.role != 'guest'}">
                    <button type="button"  th:onclick="del([[${item.id}]])"  class="btn bg-gradient-danger btn-sm">删除</button>
                    <button type="button"  th:onclick="edit([[${item.id}]])"  class="btn bg-gradient-primary btn-sm">编辑</button>
                </th:block>
              </td>
          </th:block>
          </tbody>
        </table>
      </div>
      <!-- /.card-body -->
      <div th:replace="common/page.html"></div>
    </div>
    <!-- /.card -->
  </div>
        </div>
      </div>
    </section>
  </div>
  <div th:replace="common/footer.html"></div>
  <script th:src="@{'/static/js/jQuery/jquery.form.min.js'}" type="text/javascript" charset="utf-8"></script>
</div>
<!-- ./wrapper -->
<script th:src="@{'/static/js/ospfInfo.js?v=3.3.9'}"></script>
<script th:inline="javascript">
  var msg = [[${msg}]];
  if(msg!='' && msg!=null){
    toastr.info(msg);
  }
</script>
</body>
</html>
src/main/resources/templates/ospfInfo/view.html
New file
@@ -0,0 +1,300 @@
<!DOCTYPE html>
<html>
<head>
  <div  th:replace="common/header.html"></div>
</head>
<body th:class="${application.sidebarCollapse}">
<div th:replace="common/chart.html"></div>
<div class="wrapper">
  <div th:replace="common/navbar.html"></div>
  <div th:replace="common/aside.html"></div>
  <!-- Content Wrapper. Contains page content -->
  <div class="content-wrapper"  style="font-size:0.90rem">
    <!-- Content Header (Page header) -->
    <section class="content-header">
      <div class="container-fluid">
        <div class="row mb-2">
          <div class="col-sm-6">
            <h1></h1>
          </div>
          <div class="col-sm-6">
            <ol class="breadcrumb float-sm-right">
              <li class="breadcrumb-item active"></li>
            </ol>
          </div>
        </div>
      </div><!-- /.container-fluid -->
    </section>
    <!-- Main content -->
    <section class="content">
      <div class="container-fluid">
        <div class="row">
  <div class="col-md-12">
    <div class="card card-primary">
      <div class="card-header">
        <h3 class="card-title">OSPF设备监测信息</h3>
        <div class=" float-sm-right">
          <a href="javascript:history.back()">返回</a>
        </div>
      </div>
      <!-- /.card-header -->
      <!-- form start -->
      <form role="form">
        <div class="card-body">
          <div class="form-group">
            <label>设备IP</label>
              <div><span th:text="${snmpInfo.hostname}"></span></div>
          </div>
        </div>
        <!-- /.card-body -->
      </form>
      <!-- /.card-body -->
      <div class="row">
        <div class="col-12 table-responsive">
          <table class="table table-striped"><tbody><tr>
            <th:block th:each="item : ${amList}">
              <th:block th:if="${item.code eq  am}">
                <td width="2%" style="vertical-align:bottom;"> <button type="button" title="当前已显示该时间段图表" class="btn btn-block btn-outline-danger btn-sm disabled" th:text="${item.msg}">Primary</button></td>
              </th:block>
              <th:block th:unless="${item.code eq  am}">
                <td width="2%" style="vertical-align:bottom;"> <button type="button"  th:onclick="viewDate([[${snmpInfo.id}]],[[${item.code}]])" class="btn btn-block btn-outline-primary btn-sm" th:text="${item.msg}">Primary</button></td>
              </th:block>
            </th:block>
            <td width="10%">
              <form class="form-inline ml-3   float-sm-right" action="/tssw/snmpInfo/view">
                <input type="hidden" name="id" th:value="${snmpInfo.id}"/>
                <div class="input-group input-group-sm">
                  <input type="text" autocomplete="off" value="" class="validate[maxSize[50]] form-control"  th:value="${startTime}" name="startTime" id="startTime" placeholder="开始时间" style="margin-right:5px;">
                  <label style="margin-right:5px;">至</label>
                  <input type="text" autocomplete="off" value="" class="validate[maxSize[50]] form-control"  th:value="${endTime}" name="endTime" id="endTime" placeholder="结束时间" style="margin-right:5px;">
                  <button type="submit" class="btn btn-primary btn-sm" style="margin-right:5px;">查询</button>
                  <button type="button" onclick="resetParam()" class="btn bg-danger btn-sm" style="margin-right:5px;">重置</button>
                </div>
              </form>
            </td>
            <td width="2%" style="vertical-align:bottom;text-align: right"><button type="button" th:onclick="excelExport([[${snmpInfo.id}]],[[${am}]])" class="btn btn-primary btn-sm">导出Excel</button></td>
          </tr></tbody></table>
        </div>
        <!-- /.col -->
      </div>
      <label style="margin-left: .9rem">出口/入口流量速率(MB/s)
        <span style="margin-left:20px">出口流量速率最高</span><span class="description-percentage text-danger" style="margin-left:10px;margin-right:10px;"><i class="fas fa-caret-down"></i> <span th:text="${sentSubtitleDto.maxValue}">18</span></span>
        平均<span class="description-percentage text-warning" style="margin-left:5px;margin-right:10px;"><i class="fas fa-caret-left"></i> <span th:text="${sentSubtitleDto.avgValue}">0</span></span>
        最低<span class="description-percentage text-success" style="margin-left:5px;margin-right:30px;"><i class="fas fa-caret-up"></i> <span th:text="${sentSubtitleDto.minValue}">17</span></span>
        <span style="margin-left:20px">入口流量速率最高</span><span class="description-percentage text-danger" style="margin-left:10px;margin-right:10px;"><i class="fas fa-caret-down"></i> <span th:text="${rxbytSubtitleDto.maxValue}">18</span></span>
        平均<span class="description-percentage text-warning" style="margin-left:5px;margin-right:10px;"><i class="fas fa-caret-left"></i> <span th:text="${rxbytSubtitleDto.avgValue}">0</span></span>
        最低<span class="description-percentage text-success" style="margin-left:5px;margin-right:30px;"><i class="fas fa-caret-up"></i> <span th:text="${rxbytSubtitleDto.minValue}">17</span></span></label>
        <div id="snmpStateJson"></div>
      <label style="margin-left: .9rem">cpu使用率%
        <span style="margin-left:20px">最高</span><span class="description-percentage text-danger" style="margin-left:10px;margin-right:10px;"><i class="fas fa-caret-down"></i> <span th:text="${cpuPerSubtitleDto.maxValue}">18</span></span>
        平均<span class="description-percentage text-warning" style="margin-left:5px;margin-right:10px;"><i class="fas fa-caret-left"></i> <span th:text="${cpuPerSubtitleDto.avgValue}">0</span></span>
        最低<span class="description-percentage text-success" style="margin-left:5px;margin-right:30px;"><i class="fas fa-caret-up"></i> <span th:text="${cpuPerSubtitleDto.minValue}">17</span></span></label>
      <div id="cpuStateJson"></div>
      <label style="margin-left: .9rem">内存使用率%
        <span style="margin-left:20px">最高</span><span class="description-percentage text-danger" style="margin-left:10px;margin-right:10px;"><i class="fas fa-caret-down"></i> <span th:text="${memSizeSubtitleDto.maxValue}">18</span></span>
        平均<span class="description-percentage text-warning" style="margin-left:5px;margin-right:10px;"><i class="fas fa-caret-left"></i> <span th:text="${memSizeSubtitleDto.avgValue}">0</span></span>
        最低<span class="description-percentage text-success" style="margin-left:5px;margin-right:30px;"><i class="fas fa-caret-up"></i> <span th:text="${memSizeSubtitleDto.minValue}">17</span></span></label>
      <div id="memStateJson"></div>
    </div>
    <!-- /.card -->
  </div>
        </div>
      </div>
    </section>
  </div>
  <div th:replace="common/footer.html"></div>
</div>
<!-- ./wrapper -->
<script th:src="@{'/static/js/snmp.js?v=3.4.1'}"></script>
<script th:inline="javascript">
  var startTimeResponse =[[${startTime}]];
  var endTimeResponse =[[${endTime}]];
  $(document).ready(function(){
    var startTime = $('#startTime');
    if(startTime!=null && startTime != undefined){
      startTime.daterangepicker({
        singleDatePicker: true,
        timePicker: true,
        timePicker24Hour : true,
        "opens": "center",
        "locale": {
          format: 'YYYY-MM-DD HH:mm',
          applyLabel: "应用",
          cancelLabel: "取消",
          daysOfWeek: ['日', '一', '二', '三', '四', '五', '六'],
          monthNames: ['一月', '二月', '三月', '四月', '五月', '六月', '七月', '八月', '九月', '十月', '十一月', '十二月'],
        }
      });
      if(startTimeResponse=='' || startTimeResponse==null){
        startTime.val("");
      }
    }
    var endTime = $('#endTime');
    if(endTime!=null && endTime != undefined){
      endTime.daterangepicker({
        singleDatePicker: true,
        timePicker: true,
        timePicker24Hour : true,
        "opens": "center",
        "locale": {
          format: 'YYYY-MM-DD HH:mm',
          applyLabel: "应用",
          cancelLabel: "取消",
          daysOfWeek: ['日', '一', '二', '三', '四', '五', '六'],
          monthNames: ['一月', '二月', '三月', '四月', '五月', '六月', '七月', '八月', '九月', '十月', '十一月', '十二月'],
        }
      });
      if(endTimeResponse=='' || endTimeResponse==null){
        endTime.val("");
      }
    }
  });
  function resetParam(){
    $("#startTime").val("");
    $("#endTime").val("");
  }
    var snmpStateJson =[[${snmpStateList}]];
    $(function() {
      var chart = new G2.Chart({
        container: 'snmpStateJson',
        forceFit: true,
        height: 400,
        padding: [30, 40, 70, 48]
      });
      chart.axis('dateStr', {
        label: {
          textStyle: {
            fill: '#aaaaaa'
          }
        }
      });
      chart.axis('sentAvgDouble', false);
      chart.tooltip({
        crosshairs: false
      });
      chart.legend({
        position: 'top-center'
      });
      chart.source(snmpStateJson, {
        recvAvgDouble: {
          alias: '入口MB/秒',
          min: 0,
          max: [[${snmpAvgMax}]]
        },
        sentAvgDouble: {
          alias: '出口MB/秒',
          min: 0,
          max: [[${snmpAvgMax}]]
        }
      });
      chart.scale('dateStr',{tickCount: 12,alias: '时间'});
      chart.line().position('dateStr*recvAvgDouble').color('#1890ff');
      chart.line().position('dateStr*sentAvgDouble').color('#2fc25b');
      chart.render();
      var chartCpuPer = new G2.Chart({
        container: 'cpuStateJson',
        forceFit: true,
        height: 400,
        padding: [30, 40, 70, 40]
      });
      chartCpuPer.axis('dateStr', {
        label: {
          textStyle: {
            fill: '#aaaaaa'
          }
        }
      });
      chartCpuPer.axis('cpuPerDouble', {
        label: {
          textStyle: {
            fill: '#aaaaaa'
          }
        }
      });
      chartCpuPer.tooltip({
        crosshairs: false
      });
      chartCpuPer.legend({
        position: 'top-center'
      });
      chartCpuPer.source(snmpStateJson, {
        cpuPerDouble: {
          alias: 'cpu使用率%'
        }
      });
      chartCpuPer.scale('dateStr',{tickCount: 12,alias: '时间'});
      chartCpuPer.line().position('dateStr*cpuPerDouble').color('#1890ff');
      chartCpuPer.render();
      var chartMem = new G2.Chart({
        container: 'memStateJson',
        forceFit: true,
        height: 400,
        padding: [30, 40, 70, 40]
      });
      chartMem.axis('dateStr', {
        label: {
          textStyle: {
            fill: '#aaaaaa'
          }
        }
      });
      chartMem.axis('memPerDouble', {
        label: {
          textStyle: {
            fill: '#aaaaaa'
          }
        }
      });
      chartMem.tooltip({
        crosshairs: false
      });
      chartMem.legend({
        position: 'top-center'
      });
      chartMem.source(snmpStateJson, {
        memPerDouble: {
          alias: '使用率%'
        }
      });
      chartMem.scale('dateStr', {tickCount: 12, alias: '时间'});
      chartMem.line().position('dateStr*memPerDouble').color('#8B78F6');
      chartMem.render();
    })
  var msg = [[${msg}]];
  if(msg!='' && msg!=null){
    toastr.info(msg);
  }
</script>
</body>
</html>