quartz整合前端vue加后端springboot

因工作需求,需要能修改定时的任务,前端vue3,后端是springboot

看看页面效果:

首先maven加上引入


        <dependency>
            <groupId>org.quartz-scheduler</groupId>
            <artifactId>quartz</artifactId>
            <version>2.3.1</version>
        </dependency>

然后yaml加上配置(Quartz就这点好,自动给你建表了)

#服务器配置
server:
  port: 8080
  undertow:
    threads:
      # 设置IO线程数, 它主要执行非阻塞的任务,它们会负责多个连接, 默认设置每个CPU核心一个线程
      io: 16
      # 阻塞任务线程池, 当执行类似servlet请求阻塞操作, undertow会从这个线程池中取得线程,它的值设置取决于系统的负载
      worker: 400
    # 以下的配置会影响buffer,这些buffer会用于服务器连接的IO操作,有点类似netty的池化内存管理
    buffer-size: 1024
    # 是否分配的直接内存
    direct-buffers: true

spring:
  datasource:
    driver-class-name: com.mysql.cj.jdbc.Driver
    #driver-class-name: org.postgresql.Driver
    #driver-class-name: oracle.jdbc.OracleDriver
    #driver-class-name: com.microsoft.sqlserver.jdbc.SQLServerDriver
    druid:
      # MySql、PostgreSQL、SqlServer、DaMeng校验
      validation-query: select 1
      # Oracle、YashanDB校验
      #oracle: true
      #validation-query: select 1 from dual
      validation-query-timeout: 2000
      initial-size: 5
      max-active: 20
      min-idle: 5
      max-wait: 60000
      test-on-borrow: false
      test-on-return: false
      test-while-idle: true
      time-between-eviction-runs-millis: 60000
      min-evictable-idle-time-millis: 300000
      stat-view-servlet:
        enabled: true
        login-username: 
        login-password: 
      web-stat-filter:
        enabled: true
        url-pattern: /*
        exclusions: '*.js,*.gif,*.jpg,*.bmp,*.png,*.css,*.ico,/druid/*'
        session-stat-enable: true
        session-stat-max-count: 10
  quartz:
    # 任务存储类型
    job-store-type: "jdbc"
    # 关闭时等待任务完成
    wait-for-jobs-to-complete-on-shutdown: false
    # 是否覆盖已有的任务
    overwrite-existing-jobs: true
    # 是否自动启动计划程序
    auto-startup: true
    # 延迟启动
    startup-delay: 0s
    jdbc:
      # 数据库架构初始化模式(never:从不进行初始化;always:每次都清空数据库进行初始化;embedded:只初始化内存数据库(默认值))
      initialize-schema: "always"#todo 后续改
    # 相关属性配置
    properties:
      org:
        quartz:
          scheduler:
            # 调度器实例名称
            instanceName: QuartzScheduler
            # 分布式节点ID自动生成
            instanceId: AUTO
          jobStore:
            class: org.springframework.scheduling.quartz.LocalDataSourceJobStore
            driverDelegateClass: org.quartz.impl.jdbcjobstore.StdJDBCDelegate
            # 表前缀
            tablePrefix: QRTZ_
            # 是否开启集群
            isClustered: true
            # 数据源别名(自定义)
            dataSource: quartz
            # 分布式节点有效性检查时间间隔(毫秒)
            clusterCheckinInterval: 10000
            useProperties: false
          # 线程池配置
          threadPool:
            class: org.quartz.simpl.SimpleThreadPool
            threadCount: 10
            threadPriority: 5
            threadsInheritContextClassLoaderOfInitializingThread: true

然后开始正式后台代码:

package org.springblade.etl.source.controller;

import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.github.xiaoymin.knife4j.annotations.ApiOperationSupport;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
import org.springblade.core.tool.api.R;
import org.springblade.core.tool.utils.Func;
import org.springblade.etl.source.entity.JobInfo;
import org.springblade.etl.source.service.QuartzService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

@RestController
@RequestMapping("/quartz")
public class QuartzController {

    @Autowired
    private QuartzService quartzService;
    //创建任务
    @PostMapping("/save")
    public R createJob(@RequestBody JobInfo jobInfo) {
        return quartzService.addCronJob(jobInfo.getJobName(), jobInfo.getCron(), "org.springblade.etl.source.task.TaskJob").equals("SUCCESS")?R.status(true):R.status(false);//todo 类名写在这
    }
    //删除任务
    @PostMapping("/remove")
    public R deleteJob(@RequestParam("jobName")String jobName) {
        return quartzService.deleteCronJob(jobName, null, null, null).equals("SUCCESS")?R.status(true):R.status(false);
    }
    //执行一次
    @PostMapping("/executeImmediately")
    public String executeImmediately(@RequestBody JobInfo jobInfo) {
        return quartzService.executeImmediately(jobInfo.getJobName(), "org.springblade.etl.source.task.TaskJob");
    }


    //获取任务状态
    @PostMapping("/detail")
    public R<JobInfo> getJobStatus(@RequestParam("jobName")String jobName) {
        return R.data(quartzService.getJobStatus(jobName, null));
    }

    //获取所有任务
    @PostMapping("/list")
    public R getAllJob() {
        // 创建分页对象,指定当前页码和每页显示的数量
        long currentPage = 1; // 当前页码
        long pageSize = 10; // 每页显示数量
        Page<JobInfo> page = new Page<>(currentPage, pageSize);
        page.setRecords(quartzService.getAllJob());
        return R.data(page);
    }

    //修改定时任务时间
    @PostMapping("/submit")
    public R updateJob(@RequestBody JobInfo jobInfo) {
        quartzService.deleteCronJob(jobInfo.getJobName(), jobInfo.getJobGroup(), jobInfo.getTriggerName(), jobInfo.getTriggerGroup());
        return quartzService.addCronJob(jobInfo.getJobName(), jobInfo.getCron(), "org.springblade.etl.source.task.TaskJob").equals("SUCCESS")?R.status(true):R.status(false);
    }


}
package org.springblade.etl.source.service;

import org.springblade.etl.source.entity.JobInfo;

import java.util.List;

public interface QuartzService {

    /**
     * 新增
     *
     * @param jobName
     * @param cron
     * @param jobClassName
     * @return
     */
    String addCronJob(String jobName, String cron, String jobClassName);

    /**
     * 停止
     *
     * @param jobName
     * @param jobGroup
     * @param triggerName
     * @param triggerGroup
     * @return
     */
    String deleteCronJob(String jobName, String jobGroup, String triggerName, String triggerGroup);

    /**
     * 立即执行,不定时
     *
     * @param jobName
     * @param jobClassName
     * @return
     */
    String executeImmediately(String jobName, String jobClassName);

    // 暂停

    // 获取状态
    JobInfo getJobStatus(String jobName, String jobGroup);

    List<JobInfo> getAllJob();
}
package org.springblade.etl.source.service.impl;

