Commit 014f91533c049bf2445ba6107f11e87cb3197004

Authored by YunaiV
1 parent 3959aada

1. 完成 quartz 的封装

Showing 33 changed files with 440 additions and 552 deletions
bin/clean.bat deleted
1 -@echo off  
2 -echo.  
3 -echo [ÐÅÏ¢] ÇåÀíÉú³É·¾¶¡£  
4 -echo.  
5 -  
6 -%~d0  
7 -cd %~dp0  
8 -  
9 -cd ..  
10 -call mvn clean  
11 -  
12 -pause  
13 \ No newline at end of file 0 \ No newline at end of file
bin/package.bat deleted
1 -@echo off  
2 -echo.  
3 -echo [信息] 打包Web工程,生成war/jar包文件。  
4 -echo.  
5 -  
6 -%~d0  
7 -cd %~dp0  
8 -  
9 -cd ..  
10 -call mvn clean package -Dmaven.test.skip=true  
11 -  
12 -pause  
13 \ No newline at end of file 0 \ No newline at end of file
bin/run.bat deleted
1 -@echo off  
2 -echo.  
3 -echo [ĞÅÏ¢] ÔËĞĞWeb¹¤³Ì¡£  
4 -echo.  
5 -  
6 -cd %~dp0  
7 -cd ../ruoyi-admin/target  
8 -  
9 -set JAVA_OPTS=-Xms256m -Xmx1024m -XX:MetaspaceSize=128m -XX:MaxMetaspaceSize=512m  
10 -  
11 -java -jar %JAVA_OPTS% ruoyi-admin.jar  
12 -  
13 -cd bin  
14 -pause  
15 \ No newline at end of file 0 \ No newline at end of file
ruoyi-common/src/main/java/com/ruoyi/quartz/config/ScheduleConfig.java deleted
1 -package com.ruoyi.quartz.config;  
2 -  
3 -import org.springframework.context.annotation.Bean;  
4 -import org.springframework.context.annotation.Configuration;  
5 -import org.springframework.scheduling.quartz.SchedulerFactoryBean;  
6 -  
7 -import javax.sql.DataSource;  
8 -import java.util.Properties;  
9 -  
10 -/**  
11 - * 定时任务配置  
12 - *  
13 - * @author ruoyi  
14 - */  
15 -@Configuration  
16 -public class ScheduleConfig {  
17 -  
18 - @Bean  
19 - public SchedulerFactoryBean schedulerFactoryBean(DataSource dataSource) {  
20 - SchedulerFactoryBean factory = new SchedulerFactoryBean();  
21 - factory.setDataSource(dataSource);  
22 -  
23 - // quartz参数  
24 - Properties prop = new Properties();  
25 - prop.put("org.quartz.scheduler.instanceName", "RuoyiScheduler");  
26 - prop.put("org.quartz.scheduler.instanceId", "AUTO");  
27 - // 集群配置  
28 - prop.put("org.quartz.jobStore.clusterCheckinInterval", "15000");  
29 - prop.put("org.quartz.jobStore.maxMisfiresToHandleAtATime", "1");  
30 - prop.put("org.quartz.jobStore.txIsolationLevelSerializable", "true");  
31 -  
32 - // sqlserver 启用  
33 - // prop.put("org.quartz.jobStore.selectWithLockSQL", "SELECT * FROM {0}LOCKS UPDLOCK WHERE LOCK_NAME = ?");  
34 - prop.put("org.quartz.jobStore.misfireThreshold", "12000");  
35 - factory.setQuartzProperties(prop);  
36 -  
37 - factory.setSchedulerName("RuoyiScheduler");  
38 - // 延时启动  
39 - factory.setStartupDelay(1);  
40 - factory.setApplicationContextSchedulerContextKey("applicationContextKey");  
41 - // 可选,QuartzScheduler  
42 - // 启动时更新己存在的Job,这样就不用每次修改targetObject后删除qrtz_job_details表对应记录了  
43 - factory.setOverwriteExistingJobs(true);  
44 -  
45 -  
46 - return factory;  
47 - }  
48 -}  
ruoyi-common/src/main/java/com/ruoyi/quartz/controller/SysJobLogController.java deleted
1 -package com.ruoyi.quartz.controller;  
2 -  
3 -import java.util.List;  
4 -  
5 -import org.springframework.beans.factory.annotation.Autowired;  
6 -import org.springframework.security.access.prepost.PreAuthorize;  
7 -import org.springframework.web.bind.annotation.DeleteMapping;  
8 -import org.springframework.web.bind.annotation.GetMapping;  
9 -import org.springframework.web.bind.annotation.PathVariable;  
10 -import org.springframework.web.bind.annotation.RequestMapping;  
11 -import org.springframework.web.bind.annotation.RestController;  
12 -import com.ruoyi.common.annotation.Log;  
13 -import com.ruoyi.common.core.controller.BaseController;  
14 -import com.ruoyi.common.core.domain.AjaxResult;  
15 -import com.ruoyi.common.core.page.TableDataInfo;  
16 -import com.ruoyi.common.enums.BusinessType;  
17 -import com.ruoyi.common.utils.poi.ExcelUtil;  
18 -import com.ruoyi.quartz.domain.SysJobLog;  
19 -import com.ruoyi.quartz.service.ISysJobLogService;  
20 -  
21 -/**  
22 - * 调度日志操作处理  
23 - *  
24 - * @author ruoyi  
25 - */  
26 -@RestController  
27 -@RequestMapping("/monitor/jobLog")  
28 -public class SysJobLogController extends BaseController {  
29 - @Autowired  
30 - private ISysJobLogService jobLogService;  
31 -  
32 - /**  
33 - * 查询定时任务调度日志列表  
34 - */  
35 - @PreAuthorize("@ss.hasPermi('monitor:job:list')")  
36 - @GetMapping("/list")  
37 - public TableDataInfo list(SysJobLog sysJobLog) {  
38 - startPage();  
39 - List<SysJobLog> list = jobLogService.selectJobLogList(sysJobLog);  
40 - return getDataTable(list);  
41 - }  
42 -  
43 - /**  
44 - * 导出定时任务调度日志列表  
45 - */  
46 - @PreAuthorize("@ss.hasPermi('monitor:job:export')")  
47 - @Log(title = "任务调度日志", businessType = BusinessType.EXPORT)  
48 - @GetMapping("/export")  
49 - public AjaxResult export(SysJobLog sysJobLog) {  
50 - List<SysJobLog> list = jobLogService.selectJobLogList(sysJobLog);  
51 - ExcelUtil<SysJobLog> util = new ExcelUtil<SysJobLog>(SysJobLog.class);  
52 - return util.exportExcel(list, "调度日志");  
53 - }  
54 -  
55 - /**  
56 - * 根据调度编号获取详细信息  
57 - */  
58 - @PreAuthorize("@ss.hasPermi('monitor:job:query')")  
59 - @GetMapping(value = "/{configId}")  
60 - public AjaxResult getInfo(@PathVariable Long jobLogId) {  
61 - return AjaxResult.success(jobLogService.selectJobLogById(jobLogId));  
62 - }  
63 -  
64 -}  
ruoyi-ui/src/api/infra/job.js
@@ -73,3 +73,11 @@ export function runJob(jobId) { @@ -73,3 +73,11 @@ export function runJob(jobId) {
73 method: 'put' 73 method: 'put'
74 }) 74 })
75 } 75 }
  76 +
  77 +// 获得定时任务的下 n 次执行时间
  78 +export function getJobNextTimes(jobId) {
  79 + return request({
  80 + url: '/infra/job/get_next_times?id=' + jobId,
  81 + method: 'get'
  82 + })
  83 +}
ruoyi-ui/src/api/infra/jobLog.js 0 → 100644
  1 +import request from '@/utils/request'
  2 +
  3 +// 获得定时任务
  4 +export function getJobLog(id) {
  5 + return request({
  6 + url: '/infra/job-log/get?id=' + id,
  7 + method: 'get'
  8 + })
  9 +}
  10 +
  11 +// 获得定时任务分页
  12 +export function getJobLogPage(query) {
  13 + return request({
  14 + url: '/infra/job-log/page',
  15 + method: 'get',
  16 + params: query
  17 + })
  18 +}
  19 +
  20 +// 导出定时任务 Excel
  21 +export function exportJobLogExcel(query) {
  22 + return request({
  23 + url: '/infra/job-log/export-excel',
  24 + method: 'get',
  25 + params: query,
  26 + responseType: 'blob'
  27 + })
  28 +}
