yangbq преди 4 месеца
родител
ревизия
5b8a28936a
променени са 23 файла, в които са добавени 1370 реда и са изтрити 160 реда
  1. 14 3
      pom.xml
  2. 5 1
      project-admin/pom.xml
  3. 1 1
      project-admin/src/main/java/com/project/ProjectApplication.java
  4. 24 6
      project-admin/src/main/resources/application-dev.yml
  5. 285 0
      project-admin/src/main/resources/application-local.yml
  6. 20 1
      project-admin/src/main/resources/application.yml
  7. 13 1
      project-common/pom.xml
  8. 0 29
      project-common/src/main/java/com/project/common/config/QRCodeConfig.java
  9. 0 83
      project-common/src/main/java/com/project/common/config/QRCodeReader.java
  10. 0 25
      project-common/src/main/java/com/project/common/config/QRCodeService.java
  11. 1 1
      project-framework/src/main/java/com/project/framework/config/ApplicationConfig.java
  12. 1 0
      project-framework/src/main/java/com/project/framework/config/SecurityConfig.java
  13. 37 0
      project-xxl-job/pom.xml
  14. 54 0
      project-xxl-job/src/main/java/com/xxl/job/config/XxlJobConfig.java
  15. 49 0
      project-xxl-job/src/main/java/com/xxl/job/controller/DashboardController.java
  16. 87 0
      project-xxl-job/src/main/java/com/xxl/job/controller/JobApiController.java
  17. 185 0
      project-xxl-job/src/main/java/com/xxl/job/controller/JobGroupController.java
  18. 122 0
      project-xxl-job/src/main/java/com/xxl/job/controller/JobInfoController.java
  19. 170 0
      project-xxl-job/src/main/java/com/xxl/job/controller/JobLogController.java
  20. 36 0
      project-xxl-job/src/main/java/com/xxl/job/service/AdminBizImpl.java
  21. 166 0
      project-xxl-job/src/main/java/com/xxl/job/service/XxlJobService.java
  22. 98 0
      project-zcustom/src/main/java/com/project/zcustom/controller/TestToolsController.java
  23. 2 9
      project-zcustom/src/main/java/com/project/zcustom/controller/video/PlatVideoController.java

+ 14 - 3
pom.xml

@@ -33,7 +33,7 @@
         <poi.version>4.1.2</poi.version>
         <velocity.version>2.3</velocity.version>
         <jwt.version>0.9.1</jwt.version>
-        <qr.code.version>3.3.3</qr.code.version>
+        <xxl-job.version>2.4.0</xxl-job.version>
     </properties>
 
     <!-- 依赖声明 -->
@@ -49,6 +49,10 @@
                 <scope>import</scope>
             </dependency>
             <dependency>
+                <groupId>org.springframework.boot</groupId>
+                <artifactId>spring-boot-starter-mail</artifactId>
+            </dependency>
+            <dependency>
                 <groupId>com.belerweb</groupId>
                 <artifactId>pinyin4j</artifactId>
                 <version>2.5.1</version>
@@ -197,6 +201,12 @@
                 <version>${change.version}</version>
             </dependency>
 
+            <!--<dependency>
+                <groupId>com.xuxueli</groupId>
+                <artifactId>xxl-job-core</artifactId>
+                <version>${xxl-job.version}</version>
+            </dependency>-->
+
             <!-- 系统模块-->
             <dependency>
                 <groupId>com.project</groupId>
@@ -223,7 +233,7 @@
                 <artifactId>project-extend</artifactId>
                 <version>${change.version}</version>
             </dependency>
-            <dependency>
+            <!--<dependency>
                 <groupId>com.google.zxing</groupId>
                 <artifactId>core</artifactId>
                 <version>${qr.code.version}</version>
@@ -232,7 +242,7 @@
                 <groupId>com.google.zxing</groupId>
                 <artifactId>javase</artifactId>
                 <version>${qr.code.version}</version>
-            </dependency>
+            </dependency>-->
             <dependency>
                 <groupId>org.bouncycastle</groupId>
                 <artifactId>bcprov-jdk15on</artifactId>
@@ -255,6 +265,7 @@
         <module>project-common</module>
         <module>project-extend</module>
         <module>project-zcustom</module>
+        <module>project-xxl-job</module>
     </modules>
     <packaging>pom</packaging>
 

+ 5 - 1
project-admin/pom.xml

@@ -80,7 +80,11 @@
             <groupId>com.project</groupId>
             <artifactId>project-extend</artifactId>
         </dependency>
-
+        <dependency>
+            <groupId>com.xxl.job</groupId>
+            <artifactId>project-xxl-job</artifactId>
+            <version>3.8.3</version>
+        </dependency>
 
     </dependencies>
 

+ 1 - 1
project-admin/src/main/java/com/project/ProjectApplication.java

@@ -9,7 +9,7 @@ import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration;
  *
  * @author ruoyi
  */