import lombok.extern.slf4j.Slf4j;
import org.quartz.*;
import org.quartz.impl.matchers.GroupMatcher;
import org.springblade.core.tool.utils.StringUtil;
import org.springblade.etl.source.entity.JobInfo;
import org.springblade.etl.source.service.QuartzService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.List;

@Service
@Slf4j
public class QuartzServiceImpl implements QuartzService {

    @Autowired
    private Scheduler scheduler;

    private static final String DEFAULT_JOB_GROUP = "default_job_group";

    private static final String DEFAULT_TRIGGER_GROUP = "default_trigger_group";

    private static final String TRIGGER_PRE = "Trigger_";

    @Override
    public String addCronJob(String jobName, String cron, String jobClassName) {
        try {
            // 当前任务不存在才进行添加
            JobKey jobKey = JobKey.jobKey(jobName, DEFAULT_JOB_GROUP);
            if (scheduler.checkExists(jobKey)) {
                log.info("[添加定时任务]已存在该作业,jobkey为:{}", jobKey);
                return "已存在该作业";
            }

            // 构建 Job
            JobDetail job = JobBuilder.newJob(getClass(jobClassName).getClass())
                    .withIdentity(jobKey).build();

            // cron表达式定时构造器
            CronScheduleBuilder cronScheduleBuilder = CronScheduleBuilder.cronSchedule(cron);

            // 构建 Trigger
            Trigger trigger = TriggerBuilder.newTrigger()
                    .withIdentity(TriggerKey.triggerKey(TRIGGER_PRE + jobName, DEFAULT_TRIGGER_GROUP))
//                .startAt(DateUtil.parseDate(start))
//                .endAt(DateUtil.parseDate(end))
                    .withSchedule(cronScheduleBuilder).build();

            // 启动调度器
            scheduler.scheduleJob(job, trigger);
            scheduler.start();
            return "SUCCESS";
        } catch (Exception e) {
            log.error("[新增定时任务]失败,报错:", e);
            return "FAIL";
        }

    }