ruoyi-ui/src/api/monitor/jobLog.js deleted
1 -import request from '@/utils/request'  
2 -  
3 -// 查询调度日志列表  
4 -export function listJobLog(query) {  
5 - return request({  
6 - url: '/monitor/jobLog/list',  
7 - method: 'get',  
8 - params: query  
9 - })  
10 -}  
11 -  
12 -// 删除调度日志  
13 -export function delJobLog(jobLogId) {  
14 - return request({  
15 - url: '/monitor/jobLog/' + jobLogId,  
16 - method: 'delete'  
17 - })  
18 -}  
19 -  
20 -// 清空调度日志  
21 -export function cleanJobLog() {  
22 - return request({  
23 - url: '/monitor/jobLog/clean',  
24 - method: 'delete'  
25 - })  
26 -}  
27 -  
28 -// 导出调度日志  
29 -export function exportJobLog(query) {  
30 - return request({  
31 - url: '/monitor/jobLog/export',  
32 - method: 'get',  
33 - params: query  
34 - })  
35 -}  
36 \ No newline at end of file 0 \ No newline at end of file
ruoyi-ui/src/utils/dict.js
@@ -18,6 +18,7 @@ export const DICT_TYPE = { @@ -18,6 +18,7 @@ export const DICT_TYPE = {
18 18
19 INF_REDIS_TIMEOUT_TYPE: 'inf_redis_timeout_type', 19 INF_REDIS_TIMEOUT_TYPE: 'inf_redis_timeout_type',
20 INF_JOB_STATUS: 'inf_job_status', 20 INF_JOB_STATUS: 'inf_job_status',
  21 + INF_JOB_LOG_STATUS: 'inf_job_log_status',
21 22
22 TOOL_CODEGEN_TEMPLATE_TYPE: 'tool_codegen_template_type', 23 TOOL_CODEGEN_TEMPLATE_TYPE: 'tool_codegen_template_type',
23 } 24 }
ruoyi-ui/src/views/infra/job/index.vue
@@ -30,7 +30,7 @@ @@ -30,7 +30,7 @@
30 </el-col> 30 </el-col>
31 <el-col :span="1.5"> 31 <el-col :span="1.5">
32 <el-button type="info" icon="el-icon-s-operation" size="mini" @click="handleJobLog" 32 <el-button type="info" icon="el-icon-s-operation" size="mini" @click="handleJobLog"
33 - v-hasPermi="['infra:job:query']">日志</el-button> 33 + v-hasPermi="['infra:job:query']">执行日志</el-button>
34 </el-col> 34 </el-col>
35 <right-toolbar :showSearch.sync="showSearch" @queryTable="getList"></right-toolbar> 35 <right-toolbar :showSearch.sync="showSearch" @queryTable="getList"></right-toolbar>
36 </el-row> 36 </el-row>
@@ -50,6 +50,8 @@ @@ -50,6 +50,8 @@
50 <template slot-scope="scope"> 50 <template slot-scope="scope">
51 <el-button size="mini" type="text" icon="el-icon-view" @click="handleView(scope.row)" 51 <el-button size="mini" type="text" icon="el-icon-view" @click="handleView(scope.row)"
52 v-hasPermi="['infra:job:query']">详细</el-button> 52 v-hasPermi="['infra:job:query']">详细</el-button>
  53 + <el-button size="mini" icon="el-icon-s-operation" @click="handleJobLog(scope.row)"
  54 + v-hasPermi="['infra:job:query']">执行日志</el-button>
53 <el-button size="mini" type="text" icon="el-icon-edit" @click="handleUpdate(scope.row)" 55 <el-button size="mini" type="text" icon="el-icon-edit" @click="handleUpdate(scope.row)"
54 v-hasPermi="['infra:job:update']">修改</el-button> 56 v-hasPermi="['infra:job:update']">修改</el-button>
55 <el-button size="mini" type="text" icon="el-icon-check" @click="handleChangeStatus(scope.row, true)" 57 <el-button size="mini" type="text" icon="el-icon-check" @click="handleChangeStatus(scope.row, true)"
@@ -109,13 +111,10 @@ @@ -109,13 +111,10 @@
109 <el-form-item label="处理器的名字:">{{ form.handlerName }}</el-form-item> 111 <el-form-item label="处理器的名字:">{{ form.handlerName }}</el-form-item>
110 <el-form-item label="处理器的参数:">{{ form.handlerParam }}</el-form-item> 112 <el-form-item label="处理器的参数:">{{ form.handlerParam }}</el-form-item>
111 <el-form-item label="cron表达式:">{{ form.cronExpression }}</el-form-item> 113 <el-form-item label="cron表达式:">{{ form.cronExpression }}</el-form-item>
112 - <el-form-item label="最后一次执行的开始时间:">{{ parseTime(form.executeBeginTime) }}</el-form-item>  
113 - <el-form-item label="最后一次执行的开始时间:">{{ parseTime(form.executeEndTime) }}</el-form-item>  
114 - <el-form-item label="上一次触发时间:">{{ parseTime(form.firePrevTime) }}</el-form-item>  
115 - <el-form-item label="下一次触发时间:">{{ parseTime(form.fireNextTime) }}</el-form-item>  
116 <el-form-item label="重试次数:">{{ form.retryCount }}</el-form-item> 114 <el-form-item label="重试次数:">{{ form.retryCount }}</el-form-item>
117 <el-form-item label="重试间隔:">{{ form.retryInterval + " 毫秒" }}</el-form-item> 115 <el-form-item label="重试间隔:">{{ form.retryInterval + " 毫秒" }}</el-form-item>
118 <el-form-item label="监控超时时间:">{{ form.monitorTimeout > 0 ? form.monitorTimeout + " 毫秒" : "未开启" }}</el-form-item> 116 <el-form-item label="监控超时时间:">{{ form.monitorTimeout > 0 ? form.monitorTimeout + " 毫秒" : "未开启" }}</el-form-item>
  117 + <el-form-item label="后续执行时间:">{{ Array.from(nextTimes, x => parseTime(x)).join('; ')}}</el-form-item>
119 </el-col> 118 </el-col>
120 </el-row> 119 </el-row>
121 </el-form> 120 </el-form>
@@ -128,7 +127,7 @@ @@ -128,7 +127,7 @@
128 </template> 127 </template>
129 128
130 <script> 129 <script>
131 -import { listJob, getJob, delJob, addJob, updateJob, exportJob, runJob, updateJobStatus } from "@/api/infra/job"; 130 +import { listJob, getJob, delJob, addJob, updateJob, exportJob, runJob, updateJobStatus, getJobNextTimes } from "@/api/infra/job";
132 import { InfJobStatusEnum } from "@/utils/constants"; 131 import { InfJobStatusEnum } from "@/utils/constants";
133 132
134 export default { 133 export default {
@@ -169,6 +168,7 @@ export default { @@ -169,6 +168,7 @@ export default {
169 retryCount: [{ required: true, message: "重试次数不能为空", trigger: "blur" }], 168 retryCount: [{ required: true, message: "重试次数不能为空", trigger: "blur" }],
170 retryInterval: [{ required: true, message: "重试间隔不能为空", trigger: "blur" }], 169 retryInterval: [{ required: true, message: "重试间隔不能为空", trigger: "blur" }],
171 }, 170 },
  171 + nextTimes: [], // 后续执行时间
172 172
173 // 枚举 173 // 枚举
174 InfJobStatusEnum: InfJobStatusEnum 174 InfJobStatusEnum: InfJobStatusEnum
@@ -204,6 +204,7 @@ export default { @@ -204,6 +204,7 @@ export default {
204 retryInterval: undefined, 204 retryInterval: undefined,
205 monitorTimeout: undefined, 205 monitorTimeout: undefined,
206 }; 206 };
  207 + this.nextTimes = [];
207 this.resetForm("form"); 208 this.resetForm("form");
208 }, 209 },
209 /** 搜索按钮操作 */ 210 /** 搜索按钮操作 */
@@ -234,10 +235,23 @@ export default { @@ -234,10 +235,23 @@ export default {
234 this.form = response.data; 235 this.form = response.data;
235 this.openView = true; 236 this.openView = true;
236 }); 237 });
  238 + // 获取下一次执行时间
  239 + getJobNextTimes(row.id).then(response => {
  240 + this.nextTimes = response.data;
  241 + });
