feat: 定时任务失效优化,并补充功能

This commit is contained in:
2026-11-13 17:56:58 +08:00
parent 63fc01cbb3
commit d5077d092c
16 changed files with 864 additions and 869 deletions
+1 -1
View File
@@ -139,7 +139,7 @@ quartz:
#driverDelegateClass: org.quartz.impl.jdbcjobstore.oracle.OracleDelegate
#Other delegates can see: http://www.quartz-scheduler.org/documentation/quartz-2.x/tutorials/tutorial-lesson-09.html
dataSource: myDS
tablePrefix: SYS_QRTZ_
tablePrefix: sys_qrtz_
isClustered: false
clusterCheckinInterval: 20000
maxMisfiresToHandleAtATime: 120
+159
View File
@@ -0,0 +1,159 @@
/* sys_qrtz_job_details */
CREATE TABLE IF NOT EXISTS `sys_qrtz_job_details` (
`SCHED_NAME` varchar(120) CHARACTER SET utf8mb4 COLLATE utf8mb4_german2_ci NOT NULL,
`JOB_NAME` varchar(200) CHARACTER SET utf8mb4 COLLATE utf8mb4_german2_ci NOT NULL,
`JOB_GROUP` varchar(200) CHARACTER SET utf8mb4 COLLATE utf8mb4_german2_ci NOT NULL,
`DESCRIPTION` varchar(250) CHARACTER SET utf8mb4 COLLATE utf8mb4_german2_ci NULL DEFAULT NULL,
`JOB_CLASS_NAME` varchar(250) CHARACTER SET utf8mb4 COLLATE utf8mb4_german2_ci NOT NULL,
`IS_DURABLE` varchar(1) CHARACTER SET utf8mb4 COLLATE utf8mb4_german2_ci NOT NULL,
`IS_NONCONCURRENT` varchar(1) CHARACTER SET utf8mb4 COLLATE utf8mb4_german2_ci NOT NULL,
`IS_UPDATE_DATA` varchar(1) CHARACTER SET utf8mb4 COLLATE utf8mb4_german2_ci NOT NULL,
`REQUESTS_RECOVERY` varchar(1) CHARACTER SET utf8mb4 COLLATE utf8mb4_german2_ci NOT NULL,
`JOB_DATA` blob NULL,
PRIMARY KEY (`SCHED_NAME`, `JOB_NAME`, `JOB_GROUP`) USING BTREE,
INDEX `IDX_SYS_QRTZ_01`(`SCHED_NAME` ASC, `REQUESTS_RECOVERY` ASC) USING BTREE,
INDEX `IDX_SYS_QRTZ_02`(`SCHED_NAME` ASC, `JOB_GROUP` ASC) USING BTREE
) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_german2_ci ROW_FORMAT = DYNAMIC;
/* sys_qrtz_triggers */
CREATE TABLE IF NOT EXISTS `sys_qrtz_triggers` (
`SCHED_NAME` varchar(120) CHARACTER SET utf8mb4 COLLATE utf8mb4_german2_ci NOT NULL,
`TRIGGER_NAME` varchar(200) CHARACTER SET utf8mb4 COLLATE utf8mb4_german2_ci NOT NULL,
`TRIGGER_GROUP` varchar(200) CHARACTER SET utf8mb4 COLLATE utf8mb4_german2_ci NOT NULL,
`JOB_NAME` varchar(200) CHARACTER SET utf8mb4 COLLATE utf8mb4_german2_ci NOT NULL,
`JOB_GROUP` varchar(200) CHARACTER SET utf8mb4 COLLATE utf8mb4_german2_ci NOT NULL,
`DESCRIPTION` varchar(250) CHARACTER SET utf8mb4 COLLATE utf8mb4_german2_ci NULL DEFAULT NULL,
`NEXT_FIRE_TIME` bigint NULL DEFAULT NULL,
`PREV_FIRE_TIME` bigint NULL DEFAULT NULL,
`PRIORITY` int NULL DEFAULT NULL,
`TRIGGER_STATE` varchar(16) CHARACTER SET utf8mb4 COLLATE utf8mb4_german2_ci NOT NULL,
`TRIGGER_TYPE` varchar(8) CHARACTER SET utf8mb4 COLLATE utf8mb4_german2_ci NOT NULL,
`START_TIME` bigint NOT NULL,
`END_TIME` bigint NULL DEFAULT NULL,
`CALENDAR_NAME` varchar(200) CHARACTER SET utf8mb4 COLLATE utf8mb4_german2_ci NULL DEFAULT NULL,
`MISFIRE_INSTR` smallint NULL DEFAULT NULL,
`JOB_DATA` blob NULL,
PRIMARY KEY (`SCHED_NAME`, `TRIGGER_NAME`, `TRIGGER_GROUP`) USING BTREE,
INDEX `IDX_SYS_QRTZ_03`(`SCHED_NAME` ASC, `JOB_NAME` ASC, `JOB_GROUP` ASC) USING BTREE,
INDEX `IDX_SYS_QRTZ_04`(`SCHED_NAME` ASC, `JOB_GROUP` ASC) USING BTREE,
INDEX `IDX_SYS_QRTZ_05`(`SCHED_NAME` ASC, `CALENDAR_NAME` ASC) USING BTREE,
INDEX `IDX_SYS_QRTZ_06`(`SCHED_NAME` ASC, `TRIGGER_GROUP` ASC) USING BTREE,
INDEX `IDX_SYS_QRTZ_07`(`SCHED_NAME` ASC, `TRIGGER_STATE` ASC) USING BTREE,
INDEX `IDX_SYS_QRTZ_08`(`SCHED_NAME` ASC, `TRIGGER_NAME` ASC, `TRIGGER_GROUP` ASC, `TRIGGER_STATE` ASC) USING BTREE,
INDEX `IDX_SYS_QRTZ_09`(`SCHED_NAME` ASC, `TRIGGER_GROUP` ASC, `TRIGGER_STATE` ASC) USING BTREE,
INDEX `IDX_SYS_QRTZ_10`(`SCHED_NAME` ASC, `NEXT_FIRE_TIME` ASC) USING BTREE,
INDEX `IDX_SYS_QRTZ_11`(`SCHED_NAME` ASC, `TRIGGER_STATE` ASC, `NEXT_FIRE_TIME` ASC) USING BTREE,
INDEX `IDX_SYS_QRTZ_12`(`SCHED_NAME` ASC, `MISFIRE_INSTR` ASC, `NEXT_FIRE_TIME` ASC) USING BTREE,
INDEX `IDX_SYS_QRTZ_13`(`SCHED_NAME` ASC, `MISFIRE_INSTR` ASC, `NEXT_FIRE_TIME` ASC, `TRIGGER_STATE` ASC) USING BTREE,
INDEX `IDX_SYS_QRTZ_14`(`SCHED_NAME` ASC, `MISFIRE_INSTR` ASC, `NEXT_FIRE_TIME` ASC, `TRIGGER_GROUP` ASC, `TRIGGER_STATE` ASC) USING BTREE,
CONSTRAINT `SYS_QRTZ_TRIGGERS_ibfk_1` FOREIGN KEY (`SCHED_NAME`, `JOB_NAME`, `JOB_GROUP`) REFERENCES `sys_qrtz_job_details` (`SCHED_NAME`, `JOB_NAME`, `JOB_GROUP`) ON DELETE RESTRICT ON UPDATE RESTRICT
) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_german2_ci ROW_FORMAT = DYNAMIC;
/* sys_qrtz_blob_triggers */
CREATE TABLE IF NOT EXISTS `sys_qrtz_blob_triggers` (
`SCHED_NAME` varchar(120) CHARACTER SET utf8mb4 COLLATE utf8mb4_german2_ci NOT NULL,
`TRIGGER_NAME` varchar(200) CHARACTER SET utf8mb4 COLLATE utf8mb4_german2_ci NOT NULL,
`TRIGGER_GROUP` varchar(200) CHARACTER SET utf8mb4 COLLATE utf8mb4_german2_ci NOT NULL,
`BLOB_DATA` blob NULL,
PRIMARY KEY (`SCHED_NAME`, `TRIGGER_NAME`, `TRIGGER_GROUP`) USING BTREE,
INDEX `SCHED_NAME`(`SCHED_NAME` ASC, `TRIGGER_NAME` ASC, `TRIGGER_GROUP` ASC) USING BTREE,
CONSTRAINT `SYS_QRTZ_BLOB_TRIGGERS_ibfk_1` FOREIGN KEY (`SCHED_NAME`, `TRIGGER_NAME`, `TRIGGER_GROUP`) REFERENCES `sys_qrtz_triggers` (`SCHED_NAME`, `TRIGGER_NAME`, `TRIGGER_GROUP`) ON DELETE RESTRICT ON UPDATE RESTRICT
) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_german2_ci ROW_FORMAT = DYNAMIC;
/* sys_qrtz_calendars */
CREATE TABLE IF NOT EXISTS `sys_qrtz_calendars` (
`SCHED_NAME` varchar(120) CHARACTER SET utf8mb4 COLLATE utf8mb4_german2_ci NOT NULL,
`CALENDAR_NAME` varchar(200) CHARACTER SET utf8mb4 COLLATE utf8mb4_german2_ci NOT NULL,
`CALENDAR` blob NOT NULL,
PRIMARY KEY (`SCHED_NAME`, `CALENDAR_NAME`) USING BTREE
) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_german2_ci ROW_FORMAT = DYNAMIC;
/* sys_qrtz_cron_triggers */
CREATE TABLE IF NOT EXISTS `sys_qrtz_cron_triggers` (
`SCHED_NAME` varchar(120) CHARACTER SET utf8mb4 COLLATE utf8mb4_german2_ci NOT NULL,
`TRIGGER_NAME` varchar(200) CHARACTER SET utf8mb4 COLLATE utf8mb4_german2_ci NOT NULL,
`TRIGGER_GROUP` varchar(200) CHARACTER SET utf8mb4 COLLATE utf8mb4_german2_ci NOT NULL,
`CRON_EXPRESSION` varchar(120) CHARACTER SET utf8mb4 COLLATE utf8mb4_german2_ci NOT NULL,
`TIME_ZONE_ID` varchar(80) CHARACTER SET utf8mb4 COLLATE utf8mb4_german2_ci NULL DEFAULT NULL,
PRIMARY KEY (`SCHED_NAME`, `TRIGGER_NAME`, `TRIGGER_GROUP`) USING BTREE,
CONSTRAINT `SYS_QRTZ_CRON_TRIGGERS_ibfk_1` FOREIGN KEY (`SCHED_NAME`, `TRIGGER_NAME`, `TRIGGER_GROUP`) REFERENCES `sys_qrtz_triggers` (`SCHED_NAME`, `TRIGGER_NAME`, `TRIGGER_GROUP`) ON DELETE RESTRICT ON UPDATE RESTRICT
) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_german2_ci ROW_FORMAT = DYNAMIC;
/* sys_qrtz_fired_triggers */
CREATE TABLE IF NOT EXISTS `sys_qrtz_fired_triggers` (
`SCHED_NAME` varchar(120) CHARACTER SET utf8mb4 COLLATE utf8mb4_german2_ci NOT NULL,
`ENTRY_ID` varchar(95) CHARACTER SET utf8mb4 COLLATE utf8mb4_german2_ci NOT NULL,
`TRIGGER_NAME` varchar(200) CHARACTER SET utf8mb4 COLLATE utf8mb4_german2_ci NOT NULL,
`TRIGGER_GROUP` varchar(200) CHARACTER SET utf8mb4 COLLATE utf8mb4_german2_ci NOT NULL,
`INSTANCE_NAME` varchar(200) CHARACTER SET utf8mb4 COLLATE utf8mb4_german2_ci NOT NULL,
`FIRED_TIME` bigint NOT NULL,
`SCHED_TIME` bigint NOT NULL,
`PRIORITY` int NOT NULL,
`STATE` varchar(16) CHARACTER SET utf8mb4 COLLATE utf8mb4_german2_ci NOT NULL,
`JOB_NAME` varchar(200) CHARACTER SET utf8mb4 COLLATE utf8mb4_german2_ci NULL DEFAULT NULL,
`JOB_GROUP` varchar(200) CHARACTER SET utf8mb4 COLLATE utf8mb4_german2_ci NULL DEFAULT NULL,
`IS_NONCONCURRENT` varchar(1) CHARACTER SET utf8mb4 COLLATE utf8mb4_german2_ci NULL DEFAULT NULL,
`REQUESTS_RECOVERY` varchar(1) CHARACTER SET utf8mb4 COLLATE utf8mb4_german2_ci NULL DEFAULT NULL,
PRIMARY KEY (`SCHED_NAME`, `ENTRY_ID`) USING BTREE,
INDEX `IDX_SYS_QRTZ_15`(`SCHED_NAME` ASC, `INSTANCE_NAME` ASC) USING BTREE,
INDEX `IDX_SYS_QRTZ_16`(`SCHED_NAME` ASC, `INSTANCE_NAME` ASC, `REQUESTS_RECOVERY` ASC) USING BTREE,
INDEX `IDX_SYS_QRTZ_17`(`SCHED_NAME` ASC, `JOB_NAME` ASC, `JOB_GROUP` ASC) USING BTREE,
INDEX `IDX_SYS_QRTZ_18`(`SCHED_NAME` ASC, `JOB_GROUP` ASC) USING BTREE,
INDEX `IDX_SYS_QRTZ_19`(`SCHED_NAME` ASC, `TRIGGER_NAME` ASC, `TRIGGER_GROUP` ASC) USING BTREE,
INDEX `IDX_SYS_QRTZ_20`(`SCHED_NAME` ASC, `TRIGGER_GROUP` ASC) USING BTREE
) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_german2_ci ROW_FORMAT = DYNAMIC;
/* sys_qrtz_locks */
CREATE TABLE IF NOT EXISTS `sys_qrtz_locks` (
`SCHED_NAME` varchar(120) CHARACTER SET utf8mb4 COLLATE utf8mb4_german2_ci NOT NULL,
`LOCK_NAME` varchar(40) CHARACTER SET utf8mb4 COLLATE utf8mb4_german2_ci NOT NULL,
PRIMARY KEY (`SCHED_NAME`, `LOCK_NAME`) USING BTREE
) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_german2_ci ROW_FORMAT = DYNAMIC;
/* sys_qrtz_paused_trigger_grps */
CREATE TABLE IF NOT EXISTS `sys_qrtz_paused_trigger_grps` (
`SCHED_NAME` varchar(120) CHARACTER SET utf8mb4 COLLATE utf8mb4_german2_ci NOT NULL,
`TRIGGER_GROUP` varchar(200) CHARACTER SET utf8mb4 COLLATE utf8mb4_german2_ci NOT NULL,
PRIMARY KEY (`SCHED_NAME`, `TRIGGER_GROUP`) USING BTREE
) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_german2_ci ROW_FORMAT = DYNAMIC;
/* sys_qrtz_scheduler_state */
CREATE TABLE IF NOT EXISTS `sys_qrtz_scheduler_state` (
`SCHED_NAME` varchar(120) CHARACTER SET utf8mb4 COLLATE utf8mb4_german2_ci NOT NULL,
`INSTANCE_NAME` varchar(200) CHARACTER SET utf8mb4 COLLATE utf8mb4_german2_ci NOT NULL,
`LAST_CHECKIN_TIME` bigint NOT NULL,
`CHECKIN_INTERVAL` bigint NOT NULL,
PRIMARY KEY (`SCHED_NAME`, `INSTANCE_NAME`) USING BTREE
) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_german2_ci ROW_FORMAT = DYNAMIC;
/* sys_qrtz_simple_triggers */
CREATE TABLE IF NOT EXISTS `sys_qrtz_simple_triggers` (
`SCHED_NAME` varchar(120) CHARACTER SET utf8mb4 COLLATE utf8mb4_german2_ci NOT NULL,
`TRIGGER_NAME` varchar(200) CHARACTER SET utf8mb4 COLLATE utf8mb4_german2_ci NOT NULL,
`TRIGGER_GROUP` varchar(200) CHARACTER SET utf8mb4 COLLATE utf8mb4_german2_ci NOT NULL,
`REPEAT_COUNT` bigint NOT NULL,
`REPEAT_INTERVAL` bigint NOT NULL,
`TIMES_TRIGGERED` bigint NOT NULL,
PRIMARY KEY (`SCHED_NAME`, `TRIGGER_NAME`, `TRIGGER_GROUP`) USING BTREE,
CONSTRAINT `SYS_QRTZ_SIMPLE_TRIGGERS_ibfk_1` FOREIGN KEY (`SCHED_NAME`, `TRIGGER_NAME`, `TRIGGER_GROUP`) REFERENCES `sys_qrtz_triggers` (`SCHED_NAME`, `TRIGGER_NAME`, `TRIGGER_GROUP`) ON DELETE RESTRICT ON UPDATE RESTRICT
) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_german2_ci ROW_FORMAT = DYNAMIC;
/* sys_qrtz_simprop_triggers */
CREATE TABLE IF NOT EXISTS `sys_qrtz_simprop_triggers` (
`SCHED_NAME` varchar(120) CHARACTER SET utf8mb4 COLLATE utf8mb4_german2_ci NOT NULL,
`TRIGGER_NAME` varchar(200) CHARACTER SET utf8mb4 COLLATE utf8mb4_german2_ci NOT NULL,
`TRIGGER_GROUP` varchar(200) CHARACTER SET utf8mb4 COLLATE utf8mb4_german2_ci NOT NULL,
`STR_PROP_1` varchar(512) CHARACTER SET utf8mb4 COLLATE utf8mb4_german2_ci NULL DEFAULT NULL,
`STR_PROP_2` varchar(512) CHARACTER SET utf8mb4 COLLATE utf8mb4_german2_ci NULL DEFAULT NULL,
`STR_PROP_3` varchar(512) CHARACTER SET utf8mb4 COLLATE utf8mb4_german2_ci NULL DEFAULT NULL,
`INT_PROP_1` int NULL DEFAULT NULL,
`INT_PROP_2` int NULL DEFAULT NULL,
`LONG_PROP_1` bigint NULL DEFAULT NULL,
`LONG_PROP_2` bigint NULL DEFAULT NULL,
`DEC_PROP_1` decimal(13, 4) NULL DEFAULT NULL,
`DEC_PROP_2` decimal(13, 4) NULL DEFAULT NULL,
`BOOL_PROP_1` varchar(1) CHARACTER SET utf8mb4 COLLATE utf8mb4_german2_ci NULL DEFAULT NULL,
`BOOL_PROP_2` varchar(1) CHARACTER SET utf8mb4 COLLATE utf8mb4_german2_ci NULL DEFAULT NULL,
PRIMARY KEY (`SCHED_NAME`, `TRIGGER_NAME`, `TRIGGER_GROUP`) USING BTREE,
CONSTRAINT `SYS_QRTZ_SIMPROP_TRIGGERS_ibfk_1` FOREIGN KEY (`SCHED_NAME`, `TRIGGER_NAME`, `TRIGGER_GROUP`) REFERENCES `sys_qrtz_triggers` (`SCHED_NAME`, `TRIGGER_NAME`, `TRIGGER_GROUP`) ON DELETE RESTRICT ON UPDATE RESTRICT
) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_german2_ci ROW_FORMAT = DYNAMIC;
+3
View File
@@ -32,6 +32,8 @@
</rollingPolicy>
</appender>
<appender name="TASK_EXECUTION" class="com.budwk.app.task.log.TaskExecutionLogAppender"/>
<!-- 框架日志级别(按需调整) -->
<logger name="org.eclipse.jetty" level="INFO"/>
<logger name="org.quartz" level="INFO"/>
@@ -41,6 +43,7 @@
<root level="DEBUG">
<appender-ref ref="STDOUT"/>
<appender-ref ref="ALL_FILE"/>
<appender-ref ref="TASK_EXECUTION"/>
</root>
<!--
@@ -1,732 +1,39 @@
<!doctype html>
<html>
<head>
<title>Cron表达式生成器</title>
<link href="${base}/assets/platform/cron/css/easyui.min.css" rel="stylesheet" type="text/css" />
<style type="text/css">
.line {
height: 25px;
line-height: 25px;
margin: 3px;
}
.imp {
padding-left: 25px;
}
.col {
width: 95px;
}
ul {
list-style: none;
padding-left: 10px;
}
li {
height: 20px;
}
body {
text-align: center; /*IE*/
text-align: -moz-center; /*Firefox*/
text-align: -webkit-center; /*Chrome*/
}
</style>
<script nonce="${cspNonce!}">
var base = "${base!}"
</script>
</head>
<body>
<div class="easyui-layout" style="width: 830px; height: 560px; border: 1px rgb(202, 196, 196) solid; border-radius: 5px">
<div style="height: 100%">
<div class="easyui-tabs" data-options="fit:true,border:false">
<div title="秒">
<div class="line">
<input type="radio" checked="checked" name="second" onclick="everyTime(this)" />
每秒 允许的通配符[, - * /]
</div>
<div class="line">
<input type="radio" name="second" onclick="cycle(this)" />
周期从
<input class="numberspinner" style="width: 60px" data-options="min:1,max:58" value="1" id="secondStart_0" />
-
<input class="numberspinner" style="width: 60px" data-options="min:2,max:59" value="2" id="secondEnd_0" />
秒
</div>
<div class="line">
<input type="radio" name="second" onclick="startOn(this)" />
从
<input class="numberspinner" style="width: 60px" data-options="min:0,max:59" value="0" id="secondStart_1" />
秒开始,每
<input class="numberspinner" style="width: 60px" data-options="min:1,max:59" value="1" id="secondEnd_1" />
秒执行一次
</div>
<div class="line">
<input type="radio" name="second" id="sencond_appoint" />
指定
</div>
<div class="imp secondList">
<input type="checkbox" value="0" />
00
<input type="checkbox" value="1" />
01
<input type="checkbox" value="2" />
02
<input type="checkbox" value="3" />
03
<input type="checkbox" value="4" />
04
<input type="checkbox" value="5" />
05
<input type="checkbox" value="6" />
06
<input type="checkbox" value="7" />
07
<input type="checkbox" value="8" />
08
<input type="checkbox" value="9" />
09
</div>
<div class="imp secondList">
<input type="checkbox" value="10" />
10
<input type="checkbox" value="11" />
11
<input type="checkbox" value="12" />
12
<input type="checkbox" value="13" />
13
<input type="checkbox" value="14" />
14
<input type="checkbox" value="15" />
15
<input type="checkbox" value="16" />
16
<input type="checkbox" value="17" />
17
<input type="checkbox" value="18" />
18
<input type="checkbox" value="19" />
19
</div>
<div class="imp secondList">
<input type="checkbox" value="20" />
20
<input type="checkbox" value="21" />
21
<input type="checkbox" value="22" />
22
<input type="checkbox" value="23" />
23
<input type="checkbox" value="24" />
24
<input type="checkbox" value="25" />
25
<input type="checkbox" value="26" />
26
<input type="checkbox" value="27" />
27
<input type="checkbox" value="28" />
28
<input type="checkbox" value="29" />
29
</div>
<div class="imp secondList">
<input type="checkbox" value="30" />
30
<input type="checkbox" value="31" />
31
<input type="checkbox" value="32" />
32
<input type="checkbox" value="33" />
33
<input type="checkbox" value="34" />
34
<input type="checkbox" value="35" />
35
<input type="checkbox" value="36" />
36
<input type="checkbox" value="37" />
37
<input type="checkbox" value="38" />
38
<input type="checkbox" value="39" />
39
</div>
<div class="imp secondList">
<input type="checkbox" value="40" />
40
<input type="checkbox" value="41" />
41
<input type="checkbox" value="42" />
42
<input type="checkbox" value="43" />
43
<input type="checkbox" value="44" />
44
<input type="checkbox" value="45" />
45
<input type="checkbox" value="46" />
46
<input type="checkbox" value="47" />
47
<input type="checkbox" value="48" />
48
<input type="checkbox" value="49" />
49
</div>
<div class="imp secondList">
<input type="checkbox" value="50" />
50
<input type="checkbox" value="51" />
51
<input type="checkbox" value="52" />
52
<input type="checkbox" value="53" />
53
<input type="checkbox" value="54" />
54
<input type="checkbox" value="55" />
55
<input type="checkbox" value="56" />
56
<input type="checkbox" value="57" />
57
<input type="checkbox" value="58" />
58
<input type="checkbox" value="59" />
59
</div>
</div>
<div title="分钟">
<div class="line">
<input type="radio" checked="checked" name="min" onclick="everyTime(this)" />
分钟 允许的通配符[, - * /]
</div>
<div class="line">
<input type="radio" name="min" onclick="cycle(this)" />
周期从
<input class="numberspinner" style="width: 60px" data-options="min:1,max:58" value="1" id="minStart_0" />
-
<input class="numberspinner" style="width: 60px" data-options="min:2,max:59" value="2" id="minEnd_0" />
分钟
</div>
<div class="line">
<input type="radio" name="min" onclick="startOn(this)" />
从
<input class="numberspinner" style="width: 60px" data-options="min:0,max:59" value="0" id="minStart_1" />
分钟开始,每
<input class="numberspinner" style="width: 60px" data-options="min:1,max:59" value="1" id="minEnd_1" />
分钟执行一次
</div>
<div class="line">
<input type="radio" name="min" id="min_appoint" />
指定
</div>
<div class="imp minList">
<input type="checkbox" value="0" />
00
<input type="checkbox" value="1" />
01
<input type="checkbox" value="2" />
02
<input type="checkbox" value="3" />
03
<input type="checkbox" value="4" />
04
<input type="checkbox" value="5" />
05
<input type="checkbox" value="6" />
06
<input type="checkbox" value="7" />
07
<input type="checkbox" value="8" />
08
<input type="checkbox" value="9" />
09
</div>
<div class="imp minList">
<input type="checkbox" value="10" />
10
<input type="checkbox" value="11" />
11
<input type="checkbox" value="12" />
12
<input type="checkbox" value="13" />
13
<input type="checkbox" value="14" />
14
<input type="checkbox" value="15" />
15
<input type="checkbox" value="16" />
16
<input type="checkbox" value="17" />
17
<input type="checkbox" value="18" />
18
<input type="checkbox" value="19" />
19
</div>
<div class="imp minList">
<input type="checkbox" value="20" />
20
<input type="checkbox" value="21" />
21
<input type="checkbox" value="22" />
22
<input type="checkbox" value="23" />
23
<input type="checkbox" value="24" />
24
<input type="checkbox" value="25" />
25
<input type="checkbox" value="26" />
26
<input type="checkbox" value="27" />
27
<input type="checkbox" value="28" />
28
<input type="checkbox" value="29" />
29
</div>
<div class="imp minList">
<input type="checkbox" value="30" />
30
<input type="checkbox" value="31" />
31
<input type="checkbox" value="32" />
32
<input type="checkbox" value="33" />
33
<input type="checkbox" value="34" />
34
<input type="checkbox" value="35" />
35
<input type="checkbox" value="36" />
36
<input type="checkbox" value="37" />
37
<input type="checkbox" value="38" />
38
<input type="checkbox" value="39" />
39
</div>
<div class="imp minList">
<input type="checkbox" value="40" />
40
<input type="checkbox" value="41" />
41
<input type="checkbox" value="42" />
42
<input type="checkbox" value="43" />
43
<input type="checkbox" value="44" />
44
<input type="checkbox" value="45" />
45
<input type="checkbox" value="46" />
46
<input type="checkbox" value="47" />
47
<input type="checkbox" value="48" />
48
<input type="checkbox" value="49" />
49
</div>
<div class="imp minList">
<input type="checkbox" value="50" />
50
<input type="checkbox" value="51" />
51
<input type="checkbox" value="52" />
52
<input type="checkbox" value="53" />
53
<input type="checkbox" value="54" />
54
<input type="checkbox" value="55" />
55
<input type="checkbox" value="56" />
56
<input type="checkbox" value="57" />
57
<input type="checkbox" value="58" />
58
<input type="checkbox" value="59" />
59
</div>
</div>
<div title="小时">
<div class="line">
<input type="radio" checked="checked" name="hour" onclick="everyTime(this)" />
小时 允许的通配符[, - * /]
</div>
<div class="line">
<input type="radio" name="hour" onclick="cycle(this)" />
周期从
<input class="numberspinner" style="width: 60px" data-options="min:0,max:23" value="0" id="hourStart_0" />
-
<input class="numberspinner" style="width: 60px" data-options="min:2,max:23" value="2" id="hourEnd_1" />
小时
</div>
<div class="line">
<input type="radio" name="hour" onclick="startOn(this)" />
从
<input class="numberspinner" style="width: 60px" data-options="min:0,max:23" value="0" id="hourStart_1" />
小时开始,每
<input class="numberspinner" style="width: 60px" data-options="min:1,max:23" value="1" id="hourEnd_1" />
小时执行一次
</div>
<div class="line">
<input type="radio" name="hour" id="hour_appoint" />
指定
</div>
<div class="imp hourList">
AM:
<input type="checkbox" value="0" />
00
<input type="checkbox" value="1" />
01
<input type="checkbox" value="2" />
02
<input type="checkbox" value="3" />
03
<input type="checkbox" value="4" />
04
<input type="checkbox" value="5" />
05
<input type="checkbox" value="6" />
06
<input type="checkbox" value="7" />
07
<input type="checkbox" value="8" />
08
<input type="checkbox" value="9" />
09
<input type="checkbox" value="10" />
10
<input type="checkbox" value="11" />
11
</div>
<div class="imp hourList">
PM:
<input type="checkbox" value="12" />
12
<input type="checkbox" value="13" />
13
<input type="checkbox" value="14" />
14
<input type="checkbox" value="15" />
15
<input type="checkbox" value="16" />
16
<input type="checkbox" value="17" />
17
<input type="checkbox" value="18" />
18
<input type="checkbox" value="19" />
19
<input type="checkbox" value="20" />
20
<input type="checkbox" value="21" />
21
<input type="checkbox" value="22" />
22
<input type="checkbox" value="23" />
23
</div>
</div>
<div title="日">
<div class="line">
<input type="radio" checked="checked" name="day" onclick="everyTime(this)" />
日 允许的通配符[, - * / L W]
</div>
<div class="line">
<input type="radio" name="day" onclick="unAppoint(this)" />
不指定
</div>
<div class="line">
<input type="radio" name="day" onclick="cycle(this)" />
周期从
<input class="numberspinner" style="width: 60px" data-options="min:1,max:31" value="1" id="dayStart_0" />
-
<input class="numberspinner" style="width: 60px" data-options="min:2,max:31" value="2" id="dayEnd_0" />
日
</div>
<div class="line">
<input type="radio" name="day" onclick="startOn(this)" />
从
<input class="numberspinner" style="width: 60px" data-options="min:1,max:31" value="1" id="dayStart_1" />
日开始,每
<input class="numberspinner" style="width: 60px" data-options="min:1,max:31" value="1" id="dayEnd_1" />
天执行一次
</div>
<div class="line">
<input type="radio" name="day" onclick="workDay(this)" />
每月
<input class="numberspinner" style="width: 60px" data-options="min:1,max:31" value="1" id="dayStart_2" />
号最近的那个工作日
</div>
<div class="line">
<input type="radio" name="day" onclick="lastDay(this)" />
本月最后一天
</div>
<div class="line">
<input type="radio" name="day" id="day_appoint" />
指定
</div>
<div class="imp dayList">
<input type="checkbox" value="1" />
1
<input type="checkbox" value="2" />
2
<input type="checkbox" value="3" />
3
<input type="checkbox" value="4" />
4
<input type="checkbox" value="5" />
5
<input type="checkbox" value="6" />
6
<input type="checkbox" value="7" />
7
<input type="checkbox" value="8" />
8
<input type="checkbox" value="9" />
9
<input type="checkbox" value="10" />
10
<input type="checkbox" value="11" />
11
<input type="checkbox" value="12" />
12
<input type="checkbox" value="13" />
13
<input type="checkbox" value="14" />
14
<input type="checkbox" value="15" />
15
<input type="checkbox" value="16" />
16
</div>
<div class="imp dayList">
<input type="checkbox" value="17" />
17
<input type="checkbox" value="18" />
18
<input type="checkbox" value="19" />
19
<input type="checkbox" value="20" />
20
<input type="checkbox" value="21" />
21
<input type="checkbox" value="22" />
22
<input type="checkbox" value="23" />
23
<input type="checkbox" value="24" />
24
<input type="checkbox" value="25" />
25
<input type="checkbox" value="26" />
26
<input type="checkbox" value="27" />
27
<input type="checkbox" value="28" />
28
<input type="checkbox" value="29" />
29
<input type="checkbox" value="30" />
30
<input type="checkbox" value="31" />
31
</div>
</div>
<div title="月">
<div class="line">
<input type="radio" checked="checked" name="mouth" onclick="everyTime(this)" />
月 允许的通配符[, - * /]
</div>
<div class="line">
<input type="radio" name="mouth" onclick="unAppoint(this)" />
不指定
</div>
<div class="line">
<input type="radio" name="mouth" onclick="cycle(this)" />
周期从
<input class="numberspinner" style="width: 60px" data-options="min:1,max:12" value="1" id="mouthStart_0" />
-
<input class="numberspinner" style="width: 60px" data-options="min:2,max:12" value="2" id="mouthEnd_0" />
月
</div>
<div class="line">
<input type="radio" name="mouth" onclick="startOn(this)" />
从
<input class="numberspinner" style="width: 60px" data-options="min:1,max:12" value="1" id="mouthStart_1" />
日开始,每
<input class="numberspinner" style="width: 60px" data-options="min:1,max:12" value="1" id="mouthEnd_1" />
月执行一次
</div>
<div class="line">
<input type="radio" name="mouth" id="mouth_appoint" />
指定
</div>
<div class="imp mouthList">
<input type="checkbox" value="1" />
1
<input type="checkbox" value="2" />
2
<input type="checkbox" value="3" />
3
<input type="checkbox" value="4" />
4
<input type="checkbox" value="5" />
5
<input type="checkbox" value="6" />
6
<input type="checkbox" value="7" />
7
<input type="checkbox" value="8" />
8
<input type="checkbox" value="9" />
9
<input type="checkbox" value="10" />
10
<input type="checkbox" value="11" />
11
<input type="checkbox" value="12" />
12
</div>
</div>
<div title="周">
<div class="line">
<input type="radio" checked="checked" name="week" onclick="everyTime(this)" />
周 允许的通配符[, - * / L #]
</div>
<div class="line">
<input type="radio" name="week" onclick="unAppoint(this)" />
不指定
</div>
<div class="line">
<input type="radio" name="week" onclick="startOn(this)" />
周期 从星期
<input class="numberspinner" style="width: 60px" data-options="min:1,max:7" id="weekStart_0" value="1" />
-
<input class="numberspinner" style="width: 60px" data-options="min:2,max:7" value="2" id="weekEnd_0" />
</div>
<div class="line">
<input type="radio" name="week" onclick="weekOfDay(this)" />
第
<input class="numberspinner" style="width: 60px" data-options="min:1,max:4" value="1" id="weekStart_1" />
周 的星期
<input class="numberspinner" style="width: 60px" data-options="min:1,max:7" id="weekEnd_1" value="1" />
</div>
<div class="line">
<input type="radio" name="week" onclick="lastWeek(this)" />
本月最后一个星期
<input class="numberspinner" style="width: 60px" data-options="min:1,max:7" id="weekStart_2" value="1" />
</div>
<div class="line">
<input type="radio" name="week" id="week_appoint" />
指定
</div>
<div class="imp weekList">
<input type="checkbox" value="1" />
1
<input type="checkbox" value="2" />
2
<input type="checkbox" value="3" />
3
<input type="checkbox" value="4" />
4
<input type="checkbox" value="5" />
5
<input type="checkbox" value="6" />
6
<input type="checkbox" value="7" />
7
</div>
</div>
<div title="年">
<div class="line">
<input type="radio" checked="checked" name="year" onclick="unAppoint(this)" />
不指定 允许的通配符[, - * /] 非必填
</div>
<div class="line">
<input type="radio" name="year" onclick="everyTime(this)" />
每年
</div>
<div class="line">
<input type="radio" name="year" onclick="cycle(this)" />
周期 从
<input class="numberspinner" style="width: 90px" data-options="min:2018,max:3000" id="yearStart_0" value="2018" />
-
<input class="numberspinner" style="width: 90px" data-options="min:2020,max:3000" id="yearEnd_0" value="2020" />
</div>
</div>
</div>
</div>
<div data-options="region:'south',border:false" style="height: 250px">
<fieldset style="border-radius: 3px; height: 220px">
<legend>表达式</legend>
<table style="height: 100px">
<tbody>
<tr>
<td></td>
<td align="center">秒</td>
<td align="center">分钟</td>
<td align="center">小时</td>
<td align="center">日</td>
<td align="center">
月
<br />
</td>
<td align="center">星期</td>
<td align="center">年</td>
</tr>
<tr>
<td>表达式字段:</td>
<td>
<input type="text" name="v_second" class="col" value="*" readonly="readonly" />
</td>
<td>
<input type="text" name="v_min" class="col" value="*" readonly="readonly" />
</td>
<td>
<input type="text" name="v_hour" class="col" value="*" readonly="readonly" />
</td>
<td>
<input type="text" name="v_day" class="col" value="*" readonly="readonly" />
</td>
<td>
<input type="text" name="v_mouth" class="col" value="*" readonly="readonly" />
</td>
<td>
<input type="text" name="v_week" class="col" value="?" readonly="readonly" />
</td>
<td>
<input type="text" name="v_year" class="col" readonly="readonly" />
</td>
</tr>
<tr>
<td>Cron 表达式:</td>
<td colspan="6"><input type="text" name="cron" style="width: 100%" value="* * * * * ?" id="cron" /></td>
<td><input type="button" value="反解析到UI " id="btnFan" onclick="btnFan()" /></td>
</tr>
<tr>
<td colspan="8">最近5次运行时间:</td>
</tr>
<tr>
<td colspan="8" id="runTime"></td>
</tr>
</tbody>
</table>
</fieldset>
</div>
<div></div>
</div>
<script src="${base}/assets/platform/plugins/jquery/jquery.js" type="text/javascript"></script>
<script src="${base}/assets/platform/cron/js/cron.js" type="text/javascript"></script>
</body>
</html>
<el-dialog title="Cron 表达式生成器" :visible.sync="cronDialogVisible" width="min(760px, 94vw)"
:close-on-click-modal="false" append-to-body @close="closeCronGenerator">
<el-form label-position="top" size="small" @submit.native.prevent="previewCron()">
<el-form-item label="Quartz Cron 表达式">
<el-input v-model="cronDraft" @input="resetCronPreview" placeholder="秒 分 时 日 月 星期 [年]"></el-input>
</el-form-item>
<el-form-item label="常用周期">
<el-button size="mini" @click="selectCron('0 0/5 * * * ?')">每 5 分钟</el-button>
<el-button size="mini" @click="selectCron('0 0 9 * * ?')">每天 09:00</el-button>
<el-button size="mini" @click="selectCron('0 0 9 ? * 2-6')">周一至周五 09:00</el-button>
<el-button size="mini" @click="selectCron('0 0 9 1 * ?')">每月 1 日 09:00</el-button>
<el-button size="mini" icon="el-icon-setting" @click="openCronBuilder">自定义字段</el-button>
</el-form-item>
</el-form>
<el-alert v-if="cronPreviewError" :title="cronPreviewError" type="error" :closable="false" show-icon></el-alert>
<div v-loading="cronPreviewLoading" aria-live="polite">
<strong>未来执行时间(北京时间,最多 5 次)</strong>
<ol v-if="cronPreviewTimes.length">
<li v-for="time in cronPreviewTimes" :key="time">{{time}}</li>
</ol>
<p v-else-if="!cronPreviewLoading && !cronPreviewError">输入表达式后点击预览。</p>
</div>
<span slot="footer" class="dialog-footer">
<el-button @click="cronDialogVisible = false">关闭</el-button>
<el-button :loading="cronPreviewLoading" @click="previewCron()">预览</el-button>
<el-button v-if="addDialogVisible || editDialogVisible" type="primary" :loading="cronPreviewLoading"
@click="previewCron(true)">应用到任务</el-button>
</span>
</el-dialog>
<el-dialog title="自定义 Cron 字段" :visible.sync="cronBuilderVisible" width="min(860px, 96vw)"
:close-on-click-modal="false" append-to-body custom-class="sys-task-cron-builder">
<vcron v-if="cronBuilderVisible" :expression="cronBuilderExpression"
@fill="selectCron" @hide="cronBuilderVisible = false"></vcron>
</el-dialog>
<style>
.sys-task-cron-builder .popup-result + .popup-result {
display: none;
}
</style>
@@ -1,7 +1,7 @@
<!--#
layout("/layouts/platform.html"){
#-->
<div id="app" v-cloak>
<div id="app" data-open-cron="${openCron!false}" v-cloak>
<guava>
<el-card shadow="never">
<el-row type="flex" justify="end">
@@ -17,8 +17,8 @@ layout("/layouts/platform.html"){
<el-table-column prop="jobClass" label="执行类" header-align="center" :show-overflow-tooltip="true"></el-table-column>
<el-table-column prop="data" label="执行参数" header-align="center" :show-overflow-tooltip="true"></el-table-column>
<el-table-column prop="cron" label="定时规则" header-align="center" align="center"></el-table-column>
<el-table-column prop="exeAt" label="执行时间" header-align="center" align="center">
<template slot-scope="scope">{{formatAt(scope.row.exeAt)}}</template>
<el-table-column prop="exeAt" label="最近执行时间" min-width="160" header-align="center" align="center">
<template slot-scope="scope">{{formatAt(scope.row.exeAt < 100000000000 ? scope.row.exeAt * 1000 : scope.row.exeAt)}}</template>
</el-table-column>
<el-table-column sortable prop="disabled" label="启用状态" header-align="center" align="center">
<template slot-scope="scope">
@@ -34,6 +34,7 @@ layout("/layouts/platform.html"){
<span class="ti-angle-down"></span>
</el-button>
<el-dropdown-menu slot="dropdown">
<el-dropdown-item :command="{type:'history',id:scope.row.id,name:scope.row.name}">执行历史</el-dropdown-item>
<el-dropdown-item v-if="$auth.hasPermission('sys.manager.task.edit')"
:disabled="runningOnce[scope.row.id]"
:command="{type:'runOnce',id:scope.row.id}">执行一次</el-dropdown-item>
@@ -63,7 +64,7 @@ layout("/layouts/platform.html"){
<el-form-item prop="cron" label="执行周期">
<el-input placeholder="Cron表达式" v-model="formData.cron" auto-complete="off" tabindex="3" type="text">
<template slot="append">
<a href="${base}/platform/sys/task/cron" style="color: #409eff" target="_blank">表达式生成器</a>
<el-button icon="el-icon-time" @click="openCronGenerator">表达式生成器</el-button>
</template>
</el-input>
</el-form-item>
@@ -71,7 +72,7 @@ layout("/layouts/platform.html"){
<el-input type="textarea" v-model="formData.data" placeholder="{}" tabindex="4"></el-input>
</el-form-item>
<el-form-item prop="disabled" label="启用状态">
<el-switch v-model="formData.disabled" active-color="#ff4949" inactive-color="#13ce66"></el-switch>
<el-switch v-model="formData.disabled" :active-value="false" :inactive-value="true" active-color="#13ce66" inactive-color="#ff4949"></el-switch>
</el-form-item>
</el-form>
<span slot="footer" class="dialog-footer">
@@ -90,7 +91,7 @@ layout("/layouts/platform.html"){
<el-form-item prop="cron" label="执行周期">
<el-input placeholder="Cron表达式" v-model="formData.cron" auto-complete="off" tabindex="3" type="text">
<template slot="append">
<a href="${base}/platform/sys/task/cron" style="color: #409eff" target="_blank">表达式生成器</a>
<el-button icon="el-icon-time" @click="openCronGenerator">表达式生成器</el-button>
</template>
</el-input>
</el-form-item>
@@ -98,7 +99,7 @@ layout("/layouts/platform.html"){
<el-input type="textarea" v-model="formData.data" placeholder="{}" tabindex="4"></el-input>
</el-form-item>
<el-form-item prop="disabled" label="启用状态">
<el-switch v-model="formData.disabled" active-color="#ff4949" inactive-color="#13ce66"></el-switch>
<el-switch v-model="formData.disabled" :active-value="false" :inactive-value="true" active-color="#13ce66" inactive-color="#ff4949"></el-switch>
</el-form-item>
</el-form>
<span slot="footer" class="dialog-footer">
@@ -106,16 +107,72 @@ layout("/layouts/platform.html"){
<el-button type="primary" @click="doEdit">确 定</el-button>
</span>
</el-dialog>
<el-dialog :title="historyTask.name + ' · 执行历史'" :visible.sync="historyVisible" append-to-body
width="min(780px, 94vw)" @close="closeHistory">
<el-table :data="historyRows" v-loading="historyLoading" empty-text="暂无执行记录">
<el-table-column label="开始时间(北京时间)" min-width="180">
<template slot-scope="scope">{{formatAt(scope.row.startedAt)}}</template>
</el-table-column>
<el-table-column label="结束时间(北京时间)" min-width="180">
<template slot-scope="scope">{{formatAt(scope.row.finishedAt)}}</template>
</el-table-column>
<el-table-column label="执行状态" width="100">
<template slot-scope="scope">
<el-tag size="small" :type="historyStatusType(scope.row.status)">{{historyStatus(scope.row.status)}}</el-tag>
</template>
</el-table-column>
<el-table-column label="操作" width="95">
<template slot-scope="scope">
<el-button type="text" @click="openExecutionLog(scope.row)">查看日志</el-button>
</template>
</el-table-column>
</el-table>
<div slot="footer" style="display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between">
<el-pagination :current-page="historyPage" :page-size="10" :total="historyTotal"
layout="total, prev, pager, next" @current-change="loadHistory"></el-pagination>
<el-button size="small" :loading="historyLoading" @click="loadHistory(historyPage)">刷新</el-button>
</div>
</el-dialog>
<el-dialog title="执行日志" :visible.sync="executionLogVisible" append-to-body width="min(920px, 94vw)" @close="closeExecutionLog">
<div v-loading="executionLogLoading">
<p>{{formatAt(executionLog.startedAt)}} · {{historyStatus(executionLog.status)}}</p>
<pre style="max-height: 55vh; overflow: auto; padding: 12px; white-space: pre-wrap; overflow-wrap: anywhere; background: #f5f7fa">{{executionLog.executionLog || (executionLog.status === "RUNNING" ? "任务执行结束后可查看日志。" : "暂无日志")}}</pre>
</div>
<span slot="footer">
<el-button size="small" :loading="executionLogLoading" @click="openExecutionLog(executionLog)">刷新</el-button>
</span>
</el-dialog>
<!--#include("/platform/sys/task/cron.html"){}#-->
</div>
<script nonce="${cspNonce!}">
new Vue({
el: "#app",
components: { vcron: vcrontab.default },
data: function () {
return {
addDialogVisible: false,
editDialogVisible: false,
cronDialogVisible: false,
cronDraft: "",
cronBuilderVisible: false,
cronBuilderExpression: "",
cronPreviewLoading: false,
cronPreviewRequest: 0,
cronPreviewTimes: [],
cronPreviewError: "",
tableData: [],
runningOnce: {},
historyVisible: false,
historyTask: { id: "", name: "" },
historyRows: [],
historyPage: 1,
historyTotal: 0,
historyLoading: false,
historyRequest: null,
executionLogVisible: false,
executionLog: {},
executionLogLoading: false,
executionLogRequest: null,
pageForm: {
pageNumber: 1,
pageSize: 10,
@@ -134,6 +191,53 @@ layout("/layouts/platform.html"){
}
},
methods: {
openCronGenerator: function () {
this.cronDraft = this.formData.cron || "0 0 9 * * ?"
this.cronDialogVisible = true
this.previewCron()
},
resetCronPreview: function () {
this.cronPreviewRequest++
this.cronPreviewLoading = false
this.cronPreviewTimes = []
this.cronPreviewError = ""
},
closeCronGenerator: function () {
this.cronBuilderVisible = false
this.resetCronPreview()
},
selectCron: function (expression) {
this.cronDraft = expression
this.cronBuilderVisible = false
this.previewCron()
},
openCronBuilder: function () {
this.cronBuilderExpression = this.cronDraft.trim().replace(/\s+/g, " ")
this.cronBuilderVisible = true
},
previewCron: function (apply) {
var self = this
self.resetCronPreview()
var request = self.cronPreviewRequest
var cron = self.cronDraft.trim().replace(/\s+/g, " ")
self.cronPreviewLoading = true
$.post(base + "/platform/sys/task/cronExp", { cron: cron }, function (response) {
if (request !== self.cronPreviewRequest) return
if (response.code == 0) {
self.cronPreviewTimes = response.data
if (apply === true) {
self.$set(self.formData, "cron", cron)
self.cronDialogVisible = false
}
} else {
self.cronPreviewError = response.msg || "Cron 表达式校验失败"
}
}, "json").fail(function () {
if (request === self.cronPreviewRequest) self.cronPreviewError = "获取执行时间失败"
}).always(function () {
if (request === self.cronPreviewRequest) self.cronPreviewLoading = false
})
},
pageOrder: function (column) {
//按字段排序
this.pageForm.pageOrderName = column.prop
@@ -171,18 +275,86 @@ layout("/layouts/platform.html"){
)
},
formatAt: function (val) {
if (val && val > 0) return moment(val).format("YYYY-MM-DD HH:mm:ss")
return ""
return val > 0 ? moment(val).utcOffset(480).format("YYYY-MM-DD HH:mm:ss") : "—"
},
historyStatus: function (status) {
return { RUNNING: "执行中", SUCCESS: "成功", FAILED: "失败", SKIPPED: "已跳过", INTERRUPTED: "已中断" }[status] || "—"
},
historyStatusType: function (status) {
return { RUNNING: "warning", SUCCESS: "success", FAILED: "danger" }[status] || "info"
},
openHistory: function (task) {
this.historyTask = task
this.historyRows = []
this.historyTotal = 0
this.historyVisible = true
this.loadHistory(1)
},
closeHistory: function () {
if (this.historyRequest) this.historyRequest.abort()
this.closeExecutionLog()
this.executionLogVisible = false
this.pageData()
},
loadHistory: function (page) {
var self = this
if (self.historyRequest) self.historyRequest.abort()
self.historyPage = page
self.historyLoading = true
self.historyRequest = $.post(base + "/platform/sys/task/history/" + encodeURIComponent(self.historyTask.id),
{ pageNumber: page }, function (response) {
if (response.code == 0) {
self.historyRows = response.data.list
self.historyTotal = response.data.totalCount
} else {
self.$message.error(response.msg || "获取执行历史失败")
}
}, "json").fail(function (xhr, status) {
if (status !== "abort") self.$message.error("获取执行历史失败")
}).always(function () {
self.historyLoading = false
self.historyRequest = null
})
},
closeExecutionLog: function () {
if (this.executionLogRequest) this.executionLogRequest.abort()
},
openExecutionLog: function (row) {
var self = this
if (self.executionLogRequest) self.executionLogRequest.abort()
self.executionLog = row
self.executionLogVisible = true
self.executionLogLoading = true
var url = base + "/platform/sys/task/historyLog/" + encodeURIComponent(self.historyTask.id)
+ "/" + encodeURIComponent(row.id)
self.executionLogRequest = $.post(url, {}, function (response) {
if (response.code == 0) {
self.executionLog = response.data
var record = self.historyRows.find(function (item) { return item.id === row.id })
if (record) {
record.status = response.data.status
self.$set(record, "finishedAt", response.data.finishedAt)
}
} else {
self.$message.error(response.msg || "获取执行日志失败")
}
}, "json").fail(function (xhr, status) {
if (status !== "abort") self.$message.error("获取执行日志失败")
}).always(function () {
self.executionLogLoading = false
self.executionLogRequest = null
})
},
doSearch: function () {
this.pageForm.pageNumber = 1
this.pageData()
},
openAdd: function () {
var self = this
this.formData = { name: "", jobClass: "", cron: "", data: "", disabled: false }
this.addDialogVisible = true
this.formData = {} //打开新增窗口,表单先清空
if (this.$refs["addForm"]) this.$refs["addForm"].resetFields()
this.$nextTick(function () {
this.$refs.addForm.clearValidate()
})
},
doAdd: function () {
var self = this
@@ -204,7 +376,7 @@ layout("/layouts/platform.html"){
type: "error"
})
}
self.pageData() //添加失败也可以入库,所以加载一下看看
self.pageData()
},
"json"
)
@@ -242,6 +414,10 @@ layout("/layouts/platform.html"){
dropdownCommand: function (command) {
//监听下拉框事件
var self = this
if ("history" == command.type) {
self.openHistory(command)
return
}
if ("enable" == command.type || "disable" == command.type) {
$.post(
base + "/platform/sys/task/" + command.type + "/" + command.id,
@@ -334,6 +510,9 @@ layout("/layouts/platform.html"){
},
created: function () {
this.pageData()
},
mounted: function () {
if (this.$el.dataset.openCron === "true") this.openCronGenerator()
}
})
</script>