    @Override
    public String deleteCronJob(String jobName, String jobGroup, String triggerName, String triggerGroup) {
        try {

            JobKey jobKey = JobKey.jobKey(jobName, jobGroup);
            //如果triggerName和triggerGroup为空,则使用默认值
            if (StringUtil.isBlank(triggerName)&&StringUtil.isBlank(triggerGroup)){
                triggerName = TRIGGER_PRE + jobName;
                triggerGroup = DEFAULT_TRIGGER_GROUP;
            }
            TriggerKey triggerKey = TriggerKey.triggerKey(triggerName, triggerGroup);

            Trigger trigger = scheduler.getTrigger(triggerKey);

            if (null == trigger) {
                log.info("[停止定时任务]根据triggerName:{}和triggerGroup:{}未查询到相应的trigger!");
                return "SUCCESS";
            }
            //暂停触发器
            scheduler.pauseTrigger(triggerKey);
            // 移除触发器
            scheduler.unscheduleJob(triggerKey);
            // 删除任务
            scheduler.deleteJob(jobKey);

            log.info("[停止定时任务]jobName:{},jobGroup:{}, triggerName:{}, triggerGroup:{},停止--------------", jobName, jobGroup, triggerName, triggerGroup);

            return "SUCCESS";

        } catch (SchedulerException e) {
            log.error("[停止定时任务]失败,报错:", e);
            return "FAIL";
        }
    }


    public static Job getClass(String className) throws Exception {
        Class<?> classTemp = Class.forName(className);
        return (Job) classTemp.newInstance();
    }

    @Override
    public String executeImmediately(String jobName, String jobClassName) {
        try {
            JobKey jobKey = JobKey.jobKey(jobName, DEFAULT_JOB_GROUP);
            JobDetail job = JobBuilder.newJob(getClass(jobClassName).getClass())
                    .withIdentity(jobKey).build();

            Trigger trigger = TriggerBuilder.newTrigger()
                    .withIdentity(TriggerKey.triggerKey(TRIGGER_PRE + jobName, DEFAULT_TRIGGER_GROUP))
                    .build();

            // 启动调度器
            scheduler.scheduleJob(job, trigger);
            scheduler.start();
            return "SUCCESS";
        } catch (Exception e) {
            log.error("[立即执行一次任务,不定时]失败,报错:", e);
            return "FAIL";
        }
    }





    @Override
    public JobInfo getJobStatus(String jobName, String jobGroup) {
        try {
            // 当前任务不存在才进行添加
            JobKey jobKey = JobKey.jobKey(jobName, DEFAULT_JOB_GROUP);
            // 利用JobKey查找任务是否存在
            if (scheduler.checkExists(jobKey)) {
                log.info("查找到该任务,任务名:{}, 状态为:{}", jobName, scheduler.getTriggerState(TriggerKey.triggerKey(TRIGGER_PRE + jobName, DEFAULT_TRIGGER_GROUP)));

                // 获取Cron触发器,从而获得Cron表达式
                CronTrigger cronTrigger = (CronTrigger) scheduler.getTrigger(TriggerKey.triggerKey(TRIGGER_PRE + jobName, DEFAULT_TRIGGER_GROUP));
                String cronExpression = cronTrigger.getCronExpression();
                JobInfo jobInfo = new JobInfo();
                jobInfo.setJobName(jobKey.getName());
                jobInfo.setJobGroup(jobKey.getGroup());
                jobInfo.setStatus( scheduler.getTriggerState(TriggerKey.triggerKey(TRIGGER_PRE + jobName, DEFAULT_TRIGGER_GROUP)).toString());
                jobInfo.setTriggerName(TriggerKey.triggerKey(TRIGGER_PRE + jobName, DEFAULT_TRIGGER_GROUP).getName());
                jobInfo.setTriggerGroup(DEFAULT_TRIGGER_GROUP);
                jobInfo.setCron(cronExpression);

                return jobInfo;
            } else {
                throw  new RuntimeException("任务不存在");
            }


        } catch (SchedulerException e) {
            log.error("[查询任务状态]失败,报错:", e);
            throw  new RuntimeException("任务不存在");
        }
    }