237 }, 242 },
238 /** 任务日志列表查询 */ 243 /** 任务日志列表查询 */
239 - handleJobLog() {  
240 - this.$router.push("/job/log"); 244 + handleJobLog(row) {
  245 + if (row.id) {
  246 + this.$router.push({
  247 + path:"/job/log",
  248 + query:{
  249 + jobId: row.id
  250 + }
  251 + });
  252 + } else {
  253 + this.$router.push("/job/log");
  254 + }
241 }, 255 },
242 /** 新增按钮操作 */ 256 /** 新增按钮操作 */
243 handleAdd() { 257 handleAdd() {
ruoyi-ui/src/views/infra/job/log.vue
1 <template> 1 <template>
2 <div class="app-container"> 2 <div class="app-container">
3 - <el-form :model="queryParams" ref="queryForm" :inline="true" v-show="showSearch" label-width="68px">  
4 - <el-form-item label="任务名称" prop="jobName">  
5 - <el-input  
6 - v-model="queryParams.jobName"  
7 - placeholder="请输入任务名称"  
8 - clearable  
9 - size="small"  
10 - style="width: 240px"  
11 - @keyup.enter.native="handleQuery"  
12 - /> 3 + <!-- 搜索工作栏 -->
  4 + <el-form :model="queryParams" ref="queryForm" :inline="true" v-show="showSearch" label-width="120px">
  5 + <el-form-item label="处理器的名字" prop="handlerName">
  6 + <el-input v-model="queryParams.handlerName" placeholder="请输入处理器的名字" clearable size="small" @keyup.enter.native="handleQuery"/>
13 </el-form-item> 7 </el-form-item>
14 - <el-form-item label="任务组名" prop="jobGroup">  
15 - <el-select  
16 - v-model="queryParams.jobGroup"  
17 - placeholder="请任务组名"  
18 - clearable  
19 - size="small"  
20 - style="width: 240px"  
21 - >  
22 - <el-option  
23 - v-for="dict in jobGroupOptions"  
24 - :key="dict.dictValue"  
25 - :label="dict.dictLabel"  
26 - :value="dict.dictValue"  
27 - />  
28 - </el-select> 8 + <el-form-item label="开始执行时间" prop="beginTime">
  9 + <el-date-picker clearable size="small" v-model="queryParams.beginTime" type="date" value-format="yyyy-MM-dd" placeholder="选择开始执行时间" />
29 </el-form-item> 10 </el-form-item>
30 - <el-form-item label="执行状态" prop="status">  
31 - <el-select  
32 - v-model="queryParams.status"  
33 - placeholder="请选择执行状态"  
34 - clearable  
35 - size="small"  
36 - style="width: 240px"  
37 - >  
38 - <el-option  
39 - v-for="dict in statusOptions"  
40 - :key="dict.dictValue"  
41 - :label="dict.dictLabel"  
42 - :value="dict.dictValue"  
43 - />  
44 - </el-select> 11 + <el-form-item label="结束执行时间" prop="endTime">
  12 + <el-date-picker clearable size="small" v-model="queryParams.endTime" type="date" value-format="yyyy-MM-dd" placeholder="选择结束执行时间" />
45 </el-form-item> 13 </el-form-item>
46 - <el-form-item label="执行时间">  
47 - <el-date-picker  
48 - v-model="dateRange"  
49 - size="small"  
50 - style="width: 240px"  
51 - value-format="yyyy-MM-dd"  
52 - type="daterange"  
53 - range-separator="-"  
54 - start-placeholder="开始日期"  
55 - end-placeholder="结束日期"  
56 - ></el-date-picker> 14 + <el-form-item label="任务状态" prop="status">
  15 + <el-select v-model="queryParams.status" placeholder="请选择任务状态" clearable size="small">
  16 + <el-option v-for="dict in this.getDictDatas(DICT_TYPE.INF_JOB_LOG_STATUS)"
  17 + :key="dict.value" :label="dict.label" :value="dict.value"/>
  18 + </el-select>
57 </el-form-item> 19 </el-form-item>
58 <el-form-item> 20 <el-form-item>
59 - <el-button type="cyan" icon="el-icon-search" size="mini" @click="handleQuery">搜索</el-button> 21 + <el-button type="primary" icon="el-icon-search" size="mini" @click="handleQuery">搜索</el-button>
60 <el-button icon="el-icon-refresh" size="mini" @click="resetQuery">重置</el-button> 22 <el-button icon="el-icon-refresh" size="mini" @click="resetQuery">重置</el-button>
61 </el-form-item> 23 </el-form-item>
62 </el-form> 24 </el-form>
63 25
64 <el-row :gutter="10" class="mb8"> 26 <el-row :gutter="10" class="mb8">
65 <el-col :span="1.5"> 27 <el-col :span="1.5">
66 - <el-button  
67 - type="danger"  
68 - icon="el-icon-delete"  
69 - size="mini"  
70 - :disabled="multiple"  
71 - @click="handleDelete"  
72 - v-hasPermi="['monitor:job:remove']"  
73 - >删除</el-button>  
74 - </el-col>  
75 - <el-col :span="1.5">  
76 - <el-button  
77 - type="danger"  
78 - icon="el-icon-delete"  
79 - size="mini"  
80 - @click="handleClean"  
81 - v-hasPermi="['monitor:job:remove']"  
82 - >清空</el-button>  
83 - </el-col>  
84 - <el-col :span="1.5">  
85 - <el-button  
86 - type="warning"  
87 - icon="el-icon-download"  
88 - size="mini"  
89 - @click="handleExport"  
90 - v-hasPermi="['monitor:job:export']"  
91 - >导出</el-button> 28 + <el-button type="warning" icon="el-icon-download" size="mini" @click="handleExport"
  29 + v-hasPermi="['infra:job:export']">导出</el-button>
92 </el-col> 30 </el-col>
93 <right-toolbar :showSearch.sync="showSearch" @queryTable="getList"></right-toolbar> 31 <right-toolbar :showSearch.sync="showSearch" @queryTable="getList"></right-toolbar>
94 </el-row> 32 </el-row>
95 33
96 - <el-table v-loading="loading" :data="jobLogList" @selection-change="handleSelectionChange">  
97 - <el-table-column type="selection" width="55" align="center" />  
98 - <el-table-column label="日志编号" width="80" align="center" prop="jobLogId" />  
99 - <el-table-column label="任务名称" align="center" prop="jobName" :show-overflow-tooltip="true" />  
100 - <el-table-column label="任务组名" align="center" prop="jobGroup" :formatter="jobGroupFormat" :show-overflow-tooltip="true" />  
101 - <el-table-column label="调用目标字符串" align="center" prop="invokeTarget" :show-overflow-tooltip="true" />  
102 - <el-table-column label="日志信息" align="center" prop="jobMessage" :show-overflow-tooltip="true" />  
103 - <el-table-column label="执行状态" align="center" prop="status" :formatter="statusFormat" />  
104 - <el-table-column label="执行时间" align="center" prop="createTime" width="180"> 34 + <el-table v-loading="loading" :data="list">
  35 + <el-table-column label="日志编号" align="center" prop="id" />
  36 + <el-table-column label="任务编号" align="center" prop="jobId" />
  37 + <el-table-column label="处理器的名字" align="center" prop="handlerName" />
  38 + <el-table-column label="处理器的参数" align="center" prop="handlerParam" />
  39 + <el-table-column label="第几次执行" align="center" prop="executeIndex" />
  40 + <el-table-column label="执行时间" align="center" width="180">
  41 + <template slot-scope="scope">
  42 + <span>{{ parseTime(scope.row.beginTime) + ' ~ ' + parseTime(scope.row.endTime) }}</span>
  43 + </template>
  44 + </el-table-column>
  45 + <el-table-column label="执行时长" align="center" prop="duration">
  46 + <template slot-scope="scope">
  47 + <span>{{ scope.row.duration + ' 毫秒' }}</span>
  48 + </template>
  49 + </el-table-column>
  50 + <el-table-column label="任务状态" align="center" prop="status">
105 <template slot-scope="scope"> 51 <template slot-scope="scope">
106 - <span>{{ parseTime(scope.row.createTime) }}</span> 52 + <span>{{ getDictDataLabel(DICT_TYPE.INF_JOB_LOG_STATUS, scope.row.status) }}</span>
107 </template> 53 </template>
108 </el-table-column> 54 </el-table-column>
109 <el-table-column label="操作" align="center" class-name="small-padding fixed-width"> 55 <el-table-column label="操作" align="center" class-name="small-padding fixed-width">
110 <template slot-scope="scope"> 56 <template slot-scope="scope">
111 - <el-button  
112 - size="mini"  
113 - type="text"  
114 - icon="el-icon-view"  
115 - @click="handleView(scope.row)"  
116 - v-hasPermi="['monitor:job:query']"  
117 - >详细</el-button> 57 + <el-button size="mini" type="text" icon="el-icon-view" @click="handleView(scope.row)"
  58 + v-hasPermi="['infra:job:query']">详细</el-button>
118 </template> 59 </template>
119 </el-table-column> 60 </el-table-column>
120 </el-table> 61 </el-table>
121 62
122 - <pagination  
123 - v-show="total>0"  
124 - :total="total"  
125 - :page.sync="queryParams.pageNum"  
126 - :limit.sync="queryParams.pageSize"  
127 - @pagination="getList"  
128 - /> 63 + <pagination v-show="total>0" :total="total" :page.sync="queryParams.pageNo" :limit.sync="queryParams.pageSize"
  64 + @pagination="getList"/>
129 65
130 <!-- 调度日志详细 --> 66 <!-- 调度日志详细 -->
131 <el-dialog title="调度日志详细" :visible.sync="open" width="700px" append-to-body> 67 <el-dialog title="调度日志详细" :visible.sync="open" width="700px" append-to-body>
132 - <el-form ref="form" :model="form" label-width="100px" size="mini"> 68 + <el-form ref="form" :model="form" label-width="120px" size="mini">
133 <el-row> 69 <el-row>
134 <el-col :span="12"> 70 <el-col :span="12">
135 - <el-form-item label="日志序号:">{{ form.jobLogId }}</el-form-item>  
136 - <el-form-item label="任务名称:">{{ form.jobName }}</el-form-item>  
137 - </el-col>  
138 - <el-col :span="12">  
139 - <el-form-item label="任务分组:">{{ form.jobGroup }}</el-form-item>  
140 - <el-form-item label="执行时间:">{{ form.createTime }}</el-form-item>  
141 - </el-col>  
142 - <el-col :span="24">  
143 - <el-form-item label="调用方法:">{{ form.invokeTarget }}</el-form-item>  
144 - </el-col>  
145 - <el-col :span="24">  
146 - <el-form-item label="日志信息:">{{ form.jobMessage }}</el-form-item>  
147 - </el-col>  
148 - <el-col :span="24">  
149 - <el-form-item label="执行状态:">  
150 - <div v-if="form.status == 0">正常</div>  
151 - <div v-else-if="form.status == 1">失败</div>  
152 - </el-form-item>  
153 - </el-col>  
154 - <el-col :span="24">  
155 - <el-form-item label="异常信息:" v-if="form.status == 1">{{ form.exceptionInfo }}</el-form-item> 71 + <el-form-item label="日志编号:">{{ form.id }}</el-form-item>
  72 + <el-form-item label="任务编号:">{{ form.jobId }}</el-form-item>
  73 + <el-form-item label="处理器的名字:">{{ form.handlerName }}</el-form-item>
  74 + <el-form-item label="处理器的参数:">{{ form.handlerParam }}</el-form-item>
  75 + <el-form-item label="第几次执行:">{{ form.executeIndex }}</el-form-item>
  76 + <el-form-item label="执行时间:">{{ parseTime(form.beginTime) + ' ~ ' + parseTime(form.endTime) }}</el-form-item>
  77 + <el-form-item label="执行时长:">{{ parseTime(form.duration) + ' 毫秒' }}</el-form-item>
  78 + <el-form-item label="任务状态:">{{ getDictDataLabel(DICT_TYPE.INF_JOB_LOG_STATUS, form.status) }}</el-form-item>
  79 + <el-form-item label="执行结果:">{{ form.result }}</el-form-item>
156 </el-col> 80 </el-col>
157 </el-row> 81 </el-row>
158 </el-form> 82 </el-form>
@@ -164,7 +88,7 @@ @@ -164,7 +88,7 @@
164 </template> 88 </template>
165 89
166 <script> 90 <script>
167 -import { listJobLog, delJobLog, exportJobLog, cleanJobLog } from "@/api/monitor/jobLog"; 91 +import { getJobLogPage, exportJobLogExcel } from "@/api/infra/jobLog";
168 92
169 export default { 93 export default {
170 name: "JobLog", 94 name: "JobLog",
@@ -172,125 +96,81 @@ export default { @@ -172,125 +96,81 @@ export default {
172 return { 96 return {
173 // 遮罩层 97 // 遮罩层
174 loading: true, 98 loading: true,
175 - // 选中数组  
176 - ids: [],  
177 - // 非多个禁用  
178 - multiple: true,  
179 // 显示搜索条件 99 // 显示搜索条件
180 showSearch: true, 100 showSearch: true,
181 // 总条数 101 // 总条数
182 total: 0, 102 total: 0,
183 // 调度日志表格数据 103 // 调度日志表格数据
184 - jobLogList: [], 104 + list: [],
185 // 是否显示弹出层 105 // 是否显示弹出层
186 open: false, 106 open: false,
187 - // 日期范围  
188 - dateRange: [],  
189 // 表单参数 107 // 表单参数
190 form: {}, 108 form: {},
191 - // 执行状态字典  
192 - statusOptions: [],  
193 - // 任务组名字典  
194 - jobGroupOptions: [],  
195 // 查询参数 109 // 查询参数
196 queryParams: { 110 queryParams: {
197 - pageNum: 1, 111 + pageNo: 1,
198 pageSize: 10, 112 pageSize: 10,
199 - jobName: undefined,  
200 - jobGroup: undefined,  
201 - status: undefined 113 + handlerName: null,
  114 + beginTime: null,
  115 + endTime: null,
  116 + status: null,
202 } 117 }
203 }; 118 };
204 }, 119 },
205 created() { 120 created() {
  121 + this.queryParams.jobId = this.$route.query && this.$route.query.jobId;
206 this.getList(); 122 this.getList();
207 - this.getDicts("sys_job_status").then(response => {  
208 - this.statusOptions = response.data;  
209 - });  
210 - this.getDicts("sys_job_group").then(response => {  
211 - this.jobGroupOptions = response.data;  
212 - });  
213 }, 123 },
214 methods: { 124 methods: {
215 /** 查询调度日志列表 */ 125 /** 查询调度日志列表 */
216 getList() { 126 getList() {
217 this.loading = true; 127 this.loading = true;
218 - listJobLog(this.addDateRange(this.queryParams, this.dateRange)).then(response => {  
219 - this.jobLogList = response.rows;  
220 - this.total = response.total; 128 + getJobLogPage({
  129 + ...this.queryParams,
  130 + beginTime: this.queryParams.beginTime ? this.queryParams.beginTime + ' 00:00:00' : undefined,
  131 + endTime: this.queryParams.endTime ? this.queryParams.endTime + ' 23:59:59' : undefined,
  132 + }).then(response => {
  133 + this.list = response.data.list;
  134 + this.total = response.data.total;
221 this.loading = false; 135 this.loading = false;
222 } 136 }
223 ); 137 );
224 }, 138 },
225 - // 执行状态字典翻译  
226 - statusFormat(row, column) {  
227 - return this.selectDictLabel(this.statusOptions, row.status);  
228 - },  
229 - // 任务组名字典翻译  
230 - jobGroupFormat(row, column) {  
231 - return this.selectDictLabel(this.jobGroupOptions, row.jobGroup);  
232 - },  
233 /** 搜索按钮操作 */ 139 /** 搜索按钮操作 */
234 handleQuery() { 140 handleQuery() {
235 - this.queryParams.pageNum = 1; 141 + this.queryParams.pageNo = 1;
236 this.getList(); 142 this.getList();
237 }, 143 },
238 /** 重置按钮操作 */ 144 /** 重置按钮操作 */
239 resetQuery() { 145 resetQuery() {
240 - this.dateRange = [];  
241 this.resetForm("queryForm"); 146 this.resetForm("queryForm");
242 this.handleQuery(); 147 this.handleQuery();
243 }, 148 },
244 - // 多选框选中数据  
245 - handleSelectionChange(selection) {  
246 - this.ids = selection.map(item => item.jobLogId);  
247 - this.multiple = !selection.length;  
248 - },  
249 /** 详细按钮操作 */ 149 /** 详细按钮操作 */
250 handleView(row) { 150 handleView(row) {
251 this.open = true; 151 this.open = true;
252 this.form = row; 152 this.form = row;
253 }, 153 },
254 - /** 删除按钮操作 */  
255 - handleDelete(row) {  
256 - const jobLogIds = this.ids;  
257 - this.$confirm('是否确认删除调度日志编号为"' + jobLogIds + '"的数据项?', "警告", {  
258 - confirmButtonText: "确定",  
259 - cancelButtonText: "取消",  
260 - type: "warning"  
261 - }).then(function() {  
262 - return delJobLog(jobLogIds);  
263 - }).then(() => {  
264 - this.getList();  
265 - this.msgSuccess("删除成功");  
266 - })  
267 - },  
268 - /** 清空按钮操作 */  
269 - handleClean() {  
270 - this.$confirm("是否确认清空所有调度日志数据项?", "警告", {  
271 - confirmButtonText: "确定",  
272 - cancelButtonText: "取消",  
273 - type: "warning"  
274 - }).then(function() {  
275 - return cleanJobLog();  
276 - }).then(() => {  
277 - this.getList();  
278 - this.msgSuccess("清空成功");  
279 - })  
280 - },  
281 /** 导出按钮操作 */ 154 /** 导出按钮操作 */
282 handleExport() { 155 handleExport() {
283 - const queryParams = this.queryParams;  
284 - this.$confirm("是否确认导出所有调度日志数据项?", "警告", {  
285 - confirmButtonText: "确定",  
286 - cancelButtonText: "取消",  
287 - type: "warning"  
288 - }).then(function() {  
289 - return exportJobLog(queryParams);  
290 - }).then(response => {  
291 - this.download(response.msg);  
292 - }) 156 + // 处理查询参数
  157 + let params = {...this.queryParams,
  158 + beginTime: this.queryParams.beginTime ? this.queryParams.beginTime + ' 00:00:00' : undefined,
  159 + endTime: this.queryParams.endTime ? this.queryParams.endTime + ' 23:59:59' : undefined,
  160 + };
  161 + params.pageNo = undefined;
  162 + params.pageSize = undefined;
  163 + // 执行导出
  164 + this.$confirm('是否确认导出所有定时任务日志数据项?', "警告", {
  165 + confirmButtonText: "确定",
  166 + cancelButtonText: "取消",
  167 + type: "warning"
  168 + }).then(function() {
  169 + return exportJobLogExcel(params);
  170 + }).then(response => {
  171 + this.downloadExcel(response, '定时任务日志.xls');
  172 + })
293 } 173 }
294 } 174 }
295 }; 175 };
296 -</script>  
297 \ No newline at end of file 176 \ No newline at end of file
  177 +</script>
ry.sh deleted
1 -#!/bin/bash  
2 -  
3 -AppName=ruoyi-admin.jar  
4 -  
5 -#JVM参数  
6 -JVM_OPTS="-Dname=$AppName -Duser.timezone=Asia/Shanghai -Xms512M -Xmx512M -XX:PermSize=256M -XX:MaxPermSize=512M -XX:+HeapDumpOnOutOfMemoryError -XX:+PrintGCDateStamps -XX:+PrintGCDetails -XX:NewRatio=1 -XX:SurvivorRatio=30 -XX:+UseParallelGC -XX:+UseParallelOldGC"  
7 -APP_HOME=`pwd`  
8 -LOG_PATH=$APP_HOME/logs/$AppName.log  
9 -  
10 -if [ "$1" = "" ];  
11 -then  
12 - echo -e "\033[0;31m 未输入操作名 \033[0m \033[0;34m {start|stop|restart|status} \033[0m"  
13 - exit 1  
14 -fi  
15 -  
16 -if [ "$AppName" = "" ];  
17 -then  
18 - echo -e "\033[0;31m 未输入应用名 \033[0m"  
19 - exit 1  
20 -fi  
21 -  
22 -function start()  
23 -{  
24 - PID=`ps -ef |grep java|grep $AppName|grep -v grep|awk '{print $2}'`  
25 -  
26 - if [ x"$PID" != x"" ]; then  
27 - echo "$AppName is running..."  
28 - else  
29 - nohup java -jar $JVM_OPTS target/$AppName > /dev/null 2>&1 &  
30 - echo "Start $AppName success..."  
31 - fi  
32 -}  
33 -  
34 -function stop()  
35 -{  
36 - echo "Stop $AppName"  
37 -  
38 - PID=""  
39 - query(){  
40 - PID=`ps -ef |grep java|grep $AppName|grep -v grep|awk '{print $2}'`  
41 - }  
42 -  
43 - query  
44 - if [ x"$PID" != x"" ]; then  
45 - kill -TERM $PID  
46 - echo "$AppName (pid:$PID) exiting..."  
47 - while [ x"$PID" != x"" ]  
48 - do  
49 - sleep 1  
50 - query  
51 - done  
52 - echo "$AppName exited."  
53 - else  
54 - echo "$AppName already stopped."  
55 - fi  
56 -}  
57 -  
58 -function restart()  
59 -{  
60 - stop  
61 - sleep 2  
62 - start  
63 -}  
64 -  
65 -function status()  
66 -{  
67 - PID=`ps -ef |grep java|grep $AppName|grep -v grep|wc -l`  
68 - if [ $PID != 0 ];then  
69 - echo "$AppName is running..."  
70 - else  
71 - echo "$AppName is not running..."  
72 - fi  
73 -}  
74 -  
75 -case $1 in  
76 - start)  
77 - start;;  
78 - stop)  
79 - stop;;  
80 - restart)  
81 - restart;;  
82 - status)  
83 - status;;  
84 - *)  
85 -  
86 -esac  
src/main/java/cn/iocoder/dashboard/framework/quartz/core/util/CronUtils.java
@@ -2,6 +2,11 @@ package cn.iocoder.dashboard.framework.quartz.core.util; @@ -2,6 +2,11 @@ package cn.iocoder.dashboard.framework.quartz.core.util;
2 2
3 import org.quartz.CronExpression; 3 import org.quartz.CronExpression;
4 4
  5 +import java.text.ParseException;
  6 +import java.util.ArrayList;
  7 +import java.util.Date;
  8 +import java.util.List;
  9 +
