quartz整合前端vue加后端springboot

news2024/11/16 7:39:46

因工作需求,需要能修改定时的任务,前端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'
  })
}

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

BufferedInputStream解读

咦咦咦&#xff0c;各位小可爱&#xff0c;我是你们的好伙伴——bug菌&#xff0c;今天又来给大家普及Java之IO流啦&#xff0c;别躲起来啊&#xff0c;听我讲干货还不快点赞&#xff0c;赞多了我就有动力讲得更嗨啦&#xff01;所以呀&#xff0c;养成先点赞后阅读的好习惯&am…

hash冲突四种解决办法,hash冲突除了拉链法还有什么?

1. 看hashmap 源码&#xff0c;有个问题&#xff0c;key 存放是 先hash 再与hash值的高16位值 进行异或运算。再与槽位size() 求模取余。如果多个不同的key 得出de数组位置相同。则采用链表依次存储。 2. 那么除了拉链法还有什么其他解决hash冲突的方法呢&#xff1f; a. 建立…

python程序打包

目录 1. 命令2. 安装2.1 PyInstaller2.2 cx_Freeze(笔者未用过) 3. 打包示例3.1 在 pycharm 中执行3.2 若使用打包命令时报错3.3 路径问题 python打包成可执行文件&#xff0c;用于在没有Python环境的地方运行该程序&#xff0c;与qt打包类似。&#xff08;笔者写的qt打包地址&…

Beans模块之工厂模块BeanNameAware

博主介绍&#xff1a;✌全网粉丝5W&#xff0c;全栈开发工程师&#xff0c;从事多年软件开发&#xff0c;在大厂呆过。持有软件中级、六级等证书。可提供微服务项目搭建与毕业项目实战&#xff0c;博主也曾写过优秀论文&#xff0c;查重率极低&#xff0c;在这方面有丰富的经验…

无人驾驶中的坐标转换

无人驾驶中的坐标转换 无人车上拥有各种各样的传感器&#xff0c;每个传感器的安装位置和角度又不尽相同。对于传感器的提供商&#xff0c;开始并不知道传感器会以什么角度&#xff0c;安装在什么位置&#xff0c;因此只能根据传感器自身建立坐标系。无人驾驶系统是一个多传感器…

Jenkins的快速入门

文章目录 一、Jenkins是什么&#xff1f;二、Jenkins安装和持续集成环境配置1.持续集成流程说明2.Gitlab代码托管服务器安装Gitlab简介&#xff1a;Gitlab安装Gitlab的使用切换中文添加组创建用户将用户添加到组创建项目idea中代码上传Gitlab 3.Jenkins持续集成环境服务器安装J…

牛客网python练习题库记录