    @Override
    public List<JobInfo> getAllJob() {

        ArrayList<JobInfo> jobInfos = new ArrayList<JobInfo>();
        try {
            // 获取所有的触发器组
            for (String triggerGroup : scheduler.getTriggerGroupNames()) {
                // 获取指定触发器组下的所有触发器
                for (TriggerKey triggerKey : scheduler.getTriggerKeys(GroupMatcher.triggerGroupEquals(triggerGroup))) {
                    Trigger trigger = scheduler.getTrigger(triggerKey);

                    // 判断触发器类型是否为 CronTrigger
                    if (trigger instanceof CronTrigger) {
                        CronTrigger cronTrigger = (CronTrigger) trigger;
                        JobKey jobKey = cronTrigger.getJobKey();
                        JobInfo jobInfo = new JobInfo();
                        jobInfo.setJobName(jobKey.getName());
                        jobInfo.setJobGroup(jobKey.getGroup());
                        jobInfo.setTriggerName(triggerKey.getName());
                        jobInfo.setTriggerGroup(triggerKey.getGroup());
                        //获取一下cron表达式
                        jobInfo.setCron(cronTrigger.getCronExpression());
                        jobInfo.setStatus( scheduler.getTriggerState(TriggerKey.triggerKey(TRIGGER_PRE + jobKey.getName(), DEFAULT_TRIGGER_GROUP)).toString());
                        jobInfos.add(jobInfo);
                    }
                }
            }

            if (jobInfos.size() == 0) {
                log.info("暂无定时任务");
                return null;
            }

        } catch (SchedulerException e) {
            log.error("[查询所有定时任务状态]失败,报错:", e);
            throw new RuntimeException("查询所有定时任务状态失败");
        }

        return jobInfos;
    }


}

这个时间转换cron是我的自己的业务需要(因为前段不能让用户输入cron表达式,所以我让用户输入时间即可转换适合的cron表达式)

package org.springblade.common.utils;

import org.quartz.CronExpression;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;

public class CronTimeConverter {
    public static String convertCronToTime(String cronExpression) {
        try {
            CronExpression cron = new CronExpression(cronExpression);
            Date nextExecutionTime = cron.getTimeAfter(new Date());
            // 转换为指定的时间格式,比如 HH:mm
            // 这里使用 SimpleDataFormat 进行格式化
            SimpleDateFormat sdf = new SimpleDateFormat("HH:mm");
            return sdf.format(nextExecutionTime);
        } catch (ParseException e) {
            e.printStackTrace();
            return ""; // 处理异常情况,返回空字符串或其他默认值
        }
    }

//    public static void main(String[] args) {
//        String cronExpression = "0 40 14 * * ?";
//        String time = convertCronToTime(cronExpression);
//        System.out.println("Time based on cron expression " + cronExpression + " is: " + time);
//    }


    public static String convertTimeToCron(String time) {
        String[] timeParts = time.split(":");
        if (timeParts.length != 2) {
            return ""; // 处理异常情况,返回空字符串或其他默认值
        }

        String cronExpression = String.format("0 %s %s * * ?", timeParts[1], timeParts[0]);
        return cronExpression;
    }

    public static void main(String[] args) {
        String time = "14:40";
        String cronExpression = convertTimeToCron(time);
        System.out.println("Cron expression for time " + time + " is: " + cronExpression);
    }
}

你需要一个entity对象:

package org.springblade.etl.source.entity;

import lombok.Data;
import org.springblade.common.utils.CronTimeConverter;
import org.springblade.core.tool.utils.StringUtil;

import java.time.*;
import java.time.format.DateTimeFormatter;

@Data
public class JobInfo {

    private String jobName;
    private String time = "2024-03-19T08:26:58.000Z" ;

    private String cron = "0 16 10 ? * *";

    private String jobGroup;

    private String triggerName;

    private String triggerGroup;

    private String status;



    public void setCron(String cron) {
        //顺便将时间写入
        if (StringUtil.isNotBlank(cron)) {
            this.cron = cron;
            String time = CronTimeConverter.convertCronToTime(cron);
            LocalTime localTime = LocalTime.parse(time);

            // 将当天的本地时间与当天的日期结合,并转换为ZonedDateTime对象
            ZonedDateTime localDateTime = ZonedDateTime.now().withHour(localTime.getHour()).withMinute(localTime.getMinute());


            // 将本地时间转换为UTC时间,并进行格式化
            ZonedDateTime utcDateTime = localDateTime.withZoneSameInstant(ZoneOffset.UTC);
            DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'");
            this.time = utcDateTime.format(formatter);
        }
    }

    public void setTime(String utcTime){

        if (StringUtil.isNotBlank(utcTime)) {
            this.time =utcTime;
            //顺便将cron表达式写入
            // 将UTC时间字符串转换为Instant对象
            Instant instant = Instant.parse(utcTime);

            // 将Instant对象转换为本地时间
            ZonedDateTime localTime = instant.atZone(ZoneId.systemDefault());

            // 格式化本地时间为 "HH:mm" 形式
            DateTimeFormatter formatter = DateTimeFormatter.ofPattern("HH:mm");
            String formattedTime = localTime.format(formatter);
            String cron = CronTimeConverter.convertTimeToCron(formattedTime);
            this.cron = cron;
        }
    }