5 /** 10 /**
6 * Quartz Cron 表达式的工具类 11 * Quartz Cron 表达式的工具类
7 * 12 *
@@ -19,4 +24,31 @@ public class CronUtils { @@ -19,4 +24,31 @@ public class CronUtils {
19 return CronExpression.isValidExpression(cronExpression); 24 return CronExpression.isValidExpression(cronExpression);
20 } 25 }
21 26
  27 + /**
  28 + * 基于 CRON 表达式,获得下 n 个满足执行的时间
  29 + *
  30 + * @param cronExpression CRON 表达式
  31 + * @param n 数量
  32 + * @return 满足条件的执行时间
  33 + */
  34 + public static List<Date> getNextTimes(String cronExpression, int n) {
  35 + // 获得 CronExpression 对象
  36 + CronExpression cron;
  37 + try {
  38 + cron = new CronExpression(cronExpression);
  39 + } catch (ParseException e) {
  40 + throw new IllegalArgumentException(e.getMessage());
  41 + }
  42 + // 从当前开始计算,n 个满足条件的
  43 + Date now = new Date();
  44 + List<Date> nextTimes = new ArrayList<>(n);
  45 + for (int i = 0; i < n; i++) {
  46 + Date nextTime = cron.getNextValidTimeAfter(now);
  47 + nextTimes.add(nextTime);
  48 + // 切换现在,为下一个触发时间;
  49 + now = nextTime;
  50 + }
  51 + return nextTimes;
  52 + }
  53 +
