From 516ef4b0df8c26a3088e113e39d8198f161d4ea4 Mon Sep 17 00:00:00 2001
From: liriming <1343021927@qq.com>
Date: 星期一, 14 十月 2024 10:31:11 +0800
Subject: [PATCH] 定时任务

---
 shasteel-biz/src/main/java/com/iailab/module/shasteel/job/dao/ScheduleJobLogDao.java                     |   17 
 shasteel-biz/src/main/java/com/iailab/module/shasteel/job/service/impl/ScheduleJobServiceImpl.java       |  128 ++++++
 shasteel-biz/src/main/java/com/iailab/module/shasteel/job/controller/admin/ScheduleJobController.java    |  127 ++++++
 shasteel-biz/src/main/java/com/iailab/module/shasteel/job/entity/ScheduleJobEntity.java                  |   58 ++
 shasteel-biz/src/main/resources/mapper/job/ScheduleJobLogDao.xml                                         |    7 
 shasteel-biz/src/main/java/com/iailab/module/shasteel/job/utils/ScheduleJob.java                         |   80 ++++
 shasteel-biz/src/main/java/com/iailab/module/shasteel/job/vo/ScheduleJobReqVO.java                       |   23 +
 shasteel-biz/pom.xml                                                                                     |    7 
 shasteel-biz/src/main/java/com/iailab/module/shasteel/job/controller/package-info.java                   |    1 
 shasteel-biz/src/main/java/com/iailab/module/shasteel/job/config/ScheduleConfig.java                     |   58 ++
 shasteel-biz/src/main/java/com/iailab/module/shasteel/job/service/impl/ScheduleJobLogServiceImpl.java    |   54 ++
 shasteel-biz/src/main/java/com/iailab/module/shasteel/job/task/ITask.java                                |   25 +
 shasteel-biz/src/main/java/com/iailab/module/shasteel/job/dto/ScheduleJobLogDTO.java                     |   53 ++
 shasteel-biz/src/main/java/com/iailab/module/shasteel/job/init/JobCommandLineRunner.java                 |   38 +
 shasteel-biz/src/main/java/com/iailab/module/shasteel/job/service/ScheduleJobService.java                |   55 ++
 shasteel-biz/src/main/java/com/iailab/module/shasteel/job/entity/ScheduleJobLogEntity.java               |   59 ++
 shasteel-biz/src/main/java/com/iailab/module/shasteel/job/controller/admin/ScheduleJobLogController.java |   62 +++
 shasteel-biz/src/main/java/com/iailab/module/shasteel/job/utils/ScheduleUtils.java                       |  153 +++++++
 shasteel-biz/src/main/java/com/iailab/module/shasteel/job/dao/ScheduleJobDao.java                        |   34 +
 shasteel-biz/src/main/java/com/iailab/module/shasteel/job/dto/ScheduleJobDTO.java                        |   62 +++
 shasteel-biz/src/main/resources/mapper/job/ScheduleJobDao.xml                                            |   14 
 shasteel-biz/src/main/java/com/iailab/module/shasteel/job/task/TestTask.java                             |   22 +
 shasteel-biz/src/main/resources/application.yaml                                                         |   14 
 shasteel-biz/src/main/java/com/iailab/module/shasteel/job/service/ScheduleJobLogService.java             |   29 +
 24 files changed, 1,180 insertions(+), 0 deletions(-)

diff --git a/shasteel-biz/pom.xml b/shasteel-biz/pom.xml
index 76d1a37..73cd007 100644
--- a/shasteel-biz/pom.xml
+++ b/shasteel-biz/pom.xml
@@ -131,6 +131,13 @@
             <artifactId>tencentcloud-sdk-java-sms</artifactId> <!-- 短信(腾讯云) -->
         </dependency>
 
+
+        <dependency>
+            <groupId>org.quartz-scheduler</groupId>
+            <artifactId>quartz</artifactId>
+            <version>2.3.2</version>
+        </dependency>
+
     </dependencies>
 
     <build>
