Commit 9626b5e971ddbcf6a81fc2a1b71a14c80253185b

Authored by YunaiV
1 parent e1e749d8

v3.7.0 定时任务支持在线生成cron表达式

yudao-ui-admin/src/assets/styles/ruoyi.scss
... ... @@ -37,7 +37,7 @@
37 37 .mb10 {
38 38 margin-bottom: 10px;
39 39 }
40   -.ml10 {
  40 +.ml0 {
41 41 margin-left: 10px;
42 42 }
43 43 .mt20 {
... ... @@ -49,7 +49,7 @@
49 49 .mb20 {
50 50 margin-bottom: 20px;
51 51 }
52   -.ml20 {
  52 +.m20 {
53 53 margin-left: 20px;
54 54 }
55 55  
... ... @@ -64,7 +64,7 @@
64 64 margin-top: 6vh !important;
65 65 }
66 66  
67   -.el-dialog__wrapper.scrollbar .el-dialog .el-dialog__body {
  67 +.el-dialog .el-dialog__body {
68 68 overflow: auto;
69 69 overflow-x: hidden;
70 70 max-height: 70vh;
... ... @@ -137,7 +137,7 @@
137 137 /** 表格更多操作下拉样式 */
138 138 .el-table .el-dropdown-link {
139 139 cursor: pointer;
140   - color: #409EFF;
  140 + color: #1890ff;
141 141 margin-left: 5px;
142 142 }
143 143  
... ...
yudao-ui-admin/src/components/Crontab/day.vue 0 → 100644
  1 +<template>
  2 + <el-form size="small">
  3 + <el-form-item>
  4 + <el-radio v-model='radioValue' :label="1">
  5 + 日,允许的通配符[, - * ? / L W]
  6 + </el-radio>
  7 + </el-form-item>
  8 +
  9 + <el-form-item>
  10 + <el-radio v-model='radioValue' :label="2">
  11 + 不指定
  12 + </el-radio>
  13 + </el-form-item>
  14 +
  15 + <el-form-item>
  16 + <el-radio v-model='radioValue' :label="3">
  17 + 周期从
  18 + <el-input-number v-model='cycle01' :min="1" :max="30" /> -
  19 + <el-input-number v-model='cycle02' :min="cycle01 ? cycle01 + 1 : 2" :max="31" /> 日
  20 + </el-radio>
  21 + </el-form-item>
  22 +
  23 + <el-form-item>
  24 + <el-radio v-model='radioValue' :label="4">
  25 + 从
  26 + <el-input-number v-model='average01' :min="1" :max="30" /> 号开始,每
  27 + <el-input-number v-model='average02' :min="1" :max="31 - average01 || 1" /> 日执行一次
  28 + </el-radio>
  29 + </el-form-item>
  30 +
  31 + <el-form-item>
  32 + <el-radio v-model='radioValue' :label="5">
  33 + 每月
  34 + <el-input-number v-model='workday' :min="1" :max="31" /> 号最近的那个工作日
  35 + </el-radio>
  36 + </el-form-item>
  37 +
  38 + <el-form-item>
  39 + <el-radio v-model='radioValue' :label="6">
  40 + 本月最后一天
  41 + </el-radio>
  42 + </el-form-item>
  43 +
  44 + <el-form-item>
  45 + <el-radio v-model='radioValue' :label="7">
  46 + 指定
  47 + <el-select clearable v-model="checkboxList" placeholder="可多选" multiple style="width:100%">
  48 + <el-option v-for="item in 31" :key="item" :value="item">{{item}}</el-option>
  49 + </el-select>
  50 + </el-radio>
  51 + </el-form-item>
  52 + </el-form>
  53 +</template>
  54 +
  55 +<script>
  56 +export default {
  57 + data() {
  58 + return {
  59 + radioValue: 1,
  60 + workday: 1,
  61 + cycle01: 1,
  62 + cycle02: 2,
  63 + average01: 1,
  64 + average02: 1,
  65 + checkboxList: [],
  66 + checkNum: this.$options.propsData.check
  67 + }
  68 + },
  69 + name: 'crontab-day',
  70 + props: ['check', 'cron'],
  71 + methods: {
  72 + // 单选按钮值变化时
  73 + radioChange() {
  74 + ('day rachange');
  75 + if (this.radioValue !== 2 && this.cron.week !== '?') {
  76 + this.$emit('update', 'week', '?', 'day')
  77 + }
  78 +
  79 + switch (this.radioValue) {
  80 + case 1:
  81 + this.$emit('update', 'day', '*');
  82 + break;
  83 + case 2:
  84 + this.$emit('update', 'day', '?');
  85 + break;
  86 + case 3:
  87 + this.$emit('update', 'day', this.cycleTotal);
  88 + break;
  89 + case 4:
  90 + this.$emit('update', 'day', this.averageTotal);
  91 + break;
  92 + case 5:
  93 + this.$emit('update', 'day', this.workday + 'W');
  94 + break;
  95 + case 6:
  96 + this.$emit('update', 'day', 'L');
  97 + break;
  98 + case 7:
  99 + this.$emit('update', 'day', this.checkboxString);
  100 + break;
  101 + }
  102 + ('day rachange end');
  103 + },
  104 + // 周期两个值变化时
  105 + cycleChange() {
  106 + if (this.radioValue == '3') {
  107 + this.$emit('update', 'day', this.cycleTotal);
  108 + }
  109 + },
  110 + // 平均两个值变化时
  111 + averageChange() {
  112 + if (this.radioValue == '4') {
  113 + this.$emit('update', 'day', this.averageTotal);
  114 + }
  115 + },
  116 + // 最近工作日值变化时
  117 + workdayChange() {
  118 + if (this.radioValue == '5') {
  119 + this.$emit('update', 'day', this.workdayCheck + 'W');
  120 + }
  121 + },
  122 + // checkbox值变化时
  123 + checkboxChange() {
  124 + if (this.radioValue == '7') {
  125 + this.$emit('update', 'day', this.checkboxString);
  126 + }
  127 + }
  128 + },
  129 + watch: {
  130 + 'radioValue': 'radioChange',
  131 + 'cycleTotal': 'cycleChange',
  132 + 'averageTotal': 'averageChange',
  133 + 'workdayCheck': 'workdayChange',
  134 + 'checkboxString': 'checkboxChange',
  135 + },
  136 + computed: {
  137 + // 计算两个周期值
  138 + cycleTotal: function () {
  139 + const cycle01 = this.checkNum(this.cycle01, 1, 30)
  140 + const cycle02 = this.checkNum(this.cycle02, cycle01 ? cycle01 + 1 : 2, 31, 31)
  141 + return cycle01 + '-' + cycle02;
  142 + },
  143 + // 计算平均用到的值
  144 + averageTotal: function () {
  145 + const average01 = this.checkNum(this.average01, 1, 30)
  146 + const average02 = this.checkNum(this.average02, 1, 31 - average01 || 0)
  147 + return average01 + '/' + average02;
  148 + },
  149 + // 计算工作日格式
  150 + workdayCheck: function () {
  151 + const workday = this.checkNum(this.workday, 1, 31)
  152 + return workday;
  153 + },
  154 + // 计算勾选的checkbox值合集
  155 + checkboxString: function () {
  156 + let str = this.checkboxList.join();
  157 + return str == '' ? '*' : str;
  158 + }
  159 + }
  160 +}
  161 +</script>
... ...
yudao-ui-admin/src/components/Crontab/hour.vue 0 → 100644
  1 +<template>
  2 + <el-form size="small">
  3 + <el-form-item>
  4 + <el-radio v-model='radioValue' :label="1">
  5 + 小时,允许的通配符[, - * /]
  6 + </el-radio>
  7 + </el-form-item>
  8 +
  9 + <el-form-item>
  10 + <el-radio v-model='radioValue' :label="2">
  11 + 周期从
  12 + <el-input-number v-model='cycle01' :min="0" :max="22" /> -
  13 + <el-input-number v-model='cycle02' :min="cycle01 ? cycle01 + 1 : 1" :max="23" /> 小时
  14 + </el-radio>
  15 + </el-form-item>
  16 +
  17 + <el-form-item>
  18 + <el-radio v-model='radioValue' :label="3">
  19 + 从
  20 + <el-input-number v-model='average01' :min="0" :max="22" /> 小时开始,每
  21 + <el-input-number v-model='average02' :min="1" :max="23 - average01 || 0" /> 小时执行一次
  22 + </el-radio>
  23 + </el-form-item>
  24 +
  25 + <el-form-item>
  26 + <el-radio v-model='radioValue' :label="4">
  27 + 指定
  28 + <el-select clearable v-model="checkboxList" placeholder="可多选" multiple style="width:100%">
  29 + <el-option v-for="item in 24" :key="item" :value="item-1">{{item-1}}</el-option>
  30 + </el-select>
  31 + </el-radio>
  32 + </el-form-item>
  33 + </el-form>
  34 +</template>
  35 +
  36 +<script>
  37 +export default {
  38 + data() {
  39 + return {
  40 + radioValue: 1,
  41 + cycle01: 0,
  42 + cycle02: 1,
  43 + average01: 0,
  44 + average02: 1,
  45 + checkboxList: [],
  46 + checkNum: this.$options.propsData.check
  47 + }
  48 + },
  49 + name: 'crontab-hour',
  50 + props: ['check', 'cron'],
  51 + methods: {
  52 + // 单选按钮值变化时
  53 + radioChange() {
  54 + switch (this.radioValue) {
  55 + case 1:
  56 + this.$emit('update', 'hour', '*')
  57 + break;
  58 + case 2:
  59 + this.$emit('update', 'hour', this.cycleTotal);
  60 + break;
  61 + case 3:
  62 + this.$emit('update', 'hour', this.averageTotal);
  63 + break;
  64 + case 4:
  65 + this.$emit('update', 'hour', this.checkboxString);
  66 + break;
  67 + }
  68 + },
  69 + // 周期两个值变化时
  70 + cycleChange() {
  71 + if (this.radioValue == '2') {
  72 + this.$emit('update', 'hour', this.cycleTotal);
  73 + }
  74 + },
  75 + // 平均两个值变化时
  76 + averageChange() {
  77 + if (this.radioValue == '3') {
  78 + this.$emit('update', 'hour', this.averageTotal);
  79 + }
  80 + },
  81 + // checkbox值变化时
  82 + checkboxChange() {
  83 + if (this.radioValue == '4') {
  84 + this.$emit('update', 'hour', this.checkboxString);
  85 + }
  86 + }
  87 + },
  88 + watch: {
  89 + 'radioValue': 'radioChange',
  90 + 'cycleTotal': 'cycleChange',
  91 + 'averageTotal': 'averageChange',
  92 + 'checkboxString': 'checkboxChange'
  93 + },
  94 + computed: {
  95 + // 计算两个周期值
  96 + cycleTotal: function () {
  97 + const cycle01 = this.checkNum(this.cycle01, 0, 22)
  98 + const cycle02 = this.checkNum(this.cycle02, cycle01 ? cycle01 + 1 : 1, 23)
  99 + return cycle01 + '-' + cycle02;
  100 + },
  101 + // 计算平均用到的值
  102 + averageTotal: function () {
  103 + const average01 = this.checkNum(this.average01, 0, 22)
  104 + const average02 = this.checkNum(this.average02, 1, 23 - average01 || 0)
  105 + return average01 + '/' + average02;
  106 + },
  107 + // 计算勾选的checkbox值合集
  108 + checkboxString: function () {
  109 + let str = this.checkboxList.join();
  110 + return str == '' ? '*' : str;
  111 + }
  112 + }
  113 +}
  114 +</script>
... ...
yudao-ui-admin/src/components/Crontab/index.vue 0 → 100644
  1 +<template>
  2 + <div>
  3 + <el-tabs type="border-card">
  4 + <el-tab-pane label="秒" v-if="shouldHide('second')">
  5 + <CrontabSecond
  6 + @update="updateCrontabValue"
  7 + :check="checkNumber"
  8 + :cron="crontabValueObj"
  9 + ref="cronsecond"
  10 + />
  11 + </el-tab-pane>
  12 +
  13 + <el-tab-pane label="分钟" v-if="shouldHide('min')">
  14 + <CrontabMin
  15 + @update="updateCrontabValue"
  16 + :check="checkNumber"
  17 + :cron="crontabValueObj"
  18 + ref="cronmin"
  19 + />
  20 + </el-tab-pane>
  21 +
  22 + <el-tab-pane label="小时" v-if="shouldHide('hour')">
  23 + <CrontabHour
  24 + @update="updateCrontabValue"
  25 + :check="checkNumber"
  26 + :cron="crontabValueObj"
  27 + ref="cronhour"
  28 + />
  29 + </el-tab-pane>
  30 +
  31 + <el-tab-pane label="日" v-if="shouldHide('day')">
  32 + <CrontabDay
  33 + @update="updateCrontabValue"
  34 + :check="checkNumber"
  35 + :cron="crontabValueObj"
  36 + ref="cronday"
  37 + />
  38 + </el-tab-pane>
  39 +
  40 + <el-tab-pane label="月" v-if="shouldHide('month')">
  41 + <CrontabMonth
  42 + @update="updateCrontabValue"
  43 + :check="checkNumber"
  44 + :cron="crontabValueObj"
  45 + ref="cronmonth"
  46 + />
  47 + </el-tab-pane>
  48 +
  49 + <el-tab-pane label="周" v-if="shouldHide('week')">
  50 + <CrontabWeek
  51 + @update="updateCrontabValue"
  52 + :check="checkNumber"
  53 + :cron="crontabValueObj"
  54 + ref="cronweek"
  55 + />
  56 + </el-tab-pane>
  57 +
  58 + <el-tab-pane label="年" v-if="shouldHide('year')">
  59 + <CrontabYear
  60 + @update="updateCrontabValue"
  61 + :check="checkNumber"
  62 + :cron="crontabValueObj"
  63 + ref="cronyear"
  64 + />
  65 + </el-tab-pane>
  66 + </el-tabs>
  67 +
  68 + <div class="popup-main">
  69 + <div class="popup-result">
  70 + <p class="title">时间表达式</p>
  71 + <table>
  72 + <thead>
  73 + <th v-for="item of tabTitles" width="40" :key="item">{{item}}</th>
  74 + <th>Cron 表达式</th>
  75 + </thead>
  76 + <tbody>
  77 + <td>
  78 + <span>{{crontabValueObj.second}}</span>
  79 + </td>
  80 + <td>
  81 + <span>{{crontabValueObj.min}}</span>
  82 + </td>
  83 + <td>
  84 + <span>{{crontabValueObj.hour}}</span>
  85 + </td>
  86 + <td>
  87 + <span>{{crontabValueObj.day}}</span>
  88 + </td>
  89 + <td>
  90 + <span>{{crontabValueObj.month}}</span>
  91 + </td>
  92 + <td>
  93 + <span>{{crontabValueObj.week}}</span>
  94 + </td>
  95 + <td>
  96 + <span>{{crontabValueObj.year}}</span>
  97 + </td>
  98 + <td>
  99 + <span>{{crontabValueString}}</span>
  100 + </td>
  101 + </tbody>
  102 + </table>
  103 + </div>
  104 + <CrontabResult :ex="crontabValueString"></CrontabResult>
  105 +
  106 + <div class="pop_btn">
  107 + <el-button size="small" type="primary" @click="submitFill">确定</el-button>
  108 + <el-button size="small" type="warning" @click="clearCron">重置</el-button>
  109 + <el-button size="small" @click="hidePopup">取消</el-button>
  110 + </div>
  111 + </div>
  112 + </div>
  113 +</template>
  114 +
  115 +<script>
  116 +import CrontabSecond from "./second.vue";
  117 +import CrontabMin from "./min.vue";
  118 +import CrontabHour from "./hour.vue";
  119 +import CrontabDay from "./day.vue";
  120 +import CrontabMonth from "./month.vue";
  121 +import CrontabWeek from "./week.vue";
  122 +import CrontabYear from "./year.vue";
  123 +import CrontabResult from "./result.vue";
  124 +
  125 +export default {
  126 + data() {
  127 + return {
  128 + tabTitles: ["秒", "分钟", "小时", "日", "月", "周", "年"],
  129 + tabActive: 0,
  130 + myindex: 0,
  131 + crontabValueObj: {
  132 + second: "*",
  133 + min: "*",
  134 + hour: "*",
  135 + day: "*",
  136 + month: "*",
  137 + week: "?",
  138 + year: "",
  139 + },
  140 + };
  141 + },
  142 + name: "vcrontab",
  143 + props: ["expression", "hideComponent"],
  144 + methods: {
  145 + shouldHide(key) {
  146 + if (this.hideComponent && this.hideComponent.includes(key)) return false;
  147 + return true;
  148 + },
  149 + resolveExp() {
  150 + // 反解析 表达式
  151 + if (this.expression) {
  152 + let arr = this.expression.split(" ");
  153 + if (arr.length >= 6) {
  154 + //6 位以上是合法表达式
  155 + let obj = {
  156 + second: arr[0],
  157 + min: arr[1],
  158 + hour: arr[2],
  159 + day: arr[3],
  160 + month: arr[4],
  161 + week: arr[5],
  162 + year: arr[6] ? arr[6] : "",
  163 + };
  164 + this.crontabValueObj = {
  165 + ...obj,
  166 + };
  167 + for (let i in obj) {
  168 + if (obj[i]) this.changeRadio(i, obj[i]);
  169 + }
  170 + }
  171 + } else {
  172 + // 没有传入的表达式 则还原
  173 + this.clearCron();
  174 + }
  175 + },
  176 + // tab切换值
  177 + tabCheck(index) {
  178 + this.tabActive = index;
  179 + },
  180 + // 由子组件触发,更改表达式组成的字段值
  181 + updateCrontabValue(name, value, from) {
  182 + "updateCrontabValue", name, value, from;
  183 + this.crontabValueObj[name] = value;
  184 + if (from && from !== name) {
  185 + console.log(`来自组件 ${from} 改变了 ${name} ${value}`);
  186 + this.changeRadio(name, value);
  187 + }
  188 + },
  189 + // 赋值到组件
  190 + changeRadio(name, value) {
  191 + let arr = ["second", "min", "hour", "month"],
  192 + refName = "cron" + name,
  193 + insValue;
  194 +
  195 + if (!this.$refs[refName]) return;
  196 +
  197 + if (arr.includes(name)) {
  198 + if (value === "*") {
  199 + insValue = 1;
  200 + } else if (value.indexOf("-") > -1) {
  201 + let indexArr = value.split("-");
  202 + isNaN(indexArr[0])
  203 + ? (this.$refs[refName].cycle01 = 0)
  204 + : (this.$refs[refName].cycle01 = indexArr[0]);
  205 + this.$refs[refName].cycle02 = indexArr[1];
  206 + insValue = 2;
  207 + } else if (value.indexOf("/") > -1) {
  208 + let indexArr = value.split("/");
  209 + isNaN(indexArr[0])
  210 + ? (this.$refs[refName].average01 = 0)
  211 + : (this.$refs[refName].average01 = indexArr[0]);
  212 + this.$refs[refName].average02 = indexArr[1];
  213 + insValue = 3;
  214 + } else {
  215 + insValue = 4;
  216 + this.$refs[refName].checkboxList = value.split(",");
  217 + }
  218 + } else if (name == "day") {
  219 + if (value === "*") {
  220 + insValue = 1;
  221 + } else if (value == "?") {
  222 + insValue = 2;
  223 + } else if (value.indexOf("-") > -1) {
  224 + let indexArr = value.split("-");
  225 + isNaN(indexArr[0])
  226 + ? (this.$refs[refName].cycle01 = 0)
  227 + : (this.$refs[refName].cycle01 = indexArr[0]);
  228 + this.$refs[refName].cycle02 = indexArr[1];
  229 + insValue = 3;
  230 + } else if (value.indexOf("/") > -1) {
  231 + let indexArr = value.split("/");
  232 + isNaN(indexArr[0])
  233 + ? (this.$refs[refName].average01 = 0)
  234 + : (this.$refs[refName].average01 = indexArr[0]);
  235 + this.$refs[refName].average02 = indexArr[1];
  236 + insValue = 4;
  237 + } else if (value.indexOf("W") > -1) {
  238 + let indexArr = value.split("W");
  239 + isNaN(indexArr[0])
  240 + ? (this.$refs[refName].workday = 0)
  241 + : (this.$refs[refName].workday = indexArr[0]);
  242 + insValue = 5;
  243 + } else if (value === "L") {
  244 + insValue = 6;
  245 + } else {
  246 + this.$refs[refName].checkboxList = value.split(",");
  247 + insValue = 7;
  248 + }
  249 + } else if (name == "week") {
  250 + if (value === "*") {
  251 + insValue = 1;
  252 + } else if (value == "?") {
  253 + insValue = 2;
  254 + } else if (value.indexOf("-") > -1) {
  255 + let indexArr = value.split("-");
  256 + isNaN(indexArr[0])
  257 + ? (this.$refs[refName].cycle01 = 0)
  258 + : (this.$refs[refName].cycle01 = indexArr[0]);
  259 + this.$refs[refName].cycle02 = indexArr[1];
  260 + insValue = 3;
  261 + } else if (value.indexOf("#") > -1) {
  262 + let indexArr = value.split("#");
  263 + isNaN(indexArr[0])
  264 + ? (this.$refs[refName].average01 = 1)
  265 + : (this.$refs[refName].average01 = indexArr[0]);
  266 + this.$refs[refName].average02 = indexArr[1];
  267 + insValue = 4;
  268 + } else if (value.indexOf("L") > -1) {
  269 + let indexArr = value.split("L");
  270 + isNaN(indexArr[0])
  271 + ? (this.$refs[refName].weekday = 1)
  272 + : (this.$refs[refName].weekday = indexArr[0]);
  273 + insValue = 5;
  274 + } else {
  275 + this.$refs[refName].checkboxList = value.split(",");
  276 + insValue = 6;
  277 + }
  278 + } else if (name == "year") {
  279 + if (value == "") {
  280 + insValue = 1;
  281 + } else if (value == "*") {
  282 + insValue = 2;
  283 + } else if (value.indexOf("-") > -1) {
  284 + insValue = 3;
  285 + } else if (value.indexOf("/") > -1) {
  286 + insValue = 4;
  287 + } else {
  288 + this.$refs[refName].checkboxList = value.split(",");
  289 + insValue = 5;
  290 + }
  291 + }
  292 + this.$refs[refName].radioValue = insValue;
  293 + },
  294 + // 表单选项的子组件校验数字格式(通过-props传递)
  295 + checkNumber(value, minLimit, maxLimit) {
  296 + // 检查必须为整数
  297 + value = Math.floor(value);
  298 + if (value < minLimit) {
  299 + value = minLimit;
  300 + } else if (value > maxLimit) {
  301 + value = maxLimit;
  302 + }
  303 + return value;
  304 + },
  305 + // 隐藏弹窗
  306 + hidePopup() {
  307 + this.$emit("hide");
  308 + },
  309 + // 填充表达式
  310 + submitFill() {
  311 + this.$emit("fill", this.crontabValueString);
  312 + this.hidePopup();
  313 + },
  314 + clearCron() {
  315 + // 还原选择项
  316 + ("准备还原");
  317 + this.crontabValueObj = {
  318 + second: "*",
  319 + min: "*",
  320 + hour: "*",
  321 + day: "*",
  322 + month: "*",
  323 + week: "?",
  324 + year: "",
  325 + };
  326 + for (let j in this.crontabValueObj) {
  327 + this.changeRadio(j, this.crontabValueObj[j]);
  328 + }
  329 + },
  330 + },
  331 + computed: {
  332 + crontabValueString: function() {
  333 + let obj = this.crontabValueObj;
  334 + let str =
  335 + obj.second +
  336 + " " +
  337 + obj.min +
  338 + " " +
  339 + obj.hour +
  340 + " " +
  341 + obj.day +
  342 + " " +
  343 + obj.month +
  344 + " " +
  345 + obj.week +
  346 + (obj.year == "" ? "" : " " + obj.year);
  347 + return str;
  348 + },
  349 + },
  350 + components: {
  351 + CrontabSecond,
  352 + CrontabMin,
  353 + CrontabHour,
  354 + CrontabDay,
  355 + CrontabMonth,
  356 + CrontabWeek,
  357 + CrontabYear,
  358 + CrontabResult,
  359 + },
  360 + watch: {
  361 + expression: "resolveExp",
  362 + hideComponent(value) {
  363 + // 隐藏部分组件
  364 + },
  365 + },
  366 + mounted: function() {
  367 + this.resolveExp();
  368 + },
  369 +};
  370 +</script>
  371 +<style scoped>
  372 +.pop_btn {
  373 + text-align: center;
  374 + margin-top: 20px;
  375 +}
  376 +.popup-main {
  377 + position: relative;
  378 + margin: 10px auto;
  379 + background: #fff;
  380 + border-radius: 5px;
  381 + font-size: 12px;
  382 + overflow: hidden;
  383 +}
  384 +.popup-title {
  385 + overflow: hidden;
  386 + line-height: 34px;
  387 + padding-top: 6px;
  388 + background: #f2f2f2;
  389 +}
  390 +.popup-result {
  391 + box-sizing: border-box;
  392 + line-height: 24px;
  393 + margin: 25px auto;
  394 + padding: 15px 10px 10px;
  395 + border: 1px solid #ccc;
  396 + position: relative;
  397 +}
  398 +.popup-result .title {
  399 + position: absolute;
  400 + top: -28px;
  401 + left: 50%;
  402 + width: 140px;
  403 + font-size: 14px;
  404 + margin-left: -70px;
  405 + text-align: center;
  406 + line-height: 30px;
  407 + background: #fff;
  408 +}
  409 +.popup-result table {
  410 + text-align: center;
  411 + width: 100%;
  412 + margin: 0 auto;
  413 +}
  414 +.popup-result table span {
  415 + display: block;
  416 + width: 100%;
  417 + font-family: arial;
  418 + line-height: 30px;
  419 + height: 30px;
  420 + white-space: nowrap;
  421 + overflow: hidden;
  422 + border: 1px solid #e8e8e8;
  423 +}
  424 +.popup-result-scroll {
  425 + font-size: 12px;
  426 + line-height: 24px;
  427 + height: 10em;
  428 + overflow-y: auto;
  429 +}
  430 +</style>
... ...
yudao-ui-admin/src/components/Crontab/min.vue 0 → 100644
  1 +<template>
  2 + <el-form size="small">
  3 + <el-form-item>
  4 + <el-radio v-model='radioValue' :label="1">
  5 + 分钟,允许的通配符[, - * /]
  6 + </el-radio>
  7 + </el-form-item>
  8 +
  9 + <el-form-item>
  10 + <el-radio v-model='radioValue' :label="2">
  11 + 周期从
  12 + <el-input-number v-model='cycle01' :min="0" :max="58" /> -
  13 + <el-input-number v-model='cycle02' :min="cycle01 ? cycle01 + 1 : 1" :max="59" /> 分钟
  14 + </el-radio>
  15 + </el-form-item>
  16 +
  17 + <el-form-item>
  18 + <el-radio v-model='radioValue' :label="3">
  19 + 从
  20 + <el-input-number v-model='average01' :min="0" :max="58" /> 分钟开始,每
  21 + <el-input-number v-model='average02' :min="1" :max="59 - average01 || 0" /> 分钟执行一次
  22 + </el-radio>
  23 + </el-form-item>
  24 +
  25 + <el-form-item>
  26 + <el-radio v-model='radioValue' :label="4">
  27 + 指定
  28 + <el-select clearable v-model="checkboxList" placeholder="可多选" multiple style="width:100%">
  29 + <el-option v-for="item in 60" :key="item" :value="item-1">{{item-1}}</el-option>
  30 + </el-select>
  31 + </el-radio>
  32 + </el-form-item>
  33 + </el-form>
  34 +
  35 +</template>
  36 +
  37 +<script>
  38 +export default {
  39 + data() {
  40 + return {
  41 + radioValue: 1,
  42 + cycle01: 1,
  43 + cycle02: 2,
  44 + average01: 0,
  45 + average02: 1,
  46 + checkboxList: [],
  47 + checkNum: this.$options.propsData.check
  48 + }
  49 + },
  50 + name: 'crontab-min',
  51 + props: ['check', 'cron'],
  52 + methods: {
  53 + // 单选按钮值变化时
  54 + radioChange() {
  55 + switch (this.radioValue) {
  56 + case 1:
  57 + this.$emit('update', 'min', '*', 'min');
  58 + break;
  59 + case 2:
  60 + this.$emit('update', 'min', this.cycleTotal, 'min');
  61 + break;
  62 + case 3:
  63 + this.$emit('update', 'min', this.averageTotal, 'min');
  64 + break;
  65 + case 4:
  66 + this.$emit('update', 'min', this.checkboxString, 'min');
  67 + break;
  68 + }
  69 + },
  70 + // 周期两个值变化时
  71 + cycleChange() {
  72 + if (this.radioValue == '2') {
  73 + this.$emit('update', 'min', this.cycleTotal, 'min');
  74 + }
  75 + },
  76 + // 平均两个值变化时
  77 + averageChange() {
  78 + if (this.radioValue == '3') {
  79 + this.$emit('update', 'min', this.averageTotal, 'min');
  80 + }
  81 + },
  82 + // checkbox值变化时
  83 + checkboxChange() {
  84 + if (this.radioValue == '4') {
  85 + this.$emit('update', 'min', this.checkboxString, 'min');
  86 + }
  87 + },
  88 +
  89 + },
  90 + watch: {
  91 + 'radioValue': 'radioChange',
  92 + 'cycleTotal': 'cycleChange',
  93 + 'averageTotal': 'averageChange',
  94 + 'checkboxString': 'checkboxChange',
  95 + },
  96 + computed: {
  97 + // 计算两个周期值
  98 + cycleTotal: function () {
  99 + const cycle01 = this.checkNum(this.cycle01, 0, 58)
  100 + const cycle02 = this.checkNum(this.cycle02, cycle01 ? cycle01 + 1 : 1, 59)
  101 + return cycle01 + '-' + cycle02;
  102 + },
  103 + // 计算平均用到的值
  104 + averageTotal: function () {
  105 + const average01 = this.checkNum(this.average01, 0, 58)
  106 + const average02 = this.checkNum(this.average02, 1, 59 - average01 || 0)
  107 + return average01 + '/' + average02;
  108 + },
  109 + // 计算勾选的checkbox值合集
  110 + checkboxString: function () {
  111 + let str = this.checkboxList.join();
  112 + return str == '' ? '*' : str;
  113 + }
  114 + }
  115 +}
  116 +</script>
0 117 \ No newline at end of file
... ...
yudao-ui-admin/src/components/Crontab/month.vue 0 → 100644
  1 +<template>
  2 + <el-form size='small'>
  3 + <el-form-item>
  4 + <el-radio v-model='radioValue' :label="1">
  5 + 月,允许的通配符[, - * /]
  6 + </el-radio>
  7 + </el-form-item>
  8 +
  9 + <el-form-item>
  10 + <el-radio v-model='radioValue' :label="2">
  11 + 周期从
  12 + <el-input-number v-model='cycle01' :min="1" :max="11" /> -
  13 + <el-input-number v-model='cycle02' :min="cycle01 ? cycle01 + 1 : 2" :max="12" /> 月
  14 + </el-radio>
  15 + </el-form-item>
  16 +
  17 + <el-form-item>
  18 + <el-radio v-model='radioValue' :label="3">
  19 + 从
  20 + <el-input-number v-model='average01' :min="1" :max="11" /> 月开始,每
  21 + <el-input-number v-model='average02' :min="1" :max="12 - average01 || 0" /> 月月执行一次
  22 + </el-radio>
  23 + </el-form-item>
  24 +
  25 + <el-form-item>
  26 + <el-radio v-model='radioValue' :label="4">
  27 + 指定
  28 + <el-select clearable v-model="checkboxList" placeholder="可多选" multiple style="width:100%">
  29 + <el-option v-for="item in 12" :key="item" :value="item">{{item}}</el-option>
  30 + </el-select>
  31 + </el-radio>
  32 + </el-form-item>
  33 + </el-form>
  34 +</template>
  35 +
  36 +<script>
  37 +export default {
  38 + data() {
  39 + return {
  40 + radioValue: 1,
  41 + cycle01: 1,
  42 + cycle02: 2,
  43 + average01: 1,
  44 + average02: 1,
  45 + checkboxList: [],
  46 + checkNum: this.check
  47 + }
  48 + },
  49 + name: 'crontab-month',
  50 + props: ['check', 'cron'],
  51 + methods: {
  52 + // 单选按钮值变化时
  53 + radioChange() {
  54 + switch (this.radioValue) {
  55 + case 1:
  56 + this.$emit('update', 'month', '*');
  57 + break;
  58 + case 2:
  59 + this.$emit('update', 'month', this.cycleTotal);
  60 + break;
  61 + case 3:
  62 + this.$emit('update', 'month', this.averageTotal);
  63 + break;
  64 + case 4:
  65 + this.$emit('update', 'month', this.checkboxString);
  66 + break;
  67 + }
  68 + },
  69 + // 周期两个值变化时
  70 + cycleChange() {
  71 + if (this.radioValue == '2') {
  72 + this.$emit('update', 'month', this.cycleTotal);
  73 + }
  74 + },
  75 + // 平均两个值变化时
  76 + averageChange() {
  77 + if (this.radioValue == '3') {
  78 + this.$emit('update', 'month', this.averageTotal);
  79 + }
  80 + },
  81 + // checkbox值变化时
  82 + checkboxChange() {
  83 + if (this.radioValue == '4') {
  84 + this.$emit('update', 'month', this.checkboxString);
  85 + }
  86 + }
  87 + },
  88 + watch: {
  89 + 'radioValue': 'radioChange',
  90 + 'cycleTotal': 'cycleChange',
  91 + 'averageTotal': 'averageChange',
  92 + 'checkboxString': 'checkboxChange'
  93 + },
  94 + computed: {
  95 + // 计算两个周期值
  96 + cycleTotal: function () {
  97 + const cycle01 = this.checkNum(this.cycle01, 1, 11)
  98 + const cycle02 = this.checkNum(this.cycle02, cycle01 ? cycle01 + 1 : 2, 12)
  99 + return cycle01 + '-' + cycle02;
  100 + },
  101 + // 计算平均用到的值
  102 + averageTotal: function () {
  103 + const average01 = this.checkNum(this.average01, 1, 11)
  104 + const average02 = this.checkNum(this.average02, 1, 12 - average01 || 0)
  105 + return average01 + '/' + average02;
  106 + },
  107 + // 计算勾选的checkbox值合集
  108 + checkboxString: function () {
  109 + let str = this.checkboxList.join();
  110 + return str == '' ? '*' : str;
  111 + }
  112 + }
  113 +}
  114 +</script>
... ...
yudao-ui-admin/src/components/Crontab/result.vue 0 → 100644
  1 +<template>
  2 + <div class="popup-result">
  3 + <p class="title">最近5次运行时间</p>
  4 + <ul class="popup-result-scroll">
  5 + <template v-if='isShow'>
  6 + <li v-for='item in resultList' :key="item">{{item}}</li>
  7 + </template>
  8 + <li v-else>计算结果中...</li>
  9 + </ul>
  10 + </div>
  11 +</template>
  12 +
  13 +<script>
  14 +export default {
  15 + data() {
  16 + return {
  17 + dayRule: '',
  18 + dayRuleSup: '',
  19 + dateArr: [],
  20 + resultList: [],
  21 + isShow: false
  22 + }
  23 + },
  24 + name: 'crontab-result',
  25 + methods: {
  26 + // 表达式值变化时,开始去计算结果
  27 + expressionChange() {
  28 +
  29 + // 计算开始-隐藏结果
  30 + this.isShow = false;
  31 + // 获取规则数组[0秒、1分、2时、3日、4月、5星期、6年]
  32 + let ruleArr = this.$options.propsData.ex.split(' ');
  33 + // 用于记录进入循环的次数
  34 + let nums = 0;
  35 + // 用于暂时存符号时间规则结果的数组
  36 + let resultArr = [];
  37 + // 获取当前时间精确至[年、月、日、时、分、秒]
  38 + let nTime = new Date();
  39 + let nYear = nTime.getFullYear();
  40 + let nMonth = nTime.getMonth() + 1;
  41 + let nDay = nTime.getDate();
  42 + let nHour = nTime.getHours();
  43 + let nMin = nTime.getMinutes();
  44 + let nSecond = nTime.getSeconds();
  45 + // 根据规则获取到近100年可能年数组、月数组等等
  46 + this.getSecondArr(ruleArr[0]);
  47 + this.getMinArr(ruleArr[1]);
  48 + this.getHourArr(ruleArr[2]);
  49 + this.getDayArr(ruleArr[3]);
  50 + this.getMonthArr(ruleArr[4]);
  51 + this.getWeekArr(ruleArr[5]);
  52 + this.getYearArr(ruleArr[6], nYear);
  53 + // 将获取到的数组赋值-方便使用
  54 + let sDate = this.dateArr[0];
  55 + let mDate = this.dateArr[1];
  56 + let hDate = this.dateArr[2];
  57 + let DDate = this.dateArr[3];
  58 + let MDate = this.dateArr[4];
  59 + let YDate = this.dateArr[5];
  60 + // 获取当前时间在数组中的索引
  61 + let sIdx = this.getIndex(sDate, nSecond);
  62 + let mIdx = this.getIndex(mDate, nMin);
  63 + let hIdx = this.getIndex(hDate, nHour);
  64 + let DIdx = this.getIndex(DDate, nDay);
  65 + let MIdx = this.getIndex(MDate, nMonth);
  66 + let YIdx = this.getIndex(YDate, nYear);
  67 + // 重置月日时分秒的函数(后面用的比较多)
  68 + const resetSecond = function () {
  69 + sIdx = 0;
  70 + nSecond = sDate[sIdx]
  71 + }
  72 + const resetMin = function () {
  73 + mIdx = 0;
  74 + nMin = mDate[mIdx]
  75 + resetSecond();
  76 + }
  77 + const resetHour = function () {
  78 + hIdx = 0;
  79 + nHour = hDate[hIdx]
  80 + resetMin();
  81 + }
  82 + const resetDay = function () {
  83 + DIdx = 0;
  84 + nDay = DDate[DIdx]
  85 + resetHour();
  86 + }
  87 + const resetMonth = function () {
  88 + MIdx = 0;
  89 + nMonth = MDate[MIdx]
  90 + resetDay();
  91 + }
  92 + // 如果当前年份不为数组中当前值
  93 + if (nYear !== YDate[YIdx]) {
  94 + resetMonth();
  95 + }
  96 + // 如果当前月份不为数组中当前值
  97 + if (nMonth !== MDate[MIdx]) {
  98 + resetDay();
  99 + }
  100 + // 如果当前“日”不为数组中当前值
  101 + if (nDay !== DDate[DIdx]) {
  102 + resetHour();
  103 + }
  104 + // 如果当前“时”不为数组中当前值
  105 + if (nHour !== hDate[hIdx]) {
  106 + resetMin();
  107 + }
  108 + // 如果当前“分”不为数组中当前值
  109 + if (nMin !== mDate[mIdx]) {
  110 + resetSecond();
  111 + }
  112 +
  113 + // 循环年份数组
  114 + goYear: for (let Yi = YIdx; Yi < YDate.length; Yi++) {
  115 + let YY = YDate[Yi];
  116 + // 如果到达最大值时
  117 + if (nMonth > MDate[MDate.length - 1]) {
  118 + resetMonth();
  119 + continue;
  120 + }
  121 + // 循环月份数组
  122 + goMonth: for (let Mi = MIdx; Mi < MDate.length; Mi++) {
  123 + // 赋值、方便后面运算
  124 + let MM = MDate[Mi];
  125 + MM = MM < 10 ? '0' + MM : MM;
  126 + // 如果到达最大值时
  127 + if (nDay > DDate[DDate.length - 1]) {
  128 + resetDay();
  129 + if (Mi == MDate.length - 1) {
  130 + resetMonth();
  131 + continue goYear;
  132 + }
  133 + continue;
  134 + }
  135 + // 循环日期数组
  136 + goDay: for (let Di = DIdx; Di < DDate.length; Di++) {
  137 + // 赋值、方便后面运算
  138 + let DD = DDate[Di];
  139 + let thisDD = DD < 10 ? '0' + DD : DD;
  140 +
  141 + // 如果到达最大值时
  142 + if (nHour > hDate[hDate.length - 1]) {
  143 + resetHour();
  144 + if (Di == DDate.length - 1) {
  145 + resetDay();
  146 + if (Mi == MDate.length - 1) {
  147 + resetMonth();
  148 + continue goYear;
  149 + }
  150 + continue goMonth;
  151 + }
  152 + continue;
  153 + }
  154 +
  155 + // 判断日期的合法性,不合法的话也是跳出当前循环
  156 + if (this.checkDate(YY + '-' + MM + '-' + thisDD + ' 00:00:00') !== true && this.dayRule !== 'workDay' && this.dayRule !== 'lastWeek' && this.dayRule !== 'lastDay') {
  157 + resetDay();
  158 + continue goMonth;
  159 + }
  160 + // 如果日期规则中有值时
  161 + if (this.dayRule == 'lastDay') {
  162 + // 如果不是合法日期则需要将前将日期调到合法日期即月末最后一天
  163 +
  164 + if (this.checkDate(YY + '-' + MM + '-' + thisDD + ' 00:00:00') !== true) {
  165 + while (DD > 0 && this.checkDate(YY + '-' + MM + '-' + thisDD + ' 00:00:00') !== true) {
  166 + DD--;
  167 +
  168 + thisDD = DD < 10 ? '0' + DD : DD;
  169 + }
  170 + }
  171 + } else if (this.dayRule == 'workDay') {
  172 + // 校验并调整如果是2月30号这种日期传进来时需调整至正常月底
  173 + if (this.checkDate(YY + '-' + MM + '-' + thisDD + ' 00:00:00') !== true) {
  174 + while (DD > 0 && this.checkDate(YY + '-' + MM + '-' + thisDD + ' 00:00:00') !== true) {
  175 + DD--;
  176 + thisDD = DD < 10 ? '0' + DD : DD;
  177 + }
  178 + }
  179 + // 获取达到条件的日期是星期X
  180 + let thisWeek = this.formatDate(new Date(YY + '-' + MM + '-' + thisDD + ' 00:00:00'), 'week');
  181 + // 当星期日时
  182 + if (thisWeek == 1) {
  183 + // 先找下一个日,并判断是否为月底
  184 + DD++;
  185 + thisDD = DD < 10 ? '0' + DD : DD;
  186 + // 判断下一日已经不是合法日期
  187 + if (this.checkDate(YY + '-' + MM + '-' + thisDD + ' 00:00:00') !== true) {
  188 + DD -= 3;
  189 + }
  190 + } else if (thisWeek == 7) {
  191 + // 当星期6时只需判断不是1号就可进行操作
  192 + if (this.dayRuleSup !== 1) {
  193 + DD--;
  194 + } else {
  195 + DD += 2;
  196 + }
  197 + }
  198 + } else if (this.dayRule == 'weekDay') {
  199 + // 如果指定了是星期几
  200 + // 获取当前日期是属于星期几
  201 + let thisWeek = this.formatDate(new Date(YY + '-' + MM + '-' + DD + ' 00:00:00'), 'week');
  202 + // 校验当前星期是否在星期池(dayRuleSup)中
  203 + if (this.dayRuleSup.indexOf(thisWeek) < 0) {
  204 + // 如果到达最大值时
  205 + if (Di == DDate.length - 1) {
  206 + resetDay();
  207 + if (Mi == MDate.length - 1) {
  208 + resetMonth();
  209 + continue goYear;
  210 + }
  211 + continue goMonth;
  212 + }
  213 + continue;
  214 + }
  215 + } else if (this.dayRule == 'assWeek') {
  216 + // 如果指定了是第几周的星期几
  217 + // 获取每月1号是属于星期几
  218 + let thisWeek = this.formatDate(new Date(YY + '-' + MM + '-' + DD + ' 00:00:00'), 'week');
  219 + if (this.dayRuleSup[1] >= thisWeek) {
  220 + DD = (this.dayRuleSup[0] - 1) * 7 + this.dayRuleSup[1] - thisWeek + 1;
  221 + } else {
  222 + DD = this.dayRuleSup[0] * 7 + this.dayRuleSup[1] - thisWeek + 1;
  223 + }
  224 + } else if (this.dayRule == 'lastWeek') {
  225 + // 如果指定了每月最后一个星期几
  226 + // 校验并调整如果是2月30号这种日期传进来时需调整至正常月底
  227 + if (this.checkDate(YY + '-' + MM + '-' + thisDD + ' 00:00:00') !== true) {
  228 + while (DD > 0 && this.checkDate(YY + '-' + MM + '-' + thisDD + ' 00:00:00') !== true) {
  229 + DD--;
  230 + thisDD = DD < 10 ? '0' + DD : DD;
  231 + }
  232 + }
  233 + // 获取月末最后一天是星期几
  234 + let thisWeek = this.formatDate(new Date(YY + '-' + MM + '-' + thisDD + ' 00:00:00'), 'week');
  235 + // 找到要求中最近的那个星期几
  236 + if (this.dayRuleSup < thisWeek) {
  237 + DD -= thisWeek - this.dayRuleSup;
  238 + } else if (this.dayRuleSup > thisWeek) {
  239 + DD -= 7 - (this.dayRuleSup - thisWeek)
  240 + }
  241 + }
  242 + // 判断时间值是否小于10置换成“05”这种格式
  243 + DD = DD < 10 ? '0' + DD : DD;
  244 +
  245 + // 循环“时”数组
  246 + goHour: for (let hi = hIdx; hi < hDate.length; hi++) {
  247 + let hh = hDate[hi] < 10 ? '0' + hDate[hi] : hDate[hi]
  248 +
  249 + // 如果到达最大值时
  250 + if (nMin > mDate[mDate.length - 1]) {
  251 + resetMin();
  252 + if (hi == hDate.length - 1) {
  253 + resetHour();
  254 + if (Di == DDate.length - 1) {
  255 + resetDay();
  256 + if (Mi == MDate.length - 1) {
  257 + resetMonth();
  258 + continue goYear;
  259 + }
  260 + continue goMonth;
  261 + }
  262 + continue goDay;
  263 + }
  264 + continue;
  265 + }
  266 + // 循环"分"数组
  267 + goMin: for (let mi = mIdx; mi < mDate.length; mi++) {
  268 + let mm = mDate[mi] < 10 ? '0' + mDate[mi] : mDate[mi];
  269 +
  270 + // 如果到达最大值时
  271 + if (nSecond > sDate[sDate.length - 1]) {
  272 + resetSecond();
  273 + if (mi == mDate.length - 1) {
  274 + resetMin();
  275 + if (hi == hDate.length - 1) {
  276 + resetHour();
  277 + if (Di == DDate.length - 1) {
  278 + resetDay();
  279 + if (Mi == MDate.length - 1) {
  280 + resetMonth();
  281 + continue goYear;
  282 + }
  283 + continue goMonth;
  284 + }
  285 + continue goDay;
  286 + }
  287 + continue goHour;
  288 + }
  289 + continue;
  290 + }
  291 + // 循环"秒"数组
  292 + goSecond: for (let si = sIdx; si <= sDate.length - 1; si++) {
  293 + let ss = sDate[si] < 10 ? '0' + sDate[si] : sDate[si];
  294 + // 添加当前时间(时间合法性在日期循环时已经判断)
  295 + if (MM !== '00' && DD !== '00') {
  296 + resultArr.push(YY + '-' + MM + '-' + DD + ' ' + hh + ':' + mm + ':' + ss)
  297 + nums++;
  298 + }
  299 + // 如果条数满了就退出循环
  300 + if (nums == 5) break goYear;
  301 + // 如果到达最大值时
  302 + if (si == sDate.length - 1) {
  303 + resetSecond();
  304 + if (mi == mDate.length - 1) {
  305 + resetMin();
  306 + if (hi == hDate.length - 1) {
  307 + resetHour();
  308 + if (Di == DDate.length - 1) {
  309 + resetDay();
  310 + if (Mi == MDate.length - 1) {
  311 + resetMonth();
  312 + continue goYear;
  313 + }
  314 + continue goMonth;
  315 + }
  316 + continue goDay;
  317 + }
  318 + continue goHour;
  319 + }
  320 + continue goMin;
  321 + }
  322 + } //goSecond
  323 + } //goMin
  324 + }//goHour
  325 + }//goDay
  326 + }//goMonth
  327 + }
  328 + // 判断100年内的结果条数
  329 + if (resultArr.length == 0) {
  330 + this.resultList = ['没有达到条件的结果!'];
  331 + } else {
  332 + this.resultList = resultArr;
  333 + if (resultArr.length !== 5) {
  334 + this.resultList.push('最近100年内只有上面' + resultArr.length + '条结果!')
  335 + }
  336 + }
  337 + // 计算完成-显示结果
  338 + this.isShow = true;
  339 +
  340 +
  341 + },
  342 + // 用于计算某位数字在数组中的索引
  343 + getIndex(arr, value) {
  344 + if (value <= arr[0] || value > arr[arr.length - 1]) {
  345 + return 0;
  346 + } else {
  347 + for (let i = 0; i < arr.length - 1; i++) {
  348 + if (value > arr[i] && value <= arr[i + 1]) {
  349 + return i + 1;
  350 + }
  351 + }
  352 + }
  353 + },
  354 + // 获取"年"数组
  355 + getYearArr(rule, year) {
  356 + this.dateArr[5] = this.getOrderArr(year, year + 100);
  357 + if (rule !== undefined) {
  358 + if (rule.indexOf('-') >= 0) {
  359 + this.dateArr[5] = this.getCycleArr(rule, year + 100, false)
  360 + } else if (rule.indexOf('/') >= 0) {
  361 + this.dateArr[5] = this.getAverageArr(rule, year + 100)
  362 + } else if (rule !== '*') {
  363 + this.dateArr[5] = this.getAssignArr(rule)
  364 + }
  365 + }
  366 + },
  367 + // 获取"月"数组
  368 + getMonthArr(rule) {
  369 + this.dateArr[4] = this.getOrderArr(1, 12);
  370 + if (rule.indexOf('-') >= 0) {
  371 + this.dateArr[4] = this.getCycleArr(rule, 12, false)
  372 + } else if (rule.indexOf('/') >= 0) {
  373 + this.dateArr[4] = this.getAverageArr(rule, 12)
  374 + } else if (rule !== '*') {
  375 + this.dateArr[4] = this.getAssignArr(rule)
  376 + }
  377 + },
  378 + // 获取"日"数组-主要为日期规则
  379 + getWeekArr(rule) {
  380 + // 只有当日期规则的两个值均为“”时则表达日期是有选项的
  381 + if (this.dayRule == '' && this.dayRuleSup == '') {
  382 + if (rule.indexOf('-') >= 0) {
  383 + this.dayRule = 'weekDay';
  384 + this.dayRuleSup = this.getCycleArr(rule, 7, false)
  385 + } else if (rule.indexOf('#') >= 0) {
  386 + this.dayRule = 'assWeek';
  387 + let matchRule = rule.match(/[0-9]{1}/g);
  388 + this.dayRuleSup = [Number(matchRule[1]), Number(matchRule[0])];
  389 + this.dateArr[3] = [1];
  390 + if (this.dayRuleSup[1] == 7) {
  391 + this.dayRuleSup[1] = 0;
  392 + }
  393 + } else if (rule.indexOf('L') >= 0) {
  394 + this.dayRule = 'lastWeek';
  395 + this.dayRuleSup = Number(rule.match(/[0-9]{1,2}/g)[0]);
  396 + this.dateArr[3] = [31];
  397 + if (this.dayRuleSup == 7) {
  398 + this.dayRuleSup = 0;
  399 + }
  400 + } else if (rule !== '*' && rule !== '?') {
  401 + this.dayRule = 'weekDay';
  402 + this.dayRuleSup = this.getAssignArr(rule)
  403 + }
  404 + }
  405 + },
  406 + // 获取"日"数组-少量为日期规则
  407 + getDayArr(rule) {
  408 + this.dateArr[3] = this.getOrderArr(1, 31);
  409 + this.dayRule = '';
  410 + this.dayRuleSup = '';
  411 + if (rule.indexOf('-') >= 0) {
  412 + this.dateArr[3] = this.getCycleArr(rule, 31, false)
  413 + this.dayRuleSup = 'null';
  414 + } else if (rule.indexOf('/') >= 0) {
  415 + this.dateArr[3] = this.getAverageArr(rule, 31)
  416 + this.dayRuleSup = 'null';
  417 + } else if (rule.indexOf('W') >= 0) {
  418 + this.dayRule = 'workDay';
  419 + this.dayRuleSup = Number(rule.match(/[0-9]{1,2}/g)[0]);
  420 + this.dateArr[3] = [this.dayRuleSup];
  421 + } else if (rule.indexOf('L') >= 0) {
  422 + this.dayRule = 'lastDay';
  423 + this.dayRuleSup = 'null';
  424 + this.dateArr[3] = [31];
  425 + } else if (rule !== '*' && rule !== '?') {
  426 + this.dateArr[3] = this.getAssignArr(rule)
  427 + this.dayRuleSup = 'null';
  428 + } else if (rule == '*') {
  429 + this.dayRuleSup = 'null';
  430 + }
  431 + },
  432 + // 获取"时"数组
  433 + getHourArr(rule) {
  434 + this.dateArr[2] = this.getOrderArr(0, 23);
  435 + if (rule.indexOf('-') >= 0) {
  436 + this.dateArr[2] = this.getCycleArr(rule, 24, true)
  437 + } else if (rule.indexOf('/') >= 0) {
  438 + this.dateArr[2] = this.getAverageArr(rule, 23)
  439 + } else if (rule !== '*') {
  440 + this.dateArr[2] = this.getAssignArr(rule)
  441 + }
  442 + },
  443 + // 获取"分"数组
  444 + getMinArr(rule) {
  445 + this.dateArr[1] = this.getOrderArr(0, 59);
  446 + if (rule.indexOf('-') >= 0) {
  447 + this.dateArr[1] = this.getCycleArr(rule, 60, true)
  448 + } else if (rule.indexOf('/') >= 0) {
  449 + this.dateArr[1] = this.getAverageArr(rule, 59)
  450 + } else if (rule !== '*') {
  451 + this.dateArr[1] = this.getAssignArr(rule)
  452 + }
  453 + },
  454 + // 获取"秒"数组
  455 + getSecondArr(rule) {
  456 + this.dateArr[0] = this.getOrderArr(0, 59);
  457 + if (rule.indexOf('-') >= 0) {
  458 + this.dateArr[0] = this.getCycleArr(rule, 60, true)
  459 + } else if (rule.indexOf('/') >= 0) {
  460 + this.dateArr[0] = this.getAverageArr(rule, 59)
  461 + } else if (rule !== '*') {
  462 + this.dateArr[0] = this.getAssignArr(rule)
  463 + }
  464 + },
  465 + // 根据传进来的min-max返回一个顺序的数组
  466 + getOrderArr(min, max) {
  467 + let arr = [];
  468 + for (let i = min; i <= max; i++) {
  469 + arr.push(i);
  470 + }
  471 + return arr;
  472 + },
  473 + // 根据规则中指定的零散值返回一个数组
  474 + getAssignArr(rule) {
  475 + let arr = [];
  476 + let assiginArr = rule.split(',');
  477 + for (let i = 0; i < assiginArr.length; i++) {
  478 + arr[i] = Number(assiginArr[i])
  479 + }
  480 + arr.sort(this.compare)
  481 + return arr;
  482 + },
  483 + // 根据一定算术规则计算返回一个数组
  484 + getAverageArr(rule, limit) {
  485 + let arr = [];
  486 + let agArr = rule.split('/');
  487 + let min = Number(agArr[0]);
  488 + let step = Number(agArr[1]);
  489 + while (min <= limit) {
  490 + arr.push(min);
  491 + min += step;
  492 + }
  493 + return arr;
  494 + },
  495 + // 根据规则返回一个具有周期性的数组
  496 + getCycleArr(rule, limit, status) {
  497 + // status--表示是否从0开始(则从1开始)
  498 + let arr = [];
  499 + let cycleArr = rule.split('-');
  500 + let min = Number(cycleArr[0]);
  501 + let max = Number(cycleArr[1]);
  502 + if (min > max) {
  503 + max += limit;
  504 + }
  505 + for (let i = min; i <= max; i++) {
  506 + let add = 0;
  507 + if (status == false && i % limit == 0) {
  508 + add = limit;
  509 + }
  510 + arr.push(Math.round(i % limit + add))
  511 + }
  512 + arr.sort(this.compare)
  513 + return arr;
  514 + },
  515 + // 比较数字大小(用于Array.sort)
  516 + compare(value1, value2) {
  517 + if (value2 - value1 > 0) {
  518 + return -1;
  519 + } else {
  520 + return 1;
  521 + }
  522 + },
  523 + // 格式化日期格式如:2017-9-19 18:04:33
  524 + formatDate(value, type) {
  525 + // 计算日期相关值
  526 + let time = typeof value == 'number' ? new Date(value) : value;
  527 + let Y = time.getFullYear();
  528 + let M = time.getMonth() + 1;
  529 + let D = time.getDate();
  530 + let h = time.getHours();
  531 + let m = time.getMinutes();
  532 + let s = time.getSeconds();
  533 + let week = time.getDay();
  534 + // 如果传递了type的话
  535 + if (type == undefined) {
  536 + return Y + '-' + (M < 10 ? '0' + M : M) + '-' + (D < 10 ? '0' + D : D) + ' ' + (h < 10 ? '0' + h : h) + ':' + (m < 10 ? '0' + m : m) + ':' + (s < 10 ? '0' + s : s);
  537 + } else if (type == 'week') {
  538 + // 在quartz中 1为星期日
  539 + return week + 1;
  540 + }
  541 + },
  542 + // 检查日期是否存在
  543 + checkDate(value) {
  544 + let time = new Date(value);
  545 + let format = this.formatDate(time)
  546 + return value === format;
  547 + }
  548 + },
  549 + watch: {
  550 + 'ex': 'expressionChange'
  551 + },
  552 + props: ['ex'],
  553 + mounted: function () {
  554 + // 初始化 获取一次结果
  555 + this.expressionChange();
  556 + }
  557 +}
  558 +
  559 +</script>
... ...
yudao-ui-admin/src/components/Crontab/second.vue 0 → 100644
  1 +<template>
  2 + <el-form size="small">
  3 + <el-form-item>
  4 + <el-radio v-model='radioValue' :label="1">
  5 + 秒,允许的通配符[, - * /]
  6 + </el-radio>
  7 + </el-form-item>
  8 +
  9 + <el-form-item>
  10 + <el-radio v-model='radioValue' :label="2">
  11 + 周期从
  12 + <el-input-number v-model='cycle01' :min="0" :max="58" /> -
  13 + <el-input-number v-model='cycle02' :min="cycle01 ? cycle01 + 1 : 1" :max="59" /> 秒
  14 + </el-radio>
  15 + </el-form-item>
  16 +
  17 + <el-form-item>
  18 + <el-radio v-model='radioValue' :label="3">
  19 + 从
  20 + <el-input-number v-model='average01' :min="0" :max="58" /> 秒开始,每
  21 + <el-input-number v-model='average02' :min="1" :max="59 - average01 || 0" /> 秒执行一次
  22 + </el-radio>
  23 + </el-form-item>
  24 +
  25 + <el-form-item>
  26 + <el-radio v-model='radioValue' :label="4">
  27 + 指定
  28 + <el-select clearable v-model="checkboxList" placeholder="可多选" multiple style="width:100%">
  29 + <el-option v-for="item in 60" :key="item" :value="item-1">{{item-1}}</el-option>
  30 + </el-select>
  31 + </el-radio>
  32 + </el-form-item>
  33 + </el-form>
  34 +</template>
  35 +
  36 +<script>
  37 +export default {
  38 + data() {
  39 + return {
  40 + radioValue: 1,
  41 + cycle01: 1,
  42 + cycle02: 2,
  43 + average01: 0,
  44 + average02: 1,
  45 + checkboxList: [],
  46 + checkNum: this.$options.propsData.check
  47 + }
  48 + },
  49 + name: 'crontab-second',
  50 + props: ['check', 'radioParent'],
  51 + methods: {
  52 + // 单选按钮值变化时
  53 + radioChange() {
  54 + switch (this.radioValue) {
  55 + case 1:
  56 + this.$emit('update', 'second', '*', 'second');
  57 + break;
  58 + case 2:
  59 + this.$emit('update', 'second', this.cycleTotal);
  60 + break;
  61 + case 3:
  62 + this.$emit('update', 'second', this.averageTotal);
  63 + break;
  64 + case 4:
  65 + this.$emit('update', 'second', this.checkboxString);
  66 + break;
  67 + }
  68 + },
  69 + // 周期两个值变化时
  70 + cycleChange() {
  71 + if (this.radioValue == '2') {
  72 + this.$emit('update', 'second', this.cycleTotal);
  73 + }
  74 + },
  75 + // 平均两个值变化时
  76 + averageChange() {
  77 + if (this.radioValue == '3') {
  78 + this.$emit('update', 'second', this.averageTotal);
  79 + }
  80 + },
  81 + // checkbox值变化时
  82 + checkboxChange() {
  83 + if (this.radioValue == '4') {
  84 + this.$emit('update', 'second', this.checkboxString);
  85 + }
  86 + }
  87 + },
  88 + watch: {
  89 + 'radioValue': 'radioChange',
  90 + 'cycleTotal': 'cycleChange',
  91 + 'averageTotal': 'averageChange',
  92 + 'checkboxString': 'checkboxChange',
  93 + radioParent() {
  94 + this.radioValue = this.radioParent
  95 + }
  96 + },
  97 + computed: {
  98 + // 计算两个周期值
  99 + cycleTotal: function () {
  100 + const cycle01 = this.checkNum(this.cycle01, 0, 58)
  101 + const cycle02 = this.checkNum(this.cycle02, cycle01 ? cycle01 + 1 : 1, 59)
  102 + return cycle01 + '-' + cycle02;
  103 + },
  104 + // 计算平均用到的值
  105 + averageTotal: function () {
  106 + const average01 = this.checkNum(this.average01, 0, 58)
  107 + const average02 = this.checkNum(this.average02, 1, 59 - average01 || 0)
  108 + return average01 + '/' + average02;
  109 + },
  110 + // 计算勾选的checkbox值合集
  111 + checkboxString: function () {
  112 + let str = this.checkboxList.join();
  113 + return str == '' ? '*' : str;
  114 + }
  115 + }
  116 +}
  117 +</script>
... ...
yudao-ui-admin/src/components/Crontab/week.vue 0 → 100644
  1 +<template>
  2 + <el-form size='small'>
  3 + <el-form-item>
  4 + <el-radio v-model='radioValue' :label="1">
  5 + 周,允许的通配符[, - * ? / L #]
  6 + </el-radio>
  7 + </el-form-item>
  8 +
  9 + <el-form-item>
  10 + <el-radio v-model='radioValue' :label="2">
  11 + 不指定
  12 + </el-radio>
  13 + </el-form-item>
  14 +
  15 + <el-form-item>
  16 + <el-radio v-model='radioValue' :label="3">
  17 + 周期从星期
  18 + <el-select clearable v-model="cycle01">
  19 + <el-option
  20 + v-for="(item,index) of weekList"
  21 + :key="index"
  22 + :label="item.value"
  23 + :value="item.key"
  24 + :disabled="item.key === 1"
  25 + >{{item.value}}</el-option>
  26 + </el-select>
  27 + -
  28 + <el-select clearable v-model="cycle02">
  29 + <el-option
  30 + v-for="(item,index) of weekList"
  31 + :key="index"
  32 + :label="item.value"
  33 + :value="item.key"
  34 + :disabled="item.key < cycle01 && item.key !== 1"
  35 + >{{item.value}}</el-option>
  36 + </el-select>
  37 + </el-radio>
  38 + </el-form-item>
  39 +
  40 + <el-form-item>
  41 + <el-radio v-model='radioValue' :label="4">
  42 + 第
  43 + <el-input-number v-model='average01' :min="1" :max="4" /> 周的星期
  44 + <el-select clearable v-model="average02">
  45 + <el-option v-for="(item,index) of weekList" :key="index" :label="item.value" :value="item.key">{{item.value}}</el-option>
  46 + </el-select>
  47 + </el-radio>
  48 + </el-form-item>
  49 +
  50 + <el-form-item>
  51 + <el-radio v-model='radioValue' :label="5">
  52 + 本月最后一个星期
  53 + <el-select clearable v-model="weekday">
  54 + <el-option v-for="(item,index) of weekList" :key="index" :label="item.value" :value="item.key">{{item.value}}</el-option>
  55 + </el-select>
  56 + </el-radio>
  57 + </el-form-item>
  58 +
  59 + <el-form-item>
  60 + <el-radio v-model='radioValue' :label="6">
  61 + 指定
  62 + <el-select clearable v-model="checkboxList" placeholder="可多选" multiple style="width:100%">
  63 + <el-option v-for="(item,index) of weekList" :key="index" :label="item.value" :value="String(item.key)">{{item.value}}</el-option>
  64 + </el-select>
  65 + </el-radio>
  66 + </el-form-item>
  67 +
  68 + </el-form>
  69 +</template>
  70 +
  71 +<script>
  72 +export default {
  73 + data() {
  74 + return {
  75 + radioValue: 2,
  76 + weekday: 2,
  77 + cycle01: 2,
  78 + cycle02: 3,
  79 + average01: 1,
  80 + average02: 2,
  81 + checkboxList: [],
  82 + weekList: [
  83 + {
  84 + key: 2,
  85 + value: '星期一'
  86 + },
  87 + {
  88 + key: 3,
  89 + value: '星期二'
  90 + },
  91 + {
  92 + key: 4,
  93 + value: '星期三'
  94 + },
  95 + {
  96 + key: 5,
  97 + value: '星期四'
  98 + },
  99 + {
  100 + key: 6,
  101 + value: '星期五'
  102 + },
  103 + {
  104 + key: 7,
  105 + value: '星期六'
  106 + },
  107 + {
  108 + key: 1,
  109 + value: '星期日'
  110 + }
  111 + ],
  112 + checkNum: this.$options.propsData.check
  113 + }
  114 + },
  115 + name: 'crontab-week',
  116 + props: ['check', 'cron'],
  117 + methods: {
  118 + // 单选按钮值变化时
  119 + radioChange() {
  120 + if (this.radioValue !== 2 && this.cron.day !== '?') {
  121 + this.$emit('update', 'day', '?', 'week');
  122 + }
  123 + switch (this.radioValue) {
  124 + case 1:
  125 + this.$emit('update', 'week', '*');
  126 + break;
  127 + case 2:
  128 + this.$emit('update', 'week', '?');
  129 + break;
  130 + case 3:
  131 + this.$emit('update', 'week', this.cycleTotal);
  132 + break;
  133 + case 4:
  134 + this.$emit('update', 'week', this.averageTotal);
  135 + break;
  136 + case 5:
  137 + this.$emit('update', 'week', this.weekdayCheck + 'L');
  138 + break;
  139 + case 6:
  140 + this.$emit('update', 'week', this.checkboxString);
  141 + break;
  142 + }
  143 + },
  144 +
  145 + // 周期两个值变化时
  146 + cycleChange() {
  147 + if (this.radioValue == '3') {
  148 + this.$emit('update', 'week', this.cycleTotal);
  149 + }
  150 + },
  151 + // 平均两个值变化时
  152 + averageChange() {
  153 + if (this.radioValue == '4') {
  154 + this.$emit('update', 'week', this.averageTotal);
  155 + }
  156 + },
  157 + // 最近工作日值变化时
  158 + weekdayChange() {
  159 + if (this.radioValue == '5') {
  160 + this.$emit('update', 'week', this.weekday + 'L');
  161 + }
  162 + },
  163 + // checkbox值变化时
  164 + checkboxChange() {
  165 + if (this.radioValue == '6') {
  166 + this.$emit('update', 'week', this.checkboxString);
  167 + }
  168 + },
  169 + },
  170 + watch: {
  171 + 'radioValue': 'radioChange',
  172 + 'cycleTotal': 'cycleChange',
  173 + 'averageTotal': 'averageChange',
  174 + 'weekdayCheck': 'weekdayChange',
  175 + 'checkboxString': 'checkboxChange',
  176 + },
  177 + computed: {
  178 + // 计算两个周期值
  179 + cycleTotal: function () {
  180 + this.cycle01 = this.checkNum(this.cycle01, 1, 7)
  181 + this.cycle02 = this.checkNum(this.cycle02, 1, 7)
  182 + return this.cycle01 + '-' + this.cycle02;
  183 + },
  184 + // 计算平均用到的值
  185 + averageTotal: function () {
  186 + this.average01 = this.checkNum(this.average01, 1, 4)
  187 + this.average02 = this.checkNum(this.average02, 1, 7)
  188 + return this.average02 + '#' + this.average01;
  189 + },
  190 + // 最近的工作日(格式)
  191 + weekdayCheck: function () {
  192 + this.weekday = this.checkNum(this.weekday, 1, 7)
  193 + return this.weekday;
  194 + },
  195 + // 计算勾选的checkbox值合集
  196 + checkboxString: function () {
  197 + let str = this.checkboxList.join();
  198 + return str == '' ? '*' : str;
  199 + }
  200 + }
  201 +}
  202 +</script>
... ...
yudao-ui-admin/src/components/Crontab/year.vue 0 → 100644
  1 +<template>
  2 + <el-form size="small">
  3 + <el-form-item>
  4 + <el-radio :label="1" v-model='radioValue'>
  5 + 不填,允许的通配符[, - * /]
  6 + </el-radio>
  7 + </el-form-item>
  8 +
  9 + <el-form-item>
  10 + <el-radio :label="2" v-model='radioValue'>
  11 + 每年
  12 + </el-radio>
  13 + </el-form-item>
  14 +
  15 + <el-form-item>
  16 + <el-radio :label="3" v-model='radioValue'>
  17 + 周期从
  18 + <el-input-number v-model='cycle01' :min='fullYear' :max="2098" /> -
  19 + <el-input-number v-model='cycle02' :min="cycle01 ? cycle01 + 1 : fullYear + 1" :max="2099" />
  20 + </el-radio>
  21 + </el-form-item>
  22 +
  23 + <el-form-item>
  24 + <el-radio :label="4" v-model='radioValue'>
  25 + 从
  26 + <el-input-number v-model='average01' :min='fullYear' :max="2098"/> 年开始,每
  27 + <el-input-number v-model='average02' :min="1" :max="2099 - average01 || fullYear" /> 年执行一次
  28 + </el-radio>
  29 +
  30 + </el-form-item>
  31 +
  32 + <el-form-item>
  33 + <el-radio :label="5" v-model='radioValue'>
  34 + 指定
  35 + <el-select clearable v-model="checkboxList" placeholder="可多选" multiple>
  36 + <el-option v-for="item in 9" :key="item" :value="item - 1 + fullYear" :label="item -1 + fullYear" />
  37 + </el-select>
  38 + </el-radio>
  39 + </el-form-item>
  40 + </el-form>
  41 +</template>
  42 +
  43 +<script>
  44 +export default {
  45 + data() {
  46 + return {
  47 + fullYear: 0,
  48 + radioValue: 1,
  49 + cycle01: 0,
  50 + cycle02: 0,
  51 + average01: 0,
  52 + average02: 1,
  53 + checkboxList: [],
  54 + checkNum: this.$options.propsData.check
  55 + }
  56 + },
  57 + name: 'crontab-year',
  58 + props: ['check', 'month', 'cron'],
  59 + methods: {
  60 + // 单选按钮值变化时
  61 + radioChange() {
  62 + switch (this.radioValue) {
  63 + case 1:
  64 + this.$emit('update', 'year', '');
  65 + break;
  66 + case 2:
  67 + this.$emit('update', 'year', '*');
  68 + break;
  69 + case 3:
  70 + this.$emit('update', 'year', this.cycleTotal);
  71 + break;
  72 + case 4:
  73 + this.$emit('update', 'year', this.averageTotal);
  74 + break;
  75 + case 5:
  76 + this.$emit('update', 'year', this.checkboxString);
  77 + break;
  78 + }
  79 + },
  80 + // 周期两个值变化时
  81 + cycleChange() {
  82 + if (this.radioValue == '3') {
  83 + this.$emit('update', 'year', this.cycleTotal);
  84 + }
  85 + },
  86 + // 平均两个值变化时
  87 + averageChange() {
  88 + if (this.radioValue == '4') {
  89 + this.$emit('update', 'year', this.averageTotal);
  90 + }
  91 + },
  92 + // checkbox值变化时
  93 + checkboxChange() {
  94 + if (this.radioValue == '5') {
  95 + this.$emit('update', 'year', this.checkboxString);
  96 + }
  97 + }
  98 + },
  99 + watch: {
  100 + 'radioValue': 'radioChange',
  101 + 'cycleTotal': 'cycleChange',
  102 + 'averageTotal': 'averageChange',
  103 + 'checkboxString': 'checkboxChange'
  104 + },
  105 + computed: {
  106 + // 计算两个周期值
  107 + cycleTotal: function () {
  108 + const cycle01 = this.checkNum(this.cycle01, this.fullYear, 2098)
  109 + const cycle02 = this.checkNum(this.cycle02, cycle01 ? cycle01 + 1 : this.fullYear + 1, 2099)
  110 + return cycle01 + '-' + cycle02;
  111 + },
  112 + // 计算平均用到的值
  113 + averageTotal: function () {
  114 + const average01 = this.checkNum(this.average01, this.fullYear, 2098)
  115 + const average02 = this.checkNum(this.average02, 1, 2099 - average01 || this.fullYear)
  116 + return average01 + '/' + average02;
  117 + },
  118 + // 计算勾选的checkbox值合集
  119 + checkboxString: function () {
  120 + let str = this.checkboxList.join();
  121 + return str;
  122 + }
  123 + },
  124 + mounted: function () {
  125 + // 仅获取当前年份
  126 + this.fullYear = Number(new Date().getFullYear());
  127 + this.cycle01 = this.fullYear
  128 + this.average01 = this.fullYear
  129 + }
  130 +}
  131 +</script>
... ...
yudao-ui-admin/src/views/infra/job/index.vue
... ... @@ -90,7 +90,14 @@
90 90 <el-input v-model="form.handlerParam" placeholder="请输入处理器的参数" />
91 91 </el-form-item>
92 92 <el-form-item label="CRON 表达式" prop="cronExpression">
93   - <el-input v-model="form.cronExpression" placeholder="请输入CRON 表达式" />
  93 + <el-input v-model="form.cronExpression" placeholder="请输入CRON 表达式">
  94 + <template slot="append">
  95 + <el-button type="primary" @click="handleShowCron">
  96 + 生成表达式
  97 + <i class="el-icon-time el-icon--right"></i>
  98 + </el-button>
  99 + </template>
  100 + </el-input>
94 101 </el-form-item>
95 102 <el-form-item label="重试次数" prop="retryCount">
96 103 <el-input v-model="form.retryCount" placeholder="请输入重试次数。设置为 0 时,不进行重试" />
... ... @@ -108,7 +115,11 @@
108 115 </div>
109 116 </el-dialog>
110 117  
111   - <!-- 任务日志详细 -->
  118 + <el-dialog title="Cron表达式生成器" :visible.sync="openCron" >
  119 + <crontab @hide="openCron=false" @fill="crontabFill" :expression="expression"></crontab>
  120 + </el-dialog>
  121 +
  122 + <!-- 任务详细 -->
112 123 <el-dialog title="任务详细" :visible.sync="openView" width="700px" append-to-body>
113 124 <el-form ref="form" :model="form" label-width="200px" size="mini">
114 125 <el-row>
... ... @@ -132,15 +143,16 @@
132 143 <el-button @click="openView = false">关 闭</el-button>
133 144 </div>
134 145 </el-dialog>
135   -
136 146 </div>
137 147 </template>
138 148  
139 149 <script>
140 150 import { listJob, getJob, delJob, addJob, updateJob, exportJob, runJob, updateJobStatus, getJobNextTimes } from "@/api/infra/job";
141 151 import { InfraJobStatusEnum } from "@/utils/constants";
  152 +import Crontab from '@/components/Crontab'
142 153  
143 154 export default {
  155 + components: { Crontab },
144 156 name: "Job",
145 157 data() {
146 158 return {
... ... @@ -160,6 +172,10 @@ export default {
160 172 open: false,
161 173 // 是否显示详细弹出层
162 174 openView: false,
  175 + // 是否显示Cron表达式弹出层
  176 + openCron: false,
  177 + // 传入的表达式
  178 + expression: "",
163 179 // 状态字典
164 180 statusOptions: [],
165 181 // 查询参数
... ... @@ -252,6 +268,15 @@ export default {
252 268 this.nextTimes = response.data;
253 269 });
254 270 },
  271 + /** cron表达式按钮操作 */
  272 + handleShowCron() {
  273 + this.expression = this.form.cronExpression;
  274 + this.openCron = true;
  275 + },
  276 + /** 确定后回传值 */
  277 + crontabFill(value) {
  278 + this.form.cronExpression = value;
  279 + },
255 280 /** 任务日志列表查询 */
256 281 handleJobLog(row) {
257 282 if (row.id) {
... ...