22 } 54 }
src/main/java/cn/iocoder/dashboard/modules/infra/controller/job/InfJobController.java
@@ -4,6 +4,7 @@ import cn.iocoder.dashboard.common.pojo.CommonResult; @@ -4,6 +4,7 @@ import cn.iocoder.dashboard.common.pojo.CommonResult;
4 import cn.iocoder.dashboard.common.pojo.PageResult; 4 import cn.iocoder.dashboard.common.pojo.PageResult;
5 import cn.iocoder.dashboard.framework.excel.core.util.ExcelUtils; 5 import cn.iocoder.dashboard.framework.excel.core.util.ExcelUtils;
6 import cn.iocoder.dashboard.framework.logger.operatelog.core.annotations.OperateLog; 6 import cn.iocoder.dashboard.framework.logger.operatelog.core.annotations.OperateLog;
  7 +import cn.iocoder.dashboard.framework.quartz.core.util.CronUtils;
7 import cn.iocoder.dashboard.modules.infra.controller.job.vo.job.*; 8 import cn.iocoder.dashboard.modules.infra.controller.job.vo.job.*;
8 import cn.iocoder.dashboard.modules.infra.convert.job.InfJobConvert; 9 import cn.iocoder.dashboard.modules.infra.convert.job.InfJobConvert;
9 import cn.iocoder.dashboard.modules.infra.dal.dataobject.job.InfJobDO; 10 import cn.iocoder.dashboard.modules.infra.dal.dataobject.job.InfJobDO;
@@ -22,6 +23,8 @@ import javax.servlet.http.HttpServletResponse; @@ -22,6 +23,8 @@ import javax.servlet.http.HttpServletResponse;
22 import javax.validation.Valid; 23 import javax.validation.Valid;
23 import java.io.IOException; 24 import java.io.IOException;
24 import java.util.Collection; 25 import java.util.Collection;
  26 +import java.util.Collections;
  27 +import java.util.Date;
25 import java.util.List; 28 import java.util.List;
26 29
27 import static cn.iocoder.dashboard.common.pojo.CommonResult.success; 30 import static cn.iocoder.dashboard.common.pojo.CommonResult.success;
@@ -123,4 +126,20 @@ public class InfJobController { @@ -123,4 +126,20 @@ public class InfJobController {
123 ExcelUtils.write(response, "定时任务.xls", "数据", InfJobExcelVO.class, datas); 126 ExcelUtils.write(response, "定时任务.xls", "数据", InfJobExcelVO.class, datas);
124 } 127 }
125 128
  129 + @GetMapping("/get_next_times")
  130 + @ApiOperation("获得定时任务的下 n 次执行时间")
  131 + @ApiImplicitParams({
  132 + @ApiImplicitParam(name = "id", value = "编号", required = true, example = "1024", dataTypeClass = Long.class),
  133 + @ApiImplicitParam(name = "count", value = "数量", example = "5", dataTypeClass = Long.class)
  134 + })
  135 + @PreAuthorize("@ss.hasPermission('infra:job:query')")
  136 + public CommonResult<List<Date>> getJobNextTimes(@RequestParam("id") Long id,
  137 + @RequestParam(value = "count", required = false, defaultValue = "5") Integer count) {
  138 + InfJobDO job = jobService.getJob(id);
  139 + if (job == null) {
  140 + return success(Collections.emptyList());
  141 + }
  142 + return success(CronUtils.getNextTimes(job.getCronExpression(), count));
  143 + }
  144 +
126 } 145 }
src/main/java/cn/iocoder/dashboard/modules/infra/controller/job/InfJobLogController.java 0 → 100644
  1 +package cn.iocoder.dashboard.modules.infra.controller.job;
  2 +
  3 +import cn.iocoder.dashboard.common.pojo.CommonResult;
  4 +import cn.iocoder.dashboard.common.pojo.PageResult;
  5 +import cn.iocoder.dashboard.framework.excel.core.util.ExcelUtils;
  6 +import cn.iocoder.dashboard.framework.logger.operatelog.core.annotations.OperateLog;
  7 +import cn.iocoder.dashboard.modules.infra.controller.job.vo.log.InfJobLogExcelVO;
  8 +import cn.iocoder.dashboard.modules.infra.controller.job.vo.log.InfJobLogExportReqVO;
  9 +import cn.iocoder.dashboard.modules.infra.controller.job.vo.log.InfJobLogPageReqVO;
  10 +import cn.iocoder.dashboard.modules.infra.controller.job.vo.log.InfJobLogRespVO;
  11 +import cn.iocoder.dashboard.modules.infra.convert.job.InfJobLogConvert;
  12 +import cn.iocoder.dashboard.modules.infra.dal.dataobject.job.InfJobLogDO;
  13 +import cn.iocoder.dashboard.modules.infra.service.job.InfJobLogService;
  14 +import io.swagger.annotations.Api;
  15 +import io.swagger.annotations.ApiImplicitParam;
  16 +import io.swagger.annotations.ApiOperation;
  17 +import org.springframework.security.access.prepost.PreAuthorize;
  18 +import org.springframework.validation.annotation.Validated;
  19 +import org.springframework.web.bind.annotation.GetMapping;
  20 +import org.springframework.web.bind.annotation.RequestMapping;
  21 +import org.springframework.web.bind.annotation.RequestParam;
  22 +import org.springframework.web.bind.annotation.RestController;
  23 +
  24 +import javax.annotation.Resource;
  25 +import javax.servlet.http.HttpServletResponse;
  26 +import javax.validation.Valid;
  27 +import java.io.IOException;
  28 +import java.util.Collection;
  29 +import java.util.List;
  30 +
  31 +import static cn.iocoder.dashboard.common.pojo.CommonResult.success;
  32 +import static cn.iocoder.dashboard.framework.logger.operatelog.core.enums.OperateTypeEnum.EXPORT;
  33 +
  34 +@Api(tags = "定时任务日志")
  35 +@RestController
  36 +@RequestMapping("/infra/job-log")
  37 +@Validated
  38 +public class InfJobLogController {
  39 +
  40 + @Resource
  41 + private InfJobLogService jobLogService;
  42 +
  43 + @GetMapping("/get")
  44 + @ApiOperation("获得定时任务日志")
  45 + @ApiImplicitParam(name = "id", value = "编号", required = true, example = "1024", dataTypeClass = Long.class)
  46 + @PreAuthorize("@ss.hasPermission('infra:job:query')")
  47 + public CommonResult<InfJobLogRespVO> getJobLog(@RequestParam("id") Long id) {
  48 + InfJobLogDO jobLog = jobLogService.getJobLog(id);
  49 + return success(InfJobLogConvert.INSTANCE.convert(jobLog));
  50 + }
  51 +
  52 + @GetMapping("/list")
  53 + @ApiOperation("获得定时任务日志列表")
  54 + @ApiImplicitParam(name = "ids", value = "编号列表", required = true, example = "1024,2048", dataTypeClass = List.class)
  55 + @PreAuthorize("@ss.hasPermission('infra:job:query')")
  56 + public CommonResult<List<InfJobLogRespVO>> getJobLogList(@RequestParam("ids") Collection<Long> ids) {
  57 + List<InfJobLogDO> list = jobLogService.getJobLogList(ids);
  58 + return success(InfJobLogConvert.INSTANCE.convertList(list));
  59 + }
  60 +
  61 + @GetMapping("/page")
  62 + @ApiOperation("获得定时任务日志分页")
  63 + @PreAuthorize("@ss.hasPermission('infra:job:query')")
  64 + public CommonResult<PageResult<InfJobLogRespVO>> getJobLogPage(@Valid InfJobLogPageReqVO pageVO) {
  65 + PageResult<InfJobLogDO> pageResult = jobLogService.getJobLogPage(pageVO);
  66 + return success(InfJobLogConvert.INSTANCE.convertPage(pageResult));
  67 + }
  68 +
  69 + @GetMapping("/export-excel")
  70 + @ApiOperation("导出定时任务日志 Excel")
  71 + @PreAuthorize("@ss.hasPermission('infra:job:export')")
  72 + @OperateLog(type = EXPORT)
  73 + public void exportJobLogExcel(@Valid InfJobLogExportReqVO exportReqVO,
  74 + HttpServletResponse response) throws IOException {
  75 + List<InfJobLogDO> list = jobLogService.getJobLogList(exportReqVO);
  76 + // 导出 Excel
  77 + List<InfJobLogExcelVO> datas = InfJobLogConvert.INSTANCE.convertList02(list);
  78 + ExcelUtils.write(response, "定时任务.xls", "数据", InfJobLogExcelVO.class, datas);
  79 + }
  80 +
  81 +}
