Преглед на файлове

系统监控功能修复、路由配置1

qiangxuan преди 9 месеца
родител
ревизия
489d90728a
променени са 26 файла, в които са добавени 1619 реда и са изтрити 16 реда
  1. 172 0
      zgztBus/jeecg-module-lesm/src/main/java/org/jeecg/modules/homePageData/controller/HomePageDataController.java
  2. 77 0
      zgztBus/jeecg-module-lesm/src/main/java/org/jeecg/modules/homePageData/service/IHomePageDataService.java
  3. 237 0
      zgztBus/jeecg-module-lesm/src/main/java/org/jeecg/modules/homePageData/service/impl/HomePageDataServiceImpl.java
  4. 70 0
      zgztBus/jeecg-module-lesm/src/main/java/org/jeecg/modules/systemConfig/peaksAndValleysTimeConfig/entity/PeaksAndValleysTimeConfig.java
  5. 14 0
      zgztBus/jeecg-module-lesm/src/main/java/org/jeecg/modules/systemConfig/peaksAndValleysTimeConfig/mapper/PeaksAndValleysTimeConfigMapper.java
  6. 5 0
      zgztBus/jeecg-module-lesm/src/main/java/org/jeecg/modules/systemConfig/peaksAndValleysTimeConfig/mapper/xml/PeaksAndValleysTimeConfigMapper.xml
  7. 14 0
      zgztBus/jeecg-module-lesm/src/main/java/org/jeecg/modules/systemConfig/peaksAndValleysTimeConfig/service/IPeaksAndValleysTimeConfigService.java
  8. 18 0
      zgztBus/jeecg-module-lesm/src/main/java/org/jeecg/modules/systemConfig/peaksAndValleysTimeConfig/service/impl/PeaksAndValleysTimeConfigServiceImpl.java
  9. 40 0
      zgztBus/jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/monitor/actuator/CustomActuatorConfig.java
  10. 44 0
      zgztBus/jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/monitor/actuator/httptrace/CustomHttpTraceEndpoint.java
  11. 94 0
      zgztBus/jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/monitor/actuator/httptrace/CustomInMemoryHttpTraceRepository.java
  12. 55 0
      zgztBus/jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/monitor/controller/ActuatorMemoryController.java
  13. 14 0
      zgztBus/jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/monitor/controller/ActuatorRedisController.java
  14. 11 4
      zgztBus/jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/monitor/service/RedisService.java
  15. 21 10
      zgztBus/jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/monitor/service/impl/RedisServiceImpl.java
  16. 298 0
      zgztBus/jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/quartz/controller/QuartzJobController.java
  17. 59 0
      zgztBus/jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/quartz/entity/QuartzJob.java
  18. 35 0
      zgztBus/jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/quartz/job/AsyncJob.java
  19. 23 0
      zgztBus/jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/quartz/job/SampleJob.java
  20. 32 0
      zgztBus/jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/quartz/job/SampleParamJob.java
  21. 24 0
      zgztBus/jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/quartz/mapper/QuartzJobMapper.java
  22. 9 0
      zgztBus/jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/quartz/mapper/xml/QuartzJobMapper.xml
  23. 67 0
      zgztBus/jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/quartz/service/IQuartzJobService.java
  24. 183 0
      zgztBus/jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/quartz/service/impl/QuartzJobServiceImpl.java
  25. 1 1
      zgztBus/jeecg-module-system/jeecg-system-start/src/main/resources/application-dev.yml
  26. 2 1
      zgztBus/jeecg-server-cloud/jeecg-cloud-nacos/docs/config/jeecg-gateway-router.json

+ 172 - 0
zgztBus/jeecg-module-lesm/src/main/java/org/jeecg/modules/homePageData/controller/HomePageDataController.java

@@ -0,0 +1,172 @@
+package org.jeecg.modules.homePageData.controller;
+
+
+import io.swagger.annotations.Api;
+import io.swagger.annotations.ApiOperation;
+import lombok.extern.slf4j.Slf4j;
+import org.jeecg.common.api.vo.Result;
+import org.jeecg.common.aspect.annotation.AutoLog;
+import org.jeecg.modules.homePageData.service.IHomePageDataService;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+import java.util.List;
+import java.util.Map;
+
+/**
+ * @Description: 首页数据
+ * @Author: jeecg-boot
+ * @Date:   2024-09-23
+ * @Version: V1.0
+ */
+@Api(tags="首页数据")
+@RestController
+@RequestMapping("/homePageData")
+@Slf4j
+public class HomePageDataController {
+
+    @Autowired
+    private IHomePageDataService homePageDataService;
+
+
+    /**
+     * 各区域峰平谷时间段用电量
+     *
+     * @return
+     */
+    @AutoLog(value = "各区域峰平谷时间段用电量")
+    @ApiOperation(value="各区域峰平谷时间段用电量", notes="各区域峰平谷时间段用电量")
+    @GetMapping(value = "/regionPfvElectricity")
+    public Result<List<Map<String, String>>> regionPfvElectricity() {
+        List<Map<String, String>> list = homePageDataService.regionPfvElectricity();
+        return Result.OK(list);
+    }
+
+
+    /**
+     * 设备在线情况
+     *
+     * @return
+     */
+    @AutoLog(value = "设备在线情况")
+    @ApiOperation(value="设备在线情况", notes="设备在线情况")
+    @GetMapping(value = "/deviceOnline")
+    public Result<Map<String, Object>> deviceOnline() {
+        Map<String, Object> res = homePageDataService.deviceOnline();
+        return Result.OK(res);
+    }
+
+
+    /**
+     * 峰平谷时段划分
+     *
+     * @return
+     */
+    @AutoLog(value = "峰平谷时段划分")
+    @ApiOperation(value="峰平谷时段划分", notes="峰平谷时段划分")
+    @GetMapping(value = "/fpvTime")
+    public Result<Map<String, Long>> fpvTime() {
+        Map<String, Long> res = homePageDataService.fpvTime();
+        return Result.OK(res);
+    }
+
+    /**
+     * 区域用电占比
+     *
+     * @return
+     */
+    @AutoLog(value = "区域用电占比")
+    @ApiOperation(value="区域用电占比", notes="区域用电占比")
+    @GetMapping(value = "/regionElectricityPercentage")
+    public Result<List<Map<String, String>>> regionElectricityPercentage() {
+        List<Map<String, String>> res = homePageDataService.regionElectricityPercentage();
+        return Result.OK(res);
+    }
+
+
+    /**
+     * 峰平谷时间段用电量
+     *
+     * @return
+     */
+    @AutoLog(value = "峰平谷时间段用电量")
+    @ApiOperation(value="峰平谷时间段用电量", notes="峰平谷时间段用电量")
+    @GetMapping(value = "/fpvTimeElectricity")
+    public Result<Map<String, List>> fpvTimeElectricity() {
+        Map<String, List> res = homePageDataService.fpvTimeElectricity();
+        return Result.OK(res);
+    }
+
+
+    /**
+     * 实时报警
+     *
+     * @return
+     */
+    @AutoLog(value = "实时报警")
+    @ApiOperation(value="实时报警", notes="实时报警")
+    @GetMapping(value = "/realAlarm")
+    public Result<List<Map<String, String>>> realAlarm() {
+        List<Map<String, String>> res = homePageDataService.realAlarm();
+        return Result.OK(res);
+    }
+
+
+    /**
+     * 区域用电统计
+     *
+     * @return
+     */
+    @AutoLog(value = "区域用电统计")
+    @ApiOperation(value="区域用电统计", notes="区域用电统计")
+    @GetMapping(value = "/regionElectricityStats")
+    public Result<List<Map<String, String>>> regionElectricityStats() {
+        List<Map<String, String>> res = homePageDataService.regionElectricityStats();
+        return Result.OK(res);
+    }
+
+
+    /**
+     * 峰平谷时段用电总量
+     *
+     * @return
+     */
+    @AutoLog(value = "峰平谷时段用电总量")
+    @ApiOperation(value="峰平谷时段用电总量", notes="峰平谷时段用电总量")
+    @GetMapping(value = "/fpvElectricityStats")
+    public Result<Map<String, String>> fpvElectricityStats() {
+        Map<String, String> res = homePageDataService.fpvElectricityStats();
+        return Result.OK(res);
+    }
+
+
+    /**
+     * 高耗能设备超过阈值情况
+     *
+     * @return
+     */
+    @AutoLog(value = "高耗能设备超过阈值情况")
+    @ApiOperation(value="高耗能设备超过阈值情况", notes="高耗能设备超过阈值情况")
+    @GetMapping(value = "/deviceThresholdStats")
+    public Result<Map<String, Integer>> deviceThresholdStats() {
+        Map<String, Integer> res = homePageDataService.deviceThresholdStats();
+        return Result.OK(res);
+    }
+
+
+    /**
+     * 最新消息
+     *
+     * @return
+     */
+    @AutoLog(value = "最新消息")
+    @ApiOperation(value="最新消息", notes="最新消息")
+    @GetMapping(value = "/lastestMsg")
+    public Result<List<String>> lastestMsg() {
+        List<String> res = homePageDataService.latestMsg();
+        return Result.OK(res);
+    }
+
+}