-@SpringBootApplication(exclude = {DataSourceAutoConfiguration.class})
+@SpringBootApplication(scanBasePackages = {"com.project","com.xxl.job"},exclude = {DataSourceAutoConfiguration.class})
 public class ProjectApplication {
     public static void main(String[] args) {
         // System.setProperty("spring.devtools.restart.enabled", "false");

+ 24 - 6
project-admin/src/main/resources/application-dev.yml

@@ -94,8 +94,8 @@ business:
 # 日志配置
 logging:
   level:
-    com.project: DEBUG
-    org.springframework: WARN
+    com.project: info
+    org.springframework: info
 
 # 用户配置
 user:
@@ -107,6 +107,24 @@ user:
 
 # Spring配置
 spring:
+  mail:
+    # 邮件服务器地址
+    host: smtp.qq.com
+    # 邮件服务器端口
+    port: 465
+    # 邮件服务器用户名
+    username: ''
+    password: ''
+    protocol: smtp
+    from: ''
+    properties:
+      mail:
+        smtp:
+          auth: true
+          starttls:
+            enable: true
+          connectiontimeout: 10000
+          timeout: 10000
   # 资源信息
   messages:
     # 国际化资源文件路径
@@ -129,9 +147,9 @@ spring:
     druid:
       # 主库数据源
       master:
-        url: jdbc:mysql://127.0.0.1:3306/sxgw?useSSL=false&useUnicode=true&characterEncoding=utf-8&zeroDateTimeBehavior=convertToNull&transformedBitIsBoolean=true&tinyInt1isBit=false&allowMultiQueries=true&serverTimezone=GMT%2B8
+        url: jdbc:mysql://192.168.110.130:13306/sxgw?useSSL=false&useUnicode=true&characterEncoding=utf-8&zeroDateTimeBehavior=convertToNull&transformedBitIsBoolean=true&tinyInt1isBit=false&allowPublicKeyRetrieval=true&allowMultiQueries=true&serverTimezone=GMT%2B8
         username: root
-        password: 1qaz2wsx
+        password: root
       # 从库数据源
       slave:
         # 从数据源开关/默认关闭
@@ -213,9 +231,9 @@ token:
 # MyBatisPlus配置
 mybatis-plus:
   # 搜索指定包别名
-  typeAliasesPackage: com.project.**.domain
+  typeAliasesPackage: com.project.**.domain, com.xxl.job.admin.core.model
   # 配置mapper的扫描,找到所有的mapper.xml映射文件
-  mapperLocations: classpath*:mapper/**/*Mapper.xml
+  mapperLocations: classpath*:mapper/**/*Mapper.xml,classpath:/mybatis-mapper/*Mapper.xml
   # 全局配置
   global-config:
     db-config:

+ 285 - 0
project-admin/src/main/resources/application-local.yml

@@ -0,0 +1,285 @@
+# 项目相关配置
+change:
+  # 名称
+  name: sxgw-dev
+  # 版本
+  version: 3.8.3
+  # 版权年份
+  copyrightYear: 2022
+  # 实例演示开关
+  demoEnabled: true
+  # 文件路径 示例( Windows配置D:/change/uploadPath,Linux配置 /home/change/uploadPath)
+  profile: ./uploadPath
+  # 获取ip地址开关
+  addressEnabled: false
+  # 验证码类型 math 数组计算 char 字符验证
+  captchaType: math
+  # 当前项目 redis cookie等 变量后缀
+  projectSuffix: _sxgw24
+
+# 接口地址配置
+apiurl:
+  # 服务保障中心接口地址
+  #serviceUrl: http://25.39.79.244:18080/zhhq_app/zhhq_large_screen/queryByAppOrg
+  serviceUrl: http://192.168.1.189/fxkj/php/public/home/Wechat/test
+  # 楼宇运行监控 接口前缀
+  buildPrefix: http://192.168.1.74:6789/psbims/office/energy/
+  # 楼宇运行监控 碳排放量月度变化趋势图接口
+  buildCarbonEmissionStatistics: carbonEmissionStatistics
+  # 办公能耗情况接口 年度累计综合能耗
+  buildEnergyForYear: energyForYear
+  # 办公能耗情况接口 年度综合能耗趋势接口
+  buildEnergyStatistics: energyStatistics
+  # 办公能耗情况接口 年度累计电耗接口
+  buildPowerForYear: powerForYear
+  # 办公能耗情况接口 年度电耗趋势接口
+  buildElectricityStatistics: electricityStatistics
+  # 办公能耗情况接口 年度累计水耗接口
+  buildWaterForYear: waterForYear
+  # 办公能耗情况接口 年度水耗趋势接口
+  buildWaterStatistics: waterStatistics
+  # 办公能耗情况接口 年度累计非供暖能耗接口
+  buildNonHeatingEnergyForYear: nonHeatingEnergyForYear
+  # 办公能耗情况接口 年度非供暖能耗趋势接口
+  buildUsePowerStatistics: usePowerStatistics
+  # 办公能耗情况接口 月用电量信息接口
+  buildPowerForMonth: powerForMonth
+  # 办公能耗情况接口 楼宇月用水电热信息接口
+  buildUseHeatGas: useHeatGas
+  # 数据中心机房信息接口
+  buildDataCenterRoom: dataCenterRoom
+  # 供暖能耗信息接口
+  buildHeatingEnergy: heatingEnergy
+  # 燃气用量信息接口
+  buildGasInfo: gasInfo
+  # 资源信息接口
+  buildResourceInfo: resourceInfo
+  # 可再生电力信息接口
+  buildGreenPowerInfo: greenPowerInfo
+  # 办公碳排放情况接口
+  buildOfficeCarbonForYear: officeCarbonForYear
+  # 各单位年度累计办公碳排放量统计接口
+  buildOfficeCarbonForFloor: officeCarbonForFloor
+
+znhqcamera:
+  path: /usr/local/ffmpeg/bin/ffmpeg # ffmpeg安装的位置
+  rtmp: rtmp://25.39.67.168:10612/myapp/ # rtmp 链接前缀
+  flv: http://25.39.67.168:10611/rtmpLive?port=10612&app=myapp&stream= # http访问链接前缀
+  stat: http://25.39.67.168:10611/statjson # 流媒体服务器状态文件访问路径
+  corn: 0 0/10 * * * ?   # 定时关流
+
+# 开发环境配置
+server:
+  # 服务器的HTTP端口,默认为8890
+  port: 8115
+  servlet:
+    # 应用的访问路径
+    context-path: /
+  tomcat:
+    # tomcat的URI编码
+    uri-encoding: UTF-8
+    # 连接数满后的排队数,默认为100
+    accept-count: 1000
+    threads:
+      # tomcat最大线程数,默认为200
+      max: 800
+      # Tomcat启动初始化的线程数,默认值10
+      min-spare: 100
+# 业务配置
+business:
+  # 请求、响应数据加密
+  aes-encrypt:
+    # 是否启用
+    enabled: false
+# 日志配置
+logging:
+  level:
+    com.project: DEBUG
+    org.springframework: WARN
+
+# 用户配置
+user:
+  password:
+    # 密码最大错误次数
+    maxRetryCount: 5
+    # 密码锁定时间(默认10分钟)
+    lockTime: 10
+
+# Spring配置
+spring:
+  mail:
+    # 邮件服务器地址
+    host: smtp.qq.com
+    # 邮件服务器端口
+    port: 465
+    # 邮件服务器用户名
+    username: ''
+    password: ''
+    protocol: smtp
+    from: ''
+    properties:
+      mail:
+        smtp:
+          auth: true
+          starttls:
+            enable: true
+          connectiontimeout: 10000
+          timeout: 10000
+  # 资源信息
+  messages:
+    # 国际化资源文件路径
+    basename: i18n/messages
+  # 文件上传
+  servlet:
+    multipart:
+      # 单个文件大小
+      max-file-size: 1024MB
+      # 设置总上传的文件大小
+      max-request-size: 2048MB
+  # 服务模块
+  devtools:
+    restart:
+      # 热部署开关
+      enabled: true
+  datasource:
+    type: com.alibaba.druid.pool.DruidDataSource
+    driverClassName: com.mysql.cj.jdbc.Driver
+    druid:
+      # 主库数据源
+      master:
+        url: jdbc:mysql://127.0.0.1:3306/sxgw?useSSL=false&useUnicode=true&characterEncoding=utf-8&zeroDateTimeBehavior=convertToNull&transformedBitIsBoolean=true&tinyInt1isBit=false&allowPublicKeyRetrieval=true&allowMultiQueries=true&serverTimezone=GMT%2B8
+        username: root
+        password: 1qaz2wsx
+      # 从库数据源
+      slave:
+        # 从数据源开关/默认关闭
+        enabled: false
+        url:
+        username:
+        password:
+      # 初始连接数
+      initialSize: 5
+      # 最小连接池数量
+      minIdle: 10
+      # 最大连接池数量
+      maxActive: 20
+      # 配置获取连接等待超时的时间
+      maxWait: 60000
+      # 配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位是毫秒
+      timeBetweenEvictionRunsMillis: 60000
+      # 配置一个连接在池中最小生存的时间,单位是毫秒
+      minEvictableIdleTimeMillis: 300000
+      # 配置一个连接在池中最大生存的时间,单位是毫秒
+      maxEvictableIdleTimeMillis: 900000
+      # 配置检测连接是否有效
+      validationQuery: SELECT 1 FROM DUAL
+      testWhileIdle: true
+      testOnBorrow: false
+      testOnReturn: false
+      webStatFilter:
+        enabled: true
+      statViewServlet:
+        enabled: true
+        # 设置白名单,不填则允许所有访问
+        allow:
+        url-pattern: /druid/*
+        # 控制台管理用户名和密码
+        login-username: admin
+        login-password: 123456
+      filter:
+        stat:
+          enabled: true
+          # 慢SQL记录
+          log-slow-sql: true
+          slow-sql-millis: 1000
+          merge-sql: true
+        wall:
+          config:
+            multi-statement-allow: true
+  # redis 配置
+#  redis:
+#    # 地址
+#    host: localhost
+#    # 端口,默认为6379
+#    port: 6379
+#    # 数据库索引
+#    database: 0
+#    # 密码
+#    password: 123456
+#    # 连接超时时间
+#    timeout: 10s
+#    lettuce:
+#      pool:
+#        # 连接池中的最小空闲连接
+#        min-idle: 0
+#        # 连接池中的最大空闲连接
+#        max-idle: 8
+#        # 连接池的最大数据库连接数
+#        max-active: 8
+#        # #连接池最大阻塞等待时间(使用负值表示没有限制)
+#        max-wait: -1ms
+
+# token配置
+token:
+  # 令牌自定义标识
+  header: Authorization
+  # 令牌密钥
+  secret: abcdefghijklmnopqrstuvwxyz
+  # 令牌有效期(默认30分钟)
+  expireTime: 3000
+
+# MyBatisPlus配置
+mybatis-plus:
+  # 搜索指定包别名
+  typeAliasesPackage: com.project.**.domain, com.xxl.job.admin.core.model
+  # 配置mapper的扫描,找到所有的mapper.xml映射文件
+  mapperLocations: classpath*:mapper/**/*Mapper.xml,classpath:/mybatis-mapper/*Mapper.xml
+  # 全局配置
+  global-config:
+    db-config:
+      id-type: auto
+      logic-delete-field: delFlag
+      logic-not-delete-value: "0"
+      logic-delete-value: "1"
+  configuration:
+    map-underscore-to-camel-case: true
+    #log-impl: org.apache.ibatis.logging.stdout.StdOutImpl # 打印sql
+
+# MyBatisPlusJoin配置
+mybatis-plus-join:
+  #是否打印 mybatis plus join banner 默认true
+  banner: true
+  #全局启用副表逻辑删除(默认true) 关闭后关联查询不会加副表逻辑删除
+  sub-table-logic: true
+  #拦截器MappedStatement缓存(默认true)
+  ms-cache: true
+  #表别名(默认 t)
+  table-alias: t
+  #副表逻辑删除条件的位置,支持where、on
+  #默认ON (1.4.7.2及之前版本默认为where)
+  logic-del-type: on
+
+# PageHelper分页插件
+pagehelper:
+  helperDialect: mysql
+  supportMethodsArguments: true
+  params: count=countSql
+
+# Swagger配置
+swagger:
+  # 是否开启swagger
+  enabled: true
+  # 请求前缀
+  pathMapping: /dev-api
+
+# 防止XSS攻击
+xss:
+  # 过滤开关
+  enabled: true
+  # 排除链接(多个用逗号分隔)
+  excludes: /system/notice
+  # 匹配链接
+  urlPatterns: /system/*,/monitor/*,/tool/*
+
+
+

+ 20 - 1
project-admin/src/main/resources/application.yml

@@ -1,3 +1,22 @@
 spring:
   profiles:
-    active: dev
+    active: dev
+
+
+xxl:
+  job:
+    enabled: true
+    accessToken: default_token
+    i18n: zh_CN
+    triggerpool:
+      fast:
+        max: 200
+      slow:
+        max: 100
+    logretentiondays: 30
+    executor:
+      appname: default-executor
+      address: ''
+      ip: ''
+      logpath: ./applogs/xxl-job/jobhandler
+      logretentiondays: 30 # 执行器日志文件保存天数

+ 13 - 1
project-common/pom.xml

@@ -156,14 +156,26 @@
             <groupId>org.projectlombok</groupId>
             <artifactId>lombok</artifactId>
         </dependency>
+
         <dependency>
+            <groupId>top.chenlq</groupId>
+            <artifactId>xxl-job-admin-core</artifactId>
+            <version>2.4.3</version>
+        </dependency>
+
+        <!--<dependency>
+            <groupId>com.xuxueli</groupId>
+            <artifactId>xxl-job-core</artifactId>
+            <version>${xxl-job.version}</version>
+        </dependency>-->
+        <!--<dependency>
             <groupId>com.google.zxing</groupId>
             <artifactId>core</artifactId>
         </dependency>
         <dependency>
             <groupId>com.google.zxing</groupId>
             <artifactId>javase</artifactId>
-        </dependency>
+        </dependency>-->
         <!-- Swagger3依赖 -->
         <dependency>
             <groupId>io.springfox</groupId>

+ 0 - 29
project-common/src/main/java/com/project/common/config/QRCodeConfig.java

@@ -1,29 +0,0 @@
-package com.project.common.config;
-
-import cn.hutool.extra.qrcode.QrConfig;
-import org.springframework.context.annotation.Bean;
-import org.springframework.context.annotation.Configuration;
-
-import java.awt.*;
-import java.io.File;
-import java.nio.charset.StandardCharsets;
-
-@Configuration
-public class QRCodeConfig {
-
-    @Bean
-    public QrConfig qrConfig() {
-        QrConfig qrConfig = new QrConfig();
-        qrConfig.setBackColor(Color.white);
-        qrConfig.setForeColor(Color.black);
-        qrConfig.setCharset(StandardCharsets.UTF_8);
-        qrConfig.setMargin(1);
-        qrConfig.setWidth(400);
-        qrConfig.setHeight(400);
-        //logo图片
-//        qrConfig.setImg(new File("./logo.jpeg"));
-        //logo缩放比例
-        qrConfig.setRatio(6);
-        return qrConfig;
-    }
-}

+ 0 - 83
project-common/src/main/java/com/project/common/config/QRCodeReader.java

@@ -1,83 +0,0 @@
-package com.project.common.config;
-
-import cn.hutool.extra.qrcode.BufferedImageLuminanceSource;
-import com.google.zxing.BinaryBitmap;
-import com.google.zxing.MultiFormatReader;
-import com.google.zxing.Result;
-import com.google.zxing.common.HybridBinarizer;
-import org.apache.commons.codec.binary.Base64;
-
-import javax.imageio.ImageIO;
-import java.awt.image.BufferedImage;
-import java.io.ByteArrayInputStream;
-import java.io.File;
-import java.io.FileInputStream;
-import java.io.IOException;
-
-public class QRCodeReader {
-    /**
-     * 识别二维码文件
-     * @param file 二维码文件
-     * @return
-     */
-    public static String readQRCodeFile(File file) {
-        String content = null;
-        try {
-            //将二维码图片加载为BufferedImage
-            BufferedImage bufferedImage = ImageIO.read(file);
-            //创建BufferedImageLuminanceSource
-            BufferedImageLuminanceSource source = new BufferedImageLuminanceSource(bufferedImage);
-            //使用HybridBinarizer将LuminanceSource转换为二进制位图BinaryBitmap
-            BinaryBitmap bitmap = new BinaryBitmap(new HybridBinarizer(source));
-            //使用工厂类
-            MultiFormatReader reader = new MultiFormatReader();
-            //解码
-            Result result = reader.decode(bitmap);
-            //获取内容
-            content = result.getText();
-        } catch (Exception e) {
-            e.printStackTrace();
-        }
-        return content;
-    }
-
-    public static String readQRCodeBase64(String base64Code) {
-        String content = null;
-        try {
-            //解码为字节数组
-            byte[] imageBytes = Base64.decodeBase64(base64Code);
-            //转换为输入流
-            ByteArrayInputStream bis = new ByteArrayInputStream(imageBytes);
-            //创建BufferedImage
-            BufferedImage bufferedImage = ImageIO.read(bis);
-            //创建BufferedImageLuminanceSource
-            BufferedImageLuminanceSource source = new BufferedImageLuminanceSource(bufferedImage);
-            //使用HybridBinarizer将LuminanceSource转换为二进制位图BinaryBitmap
-            BinaryBitmap bitmap = new BinaryBitmap(new HybridBinarizer(source));
-            //使用工厂类
-            MultiFormatReader reader = new MultiFormatReader();
-            //解码
-            Result result = reader.decode(bitmap);
-            //获取内容
-            content = result.getText();
-        } catch (Exception e) {
-            e.printStackTrace();
-        }
-        return content;
-    }
-
-    private static void test() throws IOException {
-        File file = new File("./test.png");
-        System.out.println(readQRCodeFile(file));
-
-        //base64编码
-        FileInputStream fis = new FileInputStream(file);
-        int length = fis.available();
-        byte[] bytes = new byte[length];
-        fis.read(bytes);
-        fis.close();
-        String base64Code = Base64.encodeBase64String(bytes);
-        System.out.println(readQRCodeBase64(base64Code));
-    }
-
-}

+ 0 - 25
project-common/src/main/java/com/project/common/config/QRCodeService.java

@@ -1,25 +0,0 @@
-package com.project.common.config;
-
-import cn.hutool.extra.qrcode.QrCodeUtil;
-import cn.hutool.extra.qrcode.QrConfig;
-import org.springframework.stereotype.Service;
-
-import javax.annotation.Resource;
-import java.io.File;
-import java.io.OutputStream;
-
-@Service
-public class QRCodeService {
-    @Resource
-    private QrConfig qrConfig;
-
-    public void generateFile(String content, File file) {
-        //生成到本地文件
-        QrCodeUtil.generate(content, qrConfig, file);
-    }
-
-    public void generateStream(String content, OutputStream outputStream) {
-        //输出到流
-        QrCodeUtil.generate(content, qrConfig, "png", outputStream);
-    }
-}

+ 1 - 1
project-framework/src/main/java/com/project/framework/config/ApplicationConfig.java

@@ -17,7 +17,7 @@ import java.util.TimeZone;
 // 表示通过aop框架暴露该代理对象,AopContext能够访问
 @EnableAspectJAutoProxy(exposeProxy = true)
 // 指定要扫描的Mapper类的包的路径
-@MapperScan("com.project.**.mapper")
+@MapperScan({"com.project.**.mapper", "com.xxl.job.admin.dao"})
 public class ApplicationConfig {
     /**
      * 时区配置

+ 1 - 0
project-framework/src/main/java/com/project/framework/config/SecurityConfig.java

@@ -124,6 +124,7 @@ public class SecurityConfig extends WebSecurityConfigurerAdapter {
 //                .antMatchers("/au/weiXinMp/getLoginUrl").anonymous()
 //                // 授权登录回调地址
                 .antMatchers("/large/**").anonymous()
+                .antMatchers("/xxl-job-admin/**").anonymous()
                 // 对于登录login 注册register 验证码captchaImage 允许匿名访问
                 .antMatchers("/login", "/register", "/captchaImage").anonymous()
                 // 静态资源,可匿名访问

+ 37 - 0
project-xxl-job/pom.xml

@@ -0,0 +1,37 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0"
+         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+    <parent>
+        <artifactId>project-service</artifactId>
+        <groupId>com.project</groupId>
+        <version>3.8.3</version>
+    </parent>
+    <modelVersion>4.0.0</modelVersion>
+
+    <groupId>com.xxl.job</groupId>
+    <artifactId>project-xxl-job</artifactId>
+
+    <properties>
+        <maven.compiler.source>8</maven.compiler.source>
+        <maven.compiler.target>8</maven.compiler.target>
+    </properties>
+
+    <dependencies>
+
+    <!-- 通用工具-->
+        <dependency>
+            <groupId>com.project</groupId>
+            <artifactId>project-common</artifactId>
+        </dependency>
+
+
+
+        <dependency>
+            <groupId>top.chenlq</groupId>
+            <artifactId>xxl-job-admin-core</artifactId>
+            <version>2.4.3</version>
+        </dependency>
+
+    </dependencies>
+</project>

+ 54 - 0
project-xxl-job/src/main/java/com/xxl/job/config/XxlJobConfig.java

@@ -0,0 +1,54 @@
+package com.xxl.job.config;
+
+import com.xxl.job.core.executor.impl.XxlJobSpringExecutor;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+
+/**
+ * @Description
+ * @Author bqyang
+ * @Date 2025/1/7 09:41
+ * @Version 1.0
+ */
+@Slf4j
+@Configuration
+public class XxlJobConfig {
+
+    @Value("${xxl.job.accessToken}")
+    private String accessToken;
+    @Value("${xxl.job.executor.appname}")
+    private String appname;
+
+    @Value("${xxl.job.executor.address}")
+    private String address;
+    @Value("${xxl.job.executor.ip}")
+    private String ip;
+    @Value("${server.port}")
+    private int port;
+    @Value("${xxl.job.executor.logpath}")
+    private String logPath;
+    @Value("${xxl.job.executor.logretentiondays}")
+    private int logRetentionDays;
+
+    public XxlJobConfig() {
+    }
+
+    @Bean
+    @ConditionalOnMissingBean
+    public XxlJobSpringExecutor xxlJobExecutor() {
+        log.info(">>>>>>>>>>> xxl-job config init <<<<<<<<<<<<<<");
+        XxlJobSpringExecutor xxlJobSpringExecutor = new XxlJobSpringExecutor();
+        xxlJobSpringExecutor.setAdminAddresses("http://localhost:"+port+"/xxl-job-admin");
+        xxlJobSpringExecutor.setAppname(this.appname);
+        xxlJobSpringExecutor.setAddress(this.address);
+        xxlJobSpringExecutor.setIp(this.ip);
+        xxlJobSpringExecutor.setPort(20000 + this.port);
+        xxlJobSpringExecutor.setAccessToken(this.accessToken);
+        xxlJobSpringExecutor.setLogPath(this.logPath);
+        xxlJobSpringExecutor.setLogRetentionDays(this.logRetentionDays);
+        return xxlJobSpringExecutor;
+    }
+}

+ 49 - 0
project-xxl-job/src/main/java/com/xxl/job/controller/DashboardController.java

@@ -0,0 +1,49 @@
+package com.xxl.job.controller;
+
+import com.xxl.job.core.biz.model.ReturnT;
+import com.xxl.job.service.XxlJobService;
+import org.springframework.beans.propertyeditors.CustomDateEditor;
+import org.springframework.web.bind.WebDataBinder;
+import org.springframework.web.bind.annotation.InitBinder;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+import javax.annotation.Resource;
+import java.text.SimpleDateFormat;
+import java.util.Date;
+import java.util.Map;
+
+/**
+ * @Description
+ * @Author bqyang
+ * @Date 2025/1/7 09:48
+ * @Version 1.0
+ */
+@RestController
+@RequestMapping("/xxl-job-admin")
+public class DashboardController {
+
+    @Resource
+    private XxlJobService xxlJobService;
+
+
+    @RequestMapping("/chartInfo")
+    public ReturnT<Map<String, Object>> chartInfo(Date startDate, Date endDate) {
+        ReturnT<Map<String, Object>> chartInfo = xxlJobService.chartInfo(startDate, endDate);
+        return chartInfo;
+    }
+
+
+    @InitBinder
+    public void initBinder(WebDataBinder binder) {
+        SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
+        dateFormat.setLenient(false);
+        binder.registerCustomEditor(Date.class, new CustomDateEditor(dateFormat, true));
+    }
+
+    @RequestMapping("/dashboardInfo")
+    public ReturnT<Map<String, Object>> dashboardInfo() {
+        Map<String, Object> dashboardInfo = xxlJobService.dashboardInfo();
+        return new ReturnT<>(dashboardInfo);
+    }
+}

+ 87 - 0
project-xxl-job/src/main/java/com/xxl/job/controller/JobApiController.java

@@ -0,0 +1,87 @@
+package com.xxl.job.controller;
+
+import com.xxl.job.admin.core.conf.XxlJobAdminConfig;
+import com.xxl.job.core.biz.AdminBiz;
+import com.xxl.job.core.biz.model.HandleCallbackParam;
+import com.xxl.job.core.biz.model.RegistryParam;
+import com.xxl.job.core.biz.model.ReturnT;
+import com.xxl.job.core.util.GsonTool;
+import com.xxl.job.core.util.XxlJobRemotingUtil;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.web.bind.annotation.PathVariable;
+import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+import javax.annotation.Resource;
+import javax.servlet.http.HttpServletRequest;
+import java.util.List;
+
+/**
+ * @Description
+ * @Author bqyang
+ * @Date 2025/1/7 09:49
+ * @Version 1.0
+ */
+@Slf4j
+@RestController
+@RequestMapping("/xxl-job-admin/api")
+public class JobApiController {
+
+    @Resource
+    private AdminBiz adminBiz;
+
+    /**
+     * api
+     *
+     * @param uri
+     * @param data
+     * @return
+     */
+    @RequestMapping("/{uri}")
+    public ReturnT<String> api(HttpServletRequest request, @PathVariable("uri") String uri, @RequestBody(required = false) String data) {
+
+        log.info("api invoked, uri-mapping={}, data={}", uri, data);
+        // valid
+        if (!"POST".equalsIgnoreCase(request.getMethod())) {
+            return new ReturnT<String>(ReturnT.FAIL_CODE, "invalid request, HttpMethod not support.");
+        }
+        if (uri == null || uri.trim().length() == 0) {
+            return new ReturnT<String>(ReturnT.FAIL_CODE, "invalid request, uri-mapping empty.");
+        }
+        if (XxlJobAdminConfig.getAdminConfig().getAccessToken() != null
+                && XxlJobAdminConfig.getAdminConfig().getAccessToken().trim().length() > 0
+                && !XxlJobAdminConfig.getAdminConfig().getAccessToken().equals(request.getHeader(XxlJobRemotingUtil.XXL_JOB_ACCESS_TOKEN))) {
+            return new ReturnT<String>(ReturnT.FAIL_CODE, "The access token is wrong.");
+        }
+
+        // services mapping
+        if ("callback".equals(uri)) {
+            List<HandleCallbackParam> callbackParamList = GsonTool.fromJson(data, List.class, HandleCallbackParam.class);
+            return adminBiz.callback(callbackParamList);
+        } else if ("registry".equals(uri)) {
+            RegistryParam registryParam = GsonTool.fromJson(data, RegistryParam.class);
+            log.info("registry api called, registryParam:" + registryParam);
+            return adminBiz.registry(registryParam);
+        } else if ("registryRemove".equals(uri)) {
+            RegistryParam registryParam = GsonTool.fromJson(data, RegistryParam.class);
+            return adminBiz.registryRemove(registryParam);
+        } else {
+            return new ReturnT<String>(ReturnT.FAIL_CODE, "invalid request, uri-mapping(" + uri + ") not found.");
+        }
+
+    }
+
+    //@RequestMapping("/registry")
+    public ReturnT<String> registry(@RequestBody(required = false) String data) {
+
+        log.info("api invoked, data={}", data);
+        // valid
+
+            RegistryParam registryParam = GsonTool.fromJson(data, RegistryParam.class);
+            log.info("registry api called, registryParam:" + registryParam);
+            return adminBiz.registry(registryParam);
+
+
+    }
+}

+ 185 - 0
project-xxl-job/src/main/java/com/xxl/job/controller/JobGroupController.java

@@ -0,0 +1,185 @@
+package com.xxl.job.controller;
+
+import com.xxl.job.admin.core.model.XxlJobGroup;
+import com.xxl.job.admin.core.model.XxlJobRegistry;
+import com.xxl.job.admin.core.util.I18nUtil;
+import com.xxl.job.admin.dao.XxlJobGroupDao;
+import com.xxl.job.admin.dao.XxlJobInfoDao;
+import com.xxl.job.admin.dao.XxlJobRegistryDao;
+import com.xxl.job.core.biz.model.ReturnT;
+import com.xxl.job.core.enums.RegistryConfig;
+import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RequestParam;
+import org.springframework.web.bind.annotation.RestController;
+
+import javax.annotation.Resource;
+import java.util.*;
+
+/**
+ * @Description
+ * @Author bqyang
+ * @Date 2025/1/7 09:50
+ * @Version 1.0
+ */
+@RestController
+@RequestMapping("/xxl-job-admin/jobgroup")
+public class JobGroupController {
+
+    @Resource
+    public XxlJobInfoDao xxlJobInfoDao;
+    @Resource
+    public XxlJobGroupDao xxlJobGroupDao;
+    @Resource
+    private XxlJobRegistryDao xxlJobRegistryDao;
+
+    @RequestMapping("/pageList")
+    public Map<String, Object> pageList(@RequestParam(required = false, defaultValue = "0") int start,
+                                        @RequestParam(required = false, defaultValue = "10") int length,
+                                        String appname, String title) {
+
+        // page query
+        List<XxlJobGroup> list = xxlJobGroupDao.pageList(start, length, appname, title);
+        int list_count = xxlJobGroupDao.pageListCount(start, length, appname, title);
+
+        // package result
+        Map<String, Object> maps = new HashMap<String, Object>();
+        maps.put("recordsTotal", list_count);        // 总记录数
+        maps.put("recordsFiltered", list_count);    // 过滤后的总记录数
+        maps.put("data", list);                    // 分页列表
+        return maps;
+    }
+
+    @RequestMapping("/add")
+    public ReturnT<String> add(@RequestBody XxlJobGroup xxlJobGroup) {
+
+        // valid
+        if (xxlJobGroup.getAppname() == null || xxlJobGroup.getAppname().trim().length() == 0) {
+            return new ReturnT<String>(500, (I18nUtil.getString("system_please_input") + "AppName"));
+        }
+        if (xxlJobGroup.getAppname().length() < 4 || xxlJobGroup.getAppname().length() > 64) {
+            return new ReturnT<String>(500, I18nUtil.getString("jobgroup_field_appname_length"));
+        }
+        if (xxlJobGroup.getAppname().contains(">") || xxlJobGroup.getAppname().contains("<")) {
+            return new ReturnT<String>(500, "AppName" + I18nUtil.getString("system_unvalid"));
+        }
+        if (xxlJobGroup.getTitle() == null || xxlJobGroup.getTitle().trim().length() == 0) {
+            return new ReturnT<String>(500, (I18nUtil.getString("system_please_input") + I18nUtil.getString("jobgroup_field_title")));
+        }
+        if (xxlJobGroup.getTitle().contains(">") || xxlJobGroup.getTitle().contains("<")) {
+            return new ReturnT<String>(500, I18nUtil.getString("jobgroup_field_title") + I18nUtil.getString("system_unvalid"));
+        }
+        if (xxlJobGroup.getAddressType() != 0) {
+            if (xxlJobGroup.getAddressList() == null || xxlJobGroup.getAddressList().trim().length() == 0) {
+                return new ReturnT<String>(500, I18nUtil.getString("jobgroup_field_addressType_limit"));
+            }
+            if (xxlJobGroup.getAddressList().contains(">") || xxlJobGroup.getAddressList().contains("<")) {
+                return new ReturnT<String>(500, I18nUtil.getString("jobgroup_field_registryList") + I18nUtil.getString("system_unvalid"));
+            }
+
+            String[] addresss = xxlJobGroup.getAddressList().split(",");
+            for (String item : addresss) {
+                if (item == null || item.trim().length() == 0) {
+                    return new ReturnT<String>(500, I18nUtil.getString("jobgroup_field_registryList_unvalid"));
+                }
+            }
+        }
+
+        // process
+        xxlJobGroup.setUpdateTime(new Date());
+
+        int ret = xxlJobGroupDao.save(xxlJobGroup);
+        return (ret > 0) ? ReturnT.SUCCESS : ReturnT.FAIL;
+    }
+
+    @RequestMapping("/update")
+    public ReturnT<String> update(@RequestBody XxlJobGroup xxlJobGroup) {
+        // valid
+        if (xxlJobGroup.getAppname() == null || xxlJobGroup.getAppname().trim().length() == 0) {
+            return new ReturnT<String>(500, (I18nUtil.getString("system_please_input") + "AppName"));
+        }
+        if (xxlJobGroup.getAppname().length() < 4 || xxlJobGroup.getAppname().length() > 64) {
+            return new ReturnT<String>(500, I18nUtil.getString("jobgroup_field_appname_length"));
+        }
+        if (xxlJobGroup.getTitle() == null || xxlJobGroup.getTitle().trim().length() == 0) {
+            return new ReturnT<String>(500, (I18nUtil.getString("system_please_input") + I18nUtil.getString("jobgroup_field_title")));
+        }
+        if (xxlJobGroup.getAddressType() == 0) {
+            // 0=自动注册
+            List<String> registryList = findRegistryByAppName(xxlJobGroup.getAppname());
+            String addressListStr = null;
+            if (registryList != null && !registryList.isEmpty()) {
+                Collections.sort(registryList);
+                addressListStr = "";
+                for (String item : registryList) {
+                    addressListStr += item + ",";
+                }
+                addressListStr = addressListStr.substring(0, addressListStr.length() - 1);
+            }
+            xxlJobGroup.setAddressList(addressListStr);
+        } else {
+            // 1=手动录入
+            if (xxlJobGroup.getAddressList() == null || xxlJobGroup.getAddressList().trim().length() == 0) {
+                return new ReturnT<String>(500, I18nUtil.getString("jobgroup_field_addressType_limit"));
+            }
+            String[] addresss = xxlJobGroup.getAddressList().split(",");
+            for (String item : addresss) {
+                if (item == null || item.trim().length() == 0) {
+                    return new ReturnT<String>(500, I18nUtil.getString("jobgroup_field_registryList_unvalid"));
+                }
+            }
+        }
+
+        // process
+        xxlJobGroup.setUpdateTime(new Date());
+
+        int ret = xxlJobGroupDao.update(xxlJobGroup);
+        return (ret > 0) ? ReturnT.SUCCESS : ReturnT.FAIL;
+    }
+
+    private List<String> findRegistryByAppName(String appnameParam) {
+        HashMap<String, List<String>> appAddressMap = new HashMap<String, List<String>>();
+        List<XxlJobRegistry> list = xxlJobRegistryDao.findAll(RegistryConfig.DEAD_TIMEOUT, new Date());
+        if (list != null) {
+            for (XxlJobRegistry item : list) {
+                if (RegistryConfig.RegistType.EXECUTOR.name().equals(item.getRegistryGroup())) {
+                    String appname = item.getRegistryKey();
+                    List<String> registryList = appAddressMap.get(appname);
+                    if (registryList == null) {
+                        registryList = new ArrayList<String>();
+                    }
+
+                    if (!registryList.contains(item.getRegistryValue())) {
+                        registryList.add(item.getRegistryValue());
+                    }
+                    appAddressMap.put(appname, registryList);
+                }
+            }
+        }
+        return appAddressMap.get(appnameParam);
+    }
+
+    @RequestMapping("/remove")
+    public ReturnT<String> remove(int id) {
+
+        // valid
+        int count = xxlJobInfoDao.pageListCount(0, 10, id, -1, null, null, null);
+        if (count > 0) {
+            return new ReturnT<String>(500, I18nUtil.getString("jobgroup_del_limit_0"));
+        }
+
+        List<XxlJobGroup> allList = xxlJobGroupDao.findAll();
+        if (allList.size() == 1) {
+            return new ReturnT<String>(500, I18nUtil.getString("jobgroup_del_limit_1"));
+        }
+
+        int ret = xxlJobGroupDao.remove(id);
+        return (ret > 0) ? ReturnT.SUCCESS : ReturnT.FAIL;
+    }
+
+    @RequestMapping("/loadById")
+    public ReturnT<XxlJobGroup> loadById(int id) {
+        XxlJobGroup jobGroup = xxlJobGroupDao.load(id);
+        return jobGroup != null ? new ReturnT<XxlJobGroup>(jobGroup) : new ReturnT<XxlJobGroup>(ReturnT.FAIL_CODE, null);
+    }
+}

+ 122 - 0
project-xxl-job/src/main/java/com/xxl/job/controller/JobInfoController.java

@@ -0,0 +1,122 @@
+package com.xxl.job.controller;
+
+import com.project.common.utils.SecurityUtils;
+import com.xxl.job.admin.core.model.XxlJobInfo;
+import com.xxl.job.admin.core.model.XxlJobUser;
+import com.xxl.job.admin.core.thread.JobScheduleHelper;
+import com.xxl.job.admin.core.thread.JobTriggerPoolHelper;
+import com.xxl.job.admin.core.trigger.TriggerTypeEnum;
+import com.xxl.job.admin.core.util.I18nUtil;
+import com.xxl.job.admin.dao.XxlJobInfoDao;
+import com.xxl.job.admin.dao.XxlJobUserDao;
+import com.xxl.job.core.biz.model.ReturnT;
+import com.xxl.job.core.util.DateUtil;
+import com.xxl.job.service.XxlJobService;
+import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RequestParam;
+import org.springframework.web.bind.annotation.RestController;
+
+import javax.annotation.Resource;
+import javax.servlet.http.HttpServletRequest;
+import java.util.ArrayList;
+import java.util.Date;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * @Description
+ * @Author bqyang
+ * @Date 2025/1/7 09:52
+ * @Version 1.0
+ */
+@RestController
+@RequestMapping("/xxl-job-admin/jobinfo")
+public class JobInfoController {
+
+    @Resource
+    private XxlJobService xxlJobService;
+    @Resource
+    private XxlJobInfoDao xxlJobInfoDao;
+    @Resource
+    private XxlJobUserDao xxlJobUserDao;
+
+
+    @RequestMapping("/pageList")
+    public Map<String, Object> pageList(@RequestParam(required = false, defaultValue = "0") int start,
+                                        @RequestParam(required = false, defaultValue = "10") int length,
+                                        int jobGroup, int triggerStatus, String jobDesc, String executorHandler, String author) {
+        XxlJobUser loginUser = xxlJobUserDao.loadByUserName(SecurityUtils.getUsername());
+        return xxlJobService.pageList(loginUser, start, length, jobGroup, triggerStatus, jobDesc, executorHandler, author);
+    }
+
+    @RequestMapping("/add")
+    public ReturnT<String> add(@RequestBody XxlJobInfo jobInfo) {
+        return xxlJobService.add(jobInfo);
+    }
+
+    @RequestMapping("/update")
+    public ReturnT<String> update(@RequestBody XxlJobInfo jobInfo) {
+        return xxlJobService.update(jobInfo);
+    }
+
+    @RequestMapping("/remove")
+    public ReturnT<String> remove(HttpServletRequest request, int id) {
+        XxlJobInfo jobInfo = xxlJobInfoDao.loadById(id);
+        return xxlJobService.remove(id);
+    }
+
+    @RequestMapping("/stop")
+    public ReturnT<String> pause(HttpServletRequest request, int id) {
+        XxlJobInfo jobInfo = xxlJobInfoDao.loadById(id);
+        return xxlJobService.stop(id);
+    }
+
+    @RequestMapping("/start")
+    public ReturnT<String> start(HttpServletRequest request, int id) {
+        XxlJobInfo jobInfo = xxlJobInfoDao.loadById(id);
+        return xxlJobService.start(id);
+    }
+
+    /**
+     * 执行一次
+     * @param id
+     * @param executorParam
+     * @param addressList
+     * @return
+     */
+    @RequestMapping("/trigger")
+    public ReturnT<String> triggerJob(int id, String executorParam, String addressList) {
+        // force cover job param
+        if (executorParam == null) {
+            executorParam = "";
+        }
+        JobTriggerPoolHelper.trigger(id, TriggerTypeEnum.MANUAL, -1, null, executorParam, addressList);
+        return ReturnT.SUCCESS;
+    }
+
+    @RequestMapping("/nextTriggerTime")
+    public ReturnT<List<String>> nextTriggerTime(String scheduleType, String scheduleConf) {
+
+        XxlJobInfo paramXxlJobInfo = new XxlJobInfo();
+        paramXxlJobInfo.setScheduleType(scheduleType);
+        paramXxlJobInfo.setScheduleConf(scheduleConf);
+
+        List<String> result = new ArrayList<>();
+        try {
+            Date lastTime = new Date();
+            for (int i = 0; i < 5; i++) {
+                lastTime = JobScheduleHelper.generateNextValidTime(paramXxlJobInfo, lastTime);
+                if (lastTime != null) {
+                    result.add(DateUtil.formatDateTime(lastTime));
+                } else {
+                    break;
+                }
+            }
+        } catch (Exception e) {
+            return new ReturnT<List<String>>(ReturnT.FAIL_CODE, (I18nUtil.getString("schedule_type") + I18nUtil.getString("system_unvalid")) + e.getMessage());
+        }
+        return new ReturnT<List<String>>(result);
+
+    }
+}

+ 170 - 0
project-xxl-job/src/main/java/com/xxl/job/controller/JobLogController.java

@@ -0,0 +1,170 @@
+package com.xxl.job.controller;
+
+import com.xxl.job.admin.core.complete.XxlJobCompleter;
+import com.xxl.job.admin.core.model.XxlJobInfo;
+import com.xxl.job.admin.core.model.XxlJobLog;
+import com.xxl.job.admin.core.scheduler.XxlJobScheduler;
+import com.xxl.job.admin.core.util.I18nUtil;
+import com.xxl.job.admin.dao.XxlJobInfoDao;
+import com.xxl.job.admin.dao.XxlJobLogDao;
+import com.xxl.job.core.biz.ExecutorBiz;
+import com.xxl.job.core.biz.model.KillParam;
+import com.xxl.job.core.biz.model.LogParam;
+import com.xxl.job.core.biz.model.LogResult;
+import com.xxl.job.core.biz.model.ReturnT;
+import com.xxl.job.core.util.DateUtil;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RequestParam;
+import org.springframework.web.bind.annotation.RestController;
+
+import javax.annotation.Resource;
+import java.util.Date;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * @Description
+ * @Author bqyang
+ * @Date 2025/1/7 09:54
+ * @Version 1.0
+ */
+@RestController
+@RequestMapping("/xxl-job-admin/joblog")
+public class JobLogController {
+
+    @Resource
+    public XxlJobInfoDao xxlJobInfoDao;
+    @Resource
+    private XxlJobLogDao xxlJobLogDao;
+
+    @RequestMapping("/getJobsByGroup")
+    public ReturnT<List<XxlJobInfo>> getJobsByGroup(int jobGroup) {
+        List<XxlJobInfo> list = xxlJobInfoDao.getJobsByGroup(jobGroup);
+        return new ReturnT<List<XxlJobInfo>>(list);
+    }
+
+    @RequestMapping("/pageList")
+    public Map<String, Object> pageList(@RequestParam(required = false, defaultValue = "0") int start,
+                                        @RequestParam(required = false, defaultValue = "10") int length,
+                                        int jobGroup, int jobId, int logStatus, String filterTime) {
+
+        // parse param
+        Date triggerTimeStart = null;
+        Date triggerTimeEnd = null;
+        if (filterTime != null && filterTime.trim().length() > 0) {
+            String[] temp = filterTime.split(" - ");
+            if (temp.length == 2) {
+                triggerTimeStart = DateUtil.parseDateTime(temp[0]);
+                triggerTimeEnd = DateUtil.parseDateTime(temp[1]);
+            }
+        }
+
+        // page query
+        List<XxlJobLog> list = xxlJobLogDao.pageList(start, length, jobGroup, jobId, triggerTimeStart, triggerTimeEnd, logStatus);
+        int list_count = xxlJobLogDao.pageListCount(start, length, jobGroup, jobId, triggerTimeStart, triggerTimeEnd, logStatus);
+
+        // package result
+        Map<String, Object> maps = new HashMap<String, Object>();
+        maps.put("recordsTotal", list_count);        // 总记录数
+        maps.put("recordsFiltered", list_count);    // 过滤后的总记录数
+        maps.put("data", list);                    // 分页列表
+        return maps;
+    }
+
+    @RequestMapping("/logDetailCat")
+    public ReturnT<LogResult> logDetailCat(long logId, int fromLineNum) {
+        try {
+            // valid
+            XxlJobLog jobLog = xxlJobLogDao.load(logId);
+            if (jobLog == null) {
+                return new ReturnT<LogResult>(ReturnT.FAIL_CODE, I18nUtil.getString("joblog_logid_unvalid"));
+            }
+
+            // log cat
+            ExecutorBiz executorBiz = XxlJobScheduler.getExecutorBiz(jobLog.getExecutorAddress());
+            ReturnT<LogResult> logResult = executorBiz.log(new LogParam(jobLog.getTriggerTime().getTime(), logId, fromLineNum));
+
+            // is end
+            if (logResult.getContent() != null && logResult.getContent().getFromLineNum() > logResult.getContent().getToLineNum()) {
+                if (jobLog.getHandleCode() > 0) {
+                    logResult.getContent().setEnd(true);
+                }
+            }
+
+            return logResult;
+        } catch (Exception e) {
+            return new ReturnT<LogResult>(ReturnT.FAIL_CODE, e.getMessage());
+        }
+    }
+
+    @RequestMapping("/logKill")
+    public ReturnT<String> logKill(int id) {
+        // base check
+        XxlJobLog log = xxlJobLogDao.load(id);
+        XxlJobInfo jobInfo = xxlJobInfoDao.loadById(log.getJobId());
+        if (jobInfo == null) {
+            return new ReturnT<String>(500, I18nUtil.getString("jobinfo_glue_jobid_unvalid"));
+        }
+        if (ReturnT.SUCCESS_CODE != log.getTriggerCode()) {
+            return new ReturnT<String>(500, I18nUtil.getString("joblog_kill_log_limit"));
+        }
+
+        // request of kill
+        ReturnT<String> runResult = null;
+        try {
+            ExecutorBiz executorBiz = XxlJobScheduler.getExecutorBiz(log.getExecutorAddress());
+            runResult = executorBiz.kill(new KillParam(jobInfo.getId()));
+        } catch (Exception e) {
+            runResult = new ReturnT<String>(500, e.getMessage());
+        }
+
+        if (ReturnT.SUCCESS_CODE == runResult.getCode()) {
+            log.setHandleCode(ReturnT.FAIL_CODE);
+            log.setHandleMsg(I18nUtil.getString("joblog_kill_log_byman") + ":" + (runResult.getMsg() != null ? runResult.getMsg() : ""));
+            log.setHandleTime(new Date());
+            XxlJobCompleter.updateHandleInfoAndFinish(log);
+            return new ReturnT<String>(runResult.getMsg());
+        } else {
+            return new ReturnT<String>(500, runResult.getMsg());
+        }
+    }
+
+    @RequestMapping("/clearLog")
+    public ReturnT<String> clearLog(int jobGroup, int jobId, int type) {
+
+        Date clearBeforeTime = null;
+        int clearBeforeNum = 0;
+        if (type == 1) {
+            clearBeforeTime = DateUtil.addMonths(new Date(), -1);    // 清理一个月之前日志数据
+        } else if (type == 2) {
+            clearBeforeTime = DateUtil.addMonths(new Date(), -3);    // 清理三个月之前日志数据
+        } else if (type == 3) {
+            clearBeforeTime = DateUtil.addMonths(new Date(), -6);    // 清理六个月之前日志数据
+        } else if (type == 4) {
+            clearBeforeTime = DateUtil.addYears(new Date(), -1);    // 清理一年之前日志数据
+        } else if (type == 5) {
+            clearBeforeNum = 1000;        // 清理一千条以前日志数据
+        } else if (type == 6) {
+            clearBeforeNum = 10000;        // 清理一万条以前日志数据
+        } else if (type == 7) {
+            clearBeforeNum = 30000;        // 清理三万条以前日志数据
+        } else if (type == 8) {
+            clearBeforeNum = 100000;    // 清理十万条以前日志数据
+        } else if (type == 9) {
+            clearBeforeNum = 0;            // 清理所有日志数据
+        } else {
+            return new ReturnT<String>(ReturnT.FAIL_CODE, I18nUtil.getString("joblog_clean_type_unvalid"));
+        }
+
+        List<Long> logIds = null;
+        do {
+            logIds = xxlJobLogDao.findClearLogIds(jobGroup, jobId, clearBeforeTime, clearBeforeNum, 1000);
+            if (logIds != null && logIds.size() > 0) {
+                xxlJobLogDao.clearLog(logIds);
+            }
+        } while (logIds != null && logIds.size() > 0);
+
+        return ReturnT.SUCCESS;
+    }
+}

+ 36 - 0
project-xxl-job/src/main/java/com/xxl/job/service/AdminBizImpl.java

@@ -0,0 +1,36 @@
+package com.xxl.job.service;
+
+import com.xxl.job.admin.core.thread.JobCompleteHelper;
+import com.xxl.job.admin.core.thread.JobRegistryHelper;
+import com.xxl.job.core.biz.AdminBiz;
+import com.xxl.job.core.biz.model.HandleCallbackParam;
+import com.xxl.job.core.biz.model.RegistryParam;
+import com.xxl.job.core.biz.model.ReturnT;
+import org.springframework.stereotype.Service;
+
+import java.util.List;
+
+/**
+ * @Description
+ * @Author bqyang
+ * @Date 2025/1/7 09:46
+ * @Version 1.0
+ */
+@Service
+public class AdminBizImpl implements AdminBiz {
+
+    @Override
+    public ReturnT<String> callback(List<HandleCallbackParam> callbackParamList) {
+        return JobCompleteHelper.getInstance().callback(callbackParamList);
+    }
+
+    @Override
+    public ReturnT<String> registry(RegistryParam registryParam) {
+        return JobRegistryHelper.getInstance().registry(registryParam);
+    }
+
+    @Override
+    public ReturnT<String> registryRemove(RegistryParam registryParam) {
+        return JobRegistryHelper.getInstance().registryRemove(registryParam);
+    }
+}

+ 166 - 0
project-xxl-job/src/main/java/com/xxl/job/service/XxlJobService.java

@@ -0,0 +1,166 @@
+package com.xxl.job.service;
+
+import com.xxl.job.admin.core.XxlJobTool;
+import com.xxl.job.admin.core.model.XxlJobGroup;
+import com.xxl.job.admin.core.model.XxlJobInfo;
+import com.xxl.job.admin.core.model.XxlJobLogReport;
+import com.xxl.job.admin.core.model.XxlJobUser;
+import com.xxl.job.admin.dao.XxlJobGroupDao;
+import com.xxl.job.admin.dao.XxlJobInfoDao;
+import com.xxl.job.admin.dao.XxlJobLogReportDao;
+import com.xxl.job.core.biz.model.ReturnT;
+import com.xxl.job.core.util.DateUtil;
+import org.springframework.stereotype.Service;
+
+import javax.annotation.Resource;
+import java.util.*;
+
+/**
+ * @Description
+ * @Author bqyang
+ * @Date 2025/1/7 09:46
+ * @Version 1.0
+ */
+@Service
+public class XxlJobService {
+
+    @Resource
+    private XxlJobGroupDao xxlJobGroupDao;
+    @Resource
+    private XxlJobInfoDao xxlJobInfoDao;
+    @Resource
+    private XxlJobLogReportDao xxlJobLogReportDao;
+    @Resource
+    private XxlJobTool xxlJobTool;
+
+    public Map<String, Object> pageList(XxlJobUser loginUser, int start, int length, int jobGroup,
+                                        int triggerStatus, String jobDesc, String executorHandler, String author) {
+
+        // page list
+        List<XxlJobInfo> list = xxlJobInfoDao.pageList(start, length, jobGroup, triggerStatus, jobDesc, executorHandler, author);
+        int list_count = xxlJobInfoDao.pageListCount(start, length, jobGroup, triggerStatus, jobDesc, executorHandler, author);
+
+        // package result
+        Map<String, Object> maps = new HashMap<String, Object>();
+        maps.put("recordsTotal", list_count);        // 总记录数
+        maps.put("recordsFiltered", list_count);    // 过滤后的总记录数
+        maps.put("data", list);                    // 分页列表
+        return maps;
+    }
+
+    public ReturnT<String> add(XxlJobInfo jobInfo) {
+        xxlJobTool.add(jobInfo);
+        return new ReturnT<String>(String.valueOf(jobInfo.getId()));
+    }
+
+
+    public ReturnT<String> update(XxlJobInfo jobInfo) {
+        xxlJobTool.update(jobInfo);
+        return ReturnT.SUCCESS;
+    }
+
+    public ReturnT<String> remove(int id) {
+        XxlJobInfo xxlJobInfo = xxlJobInfoDao.loadById(id);
+        if (xxlJobInfo == null) {
+            return ReturnT.SUCCESS;
+        }
+        xxlJobTool.remove(id);
+        return ReturnT.SUCCESS;
+    }
+
+    public ReturnT<String> start(int id) {
+        XxlJobInfo xxlJobInfo = xxlJobInfoDao.loadById(id);
+        xxlJobTool.start(xxlJobInfo);
+        return ReturnT.SUCCESS;
+    }
+
+    public ReturnT<String> stop(int id) {
+        XxlJobInfo xxlJobInfo = xxlJobInfoDao.loadById(id);
+        xxlJobTool.stop(id);
+        return ReturnT.SUCCESS;
+    }
+
+    public Map<String, Object> dashboardInfo() {
+
+        int jobInfoCount = xxlJobInfoDao.findAllCount();
+        int jobLogCount = 0;
+        int jobLogSuccessCount = 0;
+        XxlJobLogReport xxlJobLogReport = xxlJobLogReportDao.queryLogReportTotal();
+        if (xxlJobLogReport != null) {
+            jobLogCount = xxlJobLogReport.getRunningCount() + xxlJobLogReport.getSucCount() + xxlJobLogReport.getFailCount();
+            jobLogSuccessCount = xxlJobLogReport.getSucCount();
+        }
+
+        // executor count
+        Set<String> executorAddressSet = new HashSet<String>();
+        List<XxlJobGroup> groupList = xxlJobGroupDao.findAll();
+
+        if (groupList != null && !groupList.isEmpty()) {
+            for (XxlJobGroup group : groupList) {
+                if (group.getRegistryList() != null && !group.getRegistryList().isEmpty()) {
+                    executorAddressSet.addAll(group.getRegistryList());
+                }
+            }
+        }
+
+        int executorCount = executorAddressSet.size();
+
+        Map<String, Object> dashboardMap = new HashMap<String, Object>();
+        dashboardMap.put("jobInfoCount", jobInfoCount);
+        dashboardMap.put("jobLogCount", jobLogCount);
+        dashboardMap.put("jobLogSuccessCount", jobLogSuccessCount);
+        dashboardMap.put("executorCount", executorCount);
+        return dashboardMap;
+    }
+
+    public ReturnT<Map<String, Object>> chartInfo(Date startDate, Date endDate) {
+
+        // process
+        List<String> triggerDayList = new ArrayList<String>();
+        List<Integer> triggerDayCountRunningList = new ArrayList<Integer>();
+        List<Integer> triggerDayCountSucList = new ArrayList<Integer>();
+        List<Integer> triggerDayCountFailList = new ArrayList<Integer>();
+        int triggerCountRunningTotal = 0;
+        int triggerCountSucTotal = 0;
+        int triggerCountFailTotal = 0;
+
+        List<XxlJobLogReport> logReportList = xxlJobLogReportDao.queryLogReport(startDate, endDate);
+
+        if (logReportList != null && logReportList.size() > 0) {
+            for (XxlJobLogReport item : logReportList) {
+                String day = DateUtil.formatDate(item.getTriggerDay());
+                int triggerDayCountRunning = item.getRunningCount();
+                int triggerDayCountSuc = item.getSucCount();
+                int triggerDayCountFail = item.getFailCount();
+
+                triggerDayList.add(day);
+                triggerDayCountRunningList.add(triggerDayCountRunning);
+                triggerDayCountSucList.add(triggerDayCountSuc);
+                triggerDayCountFailList.add(triggerDayCountFail);
+
+                triggerCountRunningTotal += triggerDayCountRunning;
+                triggerCountSucTotal += triggerDayCountSuc;
+                triggerCountFailTotal += triggerDayCountFail;
+            }
+        } else {
+            for (int i = -6; i <= 0; i++) {
+                triggerDayList.add(DateUtil.formatDate(DateUtil.addDays(new Date(), i)));
+                triggerDayCountRunningList.add(0);
+                triggerDayCountSucList.add(0);
+                triggerDayCountFailList.add(0);
+            }
+        }
+
+        Map<String, Object> result = new HashMap<String, Object>();
+        result.put("triggerDayList", triggerDayList);
+        result.put("triggerDayCountRunningList", triggerDayCountRunningList);
+        result.put("triggerDayCountSucList", triggerDayCountSucList);
+        result.put("triggerDayCountFailList", triggerDayCountFailList);
+
+        result.put("triggerCountRunningTotal", triggerCountRunningTotal);
+        result.put("triggerCountSucTotal", triggerCountSucTotal);
+        result.put("triggerCountFailTotal", triggerCountFailTotal);
+
+        return new ReturnT<Map<String, Object>>(result);
+    }
+}

Файловите разлики са ограничени, защото са твърде много
+ 98 - 0
project-zcustom/src/main/java/com/project/zcustom/controller/TestToolsController.java


+ 2 - 9
project-zcustom/src/main/java/com/project/zcustom/controller/video/PlatVideoController.java

@@ -98,11 +98,6 @@ public class PlatVideoController extends BaseController {
                         // ...
                     }
 
-//                    String videoUrl = cache.getVideoUrl();
-                    //新增摄像头缓存的用户数据
-//                    cache.getUserIds().add(userId);
-//                    log.info("查看视频,已有推流:processConcurrentHashMap:" + ProcessConstant.processConcurrentHashMap);
-//                    return Result.data(videoUrl);
                 }
                 String resolution = resultPO.getResolution();
                 //组合执行的进程命令:海康威视
@@ -113,8 +108,8 @@ public class PlatVideoController extends BaseController {
                 command.add("-i");
                 command.add(resultPO.getUrl());
                 command.add("-vcodec");
-                command.add("libx264");//h264编码====山西专用。  解决报错:Video codec hevc not compatible with flv
-//                command.add("copy");
+                //h264编码====山西专用。  解决报错:Video codec hevc not compatible with flv
+                command.add("libx264");
                 command.add("-acodec");
                 command.add("copy");
 
@@ -126,8 +121,6 @@ public class PlatVideoController extends BaseController {
                 command.add("-max_delay");
                 command.add("100000");
                 //
-
-
                 command.add("-f");
                 command.add("flv");
 

Някои файлове не бяха показани, защото твърде много файлове са промени