diff --git a/shasteel-biz/src/main/java/com/iailab/module/shasteel/job/config/ScheduleConfig.java b/shasteel-biz/src/main/java/com/iailab/module/shasteel/job/config/ScheduleConfig.java
new file mode 100644
index 0000000..189f38c
--- /dev/null
+++ b/shasteel-biz/src/main/java/com/iailab/module/shasteel/job/config/ScheduleConfig.java
@@ -0,0 +1,58 @@
+package com.iailab.module.shasteel.job.config;
+
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.scheduling.quartz.SchedulerFactoryBean;
+
+import javax.sql.DataSource;
+import java.util.Properties;
+
+/**
+ * 定时任务配置
+ *
+ * @author Mark sunlightcs@gmail.com
+ */
+@Configuration
+public class ScheduleConfig {
+
+    @Bean
+    public SchedulerFactoryBean schedulerFactoryBean(DataSource dataSource) {
+        SchedulerFactoryBean factory = new SchedulerFactoryBean();
+        factory.setDataSource(dataSource);
+
+        //quartz参数
+        Properties prop = new Properties();
+        prop.put("org.quartz.scheduler.instanceName", "IailabDataScheduler");
+        prop.put("org.quartz.scheduler.instanceId", "AUTO");
+        //线程池配置
+        prop.put("org.quartz.threadPool.class", "org.quartz.simpl.SimpleThreadPool");
+        prop.put("org.quartz.threadPool.threadCount", "20");
+        prop.put("org.quartz.threadPool.threadPriority", "5");
+        //JobStore配置
+        prop.put("org.quartz.jobStore.class", "org.springframework.scheduling.quartz.LocalDataSourceJobStore");
+        //集群配置
+        prop.put("org.quartz.jobStore.isClustered", "true");
+        prop.put("org.quartz.jobStore.clusterCheckinInterval", "15000");
+        prop.put("org.quartz.jobStore.maxMisfiresToHandleAtATime", "1");
+
+        prop.put("org.quartz.jobStore.misfireThreshold", "12000");
+        prop.put("org.quartz.jobStore.tablePrefix", "QRTZ_");
+        prop.put("org.quartz.jobStore.selectWithLockSQL", "SELECT * FROM {0}LOCKS UPDLOCK WHERE LOCK_NAME = ?");
+
+        //PostgreSQL数据库,需要打开此注释
+        //prop.put("org.quartz.jobStore.driverDelegateClass", "org.quartz.impl.jdbcjobstore.PostgreSQLDelegate");
+
+        factory.setQuartzProperties(prop);
+
+        factory.setSchedulerName("IailabDataScheduler");
+        //延时启动
+        factory.setStartupDelay(30);
+        factory.setApplicationContextSchedulerContextKey("applicationContextKey");
+        //可选,QuartzScheduler 启动时更新己存在的Job,这样就不用每次修改targetObject后删除qrtz_job_details表对应记录了
+        factory.setOverwriteExistingJobs(true);
+        //设置自动启动,默认为true
+        factory.setAutoStartup(true);
+
+        return factory;
+    }
+}
diff --git a/shasteel-biz/src/main/java/com/iailab/module/shasteel/job/controller/admin/ScheduleJobController.java b/shasteel-biz/src/main/java/com/iailab/module/shasteel/job/controller/admin/ScheduleJobController.java
new file mode 100644
index 0000000..9b647fb
--- /dev/null
+++ b/shasteel-biz/src/main/java/com/iailab/module/shasteel/job/controller/admin/ScheduleJobController.java
@@ -0,0 +1,127 @@
+package com.iailab.module.shasteel.job.controller.admin;
+
+import com.iailab.framework.common.constant.Constant;
+import com.iailab.framework.common.pojo.CommonResult;
+import com.iailab.framework.common.pojo.PageResult;
+import com.iailab.framework.common.util.object.BeanUtils;
+import com.iailab.framework.common.util.validation.ValidationUtils;
+import com.iailab.framework.common.validation.group.AddGroup;
+import com.iailab.framework.common.validation.group.DefaultGroup;
+import com.iailab.framework.common.validation.group.UpdateGroup;
+import com.iailab.framework.tenant.core.context.TenantContextHolder;
+import com.iailab.module.shasteel.job.dto.ScheduleJobDTO;
+import com.iailab.module.shasteel.job.entity.ScheduleJobEntity;
+import com.iailab.module.shasteel.job.service.ScheduleJobService;
+import com.iailab.module.shasteel.job.vo.ScheduleJobReqVO;
+import io.swagger.v3.oas.annotations.Operation;
+import io.swagger.v3.oas.annotations.Parameter;
+import io.swagger.v3.oas.annotations.Parameters;
+import io.swagger.v3.oas.annotations.tags.Tag;
+import org.springframework.security.access.prepost.PreAuthorize;
+import org.springframework.validation.annotation.Validated;
+import org.springframework.web.bind.annotation.*;
+
+import javax.annotation.Resource;
+
+import static com.iailab.framework.common.pojo.CommonResult.success;
+
+/**
+ * 定时任务
+ *
+ * @author Mark sunlightcs@gmail.com
+ */
+@RestController
+@RequestMapping("/job/schedule")
+@Tag(name = "定时任务")
+public class ScheduleJobController {
+	@Resource
+	private ScheduleJobService scheduleJobService;
+
+	@GetMapping("page")
+	@Operation(summary = "分页")
+	@Parameters({
+		@Parameter(name = Constant.PAGE, description = "当前页码,从1开始", required = true) ,
+		@Parameter(name = Constant.LIMIT, description = "每页显示记录数", required = true) ,
+		@Parameter(name = Constant.ORDER_FIELD, description = "排序字段") ,
+		@Parameter(name = Constant.ORDER, description = "排序方式,可选值(asc、desc)") ,
+		@Parameter(name = "beanName", description = "beanName")
+	})
+	@PreAuthorize("@ss.hasPermission('data:schedule:query')")
+	public CommonResult<PageResult<ScheduleJobDTO>> page(@Validated ScheduleJobReqVO reqVO){
+		reqVO.setTenantId(TenantContextHolder.getTenantId());
+		PageResult<ScheduleJobEntity> page = scheduleJobService.page(reqVO);
+
+		return success(BeanUtils.toBean(page, ScheduleJobDTO.class));
+	}
+
+	@GetMapping("info")
+	@Operation(summary = "信息")
+	@PreAuthorize("@ss.hasPermission('data:schedule:query')")
+	public CommonResult<ScheduleJobDTO> info(@RequestParam("id") Long id){
+		ScheduleJobDTO schedule = scheduleJobService.get(id);
+		
+		return new CommonResult<ScheduleJobDTO>().setData(schedule);
+	}
+
+	@PostMapping("/create")
+	@Operation(summary = "保存")
+	@PreAuthorize("@ss.hasPermission('data:schedule:create')")
+	public CommonResult save(@RequestBody ScheduleJobDTO dto){
+		ValidationUtils.validate(dto, AddGroup.class, DefaultGroup.class);
+		
+		scheduleJobService.save(dto);
+		
+		return new CommonResult();
+	}
+
+	@PutMapping("/update")
+	@Operation(summary = "修改")
+	@PreAuthorize("@ss.hasPermission('data:schedule:update')")
+	public CommonResult update(@RequestBody ScheduleJobDTO dto){
+		ValidationUtils.validate(dto, UpdateGroup.class, DefaultGroup.class);
+				
+		scheduleJobService.update(dto);
+		
+		return new CommonResult();
+	}
+
+	@DeleteMapping("/delete")
+	@Operation(summary = "删除")
+	@PreAuthorize("@ss.hasPermission('data:schedule:delete')")
+	public CommonResult delete(@RequestParam("id") Long id){
+		scheduleJobService.deleteBatch(id);
+		
+		return new CommonResult();
+	}
+
+	@PutMapping("/run")
+	@Operation(summary = "立即执行")
+	public CommonResult run(@RequestParam("id") Long id){
+		Long[] ids = new Long[1];
+		ids[0] = id;
+		scheduleJobService.run(ids);
+		
+		return new CommonResult();
+	}
+
+	@PutMapping("/pause")
+	@Operation(summary = "暂停")
+	public CommonResult pause(@RequestParam("id") Long id){
+		Long[] ids = new Long[1];
+		ids[0] = id;
+		scheduleJobService.pause(ids);
+		
+		return new CommonResult();
+	}
+
+	@PutMapping("/resume")
+	@Operation(summary = "恢复")
+	public CommonResult resume(@RequestParam("id") Long id){
+		Long[] ids = new Long[1];
+		ids[0] = id;
+		scheduleJobService.resume(ids);
+		
+		return new CommonResult();
+	}
+
+}
\ No newline at end of file
diff --git a/shasteel-biz/src/main/java/com/iailab/module/shasteel/job/controller/admin/ScheduleJobLogController.java b/shasteel-biz/src/main/java/com/iailab/module/shasteel/job/controller/admin/ScheduleJobLogController.java
new file mode 100644
index 0000000..7d9d0a4
--- /dev/null
+++ b/shasteel-biz/src/main/java/com/iailab/module/shasteel/job/controller/admin/ScheduleJobLogController.java
@@ -0,0 +1,62 @@
+/**
+ * Copyright (c) 2018 人人开源 All rights reserved.
+ *
+ * https://www.renren.io
+ *
+ * 版权所有,侵权必究!
+ */
+
+package com.iailab.module.shasteel.job.controller.admin;
+
+import com.iailab.framework.common.constant.Constant;
+import com.iailab.framework.common.page.PageData;
+import com.iailab.framework.common.pojo.CommonResult;
+import com.iailab.module.shasteel.job.dto.ScheduleJobLogDTO;
+import com.iailab.module.shasteel.job.service.ScheduleJobLogService;
+import io.swagger.v3.oas.annotations.Operation;
+import io.swagger.v3.oas.annotations.Parameter;
+import io.swagger.v3.oas.annotations.Parameters;
+import io.swagger.v3.oas.annotations.tags.Tag;
+import org.springframework.security.access.prepost.PreAuthorize;
+import org.springframework.web.bind.annotation.*;
+
+import javax.annotation.Resource;
+import java.util.Map;
+
+/**
+ * 定时任务日志
+ *
+ * @author Mark sunlightcs@gmail.com
+ */
+@RestController
+@RequestMapping("/sys/scheduleLog")
+@Tag(name = "定时任务日志")
+public class ScheduleJobLogController {
+	@Resource
+	private ScheduleJobLogService scheduleJobLogService;
+
+	@GetMapping("page")
+	@Operation(summary = "分页")
+	@Parameters({
+		@Parameter(name = Constant.PAGE, description = "当前页码,从1开始", required = true) ,
+		@Parameter(name = Constant.LIMIT, description = "每页显示记录数", required = true) ,
+		@Parameter(name = Constant.ORDER_FIELD, description = "排序字段") ,
+		@Parameter(name = Constant.ORDER, description = "排序方式,可选值(asc、desc)") ,
+		@Parameter(name = "jobId", description = "jobId")
+	})
+	@PreAuthorize("@ss.hasPermission('sys:schedule:log')")
+	public CommonResult<PageData<ScheduleJobLogDTO>> page(@RequestParam Map<String, Object> params){
+		PageData<ScheduleJobLogDTO> page = scheduleJobLogService.page(params);
+		
+		return new CommonResult<PageData<ScheduleJobLogDTO>>().setData(page);
+	}
+
+	@GetMapping("{id}")
+	@Operation(summary = "信息")
+	@PreAuthorize("@ss.hasPermission('sys:schedule:log')")
+	public CommonResult<ScheduleJobLogDTO> info(@PathVariable("id") Long id){
+		ScheduleJobLogDTO log = scheduleJobLogService.get(id);
+		
+		return new CommonResult<ScheduleJobLogDTO>().setData(log);
+	}
+}
\ No newline at end of file
diff --git a/shasteel-biz/src/main/java/com/iailab/module/shasteel/job/controller/package-info.java b/shasteel-biz/src/main/java/com/iailab/module/shasteel/job/controller/package-info.java
new file mode 100644
index 0000000..55b12ad
--- /dev/null
+++ b/shasteel-biz/src/main/java/com/iailab/module/shasteel/job/controller/package-info.java
@@ -0,0 +1 @@
+package com.iailab.module.shasteel.job.controller;
\ No newline at end of file
diff --git a/shasteel-biz/src/main/java/com/iailab/module/shasteel/job/dao/ScheduleJobDao.java b/shasteel-biz/src/main/java/com/iailab/module/shasteel/job/dao/ScheduleJobDao.java
new file mode 100644
index 0000000..0792a00
--- /dev/null
+++ b/shasteel-biz/src/main/java/com/iailab/module/shasteel/job/dao/ScheduleJobDao.java
@@ -0,0 +1,34 @@
+package com.iailab.module.shasteel.job.dao;
+
+import com.baomidou.dynamic.datasource.annotation.Master;
+import com.iailab.framework.common.pojo.PageResult;
+import com.iailab.framework.mybatis.core.mapper.BaseMapperX;
+import com.iailab.framework.mybatis.core.query.LambdaQueryWrapperX;
+import com.iailab.module.shasteel.job.entity.ScheduleJobEntity;
+import com.iailab.module.shasteel.job.vo.ScheduleJobReqVO;
+import org.apache.ibatis.annotations.Mapper;
+
+import java.util.Map;
+
+/**
+ * 定时任务
+ *
+ * @author Mark sunlightcs@gmail.com
+ */
+@Master
+@Mapper
+public interface ScheduleJobDao extends BaseMapperX<ScheduleJobEntity> {
+
+	default PageResult<ScheduleJobEntity> selectPage(ScheduleJobReqVO reqVO) {
+		return selectPage(reqVO, new LambdaQueryWrapperX<ScheduleJobEntity>()
+				.likeIfPresent(ScheduleJobEntity::getBeanName, reqVO.getBeanName())
+				.eqIfPresent(ScheduleJobEntity::getTenantId, reqVO.getTenantId())
+				.orderByDesc(ScheduleJobEntity::getCreateDate));
+
+	}
+	
+	/**
+	 * 批量更新状态
+	 */
+	int updateBatch(Map<String, Object> map);
+}
diff --git a/shasteel-biz/src/main/java/com/iailab/module/shasteel/job/dao/ScheduleJobLogDao.java b/shasteel-biz/src/main/java/com/iailab/module/shasteel/job/dao/ScheduleJobLogDao.java
new file mode 100644
index 0000000..c31d870
--- /dev/null
+++ b/shasteel-biz/src/main/java/com/iailab/module/shasteel/job/dao/ScheduleJobLogDao.java
@@ -0,0 +1,17 @@
+package com.iailab.module.shasteel.job.dao;
+
+import com.baomidou.dynamic.datasource.annotation.Master;
+import com.iailab.framework.common.dao.BaseDao;
+import com.iailab.module.shasteel.job.entity.ScheduleJobLogEntity;
+import org.apache.ibatis.annotations.Mapper;
+
+/**
+ * 定时任务日志
+ *
+ * @author Mark sunlightcs@gmail.com
+ */
+@Master
+@Mapper
+public interface ScheduleJobLogDao extends BaseDao<ScheduleJobLogEntity> {
+	
+}
diff --git a/shasteel-biz/src/main/java/com/iailab/module/shasteel/job/dto/ScheduleJobDTO.java b/shasteel-biz/src/main/java/com/iailab/module/shasteel/job/dto/ScheduleJobDTO.java
new file mode 100644
index 0000000..42d5775
--- /dev/null
+++ b/shasteel-biz/src/main/java/com/iailab/module/shasteel/job/dto/ScheduleJobDTO.java
@@ -0,0 +1,62 @@
+/**
+ * Copyright (c) 2018 人人开源 All rights reserved.
+ *
+ * https://www.renren.io
+ *
+ * 版权所有,侵权必究!
+ */
+
+package com.iailab.module.shasteel.job.dto;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+import com.iailab.framework.common.validation.group.AddGroup;
+import com.iailab.framework.common.validation.group.DefaultGroup;
+import com.iailab.framework.common.validation.group.UpdateGroup;
+import io.swagger.v3.oas.annotations.media.Schema;
+import io.swagger.v3.oas.annotations.tags.Tag;
+import lombok.Data;
+
+import javax.validation.constraints.NotBlank;
+import javax.validation.constraints.NotNull;
+import javax.validation.constraints.Null;
+import java.io.Serializable;
+import java.util.Date;
+
+/**
+ * 定时任务
+ *
+ * @author Mark sunlightcs@gmail.com
+ * @since 1.0.0
+ */
+@Data
+@Tag(name = "定时任务")
+public class ScheduleJobDTO implements Serializable {
+    private static final long serialVersionUID = 1L;
+
+    @Schema(description = "id")
+    @Null(message="{id.null}", groups = AddGroup.class)
+    @NotNull(message="{id.require}", groups = UpdateGroup.class)
+    private Long id;
+
+    @Schema(description = "spring bean名称")
+    @NotBlank(message = "{schedule.bean.require}", groups = DefaultGroup.class)
+    private String beanName;
+
+    @Schema(description = "参数")
+    private String params;
+
+    @Schema(description = "cron表达式")
+    @NotBlank(message = "{schedule.cron.require}", groups = DefaultGroup.class)
+    private String cronExpression;
+
+    @Schema(description = "任务状态  0:暂停  1:正常")
+    private Integer status;
+
+    @Schema(description = "备注")
+    private String remark;
+
+    @Schema(description = "创建时间")
+    @JsonProperty(access = JsonProperty.Access.READ_ONLY)
+    private Date createDate;
+
+}
diff --git a/shasteel-biz/src/main/java/com/iailab/module/shasteel/job/dto/ScheduleJobLogDTO.java b/shasteel-biz/src/main/java/com/iailab/module/shasteel/job/dto/ScheduleJobLogDTO.java
new file mode 100644
index 0000000..ae3158b
--- /dev/null
+++ b/shasteel-biz/src/main/java/com/iailab/module/shasteel/job/dto/ScheduleJobLogDTO.java
@@ -0,0 +1,53 @@
+/**
+ * Copyright (c) 2018 人人开源 All rights reserved.
+ *
+ * https://www.renren.io
+ *
+ * 版权所有,侵权必究!
+ */
+
+package com.iailab.module.shasteel.job.dto;
+
+import io.swagger.v3.oas.annotations.media.Schema;
+import io.swagger.v3.oas.annotations.tags.Tag;
+import lombok.Data;
+
+import java.io.Serializable;
+import java.util.Date;
+
+/**
+ * 定时任务日志
+ *
+ * @author Mark sunlightcs@gmail.com
+ * @since 1.0.0
+ */
+@Data
+@Tag(name = "定时任务日志")
+public class ScheduleJobLogDTO implements Serializable {
+    private static final long serialVersionUID = 1L;
+
+    @Schema(description = "id")
+    private Long id;
+
+    @Schema(description = "任务id")
+    private Long jobId;
+
+    @Schema(description = "spring bean名称")
+    private String beanName;
+
+    @Schema(description = "参数")
+    private String params;
+
+    @Schema(description = "任务状态    0:失败    1:成功")
+    private Integer status;
+
+    @Schema(description = "失败信息")
+    private String error;
+
+    @Schema(description = "耗时(单位:毫秒)")
+    private Integer times;
+
+    @Schema(description = "创建时间")
+    private Date createDate;
+
+}
diff --git a/shasteel-biz/src/main/java/com/iailab/module/shasteel/job/entity/ScheduleJobEntity.java b/shasteel-biz/src/main/java/com/iailab/module/shasteel/job/entity/ScheduleJobEntity.java
new file mode 100644
index 0000000..33050e6
--- /dev/null
+++ b/shasteel-biz/src/main/java/com/iailab/module/shasteel/job/entity/ScheduleJobEntity.java
@@ -0,0 +1,58 @@
+package com.iailab.module.shasteel.job.entity;
+
+import com.baomidou.mybatisplus.annotation.FieldFill;
+import com.baomidou.mybatisplus.annotation.TableField;
+import com.baomidou.mybatisplus.annotation.TableName;
+import com.iailab.framework.common.entity.BaseEntity;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+
+import java.util.Date;
+
+/**
+ * 定时任务
+ *
+ * @author Mark sunlightcs@gmail.com
+ */
+@Data
+@EqualsAndHashCode(callSuper=false)
+@TableName("schedule_job")
+public class ScheduleJobEntity extends BaseEntity {
+	private static final long serialVersionUID = 1L;
+
+	/**
+	 * spring bean名称
+	 */
+	private String beanName;
+	/**
+	 * 参数
+	 */
+	private String params;
+	/**
+	 * cron表达式
+	 */
+	private String cronExpression;
+	/**
+	 * 任务状态  0:暂停  1:正常
+	 */
+	private Integer status;
+	/**
+	 * 备注
+	 */
+	private String remark;
+	/**
+	 * 更新者
+	 */
+	@TableField(fill = FieldFill.INSERT_UPDATE)
+	private Long updater;
+	/**
+	 * 更新时间
+	 */
+	@TableField(fill = FieldFill.INSERT_UPDATE)
+	private Date updateDate;
+
+	/**
+	 * 多租户编号
+	 */
+	private Long tenantId;
+}
\ No newline at end of file
diff --git a/shasteel-biz/src/main/java/com/iailab/module/shasteel/job/entity/ScheduleJobLogEntity.java b/shasteel-biz/src/main/java/com/iailab/module/shasteel/job/entity/ScheduleJobLogEntity.java
new file mode 100644
index 0000000..d417cab
--- /dev/null
+++ b/shasteel-biz/src/main/java/com/iailab/module/shasteel/job/entity/ScheduleJobLogEntity.java
@@ -0,0 +1,59 @@
+package com.iailab.module.shasteel.job.entity;
+
+import com.baomidou.mybatisplus.annotation.TableId;
+import com.baomidou.mybatisplus.annotation.TableName;
+import lombok.Data;
+
+import java.io.Serializable;
+import java.util.Date;
+
+/**
+ * 定时任务日志
+ *
+ * @author Mark sunlightcs@gmail.com
+ */
+@Data
+@TableName("schedule_job_log")
+public class ScheduleJobLogEntity implements Serializable {
+	private static final long serialVersionUID = 1L;
+
+	/**
+	 * id
+	 */
+	@TableId
+	private Long id;
+	/**
+	 * 任务id
+	 */
+	private Long jobId;
+	/**
+	 * spring bean名称
+	 */
+	private String beanName;
+	/**
+	 * 参数
+	 */
+	private String params;
+	/**
+	 * 任务状态    0:失败    1:成功
+	 */
+	private Integer status;
+	/**
+	 * 失败信息
+	 */
+	private String error;
+	/**
+	 * 耗时(单位:毫秒)
+	 */
+	private Integer times;
+	/**
+	 * 创建时间
+	 */
+	private Date createDate;
+
+	/**
+	 * 多租户编号
+	 */
+	private Long tenantId;
+
+}
\ No newline at end of file
diff --git a/shasteel-biz/src/main/java/com/iailab/module/shasteel/job/init/JobCommandLineRunner.java b/shasteel-biz/src/main/java/com/iailab/module/shasteel/job/init/JobCommandLineRunner.java
new file mode 100644
index 0000000..e9f61e8
--- /dev/null
+++ b/shasteel-biz/src/main/java/com/iailab/module/shasteel/job/init/JobCommandLineRunner.java
@@ -0,0 +1,38 @@
+package com.iailab.module.shasteel.job.init;
+
+import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
+import com.iailab.module.shasteel.job.dao.ScheduleJobDao;
+import com.iailab.module.shasteel.job.entity.ScheduleJobEntity;
+import com.iailab.module.shasteel.job.utils.ScheduleUtils;
+import org.quartz.CronTrigger;
+import org.quartz.Scheduler;
+import org.springframework.boot.CommandLineRunner;
+import org.springframework.stereotype.Component;
+
+import javax.annotation.Resource;
+import java.util.List;
+
+/**
+ * 初始化定时任务数据
+ */
+@Component
+public class JobCommandLineRunner implements CommandLineRunner {
+    @Resource
+    private Scheduler scheduler;
+    @Resource
+    private ScheduleJobDao scheduleJobDao;
+
+    @Override
+    public void run(String... args) {
+        List<ScheduleJobEntity> scheduleJobList = scheduleJobDao.selectList(new QueryWrapper<>());
+        for(ScheduleJobEntity scheduleJob : scheduleJobList){
+            CronTrigger cronTrigger = ScheduleUtils.getCronTrigger(scheduler, scheduleJob.getId());
+            //如果不存在,则创建
+            if(cronTrigger == null) {
+                ScheduleUtils.createScheduleJob(scheduler, scheduleJob);
+            }else {
+                ScheduleUtils.updateScheduleJob(scheduler, scheduleJob);
+            }
+        }
+    }
+}
\ No newline at end of file
diff --git a/shasteel-biz/src/main/java/com/iailab/module/shasteel/job/service/ScheduleJobLogService.java b/shasteel-biz/src/main/java/com/iailab/module/shasteel/job/service/ScheduleJobLogService.java
new file mode 100644
index 0000000..73a0b95
--- /dev/null
+++ b/shasteel-biz/src/main/java/com/iailab/module/shasteel/job/service/ScheduleJobLogService.java
@@ -0,0 +1,29 @@
+/**
+ * Copyright (c) 2018 人人开源 All rights reserved.
+ *
+ * https://www.renren.io
+ *
+ * 版权所有,侵权必究!
+ */
+
+package com.iailab.module.shasteel.job.service;
+
+import com.iailab.framework.common.page.PageData;
+import com.iailab.framework.common.service.BaseService;
+import com.iailab.module.shasteel.job.dto.ScheduleJobLogDTO;
+import com.iailab.module.shasteel.job.entity.ScheduleJobLogEntity;
+import com.iailab.module.shasteel.job.dto.ScheduleJobLogDTO;
+
+import java.util.Map;
+
+/**
+ * 定时任务日志
+ *
+ * @author Mark sunlightcs@gmail.com
+ */
+public interface ScheduleJobLogService extends BaseService<ScheduleJobLogEntity> {
+
+	PageData<ScheduleJobLogDTO> page(Map<String, Object> params);
+
+	ScheduleJobLogDTO get(Long id);
+}
diff --git a/shasteel-biz/src/main/java/com/iailab/module/shasteel/job/service/ScheduleJobService.java b/shasteel-biz/src/main/java/com/iailab/module/shasteel/job/service/ScheduleJobService.java
new file mode 100644
index 0000000..12b5c29
--- /dev/null
+++ b/shasteel-biz/src/main/java/com/iailab/module/shasteel/job/service/ScheduleJobService.java
@@ -0,0 +1,55 @@
+package com.iailab.module.shasteel.job.service;
+
+import com.iailab.framework.common.pojo.PageResult;
+import com.iailab.framework.common.service.BaseService;
+import com.iailab.module.shasteel.job.dto.ScheduleJobDTO;
+import com.iailab.module.shasteel.job.entity.ScheduleJobEntity;
+import com.iailab.module.shasteel.job.vo.ScheduleJobReqVO;
+
+
+/**
+ * 定时任务
+ *
+ * @author Mark sunlightcs@gmail.com
+ */
+public interface ScheduleJobService{
+
+	PageResult<ScheduleJobEntity> page(ScheduleJobReqVO reqVO);
+
+	ScheduleJobDTO get(Long id);
+
+	/**
+	 * 保存定时任务
+	 */
+	void save(ScheduleJobDTO dto);
+	
+	/**
+	 * 更新定时任务
+	 */
+	void update(ScheduleJobDTO dto);
+	
+	/**
+	 * 批量删除定时任务
+	 */
+	void deleteBatch(Long id);
+	
+	/**
+	 * 批量更新定时任务状态
+	 */
+	int updateBatch(Long[] ids, int status);
+	
+	/**
+	 * 立即执行
+	 */
+	void run(Long[] ids);
+	
+	/**
+	 * 暂停运行
+	 */
+	void pause(Long[] ids);
+	
+	/**
+	 * 恢复运行
+	 */
+	void resume(Long[] ids);
+}
diff --git a/shasteel-biz/src/main/java/com/iailab/module/shasteel/job/service/impl/ScheduleJobLogServiceImpl.java b/shasteel-biz/src/main/java/com/iailab/module/shasteel/job/service/impl/ScheduleJobLogServiceImpl.java
new file mode 100644
index 0000000..eb57384
--- /dev/null
+++ b/shasteel-biz/src/main/java/com/iailab/module/shasteel/job/service/impl/ScheduleJobLogServiceImpl.java
@@ -0,0 +1,54 @@
+/**
+ * Copyright (c) 2018 人人开源 All rights reserved.
+ *
+ * https://www.renren.io
+ *
+ * 版权所有,侵权必究!
+ */
+
+package com.iailab.module.shasteel.job.service.impl;
+
+import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.iailab.framework.common.constant.Constant;
+import com.iailab.framework.common.page.PageData;
+import com.iailab.framework.common.service.impl.BaseServiceImpl;
+import com.iailab.framework.common.util.object.ConvertUtils;
+import com.iailab.module.shasteel.job.dao.ScheduleJobLogDao;
+import com.iailab.module.shasteel.job.dto.ScheduleJobLogDTO;
+import com.iailab.module.shasteel.job.entity.ScheduleJobLogEntity;
+import com.iailab.module.shasteel.job.service.ScheduleJobLogService;
+import org.apache.commons.lang3.StringUtils;
+import org.springframework.stereotype.Service;
+
+import java.util.Map;
+
+@Service
+public class ScheduleJobLogServiceImpl extends BaseServiceImpl<ScheduleJobLogDao, ScheduleJobLogEntity> implements ScheduleJobLogService {
+
+	@Override
+	public PageData<ScheduleJobLogDTO> page(Map<String, Object> params) {
+		IPage<ScheduleJobLogEntity> page = baseDao.selectPage(
+			getPage(params, Constant.CREATE_DATE, false),
+			getWrapper(params)
+		);
+		return getPageData(page, ScheduleJobLogDTO.class);
+	}
+
+	private QueryWrapper<ScheduleJobLogEntity> getWrapper(Map<String, Object> params){
+		String jobId = (String)params.get("jobId");
+
+		QueryWrapper<ScheduleJobLogEntity> wrapper = new QueryWrapper<>();
+		wrapper.eq(StringUtils.isNotBlank(jobId), "job_id", jobId);
+
+		return wrapper;
+	}
+
+	@Override
+	public ScheduleJobLogDTO get(Long id) {
+		ScheduleJobLogEntity entity = baseDao.selectById(id);
+
+		return ConvertUtils.sourceToTarget(entity, ScheduleJobLogDTO.class);
+	}
+
+}
\ No newline at end of file
diff --git a/shasteel-biz/src/main/java/com/iailab/module/shasteel/job/service/impl/ScheduleJobServiceImpl.java b/shasteel-biz/src/main/java/com/iailab/module/shasteel/job/service/impl/ScheduleJobServiceImpl.java
new file mode 100644
index 0000000..ad9b2ad
--- /dev/null
+++ b/shasteel-biz/src/main/java/com/iailab/module/shasteel/job/service/impl/ScheduleJobServiceImpl.java
@@ -0,0 +1,128 @@
+package com.iailab.module.shasteel.job.service.impl;
+
+import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import com.iailab.framework.common.constant.Constant;
+import com.iailab.framework.common.pojo.PageResult;
+import com.iailab.framework.common.service.impl.BaseServiceImpl;
+import com.iailab.framework.common.util.object.ConvertUtils;
+import com.iailab.framework.security.core.util.SecurityFrameworkUtils;
+import com.iailab.framework.tenant.core.context.TenantContextHolder;
+import com.iailab.module.shasteel.job.dao.ScheduleJobDao;
+import com.iailab.module.shasteel.job.dto.ScheduleJobDTO;
+import com.iailab.module.shasteel.job.entity.ScheduleJobEntity;
+import com.iailab.module.shasteel.job.service.ScheduleJobService;
+import com.iailab.module.shasteel.job.utils.ScheduleUtils;
+import com.iailab.module.shasteel.job.vo.ScheduleJobReqVO;
+import org.apache.commons.lang3.StringUtils;
+import org.quartz.Scheduler;
+import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
+
+import javax.annotation.Resource;
+import java.util.Date;
+import java.util.HashMap;
+import java.util.Map;
+
+@Service
+public class ScheduleJobServiceImpl extends ServiceImpl<ScheduleJobDao, ScheduleJobEntity> implements ScheduleJobService {
+	@Resource
+	private Scheduler scheduler;
+
+	@Resource
+	private ScheduleJobDao scheduleJobDao;
+
+	@Override
+	public PageResult<ScheduleJobEntity> page(ScheduleJobReqVO reqVO) {
+		return scheduleJobDao.selectPage(reqVO);
+	}
+
+	@Override
+	public ScheduleJobDTO get(Long id) {
+		ScheduleJobEntity entity = scheduleJobDao.selectById(id);
+
+		return ConvertUtils.sourceToTarget(entity, ScheduleJobDTO.class);
+	}
+
+	private QueryWrapper<ScheduleJobEntity> getWrapper(Map<String, Object> params){
+		String beanName = (String)params.get("beanName");
+
+		QueryWrapper<ScheduleJobEntity> wrapper = new QueryWrapper<>();
+		wrapper.like(StringUtils.isNotBlank(beanName), "bean_name", beanName);
+
+		return wrapper;
+	}
+
+	@Override
+	@Transactional(rollbackFor = Exception.class)
+	public void save(ScheduleJobDTO dto) {
+		Long tenantId = TenantContextHolder.getRequiredTenantId();
+		ScheduleJobEntity entity = ConvertUtils.sourceToTarget(dto, ScheduleJobEntity.class);
+		entity.setId(System.currentTimeMillis());
+		entity.setStatus(Constant.ScheduleStatus.NORMAL.getValue());
+		entity.setTenantId(tenantId);
+		entity.setCreator(SecurityFrameworkUtils.getLoginUser().getId());
+		entity.setCreateDate(new Date());
+		scheduleJobDao.insert(entity);
+        
+        ScheduleUtils.createScheduleJob(scheduler, entity);
+    }
+	
+	@Override
+	@Transactional(rollbackFor = Exception.class)
+	public void update(ScheduleJobDTO dto) {
+		Long tenantId = TenantContextHolder.getRequiredTenantId();
+		ScheduleJobEntity entity = ConvertUtils.sourceToTarget(dto, ScheduleJobEntity.class);
+		entity.setUpdateDate(new Date());
+		entity.setUpdater(SecurityFrameworkUtils.getLoginUser().getId());
+		entity.setTenantId(tenantId);
+        ScheduleUtils.updateScheduleJob(scheduler, entity);
+                
+        this.updateById(entity);
+    }
+
+	@Override
+	@Transactional(rollbackFor = Exception.class)
+    public void deleteBatch(Long id) {
+		ScheduleUtils.deleteScheduleJob(scheduler, id);
+
+		scheduleJobDao.deleteById(id);
+	}
+
+	@Override
+    public int updateBatch(Long[] ids, int status){
+    	Map<String, Object> map = new HashMap<>(2);
+    	map.put("ids", ids);
+    	map.put("status", status);
+    	return scheduleJobDao.updateBatch(map);
+    }
+    
+	@Override
+	@Transactional(rollbackFor = Exception.class)
+    public void run(Long[] ids) {
+    	for(Long id : ids){
+    		ScheduleUtils.run(scheduler, scheduleJobDao.selectById(id));
+    	}
+    }
+
+	@Override
+	@Transactional(rollbackFor = Exception.class)
+    public void pause(Long[] ids) {
+        for(Long id : ids){
+    		ScheduleUtils.pauseJob(scheduler, id);
+    	}
+        
+    	updateBatch(ids, Constant.ScheduleStatus.PAUSE.getValue());
+    }
+
+	@Override
+	@Transactional(rollbackFor = Exception.class)
+    public void resume(Long[] ids) {
+    	for(Long id : ids){
+    		ScheduleUtils.resumeJob(scheduler, id);
+    	}
+
+    	updateBatch(ids, Constant.ScheduleStatus.NORMAL.getValue());
+    }
+    
+}
\ No newline at end of file
diff --git a/shasteel-biz/src/main/java/com/iailab/module/shasteel/job/task/ITask.java b/shasteel-biz/src/main/java/com/iailab/module/shasteel/job/task/ITask.java
new file mode 100644
index 0000000..6166e57
--- /dev/null
+++ b/shasteel-biz/src/main/java/com/iailab/module/shasteel/job/task/ITask.java
@@ -0,0 +1,25 @@
+/**
+ * Copyright (c) 2018 人人开源 All rights reserved.
+ *
+ * https://www.renren.io
+ *
+ * 版权所有,侵权必究!
+ */
+
+package com.iailab.module.shasteel.job.task;
+
+/**
+ * 定时任务接口,所有定时任务都要实现该接口
+ *
+ * @author Mark sunlightcs@gmail.com
+ * @since 1.0.0
+ */
+public interface ITask {
+
+    /**
+     * 执行定时任务接口
+     *
+     * @param params   参数,多参数使用JSON数据
+     */
+    void run(String params);
+}
\ No newline at end of file
diff --git a/shasteel-biz/src/main/java/com/iailab/module/shasteel/job/task/TestTask.java b/shasteel-biz/src/main/java/com/iailab/module/shasteel/job/task/TestTask.java
new file mode 100644
index 0000000..148f882
--- /dev/null
+++ b/shasteel-biz/src/main/java/com/iailab/module/shasteel/job/task/TestTask.java
@@ -0,0 +1,22 @@
+package com.iailab.module.shasteel.job.task;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.stereotype.Component;
+
+/**
+ * 测试定时任务(演示Demo,可删除)
+ *
+ * testTask为spring bean的名称
+ *
+ * @author Mark sunlightcs@gmail.com
+ */
+@Component("testTask")
+public class TestTask implements ITask{
+	private Logger logger = LoggerFactory.getLogger(getClass());
+
+	@Override
+	public void run(String params){
+		logger.debug("TestTask定时任务正在执行,参数为:{}", params);
+	}
+}
\ No newline at end of file
diff --git a/shasteel-biz/src/main/java/com/iailab/module/shasteel/job/utils/ScheduleJob.java b/shasteel-biz/src/main/java/com/iailab/module/shasteel/job/utils/ScheduleJob.java
new file mode 100644
index 0000000..2ced982
--- /dev/null
+++ b/shasteel-biz/src/main/java/com/iailab/module/shasteel/job/utils/ScheduleJob.java
@@ -0,0 +1,80 @@
+package com.iailab.module.shasteel.job.utils;
+
+import com.iailab.framework.common.constant.Constant;
+import com.iailab.framework.common.exception.ExceptionUtils;
+import com.iailab.framework.common.util.spring.SpringContextUtils;
+import com.iailab.framework.tenant.core.context.TenantContextHolder;
+import com.iailab.module.shasteel.job.entity.ScheduleJobEntity;
+import com.iailab.module.shasteel.job.entity.ScheduleJobLogEntity;
+import com.iailab.module.shasteel.job.service.ScheduleJobLogService;
+import org.quartz.DisallowConcurrentExecution;
+import org.quartz.JobExecutionContext;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.scheduling.quartz.QuartzJobBean;
+
+import java.lang.reflect.Method;
+import java.util.Date;
+
+
+/**
+ * 定时任务
+ *
+ * @author Mark sunlightcs@gmail.com
+ */
+@DisallowConcurrentExecution
+public class ScheduleJob extends QuartzJobBean {
+	private Logger logger = LoggerFactory.getLogger(getClass());
+
+    @Override
+    protected void executeInternal(JobExecutionContext context) {
+        ScheduleJobEntity scheduleJob = (ScheduleJobEntity) context.getMergedJobDataMap().
+				get(ScheduleUtils.JOB_PARAM_KEY);
+
+        //设置当前租户
+		TenantContextHolder.setTenantId(scheduleJob.getTenantId());
+		Long tenantId = TenantContextHolder.getRequiredTenantId();
+
+        //数据库保存执行记录
+        ScheduleJobLogEntity log = new ScheduleJobLogEntity();
+		log.setId(System.currentTimeMillis());
+        log.setJobId(scheduleJob.getId());
+        log.setBeanName(scheduleJob.getBeanName());
+        log.setParams(scheduleJob.getParams());
+		log.setCreateDate(new Date());
+		log.setTenantId(tenantId);
+
+        //任务开始时间
+        long startTime = System.currentTimeMillis();
+        
+        try {
+			//执行任务
+			logger.info("任务准备执行,任务ID:{}", scheduleJob.getId());
+			Object target = SpringContextUtils.getBean(scheduleJob.getBeanName());
+			Method method = target.getClass().getDeclaredMethod("run", String.class);
+			method.invoke(target, scheduleJob.getParams());
+
+			//任务执行总时长
+			long times = System.currentTimeMillis() - startTime;
+			log.setTimes((int)times);
+			//任务状态
+			log.setStatus(Constant.SUCCESS);
+			
+			logger.info("任务执行完毕,任务ID:{}  总共耗时:{} 毫秒", scheduleJob.getId(), times);
+		} catch (Exception e) {
+			logger.error("任务执行失败,任务ID:{}", scheduleJob.getId(), e);
+			
+			//任务执行总时长
+			long times = System.currentTimeMillis() - startTime;
+			log.setTimes((int)times);
+			
+			//任务状态
+			log.setStatus(Constant.FAIL);
+			log.setError(ExceptionUtils.getErrorStackTrace(e));
+		}finally {
+			//获取spring bean
+			ScheduleJobLogService scheduleJobLogService = SpringContextUtils.getBean(ScheduleJobLogService.class);
+			scheduleJobLogService.insert(log);
+		}
+    }
+}
\ No newline at end of file
diff --git a/shasteel-biz/src/main/java/com/iailab/module/shasteel/job/utils/ScheduleUtils.java b/shasteel-biz/src/main/java/com/iailab/module/shasteel/job/utils/ScheduleUtils.java
new file mode 100644
index 0000000..4f1c9f0
--- /dev/null
+++ b/shasteel-biz/src/main/java/com/iailab/module/shasteel/job/utils/ScheduleUtils.java
@@ -0,0 +1,153 @@
+package com.iailab.module.shasteel.job.utils;
+
+import com.iailab.framework.common.constant.Constant;
+import com.iailab.framework.common.enums.ErrorCode;
+import com.iailab.framework.common.exception.ServerException;
+import com.iailab.module.shasteel.job.entity.ScheduleJobEntity;
+import org.quartz.*;
+
+/**
+ * 定时任务工具类
+ *
+ * @author Mark sunlightcs@gmail.com
+ */
+public class ScheduleUtils {
+    private final static String JOB_NAME = "TASK_";
+    /**
+     * 任务调度参数key
+     */
+    public static final String JOB_PARAM_KEY = "JOB_PARAM_KEY";
+    
+    /**
+     * 获取触发器key
+     */
+    public static TriggerKey getTriggerKey(Long jobId) {
+        return TriggerKey.triggerKey(JOB_NAME + jobId);
+    }
+    
+    /**
+     * 获取jobKey
+     */
+    public static JobKey getJobKey(Long jobId) {
+        return JobKey.jobKey(JOB_NAME + jobId);
+    }
+
+    /**
+     * 获取表达式触发器
+     */
+    public static CronTrigger getCronTrigger(Scheduler scheduler, Long jobId) {
+        try {
+            return (CronTrigger) scheduler.getTrigger(getTriggerKey(jobId));
+        } catch (SchedulerException e) {
+            throw new ServerException(ErrorCode.JOB_ERROR, e.getMessage());
+        }
+    }
+
+    /**
+     * 创建定时任务
+     */
+    public static void createScheduleJob(Scheduler scheduler, ScheduleJobEntity scheduleJob) {
+        try {
+        	//构建job信息
+            JobDetail jobDetail = JobBuilder.newJob(ScheduleJob.class).withIdentity(getJobKey(scheduleJob.getId())).build();
+
+            //表达式调度构建器
+            CronScheduleBuilder scheduleBuilder = CronScheduleBuilder.cronSchedule(scheduleJob.getCronExpression())
+            		.withMisfireHandlingInstructionDoNothing();
+
+            //按新的cronExpression表达式构建一个新的trigger
+            CronTrigger trigger = TriggerBuilder.newTrigger().withIdentity(getTriggerKey(scheduleJob.getId())).withSchedule(scheduleBuilder).build();
+
+            //放入参数,运行时的方法可以获取
+            jobDetail.getJobDataMap().put(JOB_PARAM_KEY, scheduleJob);
+
+            scheduler.scheduleJob(jobDetail, trigger);
+            
+            //暂停任务
+            if(scheduleJob.getStatus() == Constant.ScheduleStatus.PAUSE.getValue()){
+            	pauseJob(scheduler, scheduleJob.getId());
+            }
+        } catch (SchedulerException e) {
+            throw new ServerException(ErrorCode.JOB_ERROR, e.getMessage());
+        }
+    }
+    
+    /**
+     * 更新定时任务
+     */
+    public static void updateScheduleJob(Scheduler scheduler, ScheduleJobEntity scheduleJob) {
+        try {
+            TriggerKey triggerKey = getTriggerKey(scheduleJob.getId());
+
+            //表达式调度构建器
+            CronScheduleBuilder scheduleBuilder = CronScheduleBuilder.cronSchedule(scheduleJob.getCronExpression())
+            		.withMisfireHandlingInstructionDoNothing();
+
+            CronTrigger trigger = getCronTrigger(scheduler, scheduleJob.getId());
+            
+            //按新的cronExpression表达式重新构建trigger
+            trigger = trigger.getTriggerBuilder().withIdentity(triggerKey).withSchedule(scheduleBuilder).build();
+            
+            //参数
+            trigger.getJobDataMap().put(JOB_PARAM_KEY, scheduleJob);
+            
+            scheduler.rescheduleJob(triggerKey, trigger);
+            
+            //暂停任务
+            if(scheduleJob.getStatus() == Constant.ScheduleStatus.PAUSE.getValue()){
+            	pauseJob(scheduler, scheduleJob.getId());
+            }
+            
+        } catch (SchedulerException e) {
+            throw new ServerException(ErrorCode.JOB_ERROR, e.getMessage());
+        }
+    }
+
+    /**
+     * 立即执行任务
+     */
+    public static void run(Scheduler scheduler, ScheduleJobEntity scheduleJob) {
+        try {
+        	//参数
+        	JobDataMap dataMap = new JobDataMap();
+        	dataMap.put(JOB_PARAM_KEY, scheduleJob);
+        	
+            scheduler.triggerJob(getJobKey(scheduleJob.getId()), dataMap);
+        } catch (SchedulerException e) {
+            throw new ServerException(ErrorCode.JOB_ERROR, e.getMessage());
+        }
+    }
+
+    /**
+     * 暂停任务
+     */
+    public static void pauseJob(Scheduler scheduler, Long jobId) {
+        try {
+            scheduler.pauseJob(getJobKey(jobId));
+        } catch (SchedulerException e) {
+            throw new ServerException(ErrorCode.JOB_ERROR, e.getMessage());
+        }
+    }
+
+    /**
+     * 恢复任务
+     */
+    public static void resumeJob(Scheduler scheduler, Long jobId) {
+        try {
+            scheduler.resumeJob(getJobKey(jobId));
+        } catch (SchedulerException e) {
+            throw new ServerException(ErrorCode.JOB_ERROR, e.getMessage());
+        }
+    }
+
+    /**
+     * 删除定时任务
+     */
+    public static void deleteScheduleJob(Scheduler scheduler, Long jobId) {
+        try {
+            scheduler.deleteJob(getJobKey(jobId));
+        } catch (SchedulerException e) {
+            throw new ServerException(ErrorCode.JOB_ERROR, e.getMessage());
+        }
+    }
+}
\ No newline at end of file
diff --git a/shasteel-biz/src/main/java/com/iailab/module/shasteel/job/vo/ScheduleJobReqVO.java b/shasteel-biz/src/main/java/com/iailab/module/shasteel/job/vo/ScheduleJobReqVO.java
new file mode 100644
index 0000000..9c37992
--- /dev/null
+++ b/shasteel-biz/src/main/java/com/iailab/module/shasteel/job/vo/ScheduleJobReqVO.java
@@ -0,0 +1,23 @@
+package com.iailab.module.shasteel.job.vo;
+
+import com.iailab.framework.common.pojo.PageParam;
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import lombok.ToString;
+
+/**
+ * @author PanZhibao
+ * @Description
+ * @createTime 2024年08月23日
+ */
+@Schema(description = "数据平台 - 定时任务分页 Request VO")
+@Data
+@EqualsAndHashCode(callSuper = true)
+@ToString(callSuper = true)
+public class ScheduleJobReqVO extends PageParam {
+
+    private String beanName;
+
+    private Long tenantId;
+}
\ No newline at end of file
diff --git a/shasteel-biz/src/main/resources/application.yaml b/shasteel-biz/src/main/resources/application.yaml
index bd4a3fe..e1a2920 100644
--- a/shasteel-biz/src/main/resources/application.yaml
+++ b/shasteel-biz/src/main/resources/application.yaml
@@ -138,6 +138,20 @@
       url:  # Admin 管理后台 UI 的地址
   tenant: # 多租户相关配置项
     enable: true