+ 77 - 0
zgztBus/jeecg-module-lesm/src/main/java/org/jeecg/modules/homePageData/service/IHomePageDataService.java

@@ -0,0 +1,77 @@
+package org.jeecg.modules.homePageData.service;
+
+import java.util.List;
+import java.util.Map;
+
+public interface IHomePageDataService {
+
+    /**
+     * 各区域峰平谷时间段用电量
+     *
+     * @return
+     */
+    List<Map<String, String>> regionPfvElectricity();
+
+    /**
+     * 设备在线情况
+     *
+     * @return
+     */
+    Map<String, Object> deviceOnline();
+
+    /**
+     * 峰平谷时段划分
+     *
+     * @return
+     */
+    Map<String, Long> fpvTime();
+
+    /**
+     * 区域用电占比
+     *
+     * @return
+     */
+    List<Map<String, String>> regionElectricityPercentage();
+
+    /**
+     * 峰平谷时间段用电量
+     *
+     * @return
+     */
+    Map<String, List> fpvTimeElectricity();
+
+    /**
+     * 实时报警
+     *
+     * @return
+     */
+    List<Map<String, String>> realAlarm();
+
+    /**
+     * 区域用电统计
+     *
+     * @return
+     */
+    List<Map<String, String>> regionElectricityStats();
+
+    /**
+     * 峰平谷时段用电总量
+     *
+     * @return
+     */
+    Map<String, String> fpvElectricityStats();
+
+    /**
+     * 高耗能设备超过阈值情况
+     *
+     * @return
+     */
+    Map<String, Integer> deviceThresholdStats();
+
+    /**
+     * 最新消息
+     *
+     * @return
+     */
+    List<String> latestMsg();
+}

+ 237 - 0
zgztBus/jeecg-module-lesm/src/main/java/org/jeecg/modules/homePageData/service/impl/HomePageDataServiceImpl.java

@@ -0,0 +1,237 @@
+package org.jeecg.modules.homePageData.service.impl;
+
+import org.jeecg.common.util.oConvertUtils;
+import org.jeecg.modules.deviceLesm.entity.DeviceInformation;
+import org.jeecg.modules.deviceLesm.entity.DeviceRegion;
+import org.jeecg.modules.deviceLesm.service.IDeviceInformationService;
+import org.jeecg.modules.deviceLesm.service.IDeviceRegionService;
+import org.jeecg.modules.homePageData.service.IHomePageDataService;
+import org.jeecg.modules.systemConfig.peaksAndValleysTimeConfig.entity.PeaksAndValleysTimeConfig;
+import org.jeecg.modules.systemConfig.peaksAndValleysTimeConfig.service.IPeaksAndValleysTimeConfigService;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+import java.text.ParseException;
+import java.text.SimpleDateFormat;
+import java.util.*;
+import java.util.concurrent.atomic.AtomicReference;
+
+
+@Service
+public class HomePageDataServiceImpl implements IHomePageDataService {
+
+    @Autowired
+    private IDeviceRegionService deviceRegionService;
+
+    @Autowired
+    private IPeaksAndValleysTimeConfigService peaksAndValleysTimeConfigService;
+
+    @Autowired
+    private IDeviceInformationService deviceInformationService;
+
+
+    @Override
+    public List<Map<String, String>> regionPfvElectricity() {
+        List<DeviceRegion> list = deviceRegionService.list();
+        List<Map<String, String>> res = new ArrayList<>();
+        if(oConvertUtils.listIsNotEmpty(list)){
+            list.forEach(deviceRegion -> {
+                Map<String, String> map = new HashMap<>();
+                Double electricity = Math.random()*100+200;
+                map.put("name",deviceRegion.getRegionTitle());
+                map.put("peaks", String.format("%.2f",electricity));
+                map.put("flat", String.format("%.2f",electricity*(Math.random()*0.2+0.7)));
+                map.put("valleys", String.format("%.2f",electricity*(Math.random()*0.2+0.5)));
+                res.add(map);
+            });
+        }
+        return res;
+    }
+
+    @Override
+    public Map<String, Object> deviceOnline() {
+        List<DeviceRegion> list = deviceRegionService.list();
+        Map<String, Object> res = new HashMap<>();
+        List<Map<String, Object>> devices = new ArrayList<>();
+        AtomicReference<Integer> online = new AtomicReference<>(0);
+        AtomicReference<Integer> offline = new AtomicReference<>(0);
+        if(oConvertUtils.listIsNotEmpty(list)){
+            list.forEach(deviceRegion -> {
+                Map<String, Object> map = new HashMap<>();
+                int total = (int)(Math.random()*50)+50;
+                map.put("online", total-(int)(Math.random()*10));
+                map.put("offline", total-(int)map.get("online"));
+                map.put("name",deviceRegion.getRegionTitle());
+                online.updateAndGet(v -> v + (int)map.get("online"));
+                offline.updateAndGet(v -> v + (int)map.get("offline"));
+                devices.add(map);
+            });
+        }
+        res.put("res",devices);
+        res.put("deviceTotal",online.get()+offline.get());
+        res.put("online",online.get()*100/(online.get()+offline.get())+"%");
+        res.put("offline",offline.get()*100/(online.get()+offline.get())+"%");
+        res.put("onlineSum",online.get());
+        res.put("offlineSum",offline.get());
+        return res;
+    }
+
+    @Override
+    public Map<String, Long> fpvTime() {
+        Date current = null;
+        List<PeaksAndValleysTimeConfig> list = peaksAndValleysTimeConfigService.list();
+        Long peaks = 0l;
+        Long flat = 0l;
+        Long valleys = 0l;
+        try {
+            SimpleDateFormat format = new SimpleDateFormat("HH:mm:ss");
+            String date = format.format(new Date());
+            current = format.parse(date);
+        } catch (ParseException e) {
+            e.printStackTrace();
+        }
+        for (PeaksAndValleysTimeConfig config : list) {
+            if(config.getStartTime().after(current)){
+                if(config.getType().equals("0")){
+                    peaks += config.getEndTime().getTime()-config.getStartTime().getTime();
+                }else if(config.getType().equals("1")){
+                    flat += config.getEndTime().getTime()-config.getStartTime().getTime();
+                }else{
+                    valleys += config.getEndTime().getTime()-config.getStartTime().getTime();
+                }
+            }else if(config.getStartTime().before(current)&&config.getEndTime().after(current)){
+                if(config.getType().equals("0")){
+                    peaks += config.getEndTime().getTime()-current.getTime();
+                }else if(config.getType().equals("1")){
+                    flat += config.getEndTime().getTime()-current.getTime();
+                }else{
+                    valleys += config.getEndTime().getTime()-current.getTime();
+                }
+            }
+        }
+        Map<String, Long> res = new HashMap<>();
+        res.put("peaks",peaks/60000);
+        res.put("flat",flat/60000);
+        res.put("valleys",valleys/60000);
+        return res;
+    }
+
+    @Override
+    public List<Map<String, String>> regionElectricityPercentage() {
+        List<DeviceRegion> list = deviceRegionService.list();
+        int per = 0;
+        Map<String,Integer> map = new HashMap<>();
+        while (per<100){
+            int index = (int)(Math.random()*list.size());
+            if(oConvertUtils.isNotEmpty(map.get(list.get(index).getRegionTitle()))){
+                map.put(list.get(index).getRegionTitle(),map.get(list.get(index).getRegionTitle())+2);
+            }else{
+                map.put(list.get(index).getRegionTitle(),2);
+            }
+            per += 2;
+        }
+        List<Map<String, String>> res = new ArrayList<>();
+        list.forEach(deviceRegion -> {
+            Map<String,String> mapo = new HashMap<>();
+            mapo.put("name",deviceRegion.getRegionTitle());
+            mapo.put("value",map.get(deviceRegion.getRegionTitle())+"%");
+            res.add(mapo);
+        });
+        return res;
+    }
+
+    @Override
+    public Map<String, List> fpvTimeElectricity() {
+        Calendar calendar = Calendar.getInstance();
+        calendar.set(Calendar.SECOND, 0);
+        calendar.set(Calendar.MINUTE, 0);
+        calendar.set(Calendar.HOUR_OF_DAY, 0);
+        calendar.set(Calendar.MILLISECOND, 0);
+        Map<String, List> res = new HashMap<>();
+        List<Map<String,String>> peaks = new ArrayList<>();
+        List<Map<String,String>> flat = new ArrayList<>();
+        List<Map<String,String>> valleys = new ArrayList<>();
+        for (int i = 0; i < 24; i++) {
+            calendar.set(Calendar.HOUR_OF_DAY, i);
+            Double electricity = Math.random()*100+200;
+            peaks.add(getMap(calendar.getTime(),String.format("%.2f",electricity)));
+            flat.add(getMap(calendar.getTime(),String.format("%.2f",electricity*(Math.random()*0.2+0.7))));
+            valleys.add(getMap(calendar.getTime(),String.format("%.2f",electricity*(Math.random()*0.2+0.5))));
+        }
+        res.put("peaks",peaks);
+        res.put("flat",flat);
+        res.put("valleys",valleys);
+        return res;
+    }
+
+    @Override
+    public List<Map<String, String>> realAlarm() {
+        List<DeviceInformation> deviceInformations = deviceInformationService.list();
+        List<Map<String, String>> res = new ArrayList<>();
+        if(oConvertUtils.listIsNotEmpty(deviceInformations)){
+            String[] alarms = new String[]{"耗电异常","停止运行","运行异常"};
+            String[] levels = new String[]{"高度","轻度","中度"};
+            long time = new Date().getTime();
+            for (int i = 0; i < 10; i++) {
+                time -= Math.random()*60*30+30*60;
+                Map<String,String> map = new HashMap<>();
+                SimpleDateFormat format = new SimpleDateFormat("HH:mm");
+                map.put("time",format.format(new Date(time)));
+                map.put("name",deviceInformations.get((int)(Math.random()*deviceInformations.size())).getDeviceTitle());
+                map.put("alarmInfo",alarms[(int)(Math.random()*3)]);
+                map.put("level",levels[(int)(Math.random()*3)]);
+                res.add(map);
+            }
+        }
+        return res;
+    }
+
+    @Override
+    public List<Map<String, String>> regionElectricityStats() {
+        List<DeviceRegion> list = deviceRegionService.list();
+        List<Map<String, String>> res = new ArrayList<>();
+        if(oConvertUtils.listIsNotEmpty(list)){
+            list.forEach(deviceRegion -> {
+                Map<String,String> map = new HashMap<>();
+                map.put("name",deviceRegion.getRegionTitle());
+                map.put("value",String.format("%.2f",Math.random()*150+100));
+                res.add(map);
+            });
+        }
+        return res;
+    }
+
+    @Override
+    public Map<String, String> fpvElectricityStats() {
+        Map<String,String> res = new HashMap<>();
+        res.put("peaks",String.format("%.2f",Math.random()*35+15));
+        res.put("flat",String.format("%.2f",Math.random()*35+15));
+        res.put("valleys",String.format("%.2f",Math.random()*35+15));
+        return res;
+    }
+
+    @Override
+    public Map<String, Integer> deviceThresholdStats() {
+        int count = (int)deviceRegionService.count();
+        Map<String,Integer> res = new HashMap<>();
+        res.put("exceed",(int)(Math.random()*count));
+        res.put("noexceed",count-res.get("exceed"));
+        return res;
+    }
+
+    @Override
+    public List<String> latestMsg() {
+        String[] alarms = new String[]{"设备故障","用电统计报表待审批","设备状态待检查"};
+        List<String> res = Arrays.asList(alarms);
+        return res;
+    }
+
+
+    private Map<String,String> getMap(Date date,String value){
+        Map<String,String> res = new HashMap<>();
+        SimpleDateFormat simpleDateFormat = new SimpleDateFormat("HH:mm");
+        res.put("time",simpleDateFormat.format(date));
+        res.put("value",value);
+        return res;
+    }
+}