        public static void main(String[] args) {
            // UTC时间字符串
            String utcTime = "2024-03-19T08:26:58.000Z";

            // 将UTC时间字符串转换为Instant对象
            Instant instant = Instant.parse(utcTime);

            // 将Instant对象转换为本地时间
            ZonedDateTime localTime = instant.atZone(ZoneId.systemDefault());

            // 格式化本地时间为 "HH:mm" 形式
            DateTimeFormatter formatter = DateTimeFormatter.ofPattern("HH:mm");
            String formattedTime = localTime.format(formatter);

            System.out.println("本地时间(HH:mm):" + formattedTime);
            System.out.println("UTC时间:" + instant);
            System.out.println("本地时间:" + formattedTime);
        }

}

下面是前端vue

<template>
  <basic-container>
    <avue-crud :option="option"
               v-model:search="search"
               v-model:page="page"
               v-model="form"
               :table-loading="loading"
               :data="data"
               :permission="permissionList"
               :before-open="beforeOpen"
               ref="crud"
               @row-update="rowUpdate"
               @row-save="rowSave"
               @row-del="rowDel"
               @search-change="searchChange"
               @search-reset="searchReset"
               @selection-change="selectionChange"
               @current-change="currentChange"
               @size-change="sizeChange"
               @refresh-change="refreshChange"
               @on-load="onLoad">
      <template #menu-left>
        <el-button type="primary"
                   icon="el-icon-s-promotion"
                   @click="handleManualTrigger">手动触发
        </el-button>
<!--        <el-button type="danger"-->
<!--                   icon="el-icon-delete"-->
<!--                   plain-->
<!--                   v-if="permission.jobInfo_delete"-->
<!--                   @click="handleDelete">删 除-->
<!--        </el-button>-->
<!--        <el-button type="warning"-->
<!--                   plain-->
<!--                   icon="el-icon-download"-->
<!--                   @click="handleExport">导 出-->
<!--        </el-button>-->
      </template>
    </avue-crud>
  </basic-container>
</template>

