Quellcode durchsuchen

Merge branch 'master' of http://39.98.38.2:13000/dumingliang/sh-model-platform

Hua vor 3 Monaten
Ursprung
Commit
10b87e6e4f
35 geänderte Dateien mit 1286 neuen und 108 gelöschten Zeilen
  1. 2 2
      ruoyi-api-patform/src/main/java/com/ruoyi/interfaces/controller/GatewayRoutesController.java
  2. 2 14
      ruoyi-api-patform/src/main/java/com/ruoyi/interfaces/controller/PtAppController.java
  3. 11 0
      ruoyi-api-patform/src/main/java/com/ruoyi/interfaces/controller/web/SnailJobController.java
  4. 0 2
      ruoyi-api-patform/src/main/java/com/ruoyi/interfaces/domain/GatewayRoutes.java
  5. 51 0
      ruoyi-api-patform/src/main/java/com/ruoyi/interfaces/domain/job/BaseQueryVO.java
  6. 74 0
      ruoyi-api-patform/src/main/java/com/ruoyi/interfaces/domain/job/DashboardLineResponseVO.java
  7. 14 0
      ruoyi-api-patform/src/main/java/com/ruoyi/interfaces/domain/job/JobLineQueryVo.java
  8. 88 0
      ruoyi-api-patform/src/main/java/com/ruoyi/interfaces/domain/job/JobSummary.java
  9. 22 0
      ruoyi-api-patform/src/main/java/com/ruoyi/interfaces/domain/job/JobTask.java
  10. 18 0
      ruoyi-api-patform/src/main/java/com/ruoyi/interfaces/domain/job/LineQueryVO.java
  11. 76 0
      ruoyi-api-patform/src/main/java/com/ruoyi/interfaces/enums/DashboardLineEnum.java
  12. 128 0
      ruoyi-api-patform/src/main/java/com/ruoyi/interfaces/enums/DateTypeEnum.java
  13. 16 2
      ruoyi-api-patform/src/main/java/com/ruoyi/interfaces/mapper/GatewayRoutesMapper.java
  14. 26 0
      ruoyi-api-patform/src/main/java/com/ruoyi/interfaces/mapper/JobSummaryMapper.java
  15. 17 4
      ruoyi-api-patform/src/main/java/com/ruoyi/interfaces/mapper/PtAppMapper.java
  16. 8 2
      ruoyi-api-patform/src/main/java/com/ruoyi/interfaces/mapper/PtServiceLogMapper.java
  17. 23 2
      ruoyi-api-patform/src/main/java/com/ruoyi/interfaces/service/GatewayRoutesService.java
  18. 11 10
      ruoyi-api-patform/src/main/java/com/ruoyi/interfaces/service/IPtServiceLogService.java
  19. 23 4
      ruoyi-api-patform/src/main/java/com/ruoyi/interfaces/service/PtAppService.java
  20. 7 0
      ruoyi-api-patform/src/main/java/com/ruoyi/interfaces/service/SnailJobService.java
  21. 38 0
      ruoyi-api-patform/src/main/java/com/ruoyi/interfaces/service/convert/JobSummaryResponseVOConverter.java
  22. 34 2
      ruoyi-api-patform/src/main/java/com/ruoyi/interfaces/service/impl/GatewayRoutesServiceImpl.java
  23. 37 4
      ruoyi-api-patform/src/main/java/com/ruoyi/interfaces/service/impl/PtAppServiceImpl.java
  24. 6 3
      ruoyi-api-patform/src/main/java/com/ruoyi/interfaces/service/impl/PtServiceLogServiceImpl.java
  25. 38 0
      ruoyi-api-patform/src/main/java/com/ruoyi/interfaces/service/impl/SnailJobServiceImpl.java
  26. 28 0
      ruoyi-api-patform/src/main/java/com/ruoyi/interfaces/utils/DbUtils.java
  27. 110 0
      ruoyi-api-patform/src/main/resources/mapper/interfaces/GatewayRoutesMapper.xml
  28. 64 0
      ruoyi-api-patform/src/main/resources/mapper/interfaces/JobSummaryMapper.xml
  29. 137 0
      ruoyi-api-patform/src/main/resources/mapper/interfaces/PtAppMapper.xml
  30. 4 0
      ruoyi-api-patform/src/main/resources/mapper/interfaces/PtServiceLogMapper.xml
  31. 14 3
      ruoyi-common/src/main/java/com/ruoyi/common/enums/DbTypeEnum.java
  32. 15 0
      ruoyi-ui/src/api/service/timing.js
  33. 139 53
      ruoyi-ui/src/views/monitor/taskMonitor/index.vue
  34. 0 1
      ruoyi-ui/src/views/standardization/bizDataShowConfig/show/index.vue
  35. 5 0
      ruoyi-ui/vite.config.js

+ 2 - 2
ruoyi-api-patform/src/main/java/com/ruoyi/interfaces/controller/GatewayRoutesController.java

@@ -58,7 +58,7 @@ public class GatewayRoutesController extends BaseController {
         QueryWrapper<GatewayRoutes> queryWrapper = new QueryWrapper<>();
         queryWrapper.eq(StringUtils.isNotBlank(gatewayRoutes.getStatus()), "status", gatewayRoutes.getStatus())
                 .like(StringUtils.isNotBlank(gatewayRoutes.getServiceName()), "service_name", gatewayRoutes.getServiceName());
-        List<GatewayRoutes> list = gatewayRoutesService.list(queryWrapper);
+        List<GatewayRoutes> list = gatewayRoutesService.list(gatewayRoutes);
         return getDataTable(list);
     }
 
@@ -68,7 +68,7 @@ public class GatewayRoutesController extends BaseController {
         QueryWrapper<GatewayRoutes> queryWrapper = new QueryWrapper<>();
         queryWrapper.eq("status", "0")
                 .like(StringUtils.isNotBlank(gatewayRoutes.getServiceName()), "service_name", gatewayRoutes.getServiceName());
-        return AjaxResult.success(gatewayRoutesService.list(queryWrapper));
+        return AjaxResult.success(gatewayRoutesService.list(gatewayRoutes));
     }
 
 }

+ 2 - 14
ruoyi-api-patform/src/main/java/com/ruoyi/interfaces/controller/PtAppController.java

@@ -1,18 +1,15 @@
 package com.ruoyi.interfaces.controller;
 
-import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
 import com.ruoyi.common.core.controller.BaseController;
 import com.ruoyi.common.core.domain.AjaxResult;
 import com.ruoyi.common.core.page.TableDataInfo;
 import com.ruoyi.interfaces.domain.PtApp;
 import com.ruoyi.interfaces.service.PtAppService;
 import io.swagger.annotations.ApiOperation;
-import org.apache.commons.lang3.StringUtils;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.web.bind.annotation.*;
 
 import java.util.Arrays;
-import java.util.Optional;
 
 @RestController
 @RequestMapping("/pt/app")
@@ -43,21 +40,12 @@ public class PtAppController extends BaseController {
     @ApiOperation("查询所有应用")
     @GetMapping(value = "/list")
     public TableDataInfo list(PtApp ptApp) {
-        QueryWrapper<PtApp> queryWrapper = new QueryWrapper<>();
-        queryWrapper
-                .eq("user_id", getUserId())
-                .like(StringUtils.isNotBlank(ptApp.getAppName()), "app_name", ptApp.getAppName());
-        startPage();
-        return getDataTable(ptAppService.list(queryWrapper));
+        return getDataTable(ptAppService.list(ptApp));
     }
 
     @ApiOperation("查询所有应用")
     @PostMapping(value = "/lists")
     public AjaxResult lists(PtApp ptApp) {
-        QueryWrapper<PtApp> queryWrapper = new QueryWrapper<>();
-        queryWrapper
-                .eq("user_id", getUserId())
-                .like(StringUtils.isNotBlank(ptApp.getAppName()), "app_name", ptApp.getAppName());
-        return AjaxResult.success(ptAppService.list(queryWrapper));
+        return AjaxResult.success(ptAppService.list(ptApp));
     }
 }

+ 11 - 0
ruoyi-api-patform/src/main/java/com/ruoyi/interfaces/controller/web/SnailJobController.java

@@ -6,6 +6,7 @@ import com.ruoyi.common.core.controller.BaseController;
 import com.ruoyi.common.core.domain.AjaxResult;
 import com.ruoyi.common.core.page.TableDataInfo;
 import com.ruoyi.interfaces.domain.Job;
+import com.ruoyi.interfaces.domain.job.JobLineQueryVo;
 import com.ruoyi.interfaces.domain.vo.JobRequestVo;
 import com.ruoyi.interfaces.service.SnailJobService;
 import org.springframework.beans.factory.annotation.Autowired;
@@ -170,4 +171,14 @@ public class SnailJobController extends BaseController {
         return success(false);
     }
 
+    @GetMapping("/task-retry-job")
+    public AjaxResult taskRetryJob() {
+        return AjaxResult.success(snailJobService.taskRetryJob());
+    }
+
+    @GetMapping("/line")
+    public AjaxResult jobLineList(JobLineQueryVo queryVO) {
+        return AjaxResult.success(snailJobService.jobLineList(queryVO));
+    }
+
 }

+ 0 - 2
ruoyi-api-patform/src/main/java/com/ruoyi/interfaces/domain/GatewayRoutes.java