+ 70 - 0
zgztBus/jeecg-module-lesm/src/main/java/org/jeecg/modules/systemConfig/peaksAndValleysTimeConfig/entity/PeaksAndValleysTimeConfig.java

@@ -0,0 +1,70 @@
+package org.jeecg.modules.systemConfig.peaksAndValleysTimeConfig.entity;
+
+import com.baomidou.mybatisplus.annotation.IdType;
+import com.baomidou.mybatisplus.annotation.TableId;
+import com.baomidou.mybatisplus.annotation.TableName;
+import com.fasterxml.jackson.annotation.JsonFormat;
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import lombok.experimental.Accessors;
+import org.jeecgframework.poi.excel.annotation.Excel;
+import org.springframework.format.annotation.DateTimeFormat;
+
+import java.io.Serializable;
+
+/**
+ * @Description: 峰平谷时段配置
+ * @Author: jeecg-boot
+ * @Date:   2024-09-25
+ * @Version: V1.0
+ */
+@Data
+@TableName("peaks_and_valleys_time_config")
+@Accessors(chain = true)
+@EqualsAndHashCode(callSuper = false)
+@ApiModel(value="peaks_and_valleys_time_config对象", description="峰平谷时段配置")
+public class PeaksAndValleysTimeConfig implements Serializable {
+    private static final long serialVersionUID = 1L;
+
+	/**主键*/
+	@TableId(type = IdType.ASSIGN_ID)
+    @ApiModelProperty(value = "主键")
+    private String id;
+	/**创建人*/
+    @ApiModelProperty(value = "创建人")
+    private String createBy;
+	/**创建日期*/
+	@JsonFormat(timezone = "GMT+8",pattern = "yyyy-MM-dd HH:mm:ss")
+    @DateTimeFormat(pattern="yyyy-MM-dd HH:mm:ss")
+    @ApiModelProperty(value = "创建日期")
+    private java.util.Date createTime;
+	/**更新人*/
+    @ApiModelProperty(value = "更新人")
+    private String updateBy;
+	/**更新日期*/
+	@JsonFormat(timezone = "GMT+8",pattern = "yyyy-MM-dd HH:mm:ss")
+    @DateTimeFormat(pattern="yyyy-MM-dd HH:mm:ss")
+    @ApiModelProperty(value = "更新日期")
+    private java.util.Date updateTime;
+	/**所属部门*/
+    @ApiModelProperty(value = "所属部门")
+    private String sysOrgCode;
+	/**开始时间*/
+	@Excel(name = "开始时间", width = 20, format = "HH:mm:ss")
+	@JsonFormat(timezone = "GMT+8",pattern = "HH:mm:ss")
+    @DateTimeFormat(pattern="HH:mm:ss")
+    @ApiModelProperty(value = "开始时间")
+    private java.util.Date startTime;
+	/**结束时间*/
+	@Excel(name = "结束时间", width = 20, format = "HH:mm:ss")
+	@JsonFormat(timezone = "GMT+8",pattern = "HH:mm:ss")
+    @DateTimeFormat(pattern="HH:mm:ss")
+    @ApiModelProperty(value = "结束时间")
+    private java.util.Date endTime;
+	/**峰平谷类型*/
+	@Excel(name = "峰平谷类型", width = 15)
+    @ApiModelProperty(value = "峰平谷类型(0:峰 1:平 2:谷)")
+    private String type;
+}

+ 14 - 0
zgztBus/jeecg-module-lesm/src/main/java/org/jeecg/modules/systemConfig/peaksAndValleysTimeConfig/mapper/PeaksAndValleysTimeConfigMapper.java

@@ -0,0 +1,14 @@
+package org.jeecg.modules.systemConfig.peaksAndValleysTimeConfig.mapper;
+
+import org.jeecg.modules.systemConfig.peaksAndValleysTimeConfig.entity.PeaksAndValleysTimeConfig;
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+
+/**
+ * @Description: 峰平谷时段配置
+ * @Author: jeecg-boot
+ * @Date:   2024-09-25
+ * @Version: V1.0
+ */
+public interface PeaksAndValleysTimeConfigMapper extends BaseMapper<PeaksAndValleysTimeConfig> {
+
+}

+ 5 - 0
zgztBus/jeecg-module-lesm/src/main/java/org/jeecg/modules/systemConfig/peaksAndValleysTimeConfig/mapper/xml/PeaksAndValleysTimeConfigMapper.xml

@@ -0,0 +1,5 @@
+<?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="org.jeecg.modules.systemConfig.peaksAndValleysTimeConfig.mapper.PeaksAndValleysTimeConfigMapper">
+
+</mapper>

+ 14 - 0
zgztBus/jeecg-module-lesm/src/main/java/org/jeecg/modules/systemConfig/peaksAndValleysTimeConfig/service/IPeaksAndValleysTimeConfigService.java

@@ -0,0 +1,14 @@
+package org.jeecg.modules.systemConfig.peaksAndValleysTimeConfig.service;
+
+import com.baomidou.mybatisplus.extension.service.IService;
+import org.jeecg.modules.systemConfig.peaksAndValleysTimeConfig.entity.PeaksAndValleysTimeConfig;
+
+/**
+ * @Description: 峰平谷时段配置
+ * @Author: jeecg-boot
+ * @Date:   2024-09-25
+ * @Version: V1.0
+ */
+public interface IPeaksAndValleysTimeConfigService extends IService<PeaksAndValleysTimeConfig> {
+
+}