<script>
  import {getList, getDetail, add, update, remove,startETLForSYNL} from "@/api/source/jobInfo";
  import option from "@/option/source/jobInfo";
  import {mapGetters} from "vuex";
  import {exportBlob} from "@/api/common";
  import {getToken} from '@/utils/auth';
  import {downloadXls} from "@/utils/util";
  import {dateNow} from "@/utils/date";
  import NProgress from 'nprogress';
  import 'nprogress/nprogress.css';

  export default {
    data() {
      return {
        form: {},
        query: {},
        search: {},
        loading: true,
        page: {
          pageSize: 10,
          currentPage: 1,
          total: 0
        },
        selectionList: [],
        option: option,
        data: []
      };
    },
    computed: {
      ...mapGetters(["permission"]),
      permissionList() {
        return {
          addBtn: this.validData(this.permission.jobInfo_add, false),
          viewBtn: this.validData(this.permission.jobInfo_view, false),
          delBtn: this.validData(this.permission.jobInfo_delete, false),
          editBtn: this.validData(this.permission.jobInfo_edit, false)
        };
      },
      ids() {
        let ids = [];
        this.selectionList.forEach(ele => {
          ids.push(ele.id);
        });
        return ids.join(",");
      }
    },
    methods: {
      rowSave(row, done, loading) {
        row.cron = null;//表达式不往后端传
        add(row).then(() => {
          this.onLoad(this.page);
          this.$message({
            type: "success",
            message: "操作成功!"
          });
          done();
        }, error => {
          loading();
          window.console.log(error);
        });
      },
      rowUpdate(row, index, done, loading) {
        row.cron = null;表达式不往后端传
        update(row).then(() => {
          this.onLoad(this.page);
          this.$message({
            type: "success",
            message: "操作成功!"
          });
          done();
        }, error => {
          loading();
          console.log(error);
        });
      },
      rowDel(row) {
        this.$confirm("确定将选择数据删除?", {
          confirmButtonText: "确定",
          cancelButtonText: "取消",
          type: "warning"
        })
          .then(() => {
            return remove(row.jobName);
          })
          .then(() => {
            this.onLoad(this.page);
            this.$message({
              type: "success",
              message: "操作成功!"
            });
          });
      },
      handleDelete() {
        if (this.selectionList.length === 0) {
          this.$message.warning("请选择至少一条数据");
          return;
        }
        this.$confirm("确定将选择数据删除?", {
          confirmButtonText: "确定",
          cancelButtonText: "取消",
          type: "warning"
        })
          .then(() => {
            return remove(this.jobName);
          })
          .then(() => {
            this.onLoad(this.page);
            this.$message({
              type: "success",
              message: "操作成功!"
            });
            this.$refs.crud.toggleSelection();
          });
      },
      handleExport() {
        let downloadUrl = `/blade-jobInfo/jobInfo/export-jobInfo?${this.website.tokenHeader}=${getToken()}`;
        const {
        } = this.query;
        let values = {
        };
        this.$confirm("是否导出数据?", "提示", {
          confirmButtonText: "确定",
          cancelButtonText: "取消",
          type: "warning"
        }).then(() => {
          NProgress.start();
          exportBlob(downloadUrl, values).then(res => {
            downloadXls(res.data, `自动任务表${dateNow()}.xlsx`);
            NProgress.done();
          })
        });
      },
      beforeOpen(done, type) {
        if (["edit", "view"].includes(type)) {
          getDetail(this.form.jobName).then(res => {
            this.form = res.data.data;
          });
        }
        done();
      },
      searchReset() {
        this.query = {};
        this.onLoad(this.page);
      },
      searchChange(params, done) {
        this.query = params;
        this.page.currentPage = 1;
        this.onLoad(this.page, params);
        done();
      },
      selectionChange(list) {
        this.selectionList = list;
      },
      selectionClear() {
        this.selectionList = [];
        this.$refs.crud.toggleSelection();
      },
      currentChange(currentPage){
        this.page.currentPage = currentPage;
      },
      sizeChange(pageSize){
        this.page.pageSize = pageSize;
      },
      refreshChange() {
        this.onLoad(this.page, this.query);
      },
      onLoad(page, params = {}) {
        this.loading = true;

        const {
        } = this.query;

        let values = {
        };

        getList(page.currentPage, page.pageSize, values).then(res => {
          console.log("定时任务得到的数据=",res);
          const data = res.data.data;
          this.page.total = data.total;
          this.data = data.records;
          this.loading = false;
          this.selectionClear();
        });
      },
      handleManualTrigger() {
        this.$confirm("确定手动触发定时任务?", {
          confirmButtonText: "确定",
          cancelButtonText: "取消",
          type: "warning"
        })
            .then(() => {
              this.$message({
                type: "success",
                message: "操作成功!"
              });
              // 调用 startETLForSYNL 方法
              startETLForSYNL().then(response => {
                const result = response.data.data; // 获取返回值
                console.log("返回值=",response)
                this.$message({
                  type: "info",
                  message: ` ${result}`
                });
              }).catch(error => {
                this.$message.error("操作失败");
              });
            });
      }

    }
  };
</script>

<style>
</style>
export default {
  height:'auto',
  calcHeight: 30,
  tip: false,
  searchShow: true,
  searchMenuSpan: 6,
  // border: true,
  // index: true,
  // viewBtn: true,
  selection: true,
  // dialogClickModal: false,
  column: [
    {
      label: "",
      prop: "id",
      type: "input",
      addDisplay: false,
      editDisplay: false,
      viewDisplay: false,
      hide: true,
    },
    {
      label: "任务名称",
      prop: "jobName",
      type: "input",
    },
    {
      label: "执行时间",
      prop: "time",
      type: "time",
      format: "HH:mm" // 设置时间格式,例如 "HH:mm"
    },
    {
      label: "定时表达式",
      prop: "cron",
      type: "input",
      editDisplay: false,
      addDisplay: false,
    },
    {
      label: "任务分组",
      prop: "jobGroup",
      type: "input",
      addDisplay: false,
      editDisplay: false,
      hide: true
    },
    {
      label: "触发器名称",
      prop: "triggerName",
      type: "input",
      addDisplay: false,
      editDisplay: false,
      hide: true
    },
    {
      label: "触发器分组",
      prop: "triggerGroup",
      type: "input",
      addDisplay: false,
      editDisplay: false,
      hide: true
    },
    {
      label: "状态",
      prop: "status",
      type: "input",
      addDisplay: false,
      editDisplay: false,
    }

  ]
}
import request from '@/axios';

export const getList = (current, size, params) => {
  return request({
    url: '/quartz/list',
    method: 'post',
    params: {
      ...params,
      current,
      size,
    }
  })
}

export const getDetail = (jobName) => {
  return request({
    url: '/quartz/detail',
    method: 'post',
    params: {
      jobName
    }
  })
}

