ant-design-vue 开发的cron表达式组件

最近研究一个github上的一个比较火的项目jeecg-boot。6月份github java开源项目排名第二,欢迎star

由于本人现在所处的公司不是特别忙,业余时间比较多,回家老婆不让玩dota,天天让我带娃,所以自己找个与技术相关且比较感兴趣的项目来研究,并有幸成为部分源码提供者之一,当时收到的第一个任务就是将网上的vue-cron改写成ant-design-vue版。

  • vue-cron 这个组件使用式vue+elementui开写的(项目中使用vue+elementui可以参考这个),elementui和ant-design-vue在组件语法上还是有很大的差别的。

vue-cron这个组件同时采用了中英文展示,能够正向生成cron表达式,但不能逆向解析将cron表达式渲染到组件面上。

  • 言归正传,本次主要介绍cron表达组件过程中任务演进。

1.初次任务:参考vue-cron 写在线cron表达式生成组件demo,不考虑逻辑。

初次任务完成事例:视频演示demo

2.修改任务1-动态效果做出来,只显示全部中文,动态生成表达式

修改任务1完成任务事例:视频演示demo

3.修改任务2-将写的代码归纳到对应的components文件夹下

4.将封装的cron表达式组件命名JCron.vue, 在【系统监控】-【定时任务】中使用

成果展示:

ab414534c623d921da44cda7c51600d8561.jpg

6b9004ef2490502380fca4ad57e7afb4306.jpg

5.任务修改:在4的成果中,cron表达式,这个控件使用了cron ={label:'',value:{}},这样的一个对象来展示的,这样的一个结果,需要修改定时器表

ALTER TABLE sys_quartz_job ADD COLUMN cron_value VARCHAR(2000) DEFAULT NULL COMMENT 'cron的原始value'(需要废弃)

现在要求只使用一个字段,也就是原始字段cron_expression来表示

同时支持复制渲染:将他处获取的cron表达式,复制到cron表达式控件,在控件页面渲染显示。

修改内容:将