+ 18 - 0
zgztBus/jeecg-module-lesm/src/main/java/org/jeecg/modules/systemConfig/peaksAndValleysTimeConfig/service/impl/PeaksAndValleysTimeConfigServiceImpl.java

@@ -0,0 +1,18 @@
+package org.jeecg.modules.systemConfig.peaksAndValleysTimeConfig.service.impl;
+
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import org.jeecg.modules.systemConfig.peaksAndValleysTimeConfig.entity.PeaksAndValleysTimeConfig;
+import org.jeecg.modules.systemConfig.peaksAndValleysTimeConfig.mapper.PeaksAndValleysTimeConfigMapper;
+import org.jeecg.modules.systemConfig.peaksAndValleysTimeConfig.service.IPeaksAndValleysTimeConfigService;
+import org.springframework.stereotype.Service;
+
+/**
+ * @Description: 峰平谷时段配置
+ * @Author: jeecg-boot
+ * @Date:   2024-09-25
+ * @Version: V1.0
+ */
+@Service
+public class PeaksAndValleysTimeConfigServiceImpl extends ServiceImpl<PeaksAndValleysTimeConfigMapper, PeaksAndValleysTimeConfig> implements IPeaksAndValleysTimeConfigService {
+
+}

+ 40 - 0
zgztBus/jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/monitor/actuator/CustomActuatorConfig.java

@@ -0,0 +1,40 @@
+package org.jeecg.modules.monitor.actuator;
+
+import org.jeecg.modules.monitor.actuator.httptrace.CustomInMemoryHttpTraceRepository;
+import org.springframework.boot.actuate.autoconfigure.trace.http.HttpTraceAutoConfiguration;
+import org.springframework.boot.actuate.autoconfigure.trace.http.HttpTraceProperties;
+import org.springframework.boot.actuate.trace.http.HttpTraceRepository;
+import org.springframework.boot.autoconfigure.AutoConfigureBefore;
+import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
+import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
+import org.springframework.boot.context.properties.EnableConfigurationProperties;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.context.annotation.Primary;
+
+/**
+ * 自定义健康监控配置类
+ *
+ * @Author: chenrui
+ * @Date: 2024/5/13 17:20
+ */
+@Configuration
+@EnableConfigurationProperties(HttpTraceProperties.class)
+@AutoConfigureBefore(HttpTraceAutoConfiguration.class)
+public class CustomActuatorConfig {
+
+    /**
+     * 请求追踪
+     * @return
+     * @author chenrui
+     * @date 2024/5/14 14:52
+     */
+    @Bean
+    @Primary
+    @ConditionalOnProperty(prefix = "management.trace.http", name = "enabled", matchIfMissing = true)
+    @ConditionalOnMissingBean(HttpTraceRepository.class)
+    public CustomInMemoryHttpTraceRepository traceRepository() {
+        return new CustomInMemoryHttpTraceRepository();
+    }
+
+}

+ 44 - 0
zgztBus/jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/monitor/actuator/httptrace/CustomHttpTraceEndpoint.java

@@ -0,0 +1,44 @@
+package org.jeecg.modules.monitor.actuator.httptrace;
+
+import lombok.Getter;
+import org.springframework.boot.actuate.endpoint.annotation.Endpoint;
+import org.springframework.boot.actuate.endpoint.annotation.ReadOperation;
+import org.springframework.boot.actuate.endpoint.annotation.Selector;
+import org.springframework.boot.actuate.trace.http.HttpTrace;
+import org.springframework.stereotype.Component;
+import org.springframework.util.Assert;
+
+import java.util.List;
+
+import static org.springframework.boot.actuate.endpoint.annotation.Selector.Match.ALL_REMAINING;
+
+/**
+ * @Description: ENDPOINT: 请求追踪(新),支持通过responseCode筛选
+ * @Author: chenrui
+ * @Date: 2024/5/13 17:02
+ */
+@Component
+@Endpoint(id = "httptrace-new")
+public class CustomHttpTraceEndpoint{
+    private final CustomInMemoryHttpTraceRepository repository;
+
+    public CustomHttpTraceEndpoint(CustomInMemoryHttpTraceRepository repository) {
+        Assert.notNull(repository, "Repository must not be null");
+        this.repository = repository;
+    }
+
+    @ReadOperation
+    public HttpTraceDescriptor traces(@Selector(match = ALL_REMAINING) String query) {
+        return new HttpTraceDescriptor(this.repository.findAll(query));
+    }
+
+    @Getter
+    public static final class HttpTraceDescriptor {
+        private final List<HttpTrace> traces;
+
+        private HttpTraceDescriptor(List<HttpTrace> traces) {
+            this.traces = traces;
+        }
+
+    }
+}

+ 94 - 0
zgztBus/jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/monitor/actuator/httptrace/CustomInMemoryHttpTraceRepository.java

@@ -0,0 +1,94 @@
+package org.jeecg.modules.monitor.actuator.httptrace;
+
+import org.springframework.boot.actuate.trace.http.HttpTrace;
+import org.springframework.boot.actuate.trace.http.InMemoryHttpTraceRepository;
+
+import java.util.List;
+import java.util.stream.Collectors;
+import java.util.stream.Stream;
+
+/**
+ * @Description: 自定义内存请求追踪存储
+ * @Author: chenrui
+ * @Date: 2024/5/13 17:02
+ */
+public class CustomInMemoryHttpTraceRepository extends InMemoryHttpTraceRepository {
+
+    @Override
+    public List<HttpTrace> findAll() {
+        return super.findAll();
+    }
+
+    public List<HttpTrace> findAll(String query) {
+        List<HttpTrace> allTrace = super.findAll();
+        if (null != allTrace && !allTrace.isEmpty()) {
+            Stream<HttpTrace> stream = allTrace.stream();
+            String[] params = query.split(",");
+            stream = filter(params, stream);
+            stream = sort(params, stream);
+            allTrace = stream.collect(Collectors.toList());
+        }
+        return allTrace;
+    }
+
+    private Stream<HttpTrace> sort(String[] params, Stream<HttpTrace> stream) {
+        if (params.length < 2) {
+            return stream;
+        }
+        String sortBy = params[1];
+        String order;
+        if (params.length > 2) {
+            order = params[2];
+        } else {
+            order = "desc";
+        }
+        return stream.sorted((o1, o2) -> {
+            int i = 0;
+            if("timeTaken".equalsIgnoreCase(sortBy)) {
+                i = o1.getTimeTaken().compareTo(o2.getTimeTaken());
+            }else if("timestamp".equalsIgnoreCase(sortBy)){
+                i = o1.getTimestamp().compareTo(o2.getTimestamp());
+            }
+            if("desc".equalsIgnoreCase(order)){
+                i *=-1;
+            }
+            return i;
+        });
+    }
+
+    private static Stream<HttpTrace> filter(String[] params, Stream<HttpTrace> stream) {
+        if (params.length == 0) {
+            return stream;
+        }
+        String statusQuery = params[0];
+        if (null != statusQuery && !statusQuery.isEmpty()) {
+            statusQuery = statusQuery.toLowerCase().trim();
+            switch (statusQuery) {
+                case "error":
+                    stream = stream.filter(httpTrace -> {
+                        int status = httpTrace.getResponse().getStatus();
+                        return status >= 404 && status < 501;
+                    });
+                    break;
+                case "warn":
+                    stream = stream.filter(httpTrace -> {
+                        int status = httpTrace.getResponse().getStatus();
+                        return status >= 201 && status < 404;
+                    });
+                    break;
+                case "success":
+                    stream = stream.filter(httpTrace -> {
+                        int status = httpTrace.getResponse().getStatus();
+                        return status == 200;
+                    });
+                    break;
+                case "all":
+                default:
+                    break;
+            }
+            return stream;
+        }
+        return stream;
+    }
+
+}

+ 55 - 0
zgztBus/jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/monitor/controller/ActuatorMemoryController.java