python格式化输出 python 读入整数数字并且换行输出 python规范输出小数点后几位 afloat(input()) format_a{.2f}.format(a) print(format_a) 小数化整数 afloat(input()) bint(a) print(b) 为整数增加小数点 input_integer int(input()) float_number float(input…

快速上手 Elasticsearch:Docker Compose 部署详解

最近面试竞争日益激烈&#xff0c;Elasticsearch作为一款广泛应用的中间件&#xff0c;几乎成为面试中必考的知识点。最近&#xff0c;AIGC也备受关注&#xff0c;而好多的AI项目中也采用了Elasticsearch作为向量数据库&#xff0c;因此我们迫切希望学习Elasticsearch。对于学习…

【Linux】Centos7安装redis

目录 下载安装包安装1.解压2.环境安装3.查看redis的安装路径4.将之前redis的配置文件&#xff0c;复制到安装路径下&#xff08;新建一个文件夹并复制&#xff09;5.redis 设置默认后台启动&#xff0c;修改配置文件6.启动redis服务默认启动通过配置文件启动查看进程 7.开放637…

【Python小工具系列】使用 Python 循环批量打开网页链接

&#x1f49d;&#x1f49d;&#x1f49d;欢迎来到我的博客&#xff0c;很高兴能够在这里和您见面&#xff01;希望您在这里可以感受到一份轻松愉快的氛围&#xff0c;不仅可以获得有趣的内容和知识&#xff0c;也可以畅所欲言、分享您的想法和见解。 推荐:kwan 的首页,持续学…

大数据Hadoop生态圈体系视频课程

课程介绍 熟悉大数据概念&#xff0c;明确大数据职位都有哪些&#xff1b;熟悉Hadoop生态系统都有哪些组件&#xff1b;学习Hadoop生态环境架构&#xff0c;了解分布式集群优势&#xff1b;动手操作Hbase的例子&#xff0c;成功部署伪分布式集群&#xff1b;动手Hadoop安装和配…

一文详解常见医学自然语言理解任务和算法

1. 引言 随着人工智能&#xff08;AI&#xff09;技术的不断发展&#xff0c;越来越多的研究者开始关注AI技术在医学健康领域的研究应用&#xff0c;其中加速AI技术产业落地的一个重要环节就是标准数据集和科学评估体系的建立。由中国中文信息学会医疗健康与生物信息处理专业委…

力扣---完全平方数---动态规划

思路&#xff1a; 还是比较好想的&#xff0c;g[i]定义为和为 i 的完全平方数的最少数量。那么递推关系式是g[i]min(g[i-1],g[i-4],g[i-9],...)1&#xff0c;数组初始化是g[0]0,g[1]1。注意这里要对g[0]初始化&#xff0c;&#xff08;举个例子&#xff09;因为在遍历到g[4]时&…

34双体系Java学习之对象的创建和引用

创建对象 ★小贴士 当声明一个引用变量时&#xff0c;要求Java虚拟机分配空间给引用变量&#xff0c;并将此变量命名为myCar。 此引用变量将永远被固定为Car类型。 当创建对象时&#xff0c;要求Java虚拟机分配堆空间给新建立的Car对象。 关键字 new 通常称为创建运算符&#x…

redis在springboot项目中的应用

一&#xff0c;将查询结果放到redis中作为缓存&#xff0c;减轻mysql的压力。 只有在数据量大的时候&#xff0c;查询速度慢的时候才有意义。 本次测试的数据量为百万级别。 测试代码: 功能为根据昵称进行模糊匹配。 GetMapping("/get-by-nick")public String get…

基于K-近邻的PLOSAR图像分类

&#x1f380;个人主页&#xff1a; https://zhangxiaoshu.blog.csdn.net &#x1f4e2;欢迎大家&#xff1a;关注&#x1f50d;点赞&#x1f44d;评论&#x1f4dd;收藏⭐️&#xff0c;如有错误敬请指正! &#x1f495;未来很长&#xff0c;值得我们全力奔赴更美好的生活&…

无代码平台开发AI已经被实现了吗?

一、背景 无代码平台AI开发是一种新兴的开发方式&#xff0c;它允许非程序员或低代码开发者通过图形化界面、拖拽组件和预设模版等方式&#xff0c;无需编写传统的程序代码就能创建、训练和部署AI模型。这种方式极大地降低了AI技术的使用门槛&#xff0c;让更多不具备编程背景…

2024年第14届生物医学工程与技术国际会议(ICBET 2024)即将召开!

2024年第14届生物医学工程与技术国际会议&#xff08;ICBET 2024&#xff09;将于2024年6月14日至17日在韩国首尔举行。 会议旨在汇聚来自世界各地的研究人员、工程师、院士和行业专业人士&#xff0c;展示他们在生物医学工程与技术领域的最新研究成果和进展。 会议以“生物医学…

轻松应对城市内涝:慧天排水数字化分析平台,城市内涝模拟新利器

​在城市排水防涝规划过程中&#xff0c;水文水动力耦合模型已经成为一种不可或缺的分析工具。在模型建立、城市内涝风险评估、排水系统性能诊断以及海绵城市规划等方面&#xff0c;内涝耦合模型提供了相应的模拟及分析工具&#xff1a; 1.1 丰富的数据处理功能&#xff0c;兼…

C语言中如何动态分配内存并进行操作

C语言文章更新目录 C语言学习资源汇总&#xff0c;史上最全面总结&#xff0c;没有之一 C/C学习资源&#xff08;百度云盘链接&#xff09; 计算机二级资料&#xff08;过级专用&#xff09; C语言学习路线&#xff08;从入门到实战&#xff09; 编写C语言程序的7个步骤和编程…