+    ignore-tables:
+      - qrtz_blob_triggers
+      - qrtz_calendars
+      - qrtz_cron_triggers
+      - qrtz_fired_triggers
+      - qrtz_job_details
+      - qrtz_locks
+      - qrtz_paused_trigger_grps
+      - qrtz_scheduler_state
+      - qrtz_simple_triggers
+      - qrtz_simprop_triggers
+      - qrtz_triggers
+      - schedule_job
+      - schedule_job_log
   swagger:
     title: 沙钢智慧能源后台
     description: 提供管理员管理的所有功能
diff --git a/shasteel-biz/src/main/resources/mapper/job/ScheduleJobDao.xml b/shasteel-biz/src/main/resources/mapper/job/ScheduleJobDao.xml
new file mode 100644
index 0000000..03761c4
--- /dev/null
+++ b/shasteel-biz/src/main/resources/mapper/job/ScheduleJobDao.xml
@@ -0,0 +1,14 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
+
+<mapper namespace="com.iailab.module.shasteel.job.dao.ScheduleJobDao">
+	
+	<!-- 批量更新状态 -->
+	<update id="updateBatch"> 
+		update schedule_job set status = #{status} where id in
+		<foreach item="id" collection="ids"  open="(" separator="," close=")">
+			#{id}
+		</foreach>
+	</update>
+
+</mapper>
\ No newline at end of file
diff --git a/shasteel-biz/src/main/resources/mapper/job/ScheduleJobLogDao.xml b/shasteel-biz/src/main/resources/mapper/job/ScheduleJobLogDao.xml
new file mode 100644
index 0000000..fe404a2
--- /dev/null
+++ b/shasteel-biz/src/main/resources/mapper/job/ScheduleJobLogDao.xml
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
+
+<mapper namespace="com.iailab.module.shasteel.job.dao.ScheduleJobLogDao">
+
+	
+</mapper>
\ No newline at end of file

--
Gitblit v1.9.3