@@ -0,0 +1,55 @@
+package org.jeecg.modules.monitor.controller;
+
+import cn.hutool.core.util.NumberUtil;
+import lombok.extern.slf4j.Slf4j;
+import org.jeecg.common.api.vo.Result;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+import java.lang.management.ManagementFactory;
+import java.lang.management.OperatingSystemMXBean;
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * @Description: 内存健康检查
+ * @author: chenrui
+ */
+@Slf4j
+@RestController
+@RequestMapping("/sys/actuator/memory")
+public class ActuatorMemoryController {
+
+
+    /**
+     * 内存详情
+     * @return
+     */
+    @GetMapping("/info")
+    public Result<?> getRedisInfo() {
+		Runtime runtime = Runtime.getRuntime();
+		Map<String,Number> result = new HashMap<>();
+		result.put("memory.runtime.total", runtime.totalMemory());
+		result.put("memory.runtime.used", runtime.freeMemory());
+		result.put("memory.runtime.max", runtime.totalMemory() - runtime.freeMemory());
+		result.put("memory.runtime.free", runtime.maxMemory() - runtime.totalMemory() + runtime.freeMemory());
+		result.put("memory.runtime.usage", NumberUtil.div(runtime.totalMemory() - runtime.freeMemory(), runtime.totalMemory()));
+		//update-begin---author:chenrui ---date:20240705  for:[TV360X-1695]内存信息-立即更新 功能报错 #6635------------
+		OperatingSystemMXBean operatingSystemMXBean = ManagementFactory.getOperatingSystemMXBean();
+		if (operatingSystemMXBean instanceof com.sun.management.OperatingSystemMXBean) {
+			com.sun.management.OperatingSystemMXBean opBean = (com.sun.management.OperatingSystemMXBean) operatingSystemMXBean;
+//			JSONObject operatingSystemJson = JSONObject.parseObject(JSONObject.toJSONString(operatingSystemMXBean));
+			long totalPhysicalMemory = opBean.getTotalPhysicalMemorySize();
+			long freePhysicalMemory = opBean.getFreePhysicalMemorySize();
+			long usedPhysicalMemory = totalPhysicalMemory - freePhysicalMemory;
+			result.put("memory.physical.total", totalPhysicalMemory);
+			result.put("memory.physical.used", freePhysicalMemory);
+			result.put("memory.physical.free", usedPhysicalMemory);
+			result.put("memory.physical.usage", NumberUtil.div(usedPhysicalMemory, totalPhysicalMemory));
+		}
+		//update-end---author:chenrui ---date:20240705  for:[TV360X-1695]内存信息-立即更新 功能报错 #6635------------
+		return Result.ok(result);
+    }
+
+}

+ 14 - 0
zgztBus/jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/monitor/controller/ActuatorRedisController.java

@@ -43,6 +43,20 @@ public class ActuatorRedisController {
         return Result.ok(infoList);
     }
 
+	//update-begin---author:chenrui ---date:20240514  for:[QQYUN-9247]系统监控功能优化------------
+	/**
+	 * Redis历史性能指标查询(过去一小时)
+	 * @return
+	 * @throws Exception
+	 * @author chenrui
+	 * @date 2024/5/14 14:56
+	 */
+	@GetMapping(value = "/metrics/history")
+	public Result<?> getMetricsHistory() throws Exception {
+		Map<String,List<Map<String,Object>>> metricsHistory = this.redisService.getMetricsHistory();
+		return Result.OK(metricsHistory);
+	}
+
     @GetMapping("/keysSize")
     public Map<String, Object> getKeysSize() throws Exception {
         return redisService.getKeysSize();

+ 11 - 4
zgztBus/jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/monitor/service/RedisService.java

@@ -1,13 +1,12 @@
 package org.jeecg.modules.monitor.service;
 
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-
 import com.alibaba.fastjson.JSONArray;
 import org.jeecg.modules.monitor.domain.RedisInfo;
 import org.jeecg.modules.monitor.exception.RedisConnectException;
 
+import java.util.List;
+import java.util.Map;
+
 /**
  * @Description: redis信息service接口
  * @author: jeecg-boot
@@ -44,4 +43,12 @@ public interface RedisService {
      * @throws RedisConnectException
 	 */
 	Map<String, JSONArray> getMapForReport(String type) throws RedisConnectException ;
+
+	/**
+	 * 获取历史性能指标
+	 * @return
+	 * @author chenrui
+	 * @date 2024/5/14 14:57
+	 */
+	Map<String, List<Map<String, Object>>> getMetricsHistory();
 }

+ 21 - 10
zgztBus/jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/monitor/service/impl/RedisServiceImpl.java

@@ -1,18 +1,10 @@
 package org.jeecg.modules.monitor.service.impl;
 
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-import java.util.Properties;
-
-import javax.annotation.Resource;
-
 import cn.hutool.core.date.DateUtil;
 import com.alibaba.fastjson.JSONArray;
 import com.alibaba.fastjson.JSONObject;
 import com.google.common.collect.Maps;
-import org.jeecg.common.constant.CommonConstant;
+import lombok.extern.slf4j.Slf4j;
 import org.jeecg.common.util.oConvertUtils;
 import org.jeecg.modules.monitor.domain.RedisInfo;
 import org.jeecg.modules.monitor.exception.RedisConnectException;
@@ -21,7 +13,8 @@ import org.springframework.cglib.beans.BeanMap;
 import org.springframework.data.redis.connection.RedisConnectionFactory;
 import org.springframework.stereotype.Service;
 
-import lombok.extern.slf4j.Slf4j;
+import javax.annotation.Resource;
+import java.util.*;
 
 /**
  * Redis 监控信息获取
@@ -40,6 +33,12 @@ public class RedisServiceImpl implements RedisService {
      */
     private static final String REDIS_MESSAGE = "3";
 
+	/**
+	 * redis性能信息记录
+	 */
+	private static final Map<String,List<Map<String, Object>>> REDIS_METRICS = new HashMap<>(2);
+
+
 	/**
 	 * Redis详细信息
 	 */
@@ -126,4 +125,16 @@ public class RedisServiceImpl implements RedisService {
 		mapJson.put("data",json);
 		return mapJson;
 	}
+
+	//update-begin---author:chenrui ---date:20240514  for:[QQYUN-9247]系统监控功能优化------------
+	/**
+	 * 获取历史性能指标
+	 * @return
+	 * @author chenrui
+	 * @date 2024/5/14 14:57
+	 */
+	@Override
+	public Map<String, List<Map<String, Object>>> getMetricsHistory() {
+		return REDIS_METRICS;
+	}
 }

+ 298 - 0
zgztBus/jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/quartz/controller/QuartzJobController.java