@@ -1,12 +1,10 @@
 package com.ruoyi.interfaces.domain;
 
-import com.baomidou.mybatisplus.annotation.TableName;
 import lombok.Data;
 
 import java.io.Serializable;
 
 @Data
-@TableName
 public class GatewayRoutes implements Serializable {
 
     private String id;

+ 51 - 0
ruoyi-api-patform/src/main/java/com/ruoyi/interfaces/domain/job/BaseQueryVO.java

@@ -0,0 +1,51 @@
+package com.ruoyi.interfaces.domain.job;
+
+import cn.hutool.core.util.ObjUtil;
+import lombok.Data;
+
+import java.time.LocalDateTime;
+
+/**
+ * @author opensnail
+ * @date 2022-02-27
+ * @since 2.0
+ */
+@Data
+@Deprecated
+public class BaseQueryVO {
+
+    /**
+     * 当前页码
+     */
+    private int page = 1;
+
+    /**
+     * 每页条数
+     */
+    private int size = 10;
+
+    /**
+     * 时间区间, 用于筛选 createDt 字段,
+     * 前端传入使用 SpringBoot 默认 ISO 8601 格式: yyyy-MM-dd'T'HH:mm:ss
+     */
+    private LocalDateTime[] datetimeRange;
+
+    /**
+     * 起始时间
+     *
+     * @return 起始时间
+     */
+    public LocalDateTime getStartDt() {
+        return ObjUtil.isEmpty(datetimeRange) ? null : datetimeRange[0];
+    }
+
+    /**
+     * 结束时间
+     *
+     * @return 结束时间
+     */
+    public LocalDateTime getEndDt() {
+        return ObjUtil.isEmpty(datetimeRange) ? null : datetimeRange[1];
+    }
+
+}

+ 74 - 0
ruoyi-api-patform/src/main/java/com/ruoyi/interfaces/domain/job/DashboardLineResponseVO.java

@@ -0,0 +1,74 @@
+package com.ruoyi.interfaces.domain.job;
+
+import lombok.Data;
+import lombok.experimental.Accessors;
+
+/**
+ * @author: wodeyangzipingpingwuqi
+ * @date : 2023-11-30
+ */
+@Data
+@Accessors(chain = true)
+public class DashboardLineResponseVO {
+
+    /**
+     * 时间x轴
+     */
+    private String createDt;
+
+    /**
+     * 总量,计算百分比
+     */
+    private Long total;
+
+    /**
+     * 重试-成功数
+     */
+    private Long successNum;
+
+    /**
+     * 重试-运行数
+     */
+    private Long runningNum;
+
+    /**
+     * 重试-最大次数
+     */
+    private Long maxCountNum;
+
+    /**
+     * 重试-暂停数
+     */
+    private Long suspendNum;
+
+    /**
+     * 定时-失败任务
+     */
+    private Long fail;
+
+    /**
+     * 定时-总任务数
+     */
+    private Long totalNum;
+
+    /**
+     * 定时-无效任务数
+     */
+    private Long failNum;
+
+    /**
+     * 定时-停止数
+     */
+    private Long stop;
+
+    /**
+     * 定时-取消数
+     */
+    private Long cancel;
+
+    /**
+     * 定时-成功数
+     */
+    private Long success;
+
+}

+ 14 - 0
ruoyi-api-patform/src/main/java/com/ruoyi/interfaces/domain/job/JobLineQueryVo.java

@@ -0,0 +1,14 @@
+package com.ruoyi.interfaces.domain.job;
+
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+
+@Data
+@EqualsAndHashCode(callSuper = true)
+public class JobLineQueryVo extends LineQueryVO {
+    /**
+     * 系统模式
+     *
+     */
+    private String mode;
+}

+ 88 - 0
ruoyi-api-patform/src/main/java/com/ruoyi/interfaces/domain/job/JobSummary.java

@@ -0,0 +1,88 @@
+package com.ruoyi.interfaces.domain.job;
+
+import com.baomidou.mybatisplus.annotation.IdType;
+import com.baomidou.mybatisplus.annotation.TableId;
+import lombok.Data;
+
+import java.time.LocalDateTime;
+
+/**
+ * 任务统计
+ *
+ * @author zhengweilin
+ * @version 2.6.0
+ * @date 2023/11/22
+ */
+@Data
+public class JobSummary {
+
+    /**
+     * 命名空间
+     */
+    private String namespaceId;
+
+    /**
+     * 组名
+     */
+    private String groupName;
+
+    /**
+     * 主键
+     */
+    @TableId(value = "id", type = IdType.AUTO)
+    private Long id;
+
+    /**
+     * '任务信息id'
+     */
+    private Long businessId;
+
+    /**
+     * '统计时间'
+     */
+    private LocalDateTime triggerAt;
+
+    /**
+     * 执行成功-日志数量
+     */
+    private Integer successNum;
+
+    /**
+     * 执行失败-日志数量
+     */
+    private Integer failNum;
+
+    /**
+     * 失败原因
+     */
+    private String failReason;
+
+    /**
+     * 执行失败-日志数量
+     */
+    private Integer stopNum;
+
+    /**
+     * 失败原因
+     */
+    private String stopReason;
+
+    /**
+     * 执行失败-日志数量
+     */
+    private Integer cancelNum;
+
+    /**
+     * 失败原因
+     */
+    private String cancelReason;
+
+    /**
+     * 任务类型 3、JOB任务 4、WORKFLOW任务
+     */
+    private Integer systemTaskType;
+
+    private LocalDateTime startTime;
+    private LocalDateTime endTime;
+    private String dateFormat;
+}

+ 22 - 0
ruoyi-api-patform/src/main/java/com/ruoyi/interfaces/domain/job/JobTask.java

@@ -0,0 +1,22 @@
+package com.ruoyi.interfaces.domain.job;
+
+import lombok.Data;
+
+import java.math.BigDecimal;
+
+
+@Data
+public class JobTask {
+    //成功
+    private Integer successNum;
+    //失败
+    private Integer failNum;
+    //取消
+    private Integer cancelNum;
+    //停止
+    private Integer stopNum;
+    // 总数
+    private Integer totalNum;
+    // 成功率
+    private BigDecimal successRate;
+}

+ 18 - 0
ruoyi-api-patform/src/main/java/com/ruoyi/interfaces/domain/job/LineQueryVO.java

@@ -0,0 +1,18 @@
+package com.ruoyi.interfaces.domain.job;
+
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+
+@Data
+@EqualsAndHashCode(callSuper = true)
+public class LineQueryVO extends BaseQueryVO {
+    /**
+     * 组名称
+     */
+    private String groupName;
+
+    /**
+     * 时间间隔类型
+     */
+    private String type = "WEEK";
+}

+ 76 - 0
ruoyi-api-patform/src/main/java/com/ruoyi/interfaces/enums/DashboardLineEnum.java

@@ -0,0 +1,76 @@
+package com.ruoyi.interfaces.enums;
+
+import lombok.AllArgsConstructor;
+import lombok.Getter;
+
+/**
+ * 年、月、日
+ *
+ * @author zhengweilin
+ * @version 1.0.0
+ * @date 2024/03/26
+ */
+@AllArgsConstructor
+@Getter
+public enum DashboardLineEnum {
+    DAY("DAY"),
+    WEEK("WEEK"),
+    MONTH("MONTH"),
+    YEAR("YEAR"),
+    ;
+
+    private final String unit;
+
+    public static DashboardLineEnum modeOf(String mode) {
+        for (DashboardLineEnum value : DashboardLineEnum.values()) {
+            if (value.getUnit().equals(mode)) {
+                return value;
+            }
+        }
+
+        return DashboardLineEnum.WEEK;
+    }
+
+    public static String dateFormat(String unit) {
+        DashboardLineEnum mode = modeOf(unit);
+
+//        if (DbUtils.getDbType().equals(DbTypeEnum.MY_SQL)) {
+//            switch (mode) {
+//                case YEAR:
+//                    return "%Y-%m";
+//                case DAY:
+//                    return "%H";
+//                default:
+//                    return "%Y-%m-%d";
+//            }
+//        } else if (DbUtils.getDbType().equals(DbTypeEnum.MARIADB)) {
+//            switch (mode) {
+//                case YEAR:
+//                    return "%Y-%m";
+//                case DAY:
+//                    return "%H";
+//                default:
+//                    return "%Y-%m-%d";
+//            }
+//        } else if (DbUtils.getDbType().equals(DbTypeEnum.SQL_SERVER)) {
+//            switch (mode) {
+//                case YEAR:
+//                    return "yyyy-MM";
+//                case DAY:
+//                    return "HH";
+//                default:
+//                    return "yyyy-MM-dd";
+//            }
+//        } else { // Oracle, Postgres, DM, Kingbase
+            switch (mode) {
+                case YEAR:
+                    return "yyyy-MM";
+                case DAY:
+                    return "HH24";
+                default:
+                    return "yyyy-MM-dd";
+            }
+//        }
+    }
+
+}

+ 128 - 0
ruoyi-api-patform/src/main/java/com/ruoyi/interfaces/enums/DateTypeEnum.java

@@ -0,0 +1,128 @@
+package com.ruoyi.interfaces.enums;
+
+import cn.hutool.core.date.LocalDateTimeUtil;
+import com.aizuda.snailjob.common.core.util.StreamUtils;
+import com.ruoyi.interfaces.domain.job.DashboardLineResponseVO;
+import lombok.AllArgsConstructor;
+import lombok.Getter;
+
+import java.time.LocalDate;
+import java.time.LocalDateTime;
+import java.time.format.DateTimeFormatter;
+import java.time.temporal.TemporalAdjusters;
+import java.util.List;
+import java.util.Map;
+import java.util.function.Consumer;
+import java.util.function.Function;
+
+/**
+ * @author: byteblogs
+ * @date: 2020/1/19 20:36
+ */
+@AllArgsConstructor
+@Getter
+public enum DateTypeEnum {
+    /**
+     * 天(按小时)
+     */
+    DAY(
+            voList -> {
+                Map<String, DashboardLineResponseVO> responseVoMap = StreamUtils.toIdentityMap(voList,
+                        DashboardLineResponseVO::getCreateDt);
+                int hourNow = LocalDateTime.now().getHour();
+                for (int hourOffset = 0; hourOffset <= hourNow; hourOffset++) {
+                    String createDt = LocalDateTime.now().plusHours(hourOffset).format(DateTimeFormatter.ofPattern("HH"));
+                    if (!responseVoMap.containsKey(createDt)) {
+                        voList.add(buildZeroedVoWithCreateDt(createDt));
+                    }
+                }
+            },
+            (startTime) -> LocalDateTimeUtil.beginOfDay(startTime),
+            (endTime) -> LocalDateTimeUtil.endOfDay(endTime)
+    ),
+
+    /**
+     * 周
+     */
+    WEEK(
+            voList -> {
+                Map<String, DashboardLineResponseVO> responseVoMap = StreamUtils.toIdentityMap(
+                        voList, DashboardLineResponseVO::getCreateDt);
+                for (int dayOffset = 0; dayOffset < 7; dayOffset++) {
+                    String createDt = LocalDateTime.now().minusDays(dayOffset).format(DateTimeFormatter.ofPattern("yyyy-MM-dd"));
+                    if (!responseVoMap.containsKey(createDt)) {
+                        voList.add(buildZeroedVoWithCreateDt(createDt));
+                    }
+                }
+            },
+            (startTime) -> LocalDateTimeUtil.beginOfDay(startTime).minusDays(7),
+            (endTime) -> LocalDateTimeUtil.endOfDay(endTime)
+    ),
+
+    /**
+     * 月
+     */
+    MONTH(
+            voList -> {
+                Map<String, DashboardLineResponseVO> responseVoMap = StreamUtils.toIdentityMap(
+                        voList, DashboardLineResponseVO::getCreateDt);
+                int lastDayOfMonth = LocalDateTime.now().with(TemporalAdjusters.lastDayOfMonth()).getDayOfMonth();
+                for (int dayOffset = 0; dayOffset < lastDayOfMonth; dayOffset++) {
+                    String createDt = LocalDate.now().minusDays(dayOffset).format(DateTimeFormatter.ofPattern("yyyy-MM-dd"));
+                    if (!responseVoMap.containsKey(createDt)) {
+                        voList.add(buildZeroedVoWithCreateDt(createDt));
+                    }
+                }
+            },
+            (startTime) -> LocalDateTimeUtil.beginOfDay(startTime).minusMonths(1),
+            (endTime) -> LocalDateTimeUtil.endOfDay(endTime)
+    ),
+
+    /**
+     * 年
+     */
+    YEAR(
+            voList -> {
+                Map<String, DashboardLineResponseVO> responseVoMap = StreamUtils.toIdentityMap(
+                        voList, DashboardLineResponseVO::getCreateDt);
+                for (int monthOffset = 0; monthOffset < 12; monthOffset++) {
+                    String createDt = LocalDateTime.now().minusMonths(monthOffset).format(DateTimeFormatter.ofPattern("yyyy-MM"));
+                    if (!responseVoMap.containsKey(createDt)) {
+                        voList.add(buildZeroedVoWithCreateDt(createDt));
+                    }
+                }
+            },
+            (startTime) -> LocalDateTimeUtil.beginOfDay(LocalDateTime.now().with(TemporalAdjusters.firstDayOfYear())),
+            (endTime) -> LocalDateTimeUtil.endOfDay(LocalDateTime.now().with(TemporalAdjusters.lastDayOfYear()))
+    ),
+
+    /**
+     * 其他类型
+     */
+    OTHERS(
+            voList -> {
+            },
+            (startTime) -> LocalDateTimeUtil.beginOfDay(startTime),
+            (endTime) -> LocalDateTimeUtil.endOfDay(endTime));
+
+    private Consumer<List<DashboardLineResponseVO>> consumer;
+    private Function<LocalDateTime, LocalDateTime> startTime;
+    private Function<LocalDateTime, LocalDateTime> endTime;
+
+    private static DashboardLineResponseVO buildZeroedVoWithCreateDt(String createDt) {
+        return new DashboardLineResponseVO()
+                .setTotal(0L)
+                .setTotalNum(0L)
+                .setFail(0L)
+                .setFailNum(0L)
+                .setMaxCountNum(0L)
+                .setRunningNum(0L)
+                .setSuccess(0L)
+                .setSuccessNum(0L)
+                .setSuspendNum(0L)
+                .setStop(0L)
+                .setCancel(0L)
+                .setCreateDt(createDt);
+    }
+
+}

+ 16 - 2
ruoyi-api-patform/src/main/java/com/ruoyi/interfaces/mapper/GatewayRoutesMapper.java

@@ -1,9 +1,23 @@
 package com.ruoyi.interfaces.mapper;
 
-import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.ruoyi.common.annotation.DataSource;
+import com.ruoyi.common.enums.DataSourceType;
 import com.ruoyi.interfaces.domain.GatewayRoutes;
+import org.apache.ibatis.annotations.Mapper;
 
-public interface GatewayRoutesMapper extends BaseMapper<GatewayRoutes> {
+import java.util.List;
 
+@Mapper
+@DataSource(DataSourceType.SLAVE)
+public interface GatewayRoutesMapper {
 
+    int insert(GatewayRoutes entity);
+
+    int update(GatewayRoutes entity);
+
+    GatewayRoutes get(String id);
+
+    int delete(String id);
+
+    List<GatewayRoutes> findList(GatewayRoutes entity);
 }

+ 26 - 0
ruoyi-api-patform/src/main/java/com/ruoyi/interfaces/mapper/JobSummaryMapper.java

@@ -0,0 +1,26 @@
+package com.ruoyi.interfaces.mapper;
+
+import com.ruoyi.common.annotation.DataSource;
+import com.ruoyi.common.enums.DataSourceType;
+import com.ruoyi.interfaces.domain.job.DashboardLineResponseVO;
+import com.ruoyi.interfaces.domain.job.JobSummary;
+import com.ruoyi.interfaces.domain.job.JobTask;
+import org.apache.ibatis.annotations.Mapper;
+
+import java.util.List;
+
+/**
+ * @author zhengweilin
+ * @version 2.6.0
+ * @date 2023/11/22
+ */
+@Mapper
+@DataSource(DataSourceType.JOB)
+public interface JobSummaryMapper {
+
+    List<DashboardLineResponseVO> selectJobLineList(JobSummary jobSummary);
+
+
+    JobTask selectJobTask(JobSummary jobSummary);
+
+}

+ 17 - 4
ruoyi-api-patform/src/main/java/com/ruoyi/interfaces/mapper/PtAppMapper.java

@@ -1,14 +1,27 @@
 package com.ruoyi.interfaces.mapper;
 
 
-import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.ruoyi.common.annotation.DataSource;
+import com.ruoyi.common.enums.DataSourceType;
 import com.ruoyi.interfaces.domain.PtApp;
+import org.apache.ibatis.annotations.Mapper;
 import org.apache.ibatis.annotations.Param;
-import org.springframework.stereotype.Repository;
 
 import java.util.List;
 
-@Repository
-public interface PtAppMapper extends BaseMapper<PtApp> {
+@Mapper
+@DataSource(DataSourceType.SLAVE)
+public interface PtAppMapper {
 
+    int insert(PtApp entity);
+
+    int update(PtApp entity);
+
+    PtApp get(String id);
+
+    int delete(String id);
+
+    List<PtApp> findList(PtApp entity);
+
+    List<PtApp> findListByIds(@Param("ids") List<String> ids);
 }

+ 8 - 2
ruoyi-api-patform/src/main/java/com/ruoyi/interfaces/mapper/PtServiceLogMapper.java

@@ -1,9 +1,11 @@
 package com.ruoyi.interfaces.mapper;
 
-import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.ruoyi.common.annotation.DataSource;
+import com.ruoyi.common.enums.DataSourceType;
 import com.ruoyi.interfaces.domain.PtServiceLog;
 import com.ruoyi.interfaces.domain.PtServiceLogStatis;
 import com.ruoyi.interfaces.domain.vo.PtServiceLogStatisVo;
+import org.apache.ibatis.annotations.Mapper;
 
 import java.util.List;
 
@@ -13,7 +15,9 @@ import java.util.List;
  * @author 朱得糠
  * @date 2025-09-01
  */
-public interface PtServiceLogMapper extends BaseMapper<PtServiceLog>
+@Mapper
+@DataSource(DataSourceType.SLAVE)
+public interface PtServiceLogMapper
 {
     /**
      * 查询服务调用日志
@@ -70,4 +74,6 @@ public interface PtServiceLogMapper extends BaseMapper<PtServiceLog>
      * @return
      */
     List<PtServiceLogStatisVo> selectServiceLogStatis(PtServiceLogStatis serviceLogStatis);
+
+    Long count();
 }

+ 23 - 2
ruoyi-api-patform/src/main/java/com/ruoyi/interfaces/service/GatewayRoutesService.java

@@ -1,9 +1,30 @@
 package com.ruoyi.interfaces.service;
 
-import com.baomidou.mybatisplus.extension.service.IService;
+import com.ruoyi.common.utils.StringUtils;
 import com.ruoyi.interfaces.domain.GatewayRoutes;
 
-public interface GatewayRoutesService extends IService<GatewayRoutes> {
+import java.util.List;
+
+public interface GatewayRoutesService  {
+
+    default boolean saveOrUpdate(GatewayRoutes gatewayRoutes) {
+        if (StringUtils.isNotBlank(gatewayRoutes.getId())) {
+            return updateById(gatewayRoutes);
+        }
+
+        return save(gatewayRoutes);
+    }
+
+    boolean save(GatewayRoutes gatewayRoutes);
+
+    boolean updateById(GatewayRoutes gatewayRoutes);
+
+    GatewayRoutes getById(String id);
+
+    boolean removeById(String id);
+
+    List<GatewayRoutes> list(GatewayRoutes gatewayRoutes);
+
 
     void refreshRoutes();
 

+ 11 - 10
ruoyi-api-patform/src/main/java/com/ruoyi/interfaces/service/IPtServiceLogService.java

@@ -1,6 +1,5 @@
 package com.ruoyi.interfaces.service;
 
-import com.baomidou.mybatisplus.extension.service.IService;
 import com.ruoyi.interfaces.domain.PtServiceLog;
 import com.ruoyi.interfaces.domain.PtServiceLogStatis;
 import com.ruoyi.interfaces.domain.vo.PtServiceLogStatisVo;
@@ -9,15 +8,14 @@ import java.util.List;
 
 /**
  * 服务调用日志Service接口
- * 
+ *
  * @author 朱得糠
  * @date 2025-09-01
  */
-public interface IPtServiceLogService extends IService<PtServiceLog>
-{
+public interface IPtServiceLogService {
     /**
      * 查询服务调用日志
-     * 
+     *
      * @param logId 服务调用日志主键
      * @return 服务调用日志
      */
@@ -25,7 +23,7 @@ public interface IPtServiceLogService extends IService<PtServiceLog>
 
     /**
      * 查询服务调用日志列表
-     * 
+     *
      * @param ptServiceLog 服务调用日志
      * @return 服务调用日志集合
      */
@@ -33,7 +31,7 @@ public interface IPtServiceLogService extends IService<PtServiceLog>
 
     /**
      * 新增服务调用日志
-     * 
+     *
      * @param ptServiceLog 服务调用日志
      * @return 结果
      */
@@ -41,7 +39,7 @@ public interface IPtServiceLogService extends IService<PtServiceLog>
 
     /**
      * 修改服务调用日志
-     * 
+     *
      * @param ptServiceLog 服务调用日志
      * @return 结果
      */
@@ -49,7 +47,7 @@ public interface IPtServiceLogService extends IService<PtServiceLog>
 
     /**
      * 批量删除服务调用日志
-     * 
+     *
      * @param logIds 需要删除的服务调用日志主键集合
      * @return 结果
      */
@@ -57,11 +55,14 @@ public interface IPtServiceLogService extends IService<PtServiceLog>
 
     /**
      * 删除服务调用日志信息
-     * 
+     *
      * @param logId 服务调用日志主键
      * @return 结果
      */
     public int deletePtServiceLogByLogId(Long logId);
 
     List<PtServiceLogStatisVo> selectServiceLogStatis(PtServiceLogStatis serviceLogStatis);
+
+    Long count();
+
 }

+ 23 - 4
ruoyi-api-patform/src/main/java/com/ruoyi/interfaces/service/PtAppService.java

@@ -1,8 +1,6 @@
 package com.ruoyi.interfaces.service;
 
-import com.baomidou.mybatisplus.extension.service.IService;
-import com.ruoyi.interfaces.core.page.Page;
-import com.ruoyi.interfaces.core.page.PageParam;
+import com.ruoyi.common.utils.StringUtils;
 import com.ruoyi.interfaces.domain.PtApp;
 
 import java.util.List;
@@ -11,6 +9,27 @@ import java.util.List;
  * @author LinQiLong
  * @date 2022/1/7 10:20
  */
-public interface PtAppService extends IService<PtApp> {
+public interface PtAppService {
 
+    default boolean saveOrUpdate(PtApp ptApp) {
+        if (StringUtils.isNotBlank(ptApp.getAppId())) {
+            return updateById(ptApp);
+        }
+
+        return save(ptApp);
+    }
+
+    boolean save(PtApp ptApp);
+
+    boolean updateById(PtApp ptApp);
+
+    PtApp getById(String id);
+
+    boolean removeById(String id);
+
+    boolean removeBatchByIds(List<String> id);
+
+    List<PtApp> list(PtApp ptApp);
+
+    List<PtApp> listByIds(List<String> ids);
 }

+ 7 - 0
ruoyi-api-patform/src/main/java/com/ruoyi/interfaces/service/SnailJobService.java

@@ -2,6 +2,9 @@ package com.ruoyi.interfaces.service;
 
 import com.ruoyi.interfaces.domain.Job;
 import com.ruoyi.interfaces.domain.JobLogVo;
+import com.ruoyi.interfaces.domain.job.DashboardLineResponseVO;
+import com.ruoyi.interfaces.domain.job.JobLineQueryVo;
+import com.ruoyi.interfaces.domain.job.JobTask;
 import com.ruoyi.interfaces.domain.vo.JobRequestVo;
 
 import java.util.List;
@@ -79,4 +82,8 @@ public interface SnailJobService {
     List<JobLogVo> listOfJobLog(JobRequestVo jobRequestVo);
 
     Map<String, Long> statistics();
+
+    JobTask taskRetryJob();
+
+    List<DashboardLineResponseVO> jobLineList(JobLineQueryVo queryVO);
 }

+ 38 - 0
ruoyi-api-patform/src/main/java/com/ruoyi/interfaces/service/convert/JobSummaryResponseVOConverter.java

@@ -0,0 +1,38 @@
+package com.ruoyi.interfaces.service.convert;
+
+import org.mapstruct.Mapper;
+import org.mapstruct.factory.Mappers;
+
+import java.math.BigDecimal;
+import java.math.RoundingMode;
+import java.util.Objects;
+
+/**
+ * @author zhengweilin
+ * @version 2.6.0
+ * @date 2023/11/24
+ */
+@Mapper
+public interface JobSummaryResponseVOConverter {
+
+    JobSummaryResponseVOConverter INSTANCE = Mappers.getMapper(JobSummaryResponseVOConverter.class);
+
+//    @Mappings({
+//            @Mapping(target = "successRate", expression = "java(JobSummaryResponseVOConverter.toSuccessRate(jobTask.getSuccessNum(), jobTask.getTotalNum()))")
+//    })
+//    JobTask convert(JobTask jobTask);
+
+//    @Mappings({
+//            @Mapping(target = "successRate", expression = "java(JobSummaryResponseVOConverter.toSuccessRate(jobTask.getSuccessNum(), jobTask.getTotalNum()))")
+//    })
+//    WorkFlowTask convertToWorkFlowTask(JobTask jobTask);
+
+//    List<Task> convertList(List<DashboardRetryLineResponseDO.Task> taskList);
+
+    static BigDecimal toSuccessRate(Integer successNum, Integer totalNum) {
+        if (Objects.isNull(totalNum) || totalNum == 0) {
+            return null;
+        }
+        return new BigDecimal(String.valueOf(successNum)).divide(new BigDecimal(String.valueOf(totalNum)), 4, RoundingMode.HALF_UP).multiply(new BigDecimal("100"));
+    }
+}

+ 34 - 2
ruoyi-api-patform/src/main/java/com/ruoyi/interfaces/service/impl/GatewayRoutesServiceImpl.java

@@ -1,22 +1,54 @@
 package com.ruoyi.interfaces.service.impl;
 
-import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
 import com.ruoyi.common.utils.OkHttpUtils;
+import com.ruoyi.common.utils.uuid.IdUtils;
 import com.ruoyi.interfaces.domain.GatewayRoutes;
 import com.ruoyi.interfaces.mapper.GatewayRoutesMapper;
 import com.ruoyi.interfaces.service.GatewayRoutesService;
 import lombok.extern.slf4j.Slf4j;
+import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.beans.factory.annotation.Value;
 import org.springframework.scheduling.annotation.Async;
 import org.springframework.stereotype.Service;
 
+import java.util.List;
+
 @Slf4j
 @Service
-public class GatewayRoutesServiceImpl extends ServiceImpl<GatewayRoutesMapper, GatewayRoutes> implements GatewayRoutesService {
+public class GatewayRoutesServiceImpl implements GatewayRoutesService {
 
     @Value("${sys.gateway.url}")
     private String gatewayUrl;
 
+    @Autowired
+    private GatewayRoutesMapper gatewayRoutesMapper;
+
+    @Override
+    public boolean save(GatewayRoutes entity) {
+        entity.setId(IdUtils.simpleUUID());
+        return gatewayRoutesMapper.insert(entity) > 0;
+    }
+
+    @Override
+    public boolean updateById(GatewayRoutes entity) {
+        return gatewayRoutesMapper.update(entity) > 0;
+    }
+
+    @Override
+    public GatewayRoutes getById(String id) {
+        return gatewayRoutesMapper.get(id);
+    }
+
+    @Override
+    public boolean removeById(String id) {
+        return gatewayRoutesMapper.delete(id) > 0;
+    }
+
+    @Override
+    public List<GatewayRoutes> list(GatewayRoutes gatewayRoutes) {
+        return gatewayRoutesMapper.findList(gatewayRoutes);
+    }
+
     @Async
     public void refreshRoutes() {
         OkHttpUtils.get(gatewayUrl + "/gateway/refresh");

+ 37 - 4
ruoyi-api-patform/src/main/java/com/ruoyi/interfaces/service/impl/PtAppServiceImpl.java

@@ -1,30 +1,63 @@
 package com.ruoyi.interfaces.service.impl;
 
-import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
 import com.ruoyi.common.utils.CheckUtils;
+import com.ruoyi.common.utils.uuid.IdUtils;
 import com.ruoyi.common.utils.uuid.UUID;
 import com.ruoyi.interfaces.domain.PtApp;
 import com.ruoyi.interfaces.mapper.PtAppMapper;
 import com.ruoyi.interfaces.service.PtAppService;
+import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Service;
 
+import java.util.List;
+
 /**
  * @author LinQiLong
  * @date 2022/1/7 10:20
  */
 @Service
-public class PtAppServiceImpl extends ServiceImpl<PtAppMapper, PtApp> implements PtAppService {
+public class PtAppServiceImpl implements PtAppService {
+
+    @Autowired
+    private PtAppMapper ptAppMapper;
 
     @Override
     public boolean save(PtApp entity) {
+        entity.setAppId(IdUtils.simpleUUID());
         entity.setAppSecret(UUID.randomUUID().toString());
-        return super.save(entity);
+        return ptAppMapper.insert(entity) > 0;
     }
 
     @Override
     public boolean updateById(PtApp entity) {
         CheckUtils.notEmpty(entity.getAppId(), "appId.no");
-        return super.updateById(entity);
+        return ptAppMapper.update(entity) > 0;
+    }
+
+    @Override
+    public PtApp getById(String id) {
+        return ptAppMapper.get(id);
+    }
+
+    @Override
+    public boolean removeById(String id) {
+        return ptAppMapper.delete(id) > 0;
+    }
+
+    @Override
+    public boolean removeBatchByIds(List<String> ids) {
+        ids.forEach(this::removeById);
+        return true;
+    }
+
+    @Override
+    public List<PtApp> list(PtApp ptApp) {
+        return ptAppMapper.findList(ptApp);
+    }
+
+    @Override
+    public List<PtApp> listByIds(List<String> ids) {
+        return ptAppMapper.findListByIds(ids);
     }
 
 }

+ 6 - 3
ruoyi-api-patform/src/main/java/com/ruoyi/interfaces/service/impl/PtServiceLogServiceImpl.java

@@ -1,6 +1,5 @@
 package com.ruoyi.interfaces.service.impl;
 
-import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
 import com.ruoyi.interfaces.domain.PtServiceLog;
 import com.ruoyi.interfaces.domain.PtServiceLogStatis;
 import com.ruoyi.interfaces.domain.vo.PtServiceLogStatisVo;
@@ -9,7 +8,6 @@ import com.ruoyi.interfaces.service.IPtServiceLogService;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Service;
 
-import java.util.Collections;
 import java.util.List;
 
 /**
@@ -19,7 +17,7 @@ import java.util.List;
  * @date 2025-09-01
  */
 @Service
-public class PtServiceLogServiceImpl extends ServiceImpl<PtServiceLogMapper, PtServiceLog> implements IPtServiceLogService {
+public class PtServiceLogServiceImpl implements IPtServiceLogService {
 
     @Autowired
     private PtServiceLogMapper ptServiceLogMapper;
@@ -94,4 +92,9 @@ public class PtServiceLogServiceImpl extends ServiceImpl<PtServiceLogMapper, PtS
     public List<PtServiceLogStatisVo> selectServiceLogStatis(PtServiceLogStatis serviceLogStatis) {
         return ptServiceLogMapper.selectServiceLogStatis(serviceLogStatis);
     }
+
+    @Override
+    public Long count() {
+        return ptServiceLogMapper.count();
+    }
 }

+ 38 - 0
ruoyi-api-patform/src/main/java/com/ruoyi/interfaces/service/impl/SnailJobServiceImpl.java

@@ -1,5 +1,6 @@
 package com.ruoyi.interfaces.service.impl;
 
+import cn.hutool.core.util.ObjUtil;
 import com.aizuda.snailjob.client.job.core.enums.AllocationAlgorithmEnum;
 import com.aizuda.snailjob.client.job.core.enums.TriggerTypeEnum;
 import com.aizuda.snailjob.client.job.core.handler.add.BroadcastAddHandler;
@@ -13,13 +14,21 @@ import com.ruoyi.common.utils.DateUtils;
 import com.ruoyi.common.utils.StringUtils;
 import com.ruoyi.interfaces.domain.Job;
 import com.ruoyi.interfaces.domain.JobLogVo;
+import com.ruoyi.interfaces.domain.job.DashboardLineResponseVO;
+import com.ruoyi.interfaces.domain.job.JobLineQueryVo;
+import com.ruoyi.interfaces.domain.job.JobSummary;
+import com.ruoyi.interfaces.domain.job.JobTask;
 import com.ruoyi.interfaces.domain.vo.JobRequestVo;
+import com.ruoyi.interfaces.enums.DashboardLineEnum;
+import com.ruoyi.interfaces.enums.DateTypeEnum;
+import com.ruoyi.interfaces.mapper.JobSummaryMapper;
 import com.ruoyi.interfaces.mapper.SnailJobMapper;
 import com.ruoyi.interfaces.service.SnailJobService;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.beans.factory.annotation.Value;
 import org.springframework.stereotype.Service;
 
+import java.time.LocalDateTime;
 import java.util.*;
 
 @Service
@@ -32,6 +41,9 @@ public class SnailJobServiceImpl implements SnailJobService {
     @Autowired
     private SnailJobMapper snailJobMapper;
 
+    @Autowired
+    private JobSummaryMapper jobSummaryMapper;
+
     @Override
     public List<Job> selectJobList(Job jobRequestVo) {
         jobRequestVo.setGroupName(groupName);
@@ -314,4 +326,30 @@ public class SnailJobServiceImpl implements SnailJobService {
         return null;
     }
 
+    @Override
+    public JobTask taskRetryJob() {
+        JobSummary jobSummary = new JobSummary();
+        jobSummary.setSystemTaskType(3);
+        return jobSummaryMapper.selectJobTask(jobSummary);
+    }
+
+    @Override
+    public List<DashboardLineResponseVO> jobLineList(JobLineQueryVo queryVO) {
+        // 折线图
+        DateTypeEnum dateTypeEnum = DateTypeEnum.valueOf(queryVO.getType());
+        LocalDateTime startDateTime = dateTypeEnum.getStartTime().apply(
+                ObjUtil.isNotNull(queryVO.getStartDt()) ? queryVO.getStartDt() : LocalDateTime.now());
+        LocalDateTime endDateTime = dateTypeEnum.getEndTime().apply(
+                ObjUtil.isNotNull(queryVO.getEndDt()) ? queryVO.getEndDt() : LocalDateTime.now());
+        JobSummary jobSummary = new JobSummary();
+        jobSummary.setSystemTaskType(3);
+        jobSummary.setStartTime(startDateTime);
+        jobSummary.setEndTime(endDateTime);
+        jobSummary.setDateFormat(DashboardLineEnum.dateFormat(queryVO.getType()));
+        List<DashboardLineResponseVO> dashboardLineResponseDOList = jobSummaryMapper.selectJobLineList(jobSummary);
+        dashboardLineResponseDOList.sort(Comparator.comparing(DashboardLineResponseVO::getCreateDt));
+        return dashboardLineResponseDOList;
+    }
+
+
 }

+ 28 - 0
ruoyi-api-patform/src/main/java/com/ruoyi/interfaces/utils/DbUtils.java

@@ -0,0 +1,28 @@
+package com.ruoyi.interfaces.utils;
+
+import com.aizuda.snailjob.common.core.context.SnailSpringContext;
+import com.ruoyi.common.enums.DbTypeEnum;
+import org.springframework.core.env.Environment;
+
+/**
+ * 数据库工具
+ *
+ * @author: 疯狂的狮子Li
+ * @date : 2024-03-27 14:17
+ */
+public class DbUtils {
+
+    public static DbTypeEnum getDbType() {
+        Environment environment = SnailSpringContext.getBean(Environment.class);
+        String url = environment.getProperty("spring.datasource.url");
+        return DbTypeEnum.modeOf(url);
+    }
+
+    public static boolean isOracle() {
+        return DbTypeEnum.ORACLE.equals(getDbType());
+    }
+
+    public static boolean notOracle() {
+        return !DbTypeEnum.ORACLE.equals(getDbType());
+    }
+}

+ 110 - 0
ruoyi-api-patform/src/main/resources/mapper/interfaces/GatewayRoutesMapper.xml

@@ -0,0 +1,110 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
+<mapper namespace="com.ruoyi.interfaces.mapper.GatewayRoutesMapper">
+
+    <resultMap type="com.ruoyi.interfaces.domain.GatewayRoutes" id="gatewayRoutesResultMap">
+        <result column="ID" property="id"/>
+        <result column="SERVICE_NAME" property="serviceName"/>
+        <result column="URI" property="uri"/>
+        <result column="PREDICATES" property="predicates"/>
+        <result column="FILTERS" property="filters"/>
+        <result column="STATUS" property="status"/>
+        <result column="RESULT_SUCCESS_FORMAT" property="resultSuccessFormat"/>
+        <result column="AUTH" property="auth"/>
+        <result column="AUTH_EXPIRATION_TIME" property="authExpirationTime"/>
+        <result column="AUTH_QUERY_OPTIONS" property="authQueryOptions"/>
+    </resultMap>
+
+    <sql id="table_columns">
+        ID
+        , SERVICE_NAME, URI, PREDICATES, FILTERS, STATUS, RESULT_SUCCESS_FORMAT, AUTH, AUTH_EXPIRATION_TIME, AUTH_QUERY_OPTIONS
+    </sql>
+    <sql id="entity_properties">
+        #{id},
+        #{serviceName},
+        #{uri},
+        #{predicates},
+        #{filters},
+        #{status},
+        #{resultSuccessFormat},
+        #{auth},
+        #{authExpirationTime},
+        #{authQueryOptions}
+    </sql>
+
+    <!-- 使用like用法:columnName like concat('%',#columnName#,'%') -->
+    <sql id="page_where">
+        <trim prefix="where" prefixOverrides="and | or ">
+            <if test="serviceName != null  and serviceName != ''">and SERVICE_NAME like CONCAT('%', #{serviceName},
+                '%')
+            </if>
+            <if test="status != null  and status != ''">and STATUS = #{status}</if>
+        </trim>
+    </sql>
+
+
+    <select id="get" resultMap="gatewayRoutesResultMap" parameterType="String">
+        select
+        <include refid="table_columns"/>
+        from GATEWAY_ROUTES where ID = #{id}
+    </select>
+
+    <select id="getBy" resultMap="gatewayRoutesResultMap">
+        select
+        <include refid="table_columns"/>
+        from GATEWAY_ROUTES
+        <include refid="page_where"/>
+    </select>
+
+    <select id="findList" resultMap="gatewayRoutesResultMap">
+        select
+        <include refid="table_columns"/>
+        from GATEWAY_ROUTES
+        <include refid="page_where"/>
+    </select>
+
+    <select id="selectCount" resultType="int">
+        select count(ID) from GATEWAY_ROUTES
+        <include refid="page_where"/>
+    </select>
+
+
+    <insert id="insert" parameterType="com.ruoyi.interfaces.domain.GatewayRoutes">
+        insert into GATEWAY_ROUTES(
+        <include refid="table_columns"/>
+        )
+        values (
+        <include refid="entity_properties"/>
+        )
+    </insert>
+
+    <delete id="delete" parameterType="java.lang.String">
+        delete
+        GATEWAY_ROUTES where ID =
+        #{id}
+    </delete>
+
+    <update id="update" parameterType="com.ruoyi.interfaces.domain.GatewayRoutes">
+        update GATEWAY_ROUTES
+        <trim prefix="set" suffixOverrides=",">
+            <if test="serviceName != null  and serviceName != ''">SERVICE_NAME = #{serviceName},</if>
+            <if test="uri != null  and uri != ''">URI = #{uri},</if>
+            <if test="predicates != null  and predicates != ''">PREDICATES = #{predicates},</if>
+            <if test="filters != null  and filters != ''">FILTERS = #{filters},</if>
+            <if test="status != null  and status != ''">STATUS = #{status},</if>
+            <if test="resultSuccessFormat != null and resultSuccessFormat != ''">RESULT_SUCCESS_FORMAT = #{resultSuccessFormat},</if>
+            <if test="auth != null  and auth != ''">AUTH = #{auth},</if>
+            <if test="authExpirationTime != null and authExpirationTime != ''">AUTH_EXPIRATION_TIME = #{authExpirationTime},</if>
+            <if test="authQueryOptions != null and authQueryOptions != ''">AUTH_QUERY_OPTIONS = #{authQueryOptions},</if>
+        </trim>
+        <where>ID = #{id}</where>
+    </update>
+
+    <update id="updateBy" parameterType="com.ruoyi.interfaces.domain.GatewayRoutes">
+        update GATEWAY_ROUTES
+        <trim prefix="set" suffixOverrides=",">
+        </trim>
+        <include refid="page_where"/>
+    </update>
+
+</mapper>

+ 64 - 0
ruoyi-api-patform/src/main/resources/mapper/interfaces/JobSummaryMapper.xml

@@ -0,0 +1,64 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
+<mapper namespace="com.ruoyi.interfaces.mapper.JobSummaryMapper">
+
+    <select id="selectJobLineList"
+            resultType="com.ruoyi.interfaces.domain.job.DashboardLineResponseVO">
+        SELECT createDt                                                     AS createDt,
+               NVL(SUM(success_num), 0)                                     AS success,
+               NVL(SUM(fail_num), 0)                                        AS failNum,
+               NVL(SUM(stop_num), 0)                                        AS stop,
+               NVL(SUM(cancel_num), 0)                                      AS cancel,
+               NVL(SUM(fail_num + stop_num + cancel_num), 0)                AS fail,
+               NVL(SUM(success_num + fail_num + stop_num + cancel_num), 0)  AS total
+          FROM (
+                SELECT
+                    TO_CHAR(trigger_at, #{dateFormat}) AS createDt,
+                    success_num,
+                    fail_num,
+                    stop_num,
+                    cancel_num
+                FROM sj_job_summary
+        <where>
+            <if test="systemTaskType != null">
+                and SYSTEM_TASK_TYPE = #{systemTaskType}
+            </if>
+            <if test="namespaceId != null and namespaceId != ''">
+                and NAMESPACE_ID = #{namespaceId}
+            </if>
+            <if test="startTime != null">
+                and TRIGGER_AT &gt;= TO_DATE(TO_CHAR(#{startTime}, 'YYYY-MM-DD'), 'YYYY-MM-DD')
+            </if>
+            <if test="endTime != null">
+                and TRIGGER_AT &lt;= TO_DATE(TO_CHAR(#{endTime}, 'YYYY-MM-DD'), 'YYYY-MM-DD')
+            </if>
+        </where>
+          )
+        GROUP BY createDt
+    </select>
+
+    <select id="selectJobTask"
+            resultType="com.ruoyi.interfaces.domain.job.JobTask">
+        SELECT NVL(sum(success_num), 0) AS successNum,
+        NVL(sum(stop_num), 0) AS stopNum,
+        NVL(sum(cancel_num), 0) AS cancelNum,
+        NVL(sum(fail_num), 0) AS failNum,
+        NVL(sum(success_num + fail_num + stop_num + cancel_num), 0) AS totalNum
+        FROM sj_job_summary
+        <where>
+            <if test="systemTaskType != null">
+                and SYSTEM_TASK_TYPE = #{systemTaskType}
+            </if>
+            <if test="namespaceId != null and namespaceId != ''">
+                and NAMESPACE_ID = #{namespaceId}
+            </if>
+            <!--            <if test="groupNames != null and groupNames.size() > 0">-->
+            <!--                and GROUP_NAME in-->
+            <!--                <foreach item="groupName" collection="groupNames" open="(" separator="," close=")">-->
+            <!--                    #{groupName}-->
+            <!--                </foreach>-->
+            <!--&#45;&#45;             </if>-->
+        </where>
+    </select>
+
+</mapper>

+ 137 - 0
ruoyi-api-patform/src/main/resources/mapper/interfaces/PtAppMapper.xml

@@ -0,0 +1,137 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
+<mapper namespace="com.ruoyi.interfaces.mapper.PtAppMapper">
+
+    <resultMap type="com.ruoyi.interfaces.domain.PtApp" id="ptAppResultMap">
+        <result column="APP_ID" property="appId"/>
+        <result column="APP_NAME" property="appName"/>
+        <result column="APP_SECRET" property="appSecret"/>
+        <result column="APP_URL" property="appUrl"/>
+        <result column="APP_DEVELOPER" property="appDeveloper"/>
+        <result column="APP_NOTE" property="appNote"/>
+        <result column="RQ_TIME" property="rqTime"/>
+        <result column="APP_PUBLISH" property="appPublish"/>
+        <result column="APP_STATE" property="appState"/>
+        <result column="AUDIT_USER" property="auditUser"/>
+        <result column="AUDIT_TIME" property="auditTime"/>
+        <result column="APP_CATE" property="appCate"/>
+        <result column="APP_TOKEN" property="appToken"/>
+        <result column="USER_ID" property="userId"/>
+        <result column="APP_TYPE" property="appType"/>
+        <result column="APP_FIELD" property="appField"/>
+        <result column="REMARK" property="remark"/>
+    </resultMap>
+
+    <sql id="table_columns">
+        APP_ID, APP_NAME,APP_SECRET,APP_URL,
+        APP_DEVELOPER,APP_NOTE,RQ_TIME,APP_PUBLISH,APP_STATE,
+        AUDIT_USER,AUDIT_TIME,APP_CATE,APP_TOKEN,USER_ID,
+        APP_TYPE,APP_FIELD,REMARK
+    </sql>
+    <sql id="entity_properties">
+        #{appId},
+        #{appName},
+        #{appSecret},
+        #{appUrl},
+        #{appDeveloper},
+        #{appNote},
+        #{rqTime},
+        #{appPublish},
+        #{appState},
+        #{auditUser},
+        #{auditTime},
+        #{appCate},
+        #{appToken},
+        #{userId},
+        #{appType},
+        #{appField},
+        #{remark}
+    </sql>
+
+    <!-- 使用like用法:columnName like concat('%',#columnName#,'%') -->
+    <sql id="page_where">
+        <trim prefix="where" prefixOverrides="and | or ">
+            <if test="appName != null  and appName != ''">and APP_NAME like CONCAT('%', #{appName},  '%')
+            </if>
+            <if test="userId != null  and userId != ''">and USER_ID = #{userId}</if>
+            <if test="appState != null  and appState != ''">and APP_STATE = #{appState}</if>
+        </trim>
+    </sql>
+
+
+    <select id="get" resultMap="ptAppResultMap" parameterType="String">
+        select
+        <include refid="table_columns"/>
+        from PT_APP where APP_ID = #{id}
+    </select>
+
+    <select id="getBy" resultMap="ptAppResultMap">
+        select
+        <include refid="table_columns"/>
+        from PT_APP
+        <include refid="page_where"/>
+    </select>
+
+    <select id="findList" resultMap="ptAppResultMap">
+        select
+        <include refid="table_columns"/>
+        from PT_APP
+        <include refid="page_where"/>
+    </select>
+
+    <select id="selectCount" resultType="int">
+        select count(APP_ID) from PT_APP
+        <include refid="page_where"/>
+    </select>
+    <select id="findListByIds" resultType="com.ruoyi.interfaces.domain.PtApp">
+
+    </select>
+
+
+    <insert id="insert" parameterType="com.ruoyi.interfaces.domain.PtApp">
+        insert into PT_APP(
+        <include refid="table_columns"/>
+        )
+        values (
+        <include refid="entity_properties"/>
+        )
+    </insert>
+
+    <delete id="delete" parameterType="java.lang.String">
+        delete
+        PT_APP where APP_ID =
+        #{id}
+    </delete>
+
+    <update id="update" parameterType="com.ruoyi.interfaces.domain.PtApp">
+        update PT_APP
+        <trim prefix="set" suffixOverrides=",">
+            <if test="appName != null  and appName != ''">APP_NAME = #{appName},</if>
+            <if test="appUrl != null  and appUrl != ''">APP_URL = #{appUrl},</if>
+            <if test="appDeveloper != null  and appDeveloper != ''">APP_DEVELOPER = #{appDeveloper},</if>
+            <if test="appNote != null and appNote != ''">APP_NOTE = #{appNote},</if>
+            <if test="rqTime != null">RQ_TIME = #{rqTime},</if>
+            <if test="appPublish != null and appPublish != ''">APP_PUBLISH =
+                #{appPublish},
+            </if>
+            <if test="appState != null and appState != ''">APP_STATE = #{appState},</if>
+            <if test="auditUser != null and auditUser != ''">AUDIT_USER = #{auditUser},</if>
+            <if test="auditTime != null">AUDIT_TIME = #{auditTime},</if>
+            <if test="appCate != null and appCate != ''">APP_CATE = #{appCate},</if>
+            <if test="appToken != null and appToken != ''">APP_TOKEN = #{appToken},</if>
+            <if test="userId != null and userId != ''">USER_ID = #{userId},</if>
+            <if test="appType != null and appType != ''">APP_TYPE = #{appType},</if>
+            <if test="appField != null and appField != ''">APP_FIELD = #{appField},</if>
+            <if test="remark != null and remark != ''">REMARK = #{remark},</if>
+        </trim>
+        <where>APP_ID = #{appId}</where>
+    </update>
+
+    <update id="updateBy" parameterType="com.ruoyi.interfaces.domain.PtApp">
+        update PT_APP
+        <trim prefix="set" suffixOverrides=",">
+        </trim>
+        <include refid="page_where"/>
+    </update>
+
+</mapper>

+ 4 - 0
ruoyi-api-patform/src/main/resources/mapper/interfaces/PtServiceLogMapper.xml

@@ -109,6 +109,10 @@
         </trim>
         where log_id = #{logId}
     </update>
+    <select id="count" resultType="Long">
+        select count(log_id)
+        from pt_service_log
+    </select>
 
     <delete id="deletePtServiceLogByLogId" parameterType="Long">
         delete

+ 14 - 3
ruoyi-common/src/main/java/com/ruoyi/common/enums/DbTypeEnum.java

@@ -2,6 +2,7 @@ package com.ruoyi.common.enums;
 
 import cn.hutool.core.util.StrUtil;
 import com.baomidou.mybatisplus.annotation.DbType;
+import com.ruoyi.common.exception.ServiceException;
 import lombok.AllArgsConstructor;
 import lombok.Getter;
 
@@ -21,7 +22,7 @@ public enum DbTypeEnum {
     /**
      * MySQL
      */
-    MY_SQL( DbType.MYSQL, "MySQL", "FIND_IN_SET('#{value}', #{column}) <> 0"),
+    MY_SQL(DbType.MYSQL, "MySQL", "FIND_IN_SET('#{value}', #{column}) <> 0"),
 
     /**
      * Oracle
@@ -30,10 +31,10 @@ public enum DbTypeEnum {
 
     /**
      * PostgreSQL
-     *
+     * <p>
      * 华为 openGauss 使用 ProductName 与 PostgreSQL 相同
      */
-    POSTGRE_SQL(DbType.POSTGRE_SQL,"PostgreSQL", "POSITION('#{value}' IN #{column}) <> 0"),
+    POSTGRE_SQL(DbType.POSTGRE_SQL, "PostgreSQL", "POSITION('#{value}' IN #{column}) <> 0"),
 
     /**
      * SQL Server
@@ -57,6 +58,16 @@ public enum DbTypeEnum {
     public static final Map<DbType, DbTypeEnum> MAP_BY_MP = Arrays.stream(values())
             .collect(Collectors.toMap(DbTypeEnum::getMpDbType, Function.identity()));
 
+    public static DbTypeEnum modeOf(String db) {
+        for (DbTypeEnum value : DbTypeEnum.values()) {
+            if (db.contains(value.getProductName())) {
+                return value;
+            }
+        }
+
+        throw new ServiceException("This database is not supported yet [" + db + "]");
+    }
+
     /**
      * MyBatis Plus 类型
      */

+ 15 - 0
ruoyi-ui/src/api/service/timing.js

@@ -57,6 +57,21 @@ export function snailJobStatistics() {
   })
 }
 
+export function snailJobTaskRetryJob() {
+  return request({
+    url: '/snail/job/task-retry-job',
+    method: 'get',
+  })
+}
+
+export function snailJobLine(params) {
+  return request({
+    url: '/snail/job/line',
+    method: 'get',
+    params
+  })
+}
+
 export function snailJobLogList(query) {
   return request({
     url: '/snail/job/log/listOfPage',

+ 139 - 53
ruoyi-ui/src/views/monitor/taskMonitor/index.vue

@@ -1,62 +1,78 @@
 <template>
   <div class="app-container" style="background-color: #F7F7F7;height: 100%;overflow: auto;">
-    <div class="gw-statistic-row" style="height: 12vh;">
+    <div class="gw-statistic-row" style="height: 10vh;">
       <gw-statistic v-for="item in statisticData" :key="item.name" :name="item.name" :value="item.value"
                     :color="item.color"></gw-statistic>
     </div>
-    <el-card>
-      <el-table
-          :data="tableData"
-          height="59vh"
-          :cell-style="{ padding: '5px' }"
-          :header-cell-style="{ height: heightAll * 0.01 + 'px' }"
-          :row-style="{ fontSize: '1rem', textAlign:'center' }"
-          border>
-        <el-table-column prop="jobName" label="任务名称" width="160"></el-table-column>
-        <el-table-column prop="taskType" label="任务类型" width="170">
-          <template #default="scope">
-            <el-tag v-if="scope.row.taskType==1" type="success">集群</el-tag>
-            <el-tag v-if="scope.row.taskType==2" type="info">广播</el-tag>
-            <el-tag v-if="scope.row.taskType==3" type="warning">Sharding</el-tag>
-            <el-tag v-if="scope.row.taskType==4" type="danger">Map</el-tag>
-            <el-tag v-if="scope.row.taskType==5">MapReduce</el-tag>
-          </template>
-        </el-table-column>
-        <el-table-column prop="triggerType" label="触发类型" width="170">
-          <template #default="scope">
-            <el-tag v-if="scope.row.triggerType==2">固定时间</el-tag>
-            <el-tag v-if="scope.row.triggerType==3">CRON 表达式</el-tag>
-            <el-tag v-if="scope.row.triggerType==99">工作流</el-tag>
-          </template>
-        </el-table-column>
-        <el-table-column prop="retryInterval" label="间隔时长" width="170"/>
-        <el-table-column prop="blockStrategy" label="阻塞策略" width="170">
-          <template #default="scope">
-            <el-tag v-if="scope.row.blockStrategy==1">丢弃</el-tag>
-            <el-tag v-if="scope.row.blockStrategy==2">覆盖</el-tag>
-            <el-tag v-if="scope.row.blockStrategy==3">并行</el-tag>
-          </template>
-        </el-table-column>
-        <el-table-column prop="executorTimeout" label="超时时间(秒)" width="170"/>
-        <el-table-column prop="executionTime" label="执行时间" width="240"/>
-        <el-table-column align="center" prop="taskStatus" label="执行状态" width="80">
-          <template #default="scope">
-            <el-tag v-if="scope.row.taskStatus == 3">成功</el-tag>
-            <el-tag v-else type="danger">失败</el-tag>
-          </template>
-        </el-table-column>
-        <el-table-column prop="resultMessage" label="执行结果" width="170"/>
-      </el-table>
-      <pagination v-show="total > 0" :total="total" v-model:page="queryParams.pageNum"
-                  v-model:limit="queryParams.pageSize" @pagination="getTaskData"/>
-    </el-card>
+    <div class="gw-statistic-row" style="height: 34vh;">
+      <gw-card>
+        <template v-slot:title>
+          <div style="display: flex;align-items: center;justify-content: space-between;">
+            <div>
+              <span>任务统计</span>
+            </div>
+            <el-segmented v-model="task" :options="taskOptions" @change="initChartTop5"/>
+          </div>
+        </template>
+        <gw-echart ref="top5Ref"></gw-echart>
+      </gw-card>
+    </div>
+    <div class="gw-statistic-row" style="height: 36vh;">
+      <gw-card>
+        <el-table
+            :data="tableData"
+            height="24vh"
+            :cell-style="{ padding: '5px' }"
+            :header-cell-style="{ height: heightAll * 0.01 + 'px' }"
+            :row-style="{ fontSize: '1rem', textAlign:'center' }"
+            border>
+          <el-table-column prop="jobName" label="任务名称"></el-table-column>
+          <el-table-column prop="taskType" label="任务类型" width="170">
+            <template #default="scope">
+              <el-tag v-if="scope.row.taskType==1" type="success">集群</el-tag>
+              <el-tag v-if="scope.row.taskType==2" type="info">广播</el-tag>
+              <el-tag v-if="scope.row.taskType==3" type="warning">Sharding</el-tag>
+              <el-tag v-if="scope.row.taskType==4" type="danger">Map</el-tag>
+              <el-tag v-if="scope.row.taskType==5">MapReduce</el-tag>
+            </template>
+          </el-table-column>
+          <el-table-column prop="triggerType" label="触发类型" width="170">
+            <template #default="scope">
+              <el-tag v-if="scope.row.triggerType==2">固定时间</el-tag>
+              <el-tag v-if="scope.row.triggerType==3">CRON 表达式</el-tag>
+              <el-tag v-if="scope.row.triggerType==99">工作流</el-tag>
+            </template>
+          </el-table-column>
+          <el-table-column prop="retryInterval" label="间隔时长" width="170"/>
+          <el-table-column prop="blockStrategy" label="阻塞策略" width="170">
+            <template #default="scope">
+              <el-tag v-if="scope.row.blockStrategy==1">丢弃</el-tag>
+              <el-tag v-if="scope.row.blockStrategy==2">覆盖</el-tag>
+              <el-tag v-if="scope.row.blockStrategy==3">并行</el-tag>
+            </template>
+          </el-table-column>
+          <el-table-column prop="executorTimeout" label="超时时间(秒)" width="170"/>
+          <el-table-column prop="executionTime" label="执行时间" width="240"/>
+          <el-table-column align="center" prop="taskStatus" label="执行状态" width="80">
+            <template #default="scope">
+              <el-tag v-if="scope.row.taskStatus == 3">成功</el-tag>
+              <el-tag v-else type="danger">失败</el-tag>
+            </template>
+          </el-table-column>
+        </el-table>
+        <pagination v-show="total > 0" :total="total" v-model:page="queryParams.pageNum"
+                    v-model:limit="queryParams.pageSize" @pagination="getTaskData"/>
+      </gw-card>
+    </div>
   </div>
 </template>
 <script setup>
 import {onMounted} from 'vue';
 import GwStatistic from "@/views/monitor/service/GwStatistic.vue";
 import Pagination from "@/components/Pagination/index.vue";
-import {snailJobLogList, snailJobStatistics} from "@/api/service/timing.js";
+import {snailJobLine, snailJobLogList, snailJobTaskRetryJob} from "@/api/service/timing.js";
+import GwCard from "@/views/monitor/service/GwCard.vue";
+import GwEchart from "@/components/chart/GwEchart.vue";
 
 const statisticData = ref([
   {name: '任务数据总数', value: 0, color: '#477ACF'},
@@ -70,6 +86,14 @@ const queryParams = ref({
 })
 const tableData = ref([])
 const total = ref(0)
+const top5Ref = ref(null)
+const task = ref('MONTH')
+const taskOptions = ref([
+  {label: '今日', value: 'DAY'},
+  {label: '最近一周', value: 'WEEK'},
+  {label: '最近一月', value: 'MONTH'},
+  {label: '全年', value: 'YEAR'},
+])
 
 function getTaskData() {
   snailJobLogList(queryParams.value).then(res => {
@@ -79,18 +103,80 @@ function getTaskData() {
 }
 
 function getStatistics() {
-  snailJobStatistics().then(res => {
+  snailJobTaskRetryJob().then(res => {
+    res.data.successRate = (res.data.successNum / res.data.totalNum * 100).toFixed(2) + '%'
     statisticData.value = [
-      {name: '任务数据总数', value: res.data.total, color: '#477ACF'},
-      {name: '任务被执行次数', value: res.data.runTotal, color: '#40B0D7'},
-      {name: '日执行量', value: res.data.nowRunTotal, color: '#2DBEA2'},
-      {name: '月执行量', value: res.data.monthRunTotal, color: '#487ACF'},
+      {name: '任务总数', value: res.data.totalNum, color: '#477ACF'},
+      {name: '任务成功', value: res.data.successNum, color: '#2DBEA2'},
+      {name: '任务失败', value: res.data.failNum, color: '#F56C6C'},
+      {name: '任务停止', value: res.data.stopNum, color: '#E6A23C'},
+      {name: '人工取消', value: res.data.cancelNum, color: '#909399'},
+      {name: '任务成功率', value: res.data.successRate, color: '#487ACF'},
     ]
   })
 }
 
+function initChartTop5() {
+  snailJobLine({type: task.value}).then(res => {
+    const chartData = res.data
+    const option = {
+      color: ['#2dbea2', '#f56c6c', '#b686d4', '#e6a23c'],
+      legend: {},
+      grid: {
+        left: '5%',
+        right: '5%',
+        bottom: '10%',
+        top: '15%',
+        containLabel: true
+      },
+      tooltip: {
+        trigger: 'axis'
+      },
+      dataset: {
+        source: [
+          ['时间', ...chartData.map(item => item.createDt)],
+          ['成功', ...chartData.map(item => item.success)],
+          ['失败', ...chartData.map(item => item.failNum)],
+          ['停止', ...chartData.map(item => item.stop)],
+          ['取消', ...chartData.map(item => item.cancel)],
+        ]
+      },
+      xAxis: {type: 'category'},
+      yAxis: {gridIndex: 0},
+      series: [
+        {
+          type: 'line',
+          smooth: true,
+          seriesLayoutBy: 'row',
+          emphasis: {focus: 'series'},
+        },
+        {
+          type: 'line',
+          smooth: true,
+          seriesLayoutBy: 'row',
+          emphasis: {focus: 'series'}
+        },
+        {
+          type: 'line',
+          smooth: true,
+          seriesLayoutBy: 'row',
+          emphasis: {focus: 'series'}
+        },
+        {
+          type: 'line',
+          smooth: true,
+          seriesLayoutBy: 'row',
+          emphasis: {focus: 'series'}
+        }
+      ]
+    };
+    top5Ref.value.loadChart(option);
+  })
+}
+
 onMounted(() => {
   getStatistics()
+  initChartTop5()
   getTaskData()
 });
 </script>

+ 0 - 1
ruoyi-ui/src/views/standardization/bizDataShowConfig/show/index.vue

@@ -85,7 +85,6 @@ const currentPage = ref(1)
 const total = ref(0)
 
 function loadData(config) {
-  debugger
   if (!config) {
     return
   }

+ 5 - 0
ruoyi-ui/vite.config.js

@@ -45,6 +45,11 @@ export default defineConfig(({mode, command}) => {
                     target: env.VITE_DEV_PATH,
                     changeOrigin: true,
                     rewrite: (p) => p.replace(/^\/sh-api/, '')
+                },
+                '/service_api': {
+                    target: 'http://localhost:8081',
+                    changeOrigin: true,
+                    rewrite: (p) => p.replace(/^\/service_api/, '')
                 }
                 // [env.VITE_APP_BASE_API]: {
                 //     target: env.VITE_DEV_PATH,