src/main/java/cn/iocoder/dashboard/modules/infra/controller/job/vo/job/InfJobBaseVO.java
@@ -23,14 +23,14 @@ public class InfJobBaseVO { @@ -23,14 +23,14 @@ public class InfJobBaseVO {
23 @NotNull(message = "CRON 表达式不能为空") 23 @NotNull(message = "CRON 表达式不能为空")
24 private String cronExpression; 24 private String cronExpression;
25 25
26 - @ApiModelProperty(value = "重试次数", required = true) 26 + @ApiModelProperty(value = "重试次数", required = true, example = "3")
27 @NotNull(message = "重试次数不能为空") 27 @NotNull(message = "重试次数不能为空")
28 private Integer retryCount; 28 private Integer retryCount;
29 29
30 - @ApiModelProperty(value = "重试间隔", required = true) 30 + @ApiModelProperty(value = "重试间隔", required = true, example = "1000")
31 @NotNull(message = "重试间隔不能为空") 31 @NotNull(message = "重试间隔不能为空")
32 private Integer retryInterval; 32 private Integer retryInterval;
33 - 33 +
34 @ApiModelProperty(value = "监控超时时间", example = "1000") 34 @ApiModelProperty(value = "监控超时时间", example = "1000")
35 private Integer monitorTimeout; 35 private Integer monitorTimeout;
36 36
src/main/java/cn/iocoder/dashboard/modules/infra/controller/job/vo/job/InfJobRespVO.java
@@ -25,18 +25,6 @@ public class InfJobRespVO extends InfJobBaseVO { @@ -25,18 +25,6 @@ public class InfJobRespVO extends InfJobBaseVO {
25 @NotNull(message = "处理器的名字不能为空") 25 @NotNull(message = "处理器的名字不能为空")
26 private String handlerName; 26 private String handlerName;
27 27
28 - @ApiModelProperty(value = "最后一次执行的开始时间")  
29 - private Date executeBeginTime;  
30 -  
31 - @ApiModelProperty(value = "最后一次执行的结束时间")  
32 - private Date executeEndTime;  
33 -  
34 - @ApiModelProperty(value = "上一次触发时间")  
35 - private Date firePrevTime;  
36 -  
37 - @ApiModelProperty(value = "下一次触发时间")  
38 - private Date fireNextTime;  
39 -  
40 @ApiModelProperty(value = "创建时间", required = true) 28 @ApiModelProperty(value = "创建时间", required = true)
41 private Date createTime; 29 private Date createTime;
42 30
src/main/java/cn/iocoder/dashboard/modules/infra/controller/job/vo/log/InfJobLogBaseVO.java
@@ -16,18 +16,18 @@ import static cn.iocoder.dashboard.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOU @@ -16,18 +16,18 @@ import static cn.iocoder.dashboard.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOU
16 @Data 16 @Data
17 public class InfJobLogBaseVO { 17 public class InfJobLogBaseVO {
18 18
19 - @ApiModelProperty(value = "任务编号", required = true) 19 + @ApiModelProperty(value = "任务编号", required = true, example = "1024")
20 @NotNull(message = "任务编号不能为空") 20 @NotNull(message = "任务编号不能为空")
21 private Long jobId; 21 private Long jobId;
22 22
23 - @ApiModelProperty(value = "处理器的名字", required = true) 23 + @ApiModelProperty(value = "处理器的名字", required = true, example = "sysUserSessionTimeoutJob")
24 @NotNull(message = "处理器的名字不能为空") 24 @NotNull(message = "处理器的名字不能为空")
25 private String handlerName; 25 private String handlerName;
26 26
27 - @ApiModelProperty(value = "处理器的参数") 27 + @ApiModelProperty(value = "处理器的参数", example = "yudao")
28 private String handlerParam; 28 private String handlerParam;
29 29
30 - @ApiModelProperty(value = "第几次执行", required = true) 30 + @ApiModelProperty(value = "第几次执行", required = true, example = "1")
31 @NotNull(message = "第几次执行不能为空") 31 @NotNull(message = "第几次执行不能为空")
32 private Integer executeIndex; 32 private Integer executeIndex;
33 33
@@ -40,14 +40,14 @@ public class InfJobLogBaseVO { @@ -40,14 +40,14 @@ public class InfJobLogBaseVO {
40 @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND) 40 @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
41 private Date endTime; 41 private Date endTime;
42 42
43 - @ApiModelProperty(value = "执行时长") 43 + @ApiModelProperty(value = "执行时长", example = "123")
44 private Integer duration; 44 private Integer duration;
45 45
46 - @ApiModelProperty(value = "任务状态", required = true) 46 + @ApiModelProperty(value = "任务状态", required = true, example = "1", notes = "参见 InfJobLogStatusEnum 枚举")
47 @NotNull(message = "任务状态不能为空") 47 @NotNull(message = "任务状态不能为空")
48 private Integer status; 48 private Integer status;
49 49
50 - @ApiModelProperty(value = "结果数据") 50 + @ApiModelProperty(value = "结果数据", example = "执行成功")
51 private String result; 51 private String result;
52 52
53 } 53 }
src/main/java/cn/iocoder/dashboard/modules/infra/controller/job/vo/log/InfJobLogExcelVO.java
1 package cn.iocoder.dashboard.modules.infra.controller.job.vo.log; 1 package cn.iocoder.dashboard.modules.infra.controller.job.vo.log;
2 2
  3 +import cn.iocoder.dashboard.framework.excel.core.annotations.DictFormat;
  4 +import cn.iocoder.dashboard.framework.excel.core.convert.DictConvert;
  5 +import cn.iocoder.dashboard.modules.system.enums.dict.SysDictTypeEnum;
3 import com.alibaba.excel.annotation.ExcelProperty; 6 import com.alibaba.excel.annotation.ExcelProperty;
4 import lombok.Data; 7 import lombok.Data;
5 8
@@ -37,7 +40,8 @@ public class InfJobLogExcelVO { @@ -37,7 +40,8 @@ public class InfJobLogExcelVO {
37 @ExcelProperty("执行时长") 40 @ExcelProperty("执行时长")
38 private Integer duration; 41 private Integer duration;
39 42
40 - @ExcelProperty("任务状态") 43 + @ExcelProperty(value = "任务状态", converter = DictConvert.class)
  44 + @DictFormat(SysDictTypeEnum.INF_JOB_STATUS)
41 private Integer status; 45 private Integer status;
42 46
43 @ExcelProperty("结果数据") 47 @ExcelProperty("结果数据")
src/main/java/cn/iocoder/dashboard/modules/infra/controller/job/vo/log/InfJobLogExportReqVO.java
@@ -5,6 +5,7 @@ import io.swagger.annotations.ApiModelProperty; @@ -5,6 +5,7 @@ import io.swagger.annotations.ApiModelProperty;
5 import lombok.Data; 5 import lombok.Data;
6 import org.springframework.format.annotation.DateTimeFormat; 6 import org.springframework.format.annotation.DateTimeFormat;
7 7
  8 +import javax.validation.constraints.NotNull;
8 import java.util.Date; 9 import java.util.Date;
9 10
10 import static cn.iocoder.dashboard.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND; 11 import static cn.iocoder.dashboard.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND;
@@ -13,7 +14,10 @@ import static cn.iocoder.dashboard.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOU @@ -13,7 +14,10 @@ import static cn.iocoder.dashboard.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOU
13 @Data 14 @Data
14 public class InfJobLogExportReqVO { 15 public class InfJobLogExportReqVO {
15 16
16 - @ApiModelProperty(value = "处理器的名字") 17 + @ApiModelProperty(value = "任务编号", example = "10")
  18 + private Long jobId;
  19 +
  20 + @ApiModelProperty(value = "处理器的名字", notes = "模糊匹配")
17 private String handlerName; 21 private String handlerName;
18 22
19 @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND) 23 @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
@@ -24,7 +28,7 @@ public class InfJobLogExportReqVO { @@ -24,7 +28,7 @@ public class InfJobLogExportReqVO {
24 @ApiModelProperty(value = "结束执行时间") 28 @ApiModelProperty(value = "结束执行时间")
25 private Date endTime; 29 private Date endTime;
26 30
27 - @ApiModelProperty(value = "任务状态") 31 + @ApiModelProperty(value = "任务状态", notes = "参见 InfJobLogStatusEnum 枚举")
28 private Integer status; 32 private Integer status;
29 33
30 } 34 }
src/main/java/cn/iocoder/dashboard/modules/infra/controller/job/vo/log/InfJobLogPageReqVO.java
@@ -18,7 +18,10 @@ import static cn.iocoder.dashboard.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOU @@ -18,7 +18,10 @@ import static cn.iocoder.dashboard.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOU
18 @ToString(callSuper = true) 18 @ToString(callSuper = true)
19 public class InfJobLogPageReqVO extends PageParam { 19 public class InfJobLogPageReqVO extends PageParam {
20 20
21 - @ApiModelProperty(value = "处理器的名字") 21 + @ApiModelProperty(value = "任务编号", example = "10")
  22 + private Long jobId;
  23 +
  24 + @ApiModelProperty(value = "处理器的名字", notes = "模糊匹配")
22 private String handlerName; 25 private String handlerName;
23 26
24 @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND) 27 @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
@@ -29,7 +32,7 @@ public class InfJobLogPageReqVO extends PageParam { @@ -29,7 +32,7 @@ public class InfJobLogPageReqVO extends PageParam {
29 @ApiModelProperty(value = "结束执行时间") 32 @ApiModelProperty(value = "结束执行时间")
30 private Date endTime; 33 private Date endTime;
31 34
32 - @ApiModelProperty(value = "任务状态") 35 + @ApiModelProperty(value = "任务状态", notes = "参见 InfJobLogStatusEnum 枚举")
33 private Integer status; 36 private Integer status;
34 37
35 } 38 }
src/main/java/cn/iocoder/dashboard/modules/infra/controller/job/vo/log/InfJobLogRespVO.java
@@ -14,7 +14,7 @@ import java.util.Date; @@ -14,7 +14,7 @@ import java.util.Date;
14 @ToString(callSuper = true) 14 @ToString(callSuper = true)
15 public class InfJobLogRespVO extends InfJobLogBaseVO { 15 public class InfJobLogRespVO extends InfJobLogBaseVO {
16 16
17 - @ApiModelProperty(value = "日志编号", required = true) 17 + @ApiModelProperty(value = "日志编号", required = true, example = "1024")
18 private Long id; 18 private Long id;
19 19
20 @ApiModelProperty(value = "创建时间", required = true) 20 @ApiModelProperty(value = "创建时间", required = true)
src/main/java/cn/iocoder/dashboard/modules/infra/convert/job/InfJobLogConvert.java 0 → 100644
  1 +package cn.iocoder.dashboard.modules.infra.convert.job;
  2 +
  3 +import cn.iocoder.dashboard.common.pojo.PageResult;
  4 +import cn.iocoder.dashboard.modules.infra.controller.job.vo.log.InfJobLogExcelVO;
  5 +import cn.iocoder.dashboard.modules.infra.controller.job.vo.log.InfJobLogRespVO;
  6 +import cn.iocoder.dashboard.modules.infra.dal.dataobject.job.InfJobLogDO;
  7 +import org.mapstruct.Mapper;
  8 +import org.mapstruct.factory.Mappers;
  9 +
  10 +import java.util.List;
  11 +
  12 +/**
  13 + * 定时任务日志 Convert
  14 + *
  15 + * @author 芋艿
  16 + */
  17 +@Mapper
  18 +public interface InfJobLogConvert {
  19 +
  20 + InfJobLogConvert INSTANCE = Mappers.getMapper(InfJobLogConvert.class);
  21 +
  22 + InfJobLogRespVO convert(InfJobLogDO bean);
  23 +
  24 + List<InfJobLogRespVO> convertList(List<InfJobLogDO> list);
  25 +
  26 + PageResult<InfJobLogRespVO> convertPage(PageResult<InfJobLogDO> page);
  27 +
  28 + List<InfJobLogExcelVO> convertList02(List<InfJobLogDO> list);
  29 +
  30 +}
src/main/java/cn/iocoder/dashboard/modules/infra/dal/dataobject/job/InfJobDO.java
@@ -6,8 +6,6 @@ import com.baomidou.mybatisplus.annotation.TableId; @@ -6,8 +6,6 @@ import com.baomidou.mybatisplus.annotation.TableId;
6 import com.baomidou.mybatisplus.annotation.TableName; 6 import com.baomidou.mybatisplus.annotation.TableName;
7 import lombok.*; 7 import lombok.*;
8 8
9 -import java.util.Date;  
10 -  
11 /** 9 /**
12 * 定时任务 DO 10 * 定时任务 DO
13 * 11 *
@@ -45,35 +43,10 @@ public class InfJobDO extends BaseDO { @@ -45,35 +43,10 @@ public class InfJobDO extends BaseDO {
45 * 处理器的参数 43 * 处理器的参数
46 */ 44 */
47 private String handlerParam; 45 private String handlerParam;
48 -  
49 - // ========== 时间相关字段 ==========  
50 -  
51 /** 46 /**
52 * CRON 表达式 47 * CRON 表达式
53 */ 48 */
54 private String cronExpression; 49 private String cronExpression;
55 - /**  
56 - * 最后一次执行的开始时间  
57 - *  
58 - * 该字段在任务执行结束后,进行记录  
59 - */  
60 - private Date executeBeginTime;  
61 - /**  
62 - * 最后一次执行的结束时间  
63 - *  
64 - * 该字段在任务执行结束后,进行记录  
65 - */  
66 - private Date executeEndTime;  
67 - /**  
68 - * 上一次触发时间,来自 Quartz SCHE_TRIGGERS 表  
69 - */  
70 - private Date firePrevTime;  
71 - /**  
72 - * 下一次触发时间,来自 Quartz SCHE_TRIGGERS 表  
73 - *  
74 - * 在触发器状态从 `ACQUIRED` 变成 `BLOCKED` 时,就会更新 PREV_FIRE_TIME、NEXT_FIRE_TIME,然后定时任务才正式开始执行  
75 - */  
76 - private Date fireNextTime;  
77 50
78 // ========== 重试相关字段 ========== 51 // ========== 重试相关字段 ==========
79 /** 52 /**
@@ -96,8 +69,4 @@ public class InfJobDO extends BaseDO { @@ -96,8 +69,4 @@ public class InfJobDO extends BaseDO {
96 */ 69 */
97 private Integer monitorTimeout; 70 private Integer monitorTimeout;
98 71
99 - // TODO misfirePolicy  
100 - // TODO concurrent  
101 - // TODO 失败重试  
102 -  
103 } 72 }
src/main/java/cn/iocoder/dashboard/modules/infra/dal/mysql/job/InfJobLogMapper.java
1 package cn.iocoder.dashboard.modules.infra.dal.mysql.job; 1 package cn.iocoder.dashboard.modules.infra.dal.mysql.job;
2 2
  3 +import cn.iocoder.dashboard.common.pojo.PageResult;
3 import cn.iocoder.dashboard.framework.mybatis.core.mapper.BaseMapperX; 4 import cn.iocoder.dashboard.framework.mybatis.core.mapper.BaseMapperX;
  5 +import cn.iocoder.dashboard.framework.mybatis.core.query.QueryWrapperX;
  6 +import cn.iocoder.dashboard.modules.infra.controller.job.vo.log.InfJobLogExportReqVO;
  7 +import cn.iocoder.dashboard.modules.infra.controller.job.vo.log.InfJobLogPageReqVO;
4 import cn.iocoder.dashboard.modules.infra.dal.dataobject.job.InfJobLogDO; 8 import cn.iocoder.dashboard.modules.infra.dal.dataobject.job.InfJobLogDO;
5 import org.apache.ibatis.annotations.Mapper; 9 import org.apache.ibatis.annotations.Mapper;
6 10
  11 +import java.util.List;
  12 +
7 /** 13 /**
8 * 任务日志 Mapper 14 * 任务日志 Mapper
9 * 15 *
@@ -11,4 +17,27 @@ import org.apache.ibatis.annotations.Mapper; @@ -11,4 +17,27 @@ import org.apache.ibatis.annotations.Mapper;
11 */ 17 */
12 @Mapper 18 @Mapper
13 public interface InfJobLogMapper extends BaseMapperX<InfJobLogDO> { 19 public interface InfJobLogMapper extends BaseMapperX<InfJobLogDO> {
  20 +
  21 + default PageResult<InfJobLogDO> selectPage(InfJobLogPageReqVO reqVO) {
  22 + return selectPage(reqVO, new QueryWrapperX<InfJobLogDO>()
  23 + .eqIfPresent("job_id", reqVO.getJobId())
  24 + .likeIfPresent("handler_name", reqVO.getHandlerName())
  25 + .geIfPresent("begin_time", reqVO.getBeginTime())
  26 + .leIfPresent("end_time", reqVO.getEndTime())
  27 + .eqIfPresent("status", reqVO.getStatus())
  28 + .orderByDesc("id") // ID 倒序
  29 + );
  30 + }
  31 +
  32 + default List<InfJobLogDO> selectList(InfJobLogExportReqVO reqVO) {
  33 + return selectList(new QueryWrapperX<InfJobLogDO>()
  34 + .eqIfPresent("job_id", reqVO.getJobId())
  35 + .likeIfPresent("handler_name", reqVO.getHandlerName())
  36 + .geIfPresent("begin_time", reqVO.getBeginTime())
  37 + .leIfPresent("end_time", reqVO.getEndTime())
  38 + .eqIfPresent("status", reqVO.getStatus())
  39 + .orderByDesc("id") // ID 倒序
  40 + );
  41 + }
  42 +
14 } 43 }
src/main/java/cn/iocoder/dashboard/modules/infra/service/job/InfJobLogService.java
1 package cn.iocoder.dashboard.modules.infra.service.job; 1 package cn.iocoder.dashboard.modules.infra.service.job;
2 2
  3 +import cn.iocoder.dashboard.common.pojo.PageResult;
3 import cn.iocoder.dashboard.framework.quartz.core.service.JobLogFrameworkService; 4 import cn.iocoder.dashboard.framework.quartz.core.service.JobLogFrameworkService;
  5 +import cn.iocoder.dashboard.modules.infra.controller.job.vo.log.InfJobLogExportReqVO;
  6 +import cn.iocoder.dashboard.modules.infra.controller.job.vo.log.InfJobLogPageReqVO;
  7 +import cn.iocoder.dashboard.modules.infra.dal.dataobject.job.InfJobLogDO;
  8 +
  9 +import java.util.Collection;
  10 +import java.util.List;
4 11
5 /** 12 /**
6 * Job 日志 Service 接口 13 * Job 日志 Service 接口
@@ -8,4 +15,37 @@ import cn.iocoder.dashboard.framework.quartz.core.service.JobLogFrameworkService @@ -8,4 +15,37 @@ import cn.iocoder.dashboard.framework.quartz.core.service.JobLogFrameworkService
8 * @author 芋道源码 15 * @author 芋道源码
9 */ 16 */
10 public interface InfJobLogService extends JobLogFrameworkService { 17 public interface InfJobLogService extends JobLogFrameworkService {
  18 +
  19 + /**
  20 + * 获得定时任务
  21 + *
  22 + * @param id 编号
  23 + * @return 定时任务
  24 + */
  25 + InfJobLogDO getJobLog(Long id);
  26 +
  27 + /**
  28 + * 获得定时任务列表
  29 + *
  30 + * @param ids 编号
  31 + * @return 定时任务列表
  32 + */
  33 + List<InfJobLogDO> getJobLogList(Collection<Long> ids);
  34 +
  35 + /**
  36 + * 获得定时任务分页
  37 + *
  38 + * @param pageReqVO 分页查询
  39 + * @return 定时任务分页
  40 + */
  41 + PageResult<InfJobLogDO> getJobLogPage(InfJobLogPageReqVO pageReqVO);
  42 +
  43 + /**
  44 + * 获得定时任务列表, 用于 Excel 导出
  45 + *
  46 + * @param exportReqVO 查询条件
  47 + * @return 定时任务分页
  48 + */
  49 + List<InfJobLogDO> getJobLogList(InfJobLogExportReqVO exportReqVO);
  50 +
11 } 51 }
src/main/java/cn/iocoder/dashboard/modules/infra/service/job/impl/InfJobLogServiceImpl.java
1 package cn.iocoder.dashboard.modules.infra.service.job.impl; 1 package cn.iocoder.dashboard.modules.infra.service.job.impl;
2 2
  3 +import cn.iocoder.dashboard.common.pojo.PageResult;
  4 +import cn.iocoder.dashboard.modules.infra.controller.job.vo.log.InfJobLogExportReqVO;
  5 +import cn.iocoder.dashboard.modules.infra.controller.job.vo.log.InfJobLogPageReqVO;
3 import cn.iocoder.dashboard.modules.infra.dal.dataobject.job.InfJobLogDO; 6 import cn.iocoder.dashboard.modules.infra.dal.dataobject.job.InfJobLogDO;
4 import cn.iocoder.dashboard.modules.infra.dal.mysql.job.InfJobLogMapper; 7 import cn.iocoder.dashboard.modules.infra.dal.mysql.job.InfJobLogMapper;
5 import cn.iocoder.dashboard.modules.infra.enums.job.InfJobLogStatusEnum; 8 import cn.iocoder.dashboard.modules.infra.enums.job.InfJobLogStatusEnum;
@@ -10,7 +13,9 @@ import org.springframework.stereotype.Service; @@ -10,7 +13,9 @@ import org.springframework.stereotype.Service;
10 import org.springframework.validation.annotation.Validated; 13 import org.springframework.validation.annotation.Validated;
11 14
12 import javax.annotation.Resource; 15 import javax.annotation.Resource;
  16 +import java.util.Collection;
13 import java.util.Date; 17 import java.util.Date;
  18 +import java.util.List;
14 19
15 /** 20 /**
16 * Job 日志 Service 实现类 21 * Job 日志 Service 实现类
@@ -46,4 +51,24 @@ public class InfJobLogServiceImpl implements InfJobLogService { @@ -46,4 +51,24 @@ public class InfJobLogServiceImpl implements InfJobLogService {
46 } 51 }
47 } 52 }
48 53
  54 + @Override
  55 + public InfJobLogDO getJobLog(Long id) {
  56 + return jobLogMapper.selectById(id);
  57 + }
  58 +
  59 + @Override
  60 + public List<InfJobLogDO> getJobLogList(Collection<Long> ids) {
  61 + return jobLogMapper.selectBatchIds(ids);
  62 + }
  63 +
  64 + @Override
  65 + public PageResult<InfJobLogDO> getJobLogPage(InfJobLogPageReqVO pageReqVO) {
  66 + return jobLogMapper.selectPage(pageReqVO);
  67 + }
  68 +
  69 + @Override
  70 + public List<InfJobLogDO> getJobLogList(InfJobLogExportReqVO exportReqVO) {
  71 + return jobLogMapper.selectList(exportReqVO);
  72 + }
  73 +
49 } 74 }
src/main/java/cn/iocoder/dashboard/modules/system/dal/mysql/dict/SysDictDataMapper.java
@@ -15,8 +15,9 @@ import java.util.List; @@ -15,8 +15,9 @@ import java.util.List;
15 @Mapper 15 @Mapper
16 public interface SysDictDataMapper extends BaseMapperX<SysDictDataDO> { 16 public interface SysDictDataMapper extends BaseMapperX<SysDictDataDO> {
17 17
18 - default SysDictDataDO selectByLabel(String label) {  
19 - return selectOne(new QueryWrapper<SysDictDataDO>().eq("label", label)); 18 + default SysDictDataDO selectByDictTypeAndLabel(String dictType, String label) {
  19 + return selectOne(new QueryWrapper<SysDictDataDO>().eq("dict_type", dictType)
  20 + .eq("label", label));
20 } 21 }
21 22
22 default int selectCountByDictType(String dictType) { 23 default int selectCountByDictType(String dictType) {
src/main/java/cn/iocoder/dashboard/modules/system/enums/dict/SysDictTypeEnum.java
@@ -18,8 +18,9 @@ public enum SysDictTypeEnum { @@ -18,8 +18,9 @@ public enum SysDictTypeEnum {
18 SYS_BOOLEAN_STRING("sys_boolean_string"), // Boolean 是否类型 18 SYS_BOOLEAN_STRING("sys_boolean_string"), // Boolean 是否类型
19 19
20 INF_REDIS_TIMEOUT_TYPE("inf_redis_timeout_type"), // Redis 超时类型 20 INF_REDIS_TIMEOUT_TYPE("inf_redis_timeout_type"), // Redis 超时类型
21 - INF_JOB_STATUS("inf_job_status") // 任务状态的枚举  
22 - ; 21 + INF_JOB_STATUS("inf_job_status"), // 定时任务状态的枚举
  22 + INF_JOB_LOG_STATUS("inf_job_log_status") // 定时任务日志状态的枚举
  23 + ,;
23 24
24 25
25 /** 26 /**
src/main/java/cn/iocoder/dashboard/modules/system/job/auth/SysUserSessionTimeoutJob.java
@@ -15,9 +15,6 @@ public class SysUserSessionTimeoutJob implements JobHandler { @@ -15,9 +15,6 @@ public class SysUserSessionTimeoutJob implements JobHandler {
15 15
16 @Override 16 @Override
17 public String execute(String param) throws Exception { 17 public String execute(String param) throws Exception {
18 - if (true) {  
19 - throw new RuntimeException("测试异常");  
20 - }  
21 // System.out.println("执行了一次任务"); 18 // System.out.println("执行了一次任务");
22 log.info("[execute][执行任务:{}]", param); 19 log.info("[execute][执行任务:{}]", param);
23 return null; 20 return null;
src/main/java/cn/iocoder/dashboard/modules/system/service/dict/impl/SysDictDataServiceImpl.java
@@ -195,13 +195,13 @@ public class SysDictDataServiceImpl implements SysDictDataService { @@ -195,13 +195,13 @@ public class SysDictDataServiceImpl implements SysDictDataService {
195 // 校验自己存在 195 // 校验自己存在
196 checkDictDataExists(id); 196 checkDictDataExists(id);
197 // 校验字典数据的值的唯一性 197 // 校验字典数据的值的唯一性
198 - checkDictDataValueUnique(id, label); 198 + checkDictDataValueUnique(id, dictType, label);
199 // 校验字典类型有效 199 // 校验字典类型有效
200 checkDictTypeValid(dictType); 200 checkDictTypeValid(dictType);
201 } 201 }
202 202
203 - private void checkDictDataValueUnique(Long id, String label) {  
204 - SysDictDataDO dictData = dictDataMapper.selectByLabel(label); 203 + private void checkDictDataValueUnique(Long id, String dictType, String label) {
  204 + SysDictDataDO dictData = dictDataMapper.selectByDictTypeAndLabel(dictType, label);
205 if (dictData == null) { 205 if (dictData == null) {
206 return; 206 return;
207 } 207 }
src/main/java/cn/iocoder/dashboard/modules/tool/controller/test/ToolTestDemoController.java
@@ -51,7 +51,7 @@ public class ToolTestDemoController { @@ -51,7 +51,7 @@ public class ToolTestDemoController {
51 51
52 @DeleteMapping("/delete") 52 @DeleteMapping("/delete")
53 @ApiOperation("删除测试示例") 53 @ApiOperation("删除测试示例")
54 - @ApiImplicitParam(name = "id", value = "编号", required = true) 54 + @ApiImplicitParam(name = "id", value = "编号", required = true, dataTypeClass = Long.class)
55 @PreAuthorize("@ss.hasPermission('tool:test-demo:delete')") 55 @PreAuthorize("@ss.hasPermission('tool:test-demo:delete')")
56 public CommonResult<Boolean> deleteTestDemo(@RequestParam("id") Long id) { 56 public CommonResult<Boolean> deleteTestDemo(@RequestParam("id") Long id) {
57 testDemoService.deleteTestDemo(id); 57 testDemoService.deleteTestDemo(id);
src/main/resources/application.yaml
@@ -50,11 +50,16 @@ spring: @@ -50,11 +50,16 @@ spring:
50 properties: # 添加 Quartz Scheduler 附加属性,更多可以看 http://www.quartz-scheduler.org/documentation/2.4.0-SNAPSHOT/configuration.html 文档 50 properties: # 添加 Quartz Scheduler 附加属性,更多可以看 http://www.quartz-scheduler.org/documentation/2.4.0-SNAPSHOT/configuration.html 文档
51 org: 51 org:
52 quartz: 52 quartz:
  53 + # Scheduler 相关配置
  54 + scheduler:
  55 + instanceName: schedulerName
  56 + instanceId: AUTO # 自动生成 instance ID
53 # JobStore 相关配置 57 # JobStore 相关配置
54 jobStore: 58 jobStore:
55 class: org.quartz.impl.jdbcjobstore.JobStoreTX # JobStore 实现类 59 class: org.quartz.impl.jdbcjobstore.JobStoreTX # JobStore 实现类
56 isClustered: true # 是集群模式 60 isClustered: true # 是集群模式
57 - clusterCheckinInterval: 1000 61 + clusterCheckinInterval: 15000 # 集群检查频率,单位:毫秒。默认为 15000,即 15 秒
  62 + misfireThreshold: 60000 # misfire 阀值,单位:毫秒。
58 # 线程池相关配置 63 # 线程池相关配置
59 threadPool: 64 threadPool:
60 threadCount: 25 # 线程池大小。默认为 10 。 65 threadCount: 25 # 线程池大小。默认为 10 。