@@ -0,0 +1,298 @@
+package org.jeecg.modules.quartz.controller;
+
+import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import io.swagger.annotations.Api;
+import io.swagger.annotations.ApiOperation;
+import lombok.extern.slf4j.Slf4j;
+import org.apache.shiro.SecurityUtils;
+import org.apache.shiro.authz.annotation.RequiresPermissions;
+import org.jeecg.common.api.vo.Result;
+import org.jeecg.common.constant.CommonConstant;
+import org.jeecg.common.constant.SymbolConstant;
+import org.jeecg.common.system.query.QueryGenerator;
+import org.jeecg.common.system.vo.LoginUser;
+import org.jeecg.common.util.ImportExcelUtil;
+import org.jeecg.common.util.oConvertUtils;
+import org.jeecg.modules.quartz.entity.QuartzJob;
+import org.jeecg.modules.quartz.service.IQuartzJobService;
+import org.jeecgframework.poi.excel.ExcelImportUtil;
+import org.jeecgframework.poi.excel.def.NormalExcelConstants;
+import org.jeecgframework.poi.excel.entity.ExportParams;
+import org.jeecgframework.poi.excel.entity.ImportParams;
+import org.jeecgframework.poi.excel.view.JeecgEntityExcelView;
+import org.quartz.Scheduler;
+import org.quartz.SchedulerException;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.*;
+import org.springframework.web.multipart.MultipartFile;
+import org.springframework.web.multipart.MultipartHttpServletRequest;
+import org.springframework.web.servlet.ModelAndView;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * @Description: 定时任务在线管理
+ * @Author: jeecg-boot
+ * @Date: 2019-01-02
+ * @Version:V1.0
+ */
+@RestController
+@RequestMapping("/sys/quartzJob")
+@Slf4j
+@Api(tags = "定时任务接口")
+public class QuartzJobController {
+	@Autowired
+	private IQuartzJobService quartzJobService;
+	@Autowired
+	private Scheduler scheduler;
+
+	/**
+	 * 分页列表查询
+	 * 
+	 * @param quartzJob
+	 * @param pageNo
+	 * @param pageSize
+	 * @param req
+	 * @return
+	 */
+	@RequestMapping(value = "/list", method = RequestMethod.GET)
+	public Result<?> queryPageList(QuartzJob quartzJob, @RequestParam(name = "pageNo", defaultValue = "1") Integer pageNo,
+			@RequestParam(name = "pageSize", defaultValue = "10") Integer pageSize, HttpServletRequest req) {
+		QueryWrapper<QuartzJob> queryWrapper = QueryGenerator.initQueryWrapper(quartzJob, req.getParameterMap());
+		Page<QuartzJob> page = new Page<QuartzJob>(pageNo, pageSize);
+		IPage<QuartzJob> pageList = quartzJobService.page(page, queryWrapper);
+        return Result.ok(pageList);
+
+	}
+
+	/**
+	 * 添加定时任务
+	 * 
+	 * @param quartzJob
+	 * @return
+	 */
+	//@RequiresRoles("admin")
+    @RequiresPermissions("system:quartzJob:add")
+	@RequestMapping(value = "/add", method = RequestMethod.POST)
+	public Result<?> add(@RequestBody QuartzJob quartzJob) {
+		quartzJobService.saveAndScheduleJob(quartzJob);
+		return Result.ok("创建定时任务成功");
+	}
+
+	/**
+	 * 更新定时任务
+	 * 
+	 * @param quartzJob
+	 * @return
+	 */
+	//@RequiresRoles("admin")
+    @RequiresPermissions("system:quartzJob:edit")
+	@RequestMapping(value = "/edit", method ={RequestMethod.PUT, RequestMethod.POST})
+	public Result<?> eidt(@RequestBody QuartzJob quartzJob) {
+		try {
+			quartzJobService.editAndScheduleJob(quartzJob);
+		} catch (SchedulerException e) {
+			log.error(e.getMessage(),e);
+			return Result.error("更新定时任务失败!");
+		}
+	    return Result.ok("更新定时任务成功!");
+	}
+
+	/**
+	 * 通过id删除
+	 * 
+	 * @param id
+	 * @return
+	 */
+	//@RequiresRoles("admin")
+    @RequiresPermissions("system:quartzJob:delete")
+	@RequestMapping(value = "/delete", method = RequestMethod.DELETE)
+	public Result<?> delete(@RequestParam(name = "id", required = true) String id) {
+		QuartzJob quartzJob = quartzJobService.getById(id);
+		if (quartzJob == null) {
+			return Result.error("未找到对应实体");
+		}
+		quartzJobService.deleteAndStopJob(quartzJob);
+        return Result.ok("删除成功!");
+
+	}
+
+	/**
+	 * 批量删除
+	 * 
+	 * @param ids
+	 * @return
+	 */
+	//@RequiresRoles("admin")
+    @RequiresPermissions("system:quartzJob:deleteBatch")
+	@RequestMapping(value = "/deleteBatch", method = RequestMethod.DELETE)
+	public Result<?> deleteBatch(@RequestParam(name = "ids", required = true) String ids) {
+		if (ids == null || "".equals(ids.trim())) {
+			return Result.error("参数不识别!");
+		}
+		for (String id : Arrays.asList(ids.split(SymbolConstant.COMMA))) {
+			QuartzJob job = quartzJobService.getById(id);
+			quartzJobService.deleteAndStopJob(job);
+		}
+        return Result.ok("删除定时任务成功!");
+	}
+
+	/**
+	 * 暂停定时任务
+	 * 
+	 * @param id
+	 * @return
+	 */
+	//@RequiresRoles("admin")
+    @RequiresPermissions("system:quartzJob:pause")
+	@GetMapping(value = "/pause")
+	@ApiOperation(value = "停止定时任务")
+	public Result<Object> pauseJob(@RequestParam(name = "id") String id) {
+		QuartzJob job = quartzJobService.getById(id);
+		if (job == null) {
+			return Result.error("定时任务不存在!");
+		}
+		quartzJobService.pause(job);
+		return Result.ok("停止定时任务成功");
+	}
+
+	/**
+	 * 启动定时任务
+	 * 
+	 * @param id
+	 * @return
+	 */
+	//@RequiresRoles("admin")
+    @RequiresPermissions("system:quartzJob:resume")
+	@GetMapping(value = "/resume")
+	@ApiOperation(value = "启动定时任务")
+	public Result<Object> resumeJob(@RequestParam(name = "id") String id) {
+		QuartzJob job = quartzJobService.getById(id);
+		if (job == null) {
+			return Result.error("定时任务不存在!");
+		}
+		quartzJobService.resumeJob(job);
+		//scheduler.resumeJob(JobKey.jobKey(job.getJobClassName().trim()));
+		return Result.ok("启动定时任务成功");
+	}
+
+	/**
+	 * 通过id查询
+	 * 
+	 * @param id
+	 * @return
+	 */
+	@RequestMapping(value = "/queryById", method = RequestMethod.GET)
+	public Result<?> queryById(@RequestParam(name = "id", required = true) String id) {
+		QuartzJob quartzJob = quartzJobService.getById(id);
+        return Result.ok(quartzJob);
+	}
+
+	/**
+	 * 导出excel
+	 * 
+	 * @param request
+	 * @param quartzJob
+	 */
+	@RequestMapping(value = "/exportXls")
+	public ModelAndView exportXls(HttpServletRequest request, QuartzJob quartzJob) {
+		// Step.1 组装查询条件
+		QueryWrapper<QuartzJob> queryWrapper = QueryGenerator.initQueryWrapper(quartzJob, request.getParameterMap());
+		// 过滤选中数据
+		String selections = request.getParameter("selections");
+		if (oConvertUtils.isNotEmpty(selections)) {
+			List<String> selectionList = Arrays.asList(selections.split(","));
+			queryWrapper.in("id",selectionList);
+		}
+		// Step.2 AutoPoi 导出Excel
+		ModelAndView mv = new ModelAndView(new JeecgEntityExcelView());
+		List<QuartzJob> pageList = quartzJobService.list(queryWrapper);
+		// 导出文件名称
+		mv.addObject(NormalExcelConstants.FILE_NAME, "定时任务列表");
+		mv.addObject(NormalExcelConstants.CLASS, QuartzJob.class);
+        //获取当前登录用户
+        //update-begin---author:wangshuai ---date:20211227  for:[JTC-116]导出人写死了------------
+        LoginUser user = (LoginUser) SecurityUtils.getSubject().getPrincipal();
+		mv.addObject(NormalExcelConstants.PARAMS, new ExportParams("定时任务列表数据", "导出人:"+user.getRealname(), "导出信息"));
+        //update-end---author:wangshuai ---date:20211227  for:[JTC-116]导出人写死了------------
+        mv.addObject(NormalExcelConstants.DATA_LIST, pageList);
+		return mv;
+	}
+
+	/**
+	 * 通过excel导入数据
+	 * 
+	 * @param request
+	 * @param response
+	 * @return
+	 */
+	@RequestMapping(value = "/importExcel", method = RequestMethod.POST)
+	public Result<?> importExcel(HttpServletRequest request, HttpServletResponse response) throws IOException {
+		MultipartHttpServletRequest multipartRequest = (MultipartHttpServletRequest) request;
+		Map<String, MultipartFile> fileMap = multipartRequest.getFileMap();
+		// 错误信息
+		List<String> errorMessage = new ArrayList<>();
+		int successLines = 0, errorLines = 0;
+		for (Map.Entry<String, MultipartFile> entity : fileMap.entrySet()) {
+            // 获取上传文件对象
+			MultipartFile file = entity.getValue();
+			ImportParams params = new ImportParams();
+			params.setTitleRows(2);
+			params.setHeadRows(1);
+			params.setNeedSave(true);
+			try {
+				List<QuartzJob> listQuartzJobs = ExcelImportUtil.importExcel(file.getInputStream(), QuartzJob.class, params);
+				//add-begin-author:taoyan date:20210909 for:导入定时任务,并不会被启动和调度,需要手动点击启动,才会加入调度任务中 #2986
+				for(QuartzJob job: listQuartzJobs){
+					job.setStatus(CommonConstant.STATUS_DISABLE);
+				}
+				List<String> list = ImportExcelUtil.importDateSave(listQuartzJobs, IQuartzJobService.class, errorMessage,CommonConstant.SQL_INDEX_UNIQ_JOB_CLASS_NAME);
+				//add-end-author:taoyan date:20210909 for:导入定时任务,并不会被启动和调度,需要手动点击启动,才会加入调度任务中 #2986
+				errorLines+=list.size();
+				successLines+=(listQuartzJobs.size()-errorLines);
+			} catch (Exception e) {
+				log.error(e.getMessage(), e);
+				return Result.error("文件导入失败!");
+			} finally {
+				try {
+					file.getInputStream().close();
+				} catch (IOException e) {
+					e.printStackTrace();
+				}
+			}
+		}
+		return ImportExcelUtil.imporReturnRes(errorLines,successLines,errorMessage);
+	}
+
+	/**
+	 * 立即执行
+	 * @param id
+	 * @return
+	 */
+	//@RequiresRoles("admin")
+    @RequiresPermissions("system:quartzJob:execute")
+	@GetMapping("/execute")
+	public Result<?> execute(@RequestParam(name = "id", required = true) String id) {
+		QuartzJob quartzJob = quartzJobService.getById(id);
+		if (quartzJob == null) {
+			return Result.error("未找到对应实体");
+		}
+		try {
+			quartzJobService.execute(quartzJob);
+		} catch (Exception e) {
+			//e.printStackTrace();
+			log.info("定时任务 立即执行失败>>"+e.getMessage());
+			return Result.error("执行失败!");
+		}
+		return Result.ok("执行成功!");
+	}
+
+}