export const remove = (jobName) => {
  return request({
    url: '/quartz/remove',
    method: 'post',
    params: {
      jobName,
    }
  })
}

export const add = (row) => {
  return request({
    url: '/quartz/submit',
    method: 'post',
    data: row
  })
}

export const update = (row) => {
  return request({
    url: '/quartz/submit',
    method: 'post',
    data: row
  })
}

export const startETLForSYNL = () => {
  return request({
    url: '/startETLForSYNL',
    method: 'get'
  })
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/478072.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

日常 ------------ (一)

使用xdd 生成 firmware.cc 文件 &#xff0c;然后程序根据需要自己解压缩,也可以完成软件升级状态的监控 objcopy 此等神奇也可以&#xff0c;但是威力太大&#xff0c;容易玩崩&#xff0c;没敢尝试

Solo 开发者周刊 (第8期):Claude公司再度上新产品,成交额将超73亿美元

这里会整合 Solo 社区每周推广内容、产品模块或活动投稿&#xff0c;每周五发布。在这期周刊中&#xff0c;我们将深入探讨开源软件产品的开发旅程&#xff0c;分享来自一线独立开发者的经验和见解。本杂志开源&#xff0c;欢迎投稿。 好文推荐 Claude是否超过Chatgpt,成为生成…

Redis 不再 “开源”,未来采用 SSPLv1 和 RSALv2 许可证

昨日&#xff0c;Redis 官方宣布了一项重要变更&#xff1a;他们将修改开源协议&#xff0c;未来所有版本将采用 “源代码可用” 的许可证。 具体来说&#xff0c;Redis 不再使用 BSD 3-Clause 开源协议进行分发。从 Redis 7.4 版本开始&#xff0c;Redis 将采用 SSPLv1 和 RSA…

【C语言】自定义类型:联合体和枚举

1. 联合体 1.1 联合体类型的声明 像结构体一样&#xff0c;联合体也是由一个或者多个成员构成&#xff0c;这些成员可以是不同的类型。 但是编译器只为最大的成员分配足够的内存空间。联合体的特点是所有成员共用同一块内存空间。所以联合体也叫&#xff1a;共用体。 给联合…

Binance labs孵化的Swan Chain明牌空投测试网零撸教程

简介&#xff1a;Swan Chain 是一个 Layer2云计算网络&#xff0c;可以将数据、计算、带宽和支付集成到一个套件&#xff0c;为Web3项目提供全面的解决方案。 相关概念&#xff1a;云计算、layer2、infrastructure 融资信息&#xff1a;项目在去年获得bi’an领投的300万美元融…

【pip安装时出现一大片红色报错】 raise ReadTimeoutError(self._pool, None, “Read timed out.“)

【pip安装时出现一大片红色报错】 raise ReadTimeoutError(self._pool, None, “Read timed out.”) 问题描述&#xff1a;pip 安装包时出现一大片莫名其妙的报错 raise ReadTimeoutError(self._pool, None, “Read timed out.”) pip._vendor.urllib3.exceptions.ReadTimeout…

onConfigurationChanged与 Save-Restore InstanceState机制与RetainNonConfiguration机制

android横竖屏切换的生命周期 没设置configChanges&#xff0c;销毁后重建&#xff1a; onCreate--onStart--onResume--onPause--onStop--onSaveInstanceState--onDestroy--onCreate--onStart--onRestoreInstanceState--onResume--onPause--onStop--onDestroy 设置configCha…

基于 Google MediaPipe 进行人体姿势估计演示

用于人体姿势估计的 MediaPipe 演示 MediaPipe简介 MediaPipe是一个开源框架&#xff0c;用于构建跨平台、多模式应用机器学习管道。它由 Google 开发&#xff0c;旨在促进基于机器学习的功能的快速开发和部署&#xff0c;特别关注音频、视频和时间序列数据。 我可以将 MediaPi…

产品经理杂谈

像游戏一样设计联赛 1、通过互联网规模化&#xff0c;然后分析数据&#xff0c;哪里好&#xff0c;哪里不好&#xff0c;大家都喜欢你的产品了&#xff0c;然后反哺更大规模 2、产品分类 toC 工具 内容 游戏 社交 电商 交易 toB 内部办公类 – 提高企业内部效率&#xff0c;…

力扣热门算法题 52. N 皇后 II,53. 最大子数组和,54. 螺旋矩阵

52. N 皇后 II&#xff0c;53. 最大子数组和&#xff0c;54. 螺旋矩阵&#xff0c;每题做详细思路梳理&#xff0c;配套Python&Java双语代码&#xff0c; 2024.03.20 可通过leetcode所有测试用例。 目录 52. N 皇后 II 解题思路 完整代码 Python Java 53. 最大子数组…

TS + Vue3 elementUI 表格列表中如何方便的标识不同类型的内容,颜色区分 enum

TS Vue3 elementUI 表格列表中如何方便的标识不同类型的内容&#xff0c;颜色区分 enum 本文内容为 TypeScript 一、基础知识 在展示列表的时候&#xff0c;列表中的某个数据可能是一个类别&#xff0c;比如&#xff1a; enum EnumOrderStatus{"未受理" 1,"…

MySQL Workbench连接云服务器内网数据库

在项目上遇到一个问题&#xff0c;生产环境是Centos&#xff0c;分配了两台云服务器&#xff0c;一台应用服务&#xff0c;一台数据库服务&#xff0c;应用服务与数据库服务采用内网连接。我作为开发和运维方&#xff0c;有权限直接访问应用服务&#xff0c;但是数据库服务器需…

C++知识点总览

1.输入输出流 在C中要想输入和输出 我们会经常用到 #include <stdio.h>在C中头文件的命名风格不用.h #include <iostream>using namespace std;为什么要用上面俩句话的解释&#xff08;自己写的博客&#xff09; c中 为什么要写&#xff1c;iostream&#xff1e;…

苹果计划与谷歌合作使用Gemini AI技术,提升iPhone功能,同时探索与OpenAI合作可能性

每周跟踪AI热点新闻动向和震撼发展 想要探索生成式人工智能的前沿进展吗&#xff1f;订阅我们的简报&#xff0c;深入解析最新的技术突破、实际应用案例和未来的趋势。与全球数同行一同&#xff0c;从行业内部的深度分析和实用指南中受益。不要错过这个机会&#xff0c;成为AI领…

面试算法-73-二叉树的最小深度

题目 给定一个二叉树&#xff0c;找出其最小深度。 最小深度是从根节点到最近叶子节点的最短路径上的节点数量。 说明&#xff1a;叶子节点是指没有子节点的节点。 示例 1&#xff1a; 输入&#xff1a;root [3,9,20,null,null,15,7] 输出&#xff1a;2 解 class Solu…

人工智能时代的引领者:AI提示工程激发大语言模型的无限潜能

文章目录 一、AI提示工程的概念与定义二、AI提示工程的应用领域三、AI提示工程的技术创新与突破四、AI提示工程的未来发展趋势《AI提示工程实战&#xff1a;从零开始利用提示工程学习应用大语言模型》亮点内容简介作者简介目录 一、AI提示工程的概念与定义 在当今日新月异的科…

智能新纪元:AI大模型的奥秘与未来

目录 AI大模型学习 数学基础和编程能力 特定领域的业务理解 模型结构和算法的优化 为人类生活和工作带来的便利 AI大模型背后的技术原理 AI大模型学习的理论基础 1. 统计学习理论 2. 优化理论 3. 神经网络和深度学习 4. 表示学习 5. 迁移学习和微调 6. 机器学习的…

[数据集][目标检测]高质量铁路轨道缺陷检测数据集VOC+YOLO格式1050张6类别

数据集格式&#xff1a;Pascal VOC格式YOLO格式(不包含分割路径的txt文件&#xff0c;仅仅包含jpg图片以及对应的VOC格式xml文件和yolo格式txt文件) 图片数量(jpg文件个数)&#xff1a;1050 标注数量(xml文件个数)&#xff1a;1050 标注数量(txt文件个数)&#xff1a;1050 标注…

Spring Web MVC入门(6)

应用分层 在开发的过程中, 我们会发现, 程序的代码有时会很"杂乱", 如果后面的项目更大了, 那就会更加地杂乱无章(文件乱, 代码内容乱). 也基于此, 接下来让我们来学习一下应用分层. 也类似于公司的组织架构 公司初创阶段, 一个人身兼数职, 既做财务, 又做人事,还有…

【C++】stringstream类 最全超详细解析(什么是stringstream? stringstrem有哪些作用? 如何在算法中应用?)

目录 一、前言 二、stringstream 是什么 &#xff1f; 三、stringstream 的用法 ✨构造函数 ✨输出字符串 ✨两种构造函数带来的不同 ✨修改、清空 stringstream 内容 四、stringsteam 的用途 ✨ 利用 stringstream 去除字符串空格 ✨ 利用 stringstream 指定字符分割字符…