result: {
          second:{
            cronEvery:'',
            incrementStart:3,
            incrementIncrement:5,
            rangeStart:1,
            rangeEnd:0,
            specificSpecific:[],
          },
          minute:{
            cronEvery:'',
            incrementStart:3,
            incrementIncrement:5,
            rangeStart:1,
            rangeEnd:'0',
            specificSpecific:[],
          },
          hour:{
            cronEvery:'',
            incrementStart:3,
            incrementIncrement:5,
            rangeStart:'0',
            rangeEnd:'0',
            specificSpecific:[],
          },
          day:{
            cronEvery:'',
            incrementStart:1,
            incrementIncrement:'1',
            rangeStart:'',
            rangeEnd:'',
            specificSpecific:[],
            cronLastSpecificDomDay:1,
            cronDaysBeforeEomMinus:1,
            cronDaysNearestWeekday:1,
          },
          week:{
            cronEvery:'',
            incrementStart:1,
            incrementIncrement:1,
            specificSpecific:[],
            cronNthDayDay:1,
            cronNthDayNth:1,
          },
          month:{
            cronEvery:'',
            incrementStart:3,
            incrementIncrement:5,
            rangeStart:1,
            rangeEnd:1,
            specificSpecific:[],
          },
          year:{
            cronEvery:'',
            incrementStart:2017,
            incrementIncrement:1,
            rangeStart:2019,
            rangeEnd: 2019,
            specificSpecific:[],
          }

这个result保存到数据库的对象,删除,使用 最终结果1,50 * * 1,13,25 1-6 ? * 来解析成 result 对象,然后渲染到组件中

逆向解析代码如下:

secondsReverseExp(seconds) {
        let val =  seconds.split(" ")[0];
        //alert(val);
        let second = {
          cronEvery:'',
          incrementStart:3,
          incrementIncrement:5,
          rangeStart:1,
          rangeEnd:0,
          specificSpecific:[]
        };
        switch (true) {
          case val.includes('*'):
            second.cronEvery = '1';
            break;
          case val.includes('/'):
            second.cronEvery = '2';
            second.incrementStart = val.split('/')[0];
            second.incrementIncrement = val.split('/')[1];
            break;
          case val.includes(','):
            second.cronEvery = '3';
            second.specificSpecific = val.split(',').map(Number).sort();
            break;
          case val.includes('-'):
            second.cronEvery = '4';
            second.rangeStart = val.split('-')[0];
            second.rangeEnd = val.split('-')[1];
            break;
          default:
            second.cronEvery = '1';
        }
        this.result.second = second;
      },
      minutesReverseExp(minutes) {
        let val =  minutes.split(" ")[1];
        let minute = {
          cronEvery:'',
          incrementStart:3,
          incrementIncrement:5,
          rangeStart:1,
          rangeEnd:0,
          specificSpecific:[],
        }
        switch (true) {
          case val.includes('*'):
            minute.cronEvery = '1';
            break;
          case val.includes('/'):
            minute.cronEvery = '2';
            minute.incrementStart = val.split('/')[0];
            minute.incrementIncrement = val.split('/')[1];
            break;
          case val.includes(','):
            minute.cronEvery = '3';
            minute.specificSpecific = val.split(',').map(Number).sort();
            break;
          case val.includes('-'):
            minute.cronEvery = '4';
            minute.rangeStart = val.split('-')[0];
            minute.rangeEnd = val.split('-')[1];
            break;
          default:
            minute.cronEvery = '1';
        }
        this.result.minute = minute;
      },
      hoursReverseExp(hours) {
        let val =  hours.split(" ")[2];
        let hour ={
            cronEvery:'',
            incrementStart:3,
            incrementIncrement:5,
            rangeStart:1,
            rangeEnd:'0',
            specificSpecific:[],
          };
        switch (true) {
          case val.includes('*'):
            hour.cronEvery = '1';
            break;
          case val.includes('/'):
            hour.cronEvery = '2';
            hour.incrementStart = val.split('/')[0];
            hour.incrementIncrement = val.split('/')[1];
            break;
          case val.includes(','):
            hour.cronEvery = '3';
            hour.specificSpecific = val.split(',').map(Number).sort();
            break;
          case val.includes('-'):
            hour.cronEvery = '4';
            hour.rangeStart = val.split('-')[0];
            hour.rangeEnd = val.split('-')[1];
            break;
          default:
            hour.cronEvery = '1';
          }
        this.result.hour = hour;
      },
      daysReverseExp(cron) {
        let days =  cron.split(" ")[3];
        let weeks =  cron.split(" ")[5];
        let day ={
          cronEvery:'',
          incrementStart:1,
          incrementIncrement:1,
          rangeStart:1,
          rangeEnd:1,
          specificSpecific:[],
          cronLastSpecificDomDay:1,
          cronDaysBeforeEomMinus:1,
          cronDaysNearestWeekday:1,
        };
        let week = {
            cronEvery:'',
            incrementStart:1,
            incrementIncrement:1,
            specificSpecific:[],
            cronNthDayDay:1,
            cronNthDayNth:'1',
        };
        if (!days.includes('?')) {
          switch (true) {
            case days.includes('*'):
              day.cronEvery = '1';
              break;
            case days.includes('?'):
              // 2、4、11
              break;
            case days.includes('/'):
              day.cronEvery = '3';
              day.incrementStart = days.split('/')[0];
              day.incrementIncrement = days.split('/')[1];
              break;
            case days.includes(','):
              day.cronEvery = '5';
              day.specificSpecific = days.split(',').map(Number).sort();
              // day.specificSpecific.forEach(function (value, index) {
              //   day.specificSpecific[index] = value -1;
              // });
              break;
            case days.includes('LW'):
              day.cronEvery = '7';
              break;
            case days.includes('L-'):
              day.cronEvery = '9';
              day.cronDaysBeforeEomMinus = days.split('L-')[1];
              break;
            case days.includes('L'):

              //alert(days);
              if(days.len == 1){
                day.cronEvery = '6';
                day.cronLastSpecificDomDay = '1';
              }
              else
              {
                day.cronEvery = '8';
                day.cronLastSpecificDomDay = Number(days.split('L')[0]);
              }
              break;
            case days.includes('W'):
              day.cronEvery = '10';
              day.cronDaysNearestWeekday = days.split('W')[0];
              break;
            default:
              day.cronEvery = '1';
          }
        }else {
          switch (true){
            case weeks.includes('/'):
              day.cronEvery = '2';
              week.incrementStart = weeks.split("/")[0];
              week.incrementIncrement = weeks.split("/")[1];
              break;
            case weeks.includes(','):
              day.cronEvery = '4';
              week.specificSpecific = weeks.split(',').map(Number).sort();
              break;
            case '#':
              day.cronEvery = '11';
              week.cronNthDayDay = weeks.split("#")[0];
              week.cronNthDayNth = weeks.split("#")[1];
              break;
            default:
              day.cronEvery = '1';
              week.cronEvery = '1';
          }
        }
        this.result.day = day;
        this.result.week = week;
      },
      monthsReverseExp(cron) {
        let months = cron.split(" ")[4];
        let month = {
          cronEvery:'',
            incrementStart:3,
            incrementIncrement:5,
            rangeStart:1,
            rangeEnd:1,
            specificSpecific:[],
        };
        switch (true){
          case months.includes('*'):
            month.cronEvery = '1';
            break;
          case months.includes('/'):
            month.cronEvery = '2';
            month.incrementStart = months.split('/')[0];
            month.incrementIncrement = months.split('/')[1];
            break;
          case months.includes(','):
            month.cronEvery = '3';
            month.specificSpecific = months.split(',').map(Number).sort();
            break;
          case months.includes('-'):
            month.cronEvery = '4';
            month.rangeStart = months.split('-')[0];
            month.rangeEnd = months.split('-')[1];
            break;
          default:
            month.cronEvery = '1';
        }
        this.result.month = month;
      },
      yearReverseExp(cron) {
        let years = cron.split(" ")[6];
        let year = {
          cronEvery:'',
          incrementStart:3,
          incrementIncrement:5,
          rangeStart:2019,
          rangeEnd:2019,
          specificSpecific:[],
        };
        switch (true){
          case years.includes('*'):
            year.cronEvery = '1';
            break;
          case years.includes('/'):
            year.cronEvery = '2';
            year.incrementStart = years.split('/')[0];
            year.incrementIncrement = years.split('/')[1];
            break;
          case years.includes(','):
            year.cronEvery = '3';
            year.specificSpecific = years.split(',').map(Number).sort();
            break;
          case years.includes('-'):
            year.cronEvery = '4';
            year.rangeStart = years.split('-')[0];
            year.rangeEnd = years.split('-')[1];
            break;
          default:
            year.cronEvery = '1';
        }
        this.result.year = year;
      }

遇到的问题:对象深度复制

次数方案方案内容结果结论
1Object.assignvar param = Object.assign(sqp, this.queryParam, this.isorter ,this.filters);失败Object.assign适合浅复制,对于复杂的嵌套对象失败
2定义递归方法可以,递归条件typeof e==='object',递归成功能成功深度复制,但我要的对象要部分属性是必须有默认值,所以这个方案不成功
3lodash.clonedeepclone(this.defaultValue)成功但是基于给开源项目提供代码,少引用点插件,项目保证小点,插件最好有开源组织者来确认
4JSON实现JSON.stringify(this.defaultValue)成功简单粗暴。最终采纳次方案

最终代码如下:

1.JCronModal.vue

这个文件经过三次重构:

这个vue文件是生成cron表达式的核心文件,源码如下

<template>
  <a-modal
          title="corn表达式"
          :width="modalWidth"
          :visible="visible"
          :confirmLoading="confirmLoading"
          @ok="handleSubmit"
          @cancel="close"
          cancelText="关闭">
    <div class="card-container">
      <a-tabs type="card">
        <a-tab-pane key="1" type="card">
          <span slot="tab"><a-icon type="schedule" /> 秒</span>
          <a-radio-group v-model="result.second.cronEvery">
            <a-row>
              <a-radio value="1">每一秒钟</a-radio>
            </a-row>
            <a-row>
              <a-radio value="2">每隔
                <a-input-number size="small" v-model="result.second.incrementIncrement" :min="1" :max="60"></a-input-number>
                秒执行 从
                <a-input-number size="small" v-model="result.second.incrementStart" :min="0" :max="59"></a-input-number>
                秒开始
              </a-radio>
            </a-row>
            <a-row>
              <a-radio value="3">具体秒数(可多选)</a-radio>
              <a-select style="width:354px;" size="small" mode="multiple" v-model="result.second.specificSpecific">
                <a-select-option v-for="(val,index) in 60" :key="index" :value="index">{{ index }}</a-select-option>
              </a-select>
            </a-row>
            <a-row>
              <a-radio value="4">周期从
                <a-input-number size="small" v-model="result.second.rangeStart" :min="1" :max="60"></a-input-number>
                到
                <a-input-number size="small" v-model="result.second.rangeEnd" :min="0" :max="59"></a-input-number>
                秒
              </a-radio>
            </a-row>
          </a-radio-group>
        </a-tab-pane>
        <a-tab-pane key="2">
          <span slot="tab"><a-icon type="schedule" />分</span>
          <div class="tabBody">
            <a-radio-group v-model="result.minute.cronEvery">
              <a-row>
                <a-radio value="1">每一分钟</a-radio>
              </a-row>
              <a-row>
                <a-radio value="2">每隔
                  <a-input-number size="small" v-model="result.minute.incrementIncrement" :min="1" :max="60"></a-input-number>
                  分执行 从
                  <a-input-number size="small" v-model="result.minute.incrementStart" :min="0" :max="59"></a-input-number>
                  分开始
                </a-radio>
              </a-row>
              <a-row>
                <a-radio value="3">具体分钟数(可多选)</a-radio>
                <a-select style="width:340px;" size="small" mode="multiple" v-model="result.minute.specificSpecific">
                  <a-select-option v-for="(val,index) in Array(60)" :key="index" :value="index"> {{ index }}</a-select-option>
                </a-select>
              </a-row>
              <a-row>
                <a-radio value="4">周期从
                  <a-input-number size="small" v-model="result.minute.rangeStart" :min="1" :max="60"></a-input-number>
                  到
                  <a-input-number size="small" v-model="result.minute.rangeEnd" :min="0" :max="59"></a-input-number>
                  分
                </a-radio>
              </a-row>
            </a-radio-group>
          </div>
        </a-tab-pane>
        <a-tab-pane key="3">
          <span slot="tab"><a-icon type="schedule" /> 时</span>
          <div class="tabBody">
            <a-radio-group v-model="result.hour.cronEvery">
              <a-row>
                <a-radio value="1">每一小时</a-radio>
              </a-row>
              <a-row>
                <a-radio value="2">每隔
                  <a-input-number size="small" v-model="result.hour.incrementIncrement" :min="0" :max="23"></a-input-number>
                  小时执行 从
                  <a-input-number size="small" v-model="result.hour.incrementStart" :min="0" :max="23"></a-input-number>
                  小时开始
                </a-radio>
              </a-row>
              <a-row>
                <a-radio class="long" value="3">具体小时数(可多选)</a-radio>
                <a-select style="width:340px;" size="small" mode="multiple" v-model="result.hour.specificSpecific">
                  <a-select-option v-for="(val,index) in Array(24)" :key="index" >{{ index }}</a-select-option>
                </a-select>
              </a-row>
              <a-row>
                <a-radio value="4">周期从
                  <a-input-number size="small" v-model="result.hour.rangeStart" :min="0" :max="23"></a-input-number>
                  到
                  <a-input-number size="small" v-model="result.hour.rangeEnd" :min="0" :max="23"></a-input-number>
                  小时
                </a-radio>
              </a-row>
            </a-radio-group>
          </div>
        </a-tab-pane>
        <a-tab-pane key="4">
          <span slot="tab"><a-icon type="schedule" />  天</span>
          <div class="tabBody">
            <a-radio-group v-model="result.day.cronEvery">
              <a-row>
                <a-radio value="1">每一天</a-radio>
              </a-row>
              <a-row>
                <a-radio value="2">每隔
                  <a-input-number size="small" v-model="result.week.incrementIncrement" :min="1" :max="7"></a-input-number>
                  周执行 从
                  <a-select size="small" v-model="result.week.incrementStart">
                    <a-select-option v-for="(val,index) in Array(7)" :key="index" :value="index+1">{{ weekDays[index] }}</a-select-option>
                  </a-select>
                  开始
                </a-radio>
              </a-row>
              <a-row>
                <a-radio value="3">每隔
                  <a-input-number size="small" v-model="result.day.incrementIncrement" :min="1" :max="31"></a-input-number>
                  天执行 从
                  <a-input-number size="small" v-model="result.day.incrementStart" :min="1" :max="31"></a-input-number>
                  天开始
                </a-radio>
              </a-row>
              <a-row>
                <a-radio class="long" value="4">具体星期几(可多选)</a-radio>
                <a-select style="width:340px;" size="small" mode="multiple" v-model="result.week.specificSpecific">
                  <a-select-option v-for="(val,index) in Array(7)" :key="index" :value="index+1">{{ weekDays[index] }}</a-select-option>
                </a-select>
              </a-row>
              <a-row>
                <a-radio class="long" value="5">具体天数(可多选)</a-radio>
                <a-select style="width:354px;" size="small" mode="multiple" v-model="result.day.specificSpecific">
                  <a-select-option v-for="(val,index) in Array(31)" :key="index" :value="index+1">{{ index+1 }}</a-select-option>
                </a-select>
              </a-row>
              <a-row>
                <a-radio value="6">在这个月的最后一天</a-radio>
              </a-row>
              <a-row>
                <a-radio value="7">在这个月的最后一个工作日</a-radio>
              </a-row>
              <a-row>
                <a-radio value="8">在这个月的最后一个
                  <a-select size="small" v-model="result.day.cronLastSpecificDomDay">
                    <a-select-option v-for="(val,index) in Array(7)" :key="index" :value="index+1">{{ weekDays[index] }}</a-select-option>
                  </a-select>
                </a-radio>
              </a-row>
              <a-row>
                <a-radio value="9">
                  在本月底前
                  <a-input-number size="small" v-model="result.day.cronDaysBeforeEomMinus" :min="1" :max="31"></a-input-number>
                  天
                </a-radio>
              </a-row>
              <a-row>
                <a-radio value="10">最近的工作日(周一至周五)至本月
                  <a-input-number size="small" v-model="result.day.cronDaysNearestWeekday" :min="1" :max="31"></a-input-number>
                  日
                </a-radio>
              </a-row>
              <a-row>
                <a-radio value="11">在这个月的第
                  <a-input-number size="small" v-model="result.week.cronNthDayNth" :min="1" :max="5"></a-input-number>
                  个
                  <a-select size="small" v-model="result.week.cronNthDayDay">
                    <a-select-option v-for="(val,index) in Array(7)" :key="index" :value="index+1">{{ weekDays[index] }}</a-select-option>
                  </a-select>

                </a-radio>
              </a-row>
            </a-radio-group>
          </div>
        </a-tab-pane>
        <a-tab-pane key="5">
          <span slot="tab"><a-icon type="schedule" /> 月</span>
          <div class="tabBody">
            <a-radio-group v-model="result.month.cronEvery">
              <a-row>
                <a-radio value="1">每一月</a-radio>
              </a-row>
              <a-row>
                <a-radio value="2">每隔
                  <a-input-number size="small" v-model="result.month.incrementIncrement" :min="0" :max="12"></a-input-number>
                  月执行 从
                  <a-input-number size="small" v-model="result.month.incrementStart" :min="0" :max="12"></a-input-number>
                  月开始
                </a-radio>
              </a-row>
              <a-row>
                <a-radio class="long" value="3">具体月数(可多选)</a-radio>
                <a-select style="width:354px;" size="small" filterable mode="multiple" v-model="result.month.specificSpecific">
                  <a-select-option v-for="(val,index) in Array(12)" :key="index" :value="index+1">{{ index+1 }}</a-select-option>
                </a-select>
              </a-row>
              <a-row>
                <a-radio value="4">从
                  <a-input-number size="small" v-model="result.month.rangeStart" :min="1" :max="12"></a-input-number>
                  到
                  <a-input-number size="small" v-model="result.month.rangeEnd" :min="1" :max="12"></a-input-number>
                  月之间的每个月
                </a-radio>
              </a-row>
            </a-radio-group>
          </div>
        </a-tab-pane>
        <a-tab-pane key="6">
          <span slot="tab"><a-icon type="schedule" /> 年</span>
          <div class="tabBody">
            <a-radio-group v-model="result.year.cronEvery">
              <a-row>
                <a-radio value="1">每一年</a-radio>
              </a-row>
              <a-row>
                <a-radio value="2">每隔
                  <a-input-number size="small" v-model="result.year.incrementIncrement" :min="1" :max="99"></a-input-number>
                  年执行 从
                  <a-input-number size="small" v-model="result.year.incrementStart" :min="2019" :max="2119"></a-input-number>
                  年开始
                </a-radio>
              </a-row>
              <a-row>
                <a-radio class="long" value="3">具体年份(可多选)</a-radio>
                <a-select style="width:354px;" size="small" filterable mode="multiple" v-model="result.year.specificSpecific">
                  <a-select-option v-for="(val,index) in Array(100)" :key="index" :value="2019+index">{{ 2019+index }}</a-select-option>
                </a-select>
              </a-row>
              <a-row>
                <a-radio value="4">从
                  <a-input-number size="small" v-model="result.year.rangeStart" :min="2019" :max="2119"></a-input-number>
                  到
                  <a-input-number size="small" v-model="result.year.rangeEnd" :min="2019" :max="2119"></a-input-number>
                  年之间的每一年
                </a-radio>
              </a-row>
            </a-radio-group>
          </div>
        </a-tab-pane>
      </a-tabs>
      <div class="bottom">
        <span class="value">{{this.cron }}</span>
      </div>
    </div>
  </a-modal>
</template>
<script>
  export default {
    name:'VueCron',
    props:['data'],
    data(){
      return {
        visible: false,
        confirmLoading:false,
        size:'large',
        weekDays:['天','一','二','三','四','五','六'].map(val=>'星期'+val),
        result: {
          second:{},
          minute:{},
          hour:{},
          day:{},
          week:{},
          month:{},
          year:{}
        },
        defaultValue: {
          second:{
            cronEvery:'',
            incrementStart:3,
            incrementIncrement:5,
            rangeStart:1,
            rangeEnd:0,
            specificSpecific:[],
          },
          minute:{
            cronEvery:'',
            incrementStart:3,
            incrementIncrement:5,
            rangeStart:1,
            rangeEnd:'0',
            specificSpecific:[],
          },
          hour:{
            cronEvery:'',
            incrementStart:3,
            incrementIncrement:5,
            rangeStart:'0',
            rangeEnd:'0',
            specificSpecific:[],
          },
          day:{
            cronEvery:'',
            incrementStart:1,
            incrementIncrement:'1',
            rangeStart:'',
            rangeEnd:'',
            specificSpecific:[],
            cronLastSpecificDomDay:1,
            cronDaysBeforeEomMinus:1,
            cronDaysNearestWeekday:1,
          },
          week:{
            cronEvery:'',
            incrementStart:1,
            incrementIncrement:1,
            specificSpecific:[],
            cronNthDayDay:1,
            cronNthDayNth:1,
          },
          month:{
            cronEvery:'',
            incrementStart:3,
            incrementIncrement:5,
            rangeStart:1,
            rangeEnd:1,
            specificSpecific:[],
          },
          year:{
            cronEvery:'',
            incrementStart:2017,
            incrementIncrement:1,
            rangeStart:2019,
            rangeEnd: 2019,
            specificSpecific:[],
          },
          label:''
        }
      }
    },
    computed: {
      modalWidth(){
        return 608;
      },
      secondsText() {
        let seconds = '';
        let cronEvery=this.result.second.cronEvery||'';
        switch (cronEvery.toString()){
          case '1':
            seconds = '*';
            break;
          case '2':
            seconds = this.result.second.incrementStart+'/'+this.result.second.incrementIncrement;
            break;
          case '3':
            this.result.second.specificSpecific.map(val=> {seconds += val+','});
            seconds = seconds.slice(0, -1);
            break;
          case '4':
            seconds = this.result.second.rangeStart+'-'+this.result.second.rangeEnd;
            break;
        }
        return seconds;
      },
      minutesText() {
        let minutes = '';
        let cronEvery=this.result.minute.cronEvery||'';
        switch (cronEvery.toString()){
          case '1':
            minutes = '*';
            break;
          case '2':
            minutes = this.result.minute.incrementStart+'/'+this.result.minute.incrementIncrement;
            break;
          case '3':
            this.result.minute.specificSpecific.map(val=> {
              minutes += val+','
            });
            minutes = minutes.slice(0, -1);
            break;
          case '4':
            minutes = this.result.minute.rangeStart+'-'+this.result.minute.rangeEnd;
            break;
        }
        return minutes;
      },
      hoursText() {
        let hours = '';
        let cronEvery=this.result.hour.cronEvery||'';
        switch (cronEvery.toString()){
          case '1':
            hours = '*';
            break;
          case '2':
            hours = this.result.hour.incrementStart+'/'+this.result.hour.incrementIncrement;
            break;
          case '3':
            this.result.hour.specificSpecific.map(val=> {
              hours += val+','
            });
            hours = hours.slice(0, -1);
            break;
          case '4':
            hours = this.result.hour.rangeStart+'-'+this.result.hour.rangeEnd;
            break;
        }
        return hours;
      },
      daysText() {
        let days='';
        let cronEvery=this.result.day.cronEvery||'';
        switch (cronEvery.toString()){
          case '1':
            break;
          case '2':
          case '4':
          case '11':
            days = '?';
            break;
          case '3':
            days = this.result.day.incrementStart+'/'+this.result.day.incrementIncrement;
            break;
          case '5':
            this.result.day.specificSpecific.map(val=> {
              days += val+','
            });
            days = days.slice(0, -1);
            break;
          case '6':
            days = "L";
            break;
          case '7':
            days = "LW";
            break;
          case '8':
            days = this.result.day.cronLastSpecificDomDay + 'L';
            break;
          case '9':
            days = 'L-' + this.result.day.cronDaysBeforeEomMinus;
            break;
          case '10':
            days = this.result.day.cronDaysNearestWeekday+"W";
            break
        }
        return days;
      },
      weeksText() {
        let weeks = '';
        let cronEvery=this.result.day.cronEvery||'';
        switch (cronEvery.toString()){
          case '1':
          case '3':
          case '5':
            weeks = '?';
            break;
          case '2':
            weeks = this.result.week.incrementStart+'/'+this.result.week.incrementIncrement;
            break;
          case '4':
            this.result.week.specificSpecific.map(val=> {
              weeks += val+','
            });
            weeks = weeks.slice(0, -1);
            break;
          case '6':
          case '7':
          case '8':
          case '9':
          case '10':
            weeks = "?";
            break;
          case '11':
            weeks = this.result.week.cronNthDayDay+"#"+this.result.week.cronNthDayNth;
            break;
        }
        return weeks;
      },
      monthsText() {
        let months = '';
        let cronEvery=this.result.month.cronEvery||'';
        switch (cronEvery.toString()){
          case '1':
            months = '*';
            break;
          case '2':
            months = this.result.month.incrementStart+'/'+this.result.month.incrementIncrement;
            break;
          case '3':
            this.result.month.specificSpecific.map(val=> {
              months += val+','
            });
            months = months.slice(0, -1);
            break;
          case '4':
            months = this.result.month.rangeStart+'-'+this.result.month.rangeEnd;
            break;
        }
        return months;
      },
      yearsText() {
        let years = '';
        let cronEvery=this.result.year.cronEvery||'';
        switch (cronEvery.toString()){
          case '1':
            years = '*';
            break;
          case '2':
            years = this.result.year.incrementStart+'/'+this.result.year.incrementIncrement;
            break;
          case '3':
            this.result.year.specificSpecific.map(val=> {
              years += val+','
            });
            years = years.slice(0, -1);
            break;
          case '4':
            years = this.result.year.rangeStart+'-'+this.result.year.rangeEnd;
            break;
        }
        return years;
      },
      cron(){
        return `${this.secondsText||'*'} ${this.minutesText||'*'} ${this.hoursText||'*'} ${this.daysText||'*'} ${this.monthsText||'*'} ${this.weeksText||'?'} ${this.yearsText||'*'}`
      },
    },
    watch:{
      visible:{
        handler() {
          // if(this.data){
          //   //this. result = Object.keys(this.data.value).length>0?this.deepCopy(this.data.value):this.deepCopy(this.defaultValue);
          //   //this.result = Object.keys(this.data.value).length>0?clone(this.data.value):clone(this.defaultValue);
          //   //this.result = Object.keys(this.data.value).length>0?clone(JSON.parse(this.data.value)):clone(this.defaultValue);
          //   this.result = Object.keys(this.data.value).length>0?JSON.parse(this.data.value):JSON.parse(JSON.stringify(this.defaultValue));
          // }else{
          //   //this.result = this.deepCopy(this.defaultValue);
          //   //this.result = clone(this.defaultValue);
          //   this.result = JSON.parse(JSON.stringify(this.defaultValue));
          // }
          let label = this.data;
          if(label){
            this.secondsReverseExp(label)
            this.minutesReverseExp(label);
            this.hoursReverseExp(label);
            this.daysReverseExp(label);
            this.daysReverseExp(label);
            this.monthsReverseExp(label);
            this.yearReverseExp(label);
            JSON.parse(JSON.stringify(label));
          }else {
            this.result = JSON.parse(JSON.stringify(this.defaultValue));
          }
        }
      }
    },
    methods: {
      show(){
        this.visible = true;
        // console.log('secondsReverseExp',this.secondsReverseExp(this.data));
        // console.log('minutesReverseExp',this.minutesReverseExp(this.data));
        // console.log('hoursReverseExp',this.hoursReverseExp(this.data));
        // console.log('daysReverseExp',this.daysReverseExp(this.data));
        // console.log('monthsReverseExp',this.monthsReverseExp(this.data));
        // console.log('yearReverseExp',this.yearReverseExp(this.data));

      },
      handleSubmit(){
        this.$emit('ok',this.cron);
        this.close();
        this.visible = false;
      },
      close(){
        this.visible = false;
      },
      secondsReverseExp(seconds) {
        let val =  seconds.split(" ")[0];
        //alert(val);
        let second = {
          cronEvery:'',
          incrementStart:3,
          incrementIncrement:5,
          rangeStart:1,
          rangeEnd:0,
          specificSpecific:[]
        };
        switch (true) {
          case val.includes('*'):
            second.cronEvery = '1';
            break;
          case val.includes('/'):
            second.cronEvery = '2';
            second.incrementStart = val.split('/')[0];
            second.incrementIncrement = val.split('/')[1];
            break;
          case val.includes(','):
            second.cronEvery = '3';
            second.specificSpecific = val.split(',').map(Number).sort();
            break;
          case val.includes('-'):
            second.cronEvery = '4';
            second.rangeStart = val.split('-')[0];
            second.rangeEnd = val.split('-')[1];
            break;
          default:
            second.cronEvery = '1';
        }
        this.result.second = second;
      },
      minutesReverseExp(minutes) {
        let val =  minutes.split(" ")[1];
        let minute = {
          cronEvery:'',
          incrementStart:3,
          incrementIncrement:5,
          rangeStart:1,
          rangeEnd:0,
          specificSpecific:[],
        }
        switch (true) {
          case val.includes('*'):
            minute.cronEvery = '1';
            break;
          case val.includes('/'):
            minute.cronEvery = '2';
            minute.incrementStart = val.split('/')[0];
            minute.incrementIncrement = val.split('/')[1];
            break;
          case val.includes(','):
            minute.cronEvery = '3';
            minute.specificSpecific = val.split(',').map(Number).sort();
            break;
          case val.includes('-'):
            minute.cronEvery = '4';
            minute.rangeStart = val.split('-')[0];
            minute.rangeEnd = val.split('-')[1];
            break;
          default:
            minute.cronEvery = '1';
        }
        this.result.minute = minute;
      },
      hoursReverseExp(hours) {
        let val =  hours.split(" ")[2];
        let hour ={
            cronEvery:'',
            incrementStart:3,
            incrementIncrement:5,
            rangeStart:1,
            rangeEnd:'0',
            specificSpecific:[],
          };
        switch (true) {
          case val.includes('*'):
            hour.cronEvery = '1';
            break;
          case val.includes('/'):
            hour.cronEvery = '2';
            hour.incrementStart = val.split('/')[0];
            hour.incrementIncrement = val.split('/')[1];
            break;
          case val.includes(','):
            hour.cronEvery = '3';
            hour.specificSpecific = val.split(',').map(Number).sort();
            break;
          case val.includes('-'):
            hour.cronEvery = '4';
            hour.rangeStart = val.split('-')[0];
            hour.rangeEnd = val.split('-')[1];
            break;
          default:
            hour.cronEvery = '1';
          }
        this.result.hour = hour;
      },
      daysReverseExp(cron) {
        let days =  cron.split(" ")[3];
        let weeks =  cron.split(" ")[5];
        let day ={
          cronEvery:'',
          incrementStart:1,
          incrementIncrement:1,
          rangeStart:1,
          rangeEnd:1,
          specificSpecific:[],
          cronLastSpecificDomDay:1,
          cronDaysBeforeEomMinus:1,
          cronDaysNearestWeekday:1,
        };
        let week = {
            cronEvery:'',
            incrementStart:1,
            incrementIncrement:1,
            specificSpecific:[],
            cronNthDayDay:1,
            cronNthDayNth:'1',
        };
        if (!days.includes('?')) {
          switch (true) {
            case days.includes('*'):
              day.cronEvery = '1';
              break;
            case days.includes('?'):
              // 2、4、11
              break;
            case days.includes('/'):
              day.cronEvery = '3';
              day.incrementStart = days.split('/')[0];
              day.incrementIncrement = days.split('/')[1];
              break;
            case days.includes(','):
              day.cronEvery = '5';
              day.specificSpecific = days.split(',').map(Number).sort();
              // day.specificSpecific.forEach(function (value, index) {
              //   day.specificSpecific[index] = value -1;
              // });
              break;
            case days.includes('LW'):
              day.cronEvery = '7';
              break;
            case days.includes('L-'):
              day.cronEvery = '9';
              day.cronDaysBeforeEomMinus = days.split('L-')[1];
              break;
            case days.includes('L'):

              //alert(days);
              if(days.len == 1){
                day.cronEvery = '6';
                day.cronLastSpecificDomDay = '1';
              }
              else
              {
                day.cronEvery = '8';
                day.cronLastSpecificDomDay = Number(days.split('L')[0]);
              }
              break;
            case days.includes('W'):
              day.cronEvery = '10';
              day.cronDaysNearestWeekday = days.split('W')[0];
              break;
            default:
              day.cronEvery = '1';
          }
        }else {
          switch (true){
            case weeks.includes('/'):
              day.cronEvery = '2';
              week.incrementStart = weeks.split("/")[0];
              week.incrementIncrement = weeks.split("/")[1];
              break;
            case weeks.includes(','):
              day.cronEvery = '4';
              week.specificSpecific = weeks.split(',').map(Number).sort();
              break;
            case '#':
              day.cronEvery = '11';
              week.cronNthDayDay = weeks.split("#")[0];
              week.cronNthDayNth = weeks.split("#")[1];
              break;
            default:
              day.cronEvery = '1';
              week.cronEvery = '1';
          }
        }
        this.result.day = day;
        this.result.week = week;
      },
      monthsReverseExp(cron) {
        let months = cron.split(" ")[4];
        let month = {
          cronEvery:'',
            incrementStart:3,
            incrementIncrement:5,
            rangeStart:1,
            rangeEnd:1,
            specificSpecific:[],
        };
        switch (true){
          case months.includes('*'):
            month.cronEvery = '1';
            break;
          case months.includes('/'):
            month.cronEvery = '2';
            month.incrementStart = months.split('/')[0];
            month.incrementIncrement = months.split('/')[1];
            break;
          case months.includes(','):
            month.cronEvery = '3';
            month.specificSpecific = months.split(',').map(Number).sort();
            break;
          case months.includes('-'):
            month.cronEvery = '4';
            month.rangeStart = months.split('-')[0];
            month.rangeEnd = months.split('-')[1];
            break;
          default:
            month.cronEvery = '1';
        }
        this.result.month = month;
      },
      yearReverseExp(cron) {
        let years = cron.split(" ")[6];
        let year = {
          cronEvery:'',
          incrementStart:3,
          incrementIncrement:5,
          rangeStart:2019,
          rangeEnd:2019,
          specificSpecific:[],
        };
        switch (true){
          case years.includes('*'):
            year.cronEvery = '1';
            break;
          case years.includes('/'):
            year.cronEvery = '2';
            year.incrementStart = years.split('/')[0];
            year.incrementIncrement = years.split('/')[1];
            break;
          case years.includes(','):
            year.cronEvery = '3';
            year.specificSpecific = years.split(',').map(Number).sort();
            break;
          case years.includes('-'):
            year.cronEvery = '4';
            year.rangeStart = years.split('-')[0];
            year.rangeEnd = years.split('-')[1];
            break;
          default:
            year.cronEvery = '1';
        }
        this.result.year = year;
      }
    }
  }
</script>

<style lang="scss">
  .card-container {
    background: #fff;
    overflow: hidden;
    padding: 12px;
    position: relative;
    width: 100%;
    .ant-tabs{
      border:1px solid #e6ebf5;
      padding: 0;
      .ant-tabs-bar {
        margin: 0;
        outline: none;
        border-bottom: none;
        .ant-tabs-nav-container{
          margin: 0;
          .ant-tabs-tab {
            padding: 0 24px!important;
            background-color: #f5f7fa!important;
            margin-right: 0px!important;
            border-radius: 0;
            line-height: 38px;
            border: 1px solid transparent!important;
            border-bottom: 1px solid #e6ebf5!important;
          }
          .ant-tabs-tab-active.ant-tabs-tab{
            color: #409eff;
            background-color: #fff!important;
            border-right:1px solid #e6ebf5!important;
            border-left:1px solid #e6ebf5!important;
            border-bottom:1px solid #fff!important;
            font-weight: normal;
            transition:none!important;
          }
        }
      }
      .ant-tabs-tabpane{
        padding: 15px;
        .ant-row{
          margin: 10px 0;
        }
        .ant-select,.ant-input-number{
          width: 100px;
        }
      }
    }
  }
</style>
<style lang="scss" scoped>
  .container-widthEn{
    width: 755px;
  }
  .container-widthCn{
    width: 608px;
  }
  .language{
    text-align: center;
    position: absolute;
    right: 13px;
    top: 13px;
    border: 1px solid transparent;
    height: 40px;
    line-height: 38px;
    font-size: 16px;
    color: #409eff;
    z-index: 1;
    background: #f5f7fa;
    outline: none;
    width: 47px;
    border-bottom: 1px solid #e6ebf5;
    border-radius: 0;
  }
  .card-container{
    .bottom{
      display: flex;
      justify-content: center;
      padding: 10px 0 0 0;
      .cronButton{
        margin: 0 10px;
        line-height: 40px;
      }
    }
  }
  .tabBody{
    .a-row{
      margin: 10px 0;
      .long{
        .a-select{
          width:354px;
        }
      }
      .a-input-number{
        width: 110px;
      }
    }
  }
</style>




 2.JCron.vue

引用1.JCronModal.vue

<template>
  <div class="components-input-demo-presuffix">
    <a-input @click="openModal" placeholder="corn表达式" v-model="cron" @change="handleOK">
      <a-icon slot="prefix" type="schedule" title="corn控件"/>
      <a-icon v-if="cron" slot="suffix" type="close-circle" @click="handleEmpty" title="清空"/>
    </a-input>
    <JCronModal ref="innerVueCron" :data="cron" @ok="handleOK"></JCronModal>
  </div>
</template>
<script>
  import JCronModal from "./modal/JCronModal";
  export default {
    name: 'JCron',
    components: {
      JCronModal
    },
    props: {
      value: {
        required: false,
        type: String,
        default:()=>{
          return '* * * * * ? *'
        }
      }
    },
    data(){
      return {
        cron: this.value,
      }
    },
    watch:{
      value(val){
        this.cron = val
      }
    },
    methods:{
      openModal(){
        this.$refs.innerVueCron.show();
      },
      handleOK(val){
        this.cron = val;
        this.$emit("change", this.cron);
        //this.$emit("change", Object.assign({},  this.cron));
      },
      handleEmpty(){
        this.handleOK('')
      }
    },
    model: {
      prop: 'value',
      event: 'change'
    }
  }
</script>
<style scoped>
  .components-input-demo-presuffix .anticon-close-circle {
    cursor: pointer;
    color: #ccc;
    transition: color 0.3s;
    font-size: 12px;
  }
  .components-input-demo-presuffix .anticon-close-circle:hover {
    color: #f5222d;
  }
  .components-input-demo-presuffix .anticon-close-circle:active {
    color: #666;
  }
</style>

3.QuartzJobModal.vue

引用JCron.vue(cron表达式插件)

<template>
  <a-modal
    :title="title"
    :width="800"
    :visible="visible"
    :confirmLoading="confirmLoading"
    @ok="handleOk"
    @cancel="handleCancel"
    okText="保存并安排任务"
    cancelText="关闭">

    <a-spin :spinning="confirmLoading">
      <a-form :form="form">

        <a-form-item
          :labelCol="labelCol"
          :wrapperCol="wrapperCol"
          label="任务类名"
          hasFeedback >
          <a-input placeholder="请输入任务类名" v-decorator="['jobClassName', {rules: [{ required: true, message: '请输入任务类名!' }]}]" />
        </a-form-item>
        <a-form-item
          :labelCol="labelCol"
          :wrapperCol="wrapperCol"
          label="cron表达式">
<!--                    <a-input placeholder="请输入cron表达式" v-decorator="['cronExpression', {'initialValue':'0/1 * * * * ?',rules: [{ required: true, message: '请输入任务类名!' }]}]" />-->
<!--                    <a target="_blank" href="http://cron.qqe2.com/">-->
<!--                      <a-icon type="share-alt" />-->
<!--                      在线cron表达式生成-->
<!--                    </a>-->
          <j-cron ref="innerVueCron" v-decorator="['cronExpression', {'initialValue':'0/1 * * * * ?',rules: [{ required: true, message: '请输入cron表达式!' }]}]"  @change="setCorn"></j-cron>
        </a-form-item>
        <a-form-item
          :labelCol="labelCol"
          :wrapperCol="wrapperCol"
          label="参数"
          hasFeedback >
          <a-input placeholder="请输入参数" v-decorator="['parameter', {}]" />
        </a-form-item>
        <a-form-item
          :labelCol="labelCol"
          :wrapperCol="wrapperCol"
          label="描述"
          hasFeedback >
          <a-input placeholder="请输入描述" v-decorator="['description', {}]" />
        </a-form-item>
        <a-form-item
          :labelCol="labelCol"
          :wrapperCol="wrapperCol"
          label="状态">
          <a-radio-group buttonStyle="solid" v-decorator="[ 'status', {'initialValue':0}]">
            <a-radio-button :value="0">正常</a-radio-button>
            <a-radio-button :value="-1">停止</a-radio-button>
          </a-radio-group>
        </a-form-item>

      </a-form>
    </a-spin>
  </a-modal>
</template>

<script>
  import { httpAction } from '@/api/manage'
  import JCron from "@/components/jeecg/JCron.vue";
  import pick from 'lodash.pick'
  import moment from "moment"

  export default {
    name: "QuartzJobModal",
    components: {
      JCron
    },
    data () {
      return {
        title:"操作",
        visible: false,
        model: {},
        labelCol: {
          xs: { span: 24 },
          sm: { span: 5 },
        },
        wrapperCol: {
          xs: { span: 24 },
          sm: { span: 16 },
        },
        cron: {
          label: '',
          value: ''
        },
        confirmLoading: false,
        form: this.$form.createForm(this),
        validatorRules: {
          cron: {
            rules: [{
              required: true, message: '请输入cron表达式!'
            }]
          }
        },
        url: {
          add: "/sys/quartzJob/add",
          edit: "/sys/quartzJob/edit",
        },
      }
    },
    created () {
    },
    methods: {
      add () {
        this.edit({});
      },
      edit (record) {
        this.model = Object.assign({},record);
        console.log(this.model)
        this.visible = true;
        this.$nextTick(() => {
          this.form.setFieldsValue(pick(this.model,'jobClassName','cronExpression','parameter','description','status'));
        });

      },
      close () {
        this.$emit('close');
        this.visible = false;
      },
      handleOk () {
        const that = this;
        // 触发表单验证
        this.form.validateFields((err, values) => {
          console.log('values',values)
          if (!err) {
            // if (typeof values.cronExpression == "undefined" || Object.keys(values.cronExpression).length==0 ) {
            //   this.$message.warning('请输入cron表达式!');
            //   return false;
            // }

            that.confirmLoading = true;
            let httpurl = '';
            let method = '';
            if(!this.model.id){
              httpurl+=this.url.add;
              method = 'post';
            }else{
              httpurl+=this.url.edit;
              method = 'put';
            }
            let formData = Object.assign(this.model, values);
            //时间格式化

            console.log('提交参数',formData)
            httpAction(httpurl,formData,method).then((res)=>{
              if(res.success){
                that.$message.success(res.message);
                that.$emit('ok');
              }else{
                that.$message.warning(res.message);
              }
            }).finally(() => {
              that.confirmLoading = false;
              that.close();
            })

          }
        })
      },
      handleCancel () {
        this.close()
      },
      setCorn(data){
        console.log('data)',data);
        this.$nextTick(() => {
          this.model.cronExpression = data;
        })

        // console.log(Object.keys(data).length==0);
        // if (Object.keys(data).length==0) {
        //   this.$message.warning('请输入cron表达式!');
        // }
      },
      validateCron(rule, value, callback){
        if(!value){
          callback()
        }else if (Object.keys(value).length==0) {
          callback("请输入cron表达式!");
        }
      },

    }
  }
</script>

<style scoped>

</style>

4.引用依赖关系:QuartzJobModal.vue--->JCron.vue-->JCronModal.vue

调用方法:

......
<a-form-item
   :labelCol="labelCol"
   :wrapperCol="wrapperCol"
   label="cron表达式">
   <j-cron ref="innerVueCron" v-decorator="['cronExpression', {'initialValue':'0/1 * * * * ?',rules: 
    [{ required: true, message: '请输入cron表达式!' }]}]"  @change="setCorn"></j-cron>
</a-form-item>
.....

import JCron from "@/components/jeecg/JCron.vue";

export default {
    name: "QuartzJobModal",
    components: {
      JCron
    },
    .....
     setCorn(data){
        console.log('data)',data);
        this.$nextTick(() => {
          this.model.cronExpression = data;
        })
 }

本人很少写博客,以前都是使用有道云或印象笔记记录流水式的解决某个问题,后续会经常来锻炼写博客,还望多多指点!

参考资料:

ant-design-vue

  https://vue.ant.design/docs/vue/introduce-cn/

cron-vue:

    https://1615450788.github.io/vue-cron/dist/index
    https://www.npmjs.com/package/vue-cron/v/1.0.9
    https://github.com/1615450788/vue-cron

cron在线表达式

http://www.toolzl.com/tools/croncreate.html

 

 

转载于:https://my.oschina.net/u/3903209/blog/3073789

  • 5
    点赞
  • 14
    收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
©️2022 CSDN 皮肤主题:编程工作室 设计师:CSDN官方博客 返回首页
评论
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、C币套餐、付费专栏及课程。

余额充值