+ 59 - 0
zgztBus/jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/quartz/entity/QuartzJob.java

@@ -0,0 +1,59 @@
+package org.jeecg.modules.quartz.entity;
+
+import com.baomidou.mybatisplus.annotation.IdType;
+import com.baomidou.mybatisplus.annotation.TableId;
+import com.baomidou.mybatisplus.annotation.TableName;
+import com.fasterxml.jackson.annotation.JsonFormat;
+import lombok.Data;
+import org.jeecg.common.aspect.annotation.Dict;
+import org.jeecgframework.poi.excel.annotation.Excel;
+import org.springframework.format.annotation.DateTimeFormat;
+
+import java.io.Serializable;
+
+/**
+ * @Description: 定时任务在线管理
+ * @Author: jeecg-boot
+ * @Date:  2019-01-02
+ * @Version: V1.0
+ */
+@Data
+@TableName("sys_quartz_job")
+public class QuartzJob implements Serializable {
+    private static final long serialVersionUID = 1L;
+    
+	/**id*/
+	@TableId(type = IdType.ASSIGN_ID)
+	private String id;
+	/**创建人*/
+	private String createBy;
+	/**创建时间*/
+	@JsonFormat(timezone = "GMT+8",pattern = "yyyy-MM-dd HH:mm:ss")
+    @DateTimeFormat(pattern="yyyy-MM-dd HH:mm:ss")
+	private java.util.Date createTime;
+	/**删除状态*/
+	private Integer delFlag;
+	/**修改人*/
+	private String updateBy;
+	/**修改时间*/
+	@JsonFormat(timezone = "GMT+8",pattern = "yyyy-MM-dd HH:mm:ss")
+    @DateTimeFormat(pattern="yyyy-MM-dd HH:mm:ss")
+	private java.util.Date updateTime;
+	/**任务类名*/
+	@Excel(name="任务类名",width=40)
+	private String jobClassName;
+	/**cron表达式*/
+	@Excel(name="cron表达式",width=30)
+	private String cronExpression;
+	/**参数*/
+	@Excel(name="参数",width=15)
+	private String parameter;
+	/**描述*/
+	@Excel(name="描述",width=40)
+	private String description;
+	/**状态 0正常 -1停止*/
+	@Excel(name="状态",width=15,dicCode="quartz_status")
+	@Dict(dicCode = "quartz_status")
+	private Integer status;
+
+}

+ 35 - 0
zgztBus/jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/quartz/job/AsyncJob.java

@@ -0,0 +1,35 @@
+package org.jeecg.modules.quartz.job;
+
+import lombok.extern.slf4j.Slf4j;
+import org.jeecg.common.util.DateUtils;
+import org.quartz.*;
+
+/**
+ * @Description: 同步定时任务测试
+ *
+ * 此处的同步是指 当定时任务的执行时间大于任务的时间间隔时
+ * 会等待第一个任务执行完成才会走第二个任务
+ *
+ *
+ * @author: taoyan
+ * @date: 2020年06月19日
+ */
+@PersistJobDataAfterExecution
+@DisallowConcurrentExecution
+@Slf4j
+public class AsyncJob implements Job {
+
+    @Override
+    public void execute(JobExecutionContext jobExecutionContext) throws JobExecutionException {
+        log.info(" --- 同步任务调度开始 --- ");
+        try {
+            //此处模拟任务执行时间 5秒  任务表达式配置为每秒执行一次:0/1 * * * * ? *
+            Thread.sleep(5000);
+        } catch (InterruptedException e) {
+            e.printStackTrace();
+        }
+        //测试发现 每5秒执行一次
+        log.info(" --- 执行完毕,时间:"+DateUtils.now()+"---");
+    }
+
+}

+ 23 - 0
zgztBus/jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/quartz/job/SampleJob.java

@@ -0,0 +1,23 @@
+package org.jeecg.modules.quartz.job;
+
+import org.jeecg.common.util.DateUtils;
+import org.quartz.Job;
+import org.quartz.JobExecutionContext;
+import org.quartz.JobExecutionException;
+
+import lombok.extern.slf4j.Slf4j;
+
+/**
+ * 示例不带参定时任务
+ * 
+ * @Author Scott
+ */
+@Slf4j
+public class SampleJob implements Job {
+
+	@Override
+	public void execute(JobExecutionContext jobExecutionContext) throws JobExecutionException {
+		log.info(" Job Execution key:"+jobExecutionContext.getJobDetail().getKey());
+		log.info(String.format(" Jeecg-Boot 普通定时任务 SampleJob !  时间:" + DateUtils.getTimestamp()));
+	}
+}

+ 32 - 0
zgztBus/jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/quartz/job/SampleParamJob.java

@@ -0,0 +1,32 @@
+package org.jeecg.modules.quartz.job;
+
+import org.jeecg.common.util.DateUtils;
+import org.quartz.Job;
+import org.quartz.JobExecutionContext;
+import org.quartz.JobExecutionException;
+
+import lombok.extern.slf4j.Slf4j;
+
+/**
+ * 示例带参定时任务
+ * 
+ * @Author Scott
+ */
+@Slf4j
+public class SampleParamJob implements Job {
+
+	/**
+	 * 若参数变量名修改 QuartzJobController中也需对应修改
+	 */
+	private String parameter;
+
+	public void setParameter(String parameter) {
+		this.parameter = parameter;
+	}
+
+	@Override
+	public void execute(JobExecutionContext jobExecutionContext) throws JobExecutionException {
+		log.info(" Job Execution key:"+jobExecutionContext.getJobDetail().getKey());
+		log.info( String.format("welcome %s! Jeecg-Boot 带参数定时任务 SampleParamJob !   时间:" + DateUtils.now(), this.parameter));
+	}
+}

+ 24 - 0
zgztBus/jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/quartz/mapper/QuartzJobMapper.java

@@ -0,0 +1,24 @@
+package org.jeecg.modules.quartz.mapper;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import org.apache.ibatis.annotations.Param;
+import org.jeecg.modules.quartz.entity.QuartzJob;
+
+import java.util.List;
+
+/**
+ * @Description: 定时任务在线管理
+ * @Author: jeecg-boot
+ * @Date:  2019-01-02
+ * @Version: V1.0
+ */
+public interface QuartzJobMapper extends BaseMapper<QuartzJob> {
+
+    /**
+     * 根据jobClassName查询
+     * @param jobClassName 任务类名
+     * @return
+     */
+	public List<QuartzJob> findByJobClassName(@Param("jobClassName") String jobClassName);
+
+}

+ 9 - 0
zgztBus/jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/quartz/mapper/xml/QuartzJobMapper.xml

@@ -0,0 +1,9 @@
+<?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="org.jeecg.modules.quartz.mapper.QuartzJobMapper">
+
+	<!-- 根据jobClassName查询 -->
+	<select id="findByJobClassName" resultType="org.jeecg.modules.quartz.entity.QuartzJob">
+		select * from  sys_quartz_job  where job_class_name = #{jobClassName}
+	</select>
+</mapper>

+ 67 - 0
zgztBus/jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/quartz/service/IQuartzJobService.java

@@ -0,0 +1,67 @@
+package org.jeecg.modules.quartz.service;
+
+import java.util.List;
+
+import org.jeecg.modules.quartz.entity.QuartzJob;
+import org.quartz.SchedulerException;
+
+import com.baomidou.mybatisplus.extension.service.IService;
+
+/**
+ * @Description: 定时任务在线管理
+ * @Author: jeecg-boot
+ * @Date: 2019-04-28
+ * @Version: V1.1
+ */
+public interface IQuartzJobService extends IService<QuartzJob> {
+
+    /**
+     * 通过类名寻找定时任务
+     * @param jobClassName 类名
+     * @return List<QuartzJob>
+     */
+	List<QuartzJob> findByJobClassName(String jobClassName);
+
+    /**
+     * 保存定时任务
+     * @param quartzJob
+     * @return boolean
+     */
+	boolean saveAndScheduleJob(QuartzJob quartzJob);
+
+    /**
+     * 编辑定时任务
+     * @param quartzJob
+     * @return boolean
+     * @throws SchedulerException
+     */
+	boolean editAndScheduleJob(QuartzJob quartzJob) throws SchedulerException;
+
+    /**
+     * 删除定时任务
+     * @param quartzJob
+     * @return boolean
+     */
+	boolean deleteAndStopJob(QuartzJob quartzJob);
+
+    /**
+     * 恢复定时任务
+     * @param quartzJob
+     * @return
+     */
+	boolean resumeJob(QuartzJob quartzJob);
+
+	/**
+	 * 执行定时任务
+	 * @param quartzJob
+     * @throws Exception
+	 */
+	void execute(QuartzJob quartzJob) throws Exception;
+
+	/**
+	 * 暂停任务
+	 * @param quartzJob
+	 * @throws SchedulerException
+	 */
+	void pause(QuartzJob quartzJob);
+}

+ 183 - 0
zgztBus/jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/quartz/service/impl/QuartzJobServiceImpl.java

@@ -0,0 +1,183 @@
+package org.jeecg.modules.quartz.service.impl;
+
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import lombok.extern.slf4j.Slf4j;
+import org.jeecg.common.constant.CommonConstant;
+import org.jeecg.common.exception.JeecgBootException;
+import org.jeecg.common.util.DateUtils;
+import org.jeecg.modules.quartz.entity.QuartzJob;
+import org.jeecg.modules.quartz.mapper.QuartzJobMapper;
+import org.jeecg.modules.quartz.service.IQuartzJobService;
+import org.quartz.*;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
+
+import java.util.Date;
+import java.util.List;
+
+/**
+ * @Description: 定时任务在线管理
+ * @Author: jeecg-boot
+ * @Date: 2019-04-28
+ * @Version: V1.1
+ */
+@Slf4j
+@Service
+public class QuartzJobServiceImpl extends ServiceImpl<QuartzJobMapper, QuartzJob> implements IQuartzJobService {
+	@Autowired
+	private QuartzJobMapper quartzJobMapper;
+	@Autowired
+	private Scheduler scheduler;
+
+	/**
+	 * 立即执行的任务分组
+	 */
+	private static final String JOB_TEST_GROUP = "test_group";
+
+	@Override
+	public List<QuartzJob> findByJobClassName(String jobClassName) {
+		return quartzJobMapper.findByJobClassName(jobClassName);
+	}
+
+	/**
+	 * 保存&启动定时任务
+	 */
+	@Override
+	@Transactional(rollbackFor = JeecgBootException.class)
+	public boolean saveAndScheduleJob(QuartzJob quartzJob) {
+		// DB设置修改
+		quartzJob.setDelFlag(CommonConstant.DEL_FLAG_0);
+		boolean success = this.save(quartzJob);
+		if (success) {
+			if (CommonConstant.STATUS_NORMAL.equals(quartzJob.getStatus())) {
+				// 定时器添加
+				this.schedulerAdd(quartzJob.getId(), quartzJob.getJobClassName().trim(), quartzJob.getCronExpression().trim(), quartzJob.getParameter());
+			}
+		}
+		return success;
+	}
+
+	/**
+	 * 恢复定时任务
+	 */
+	@Override
+	@Transactional(rollbackFor = JeecgBootException.class)
+	public boolean resumeJob(QuartzJob quartzJob) {
+		schedulerDelete(quartzJob.getId());
+		schedulerAdd(quartzJob.getId(), quartzJob.getJobClassName().trim(), quartzJob.getCronExpression().trim(), quartzJob.getParameter());
+		quartzJob.setStatus(CommonConstant.STATUS_NORMAL);
+		return this.updateById(quartzJob);
+	}
+
+	/**
+	 * 编辑&启停定时任务
+	 * @throws SchedulerException 
+	 */
+	@Override
+	@Transactional(rollbackFor = JeecgBootException.class)
+	public boolean editAndScheduleJob(QuartzJob quartzJob) throws SchedulerException {
+		if (CommonConstant.STATUS_NORMAL.equals(quartzJob.getStatus())) {
+			schedulerDelete(quartzJob.getId());
+			schedulerAdd(quartzJob.getId(), quartzJob.getJobClassName().trim(), quartzJob.getCronExpression().trim(), quartzJob.getParameter());
+		}else{
+			scheduler.pauseJob(JobKey.jobKey(quartzJob.getId()));
+		}
+		return this.updateById(quartzJob);
+	}
+
+	/**
+	 * 删除&停止删除定时任务
+	 */
+	@Override
+	@Transactional(rollbackFor = JeecgBootException.class)
+	public boolean deleteAndStopJob(QuartzJob job) {
+		schedulerDelete(job.getId());
+		boolean ok = this.removeById(job.getId());
+		return ok;
+	}
+
+	@Override
+	public void execute(QuartzJob quartzJob) throws Exception {
+		String jobName = quartzJob.getJobClassName().trim();
+		Date startDate = new Date();
+		String ymd = DateUtils.date2Str(startDate,DateUtils.yyyymmddhhmmss.get());
+		String identity =  jobName + ymd;
+		//3秒后执行 只执行一次
+		// update-begin--author:sunjianlei ---- date:20210511--- for:定时任务立即执行,延迟3秒改成0.1秒-------
+		startDate.setTime(startDate.getTime() + 100L);
+		// update-end--author:sunjianlei ---- date:20210511--- for:定时任务立即执行,延迟3秒改成0.1秒-------
+		// 定义一个Trigger
+		SimpleTrigger trigger = (SimpleTrigger)TriggerBuilder.newTrigger()
+				.withIdentity(identity, JOB_TEST_GROUP)
+				.startAt(startDate)
+				.build();
+		// 构建job信息
+		JobDetail jobDetail = JobBuilder.newJob(getClass(jobName).getClass()).withIdentity(identity).usingJobData("parameter", quartzJob.getParameter()).build();
+		// 将trigger和 jobDetail 加入这个调度
+		scheduler.scheduleJob(jobDetail, trigger);
+		// 启动scheduler
+		scheduler.start();
+	}
+
+	@Override
+	@Transactional(rollbackFor = JeecgBootException.class)
+	public void pause(QuartzJob quartzJob){
+		schedulerDelete(quartzJob.getId());
+		quartzJob.setStatus(CommonConstant.STATUS_DISABLE);
+		this.updateById(quartzJob);
+	}
+
+	/**
+	 * 添加定时任务
+	 *
+	 * @param jobClassName
+	 * @param cronExpression
+	 * @param parameter
+	 */
+	private void schedulerAdd(String id, String jobClassName, String cronExpression, String parameter) {
+		try {
+			// 启动调度器
+			scheduler.start();
+
+			// 构建job信息
+			JobDetail jobDetail = JobBuilder.newJob(getClass(jobClassName).getClass()).withIdentity(id).usingJobData("parameter", parameter).build();
+
+			// 表达式调度构建器(即任务执行的时间)
+			CronScheduleBuilder scheduleBuilder = CronScheduleBuilder.cronSchedule(cronExpression);
+
+			// 按新的cronExpression表达式构建一个新的trigger
+			CronTrigger trigger = TriggerBuilder.newTrigger().withIdentity(id).withSchedule(scheduleBuilder).build();
+
+			scheduler.scheduleJob(jobDetail, trigger);
+		} catch (SchedulerException e) {
+			throw new JeecgBootException("创建定时任务失败", e);
+		} catch (RuntimeException e) {
+			throw new JeecgBootException(e.getMessage(), e);
+		}catch (Exception e) {
+			throw new JeecgBootException("后台找不到该类名:" + jobClassName, e);
+		}
+	}
+
+	/**
+	 * 删除定时任务
+	 * 
+	 * @param id
+	 */
+	private void schedulerDelete(String id) {
+		try {
+			scheduler.pauseTrigger(TriggerKey.triggerKey(id));
+			scheduler.unscheduleJob(TriggerKey.triggerKey(id));
+			scheduler.deleteJob(JobKey.jobKey(id));
+		} catch (Exception e) {
+			log.error(e.getMessage(), e);
+			throw new JeecgBootException("删除定时任务失败");
+		}
+	}
+
+	private static Job getClass(String classname) throws Exception {
+		Class<?> class1 = Class.forName(classname);
+		return (Job) class1.newInstance();
+	}
+
+}

+ 1 - 1
zgztBus/jeecg-module-system/jeecg-system-start/src/main/resources/application-dev.yml

@@ -17,7 +17,7 @@ management:
   endpoints:
     web:
       exposure:
-        include: metrics,httptrace
+        include: metrics,httptrace-new
 
 spring:
   influx:

+ 2 - 1
zgztBus/jeecg-server-cloud/jeecg-cloud-nacos/docs/config/jeecg-gateway-router.json

@@ -62,7 +62,8 @@
       "_genkey_1": "/events/**",
       "_genkey_2": "/expressio/**",
       "_genkey_3": "/device/deviceInformation/**",
-      "_genkey_4": "/device/deviceRegion/**"
+      "_genkey_4": "/device/deviceRegion/**",
+      "_genkey_5": "/homePageData/**"
     }
   }],
   "filters": [],