前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
社区首页 >专栏 >Vue3项目-生成Cron表达式组件

Vue3项目-生成Cron表达式组件

作者头像
用户1174387
发布于 2022-12-18 10:11:29
发布于 2022-12-18 10:11:29
5.6K00
代码可运行
举报
文章被收录于专栏:web开发web开发
运行总次数:0
代码可运行

  最近做的一个vue3项目过程中,需要用到cron表达式功能,而对于普通业务人员,他们是不懂cron表达式规则的,所以需要做一个可手动配置生成cron表达式的功能。从网上查找了一些相关资料,然后结合vue3+Element Plus,改造成适合自己项目的组件。记录代码如下:

1、components目录下新建 vue3Cron/Index.vue

src/components/vue3Cron/Index.vue

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
<template>
  <div class="v3c">
    <ul class="v3c-tab">
      <li class="v3c-tab-item" :class="{ 'v3c-active': tabActive == 1 }" @click="onHandleTab(1)"></li>
      <li class="v3c-tab-item" :class="{ 'v3c-active': tabActive == 2 }" @click="onHandleTab(2)"></li>
      <li class="v3c-tab-item" :class="{ 'v3c-active': tabActive == 3 }" @click="onHandleTab(3)"></li>
      <li class="v3c-tab-item" :class="{ 'v3c-active': tabActive == 4 }" @click="onHandleTab(4)"></li>
      <li class="v3c-tab-item" :class="{ 'v3c-active': tabActive == 5 }" @click="onHandleTab(5)"></li>
      <li class="v3c-tab-item" :class="{ 'v3c-active': tabActive == 6 }" @click="onHandleTab(6)"></li>
    </ul>
    <!---->
    <div class="v3c-content" v-show="tabActive == 1">
      <!-- 每一秒 -->
      <div>
        <el-radio label="1" v-model="state.second.cronEvery">每一秒钟</el-radio>
      </div>
      <!-- 每隔多久 -->
      <div class="mt-15">
        <el-radio label="2" v-model="state.second.cronEvery">每隔</el-radio>
        <el-input-number v-model="state.second.incrementIncrement" :min="1" :max="60" controls-position="right" />
        <span class="ml-5 mr-5">秒执行, 从</span>
        <el-input-number v-model="state.second.incrementStart" :min="0" :max="59" controls-position="right" />
        <span>秒开始</span>
      </div>
      <!-- 具体秒数 -->
      <div class="mt-15">
        <el-radio label="3" v-model="state.second.cronEvery">具体秒数(可多选)</el-radio>
        <el-select v-model="state.second.specificSpecific" multiple clearable style="width: 140px">
          <el-option v-for="(item, index) in 60" :key="index" :label="index" :value="index" />
        </el-select>
      </div>
      <!-- 周期从 -->
      <div class="mt-15">
        <el-radio label="4" v-model="state.second.cronEvery">周期从</el-radio>
        <el-input-number v-model="state.second.rangeStart" :min="0" :max="59" controls-position="right" />
        <sapn></sapn><span class="ml-10 mr-5"></span>
        <el-input-number v-model="state.second.rangeEnd" :min="0" :max="59" controls-position="right" />
        <sapn></sapn>
      </div>
    </div>
    <!-- 分钟 -->
    <div class="v3c-content" v-show="tabActive == 2">
      <!-- 每一分钟 -->
      <div>
        <el-radio label="1" v-model="state.minute.cronEvery">每一分钟</el-radio>
      </div>
      <!-- 每隔多久 -->
      <div class="mt-15">
        <el-radio label="2" v-model="state.minute.cronEvery">每隔</el-radio>
        <el-input-number v-model="state.minute.incrementIncrement" :min="1" :max="60" controls-position="right" />
        <span class="ml-5 mr-5">分执行,从</span>
        <el-input-number v-model="state.minute.incrementStart" :min="0" :max="59" controls-position="right" />
        <span>分开始</span>
      </div>
      <!-- 具体分钟数 -->
      <div class="mt-15">
        <el-radio label="3" v-model="state.minute.cronEvery">具体分钟数(可多选)</el-radio>
        <el-select v-model="state.minute.specificSpecific" multiple clearable style="width: 140px">
          <el-option v-for="(item, index) in 60" :key="index" :label="index" :value="index" />
        </el-select>
      </div>
      <!-- 周期从 -->
      <div class="mt-15">
        <el-radio label="4" v-model="state.minute.cronEvery">周期从</el-radio>
        <el-input-number v-model="state.minute.rangeStart" :min="0" :max="59" controls-position="right" />
        <span></span><span class="ml-10 mr-5"></span>
        <el-input-number v-model="state.minute.rangeEnd" :min="0" :max="59" controls-position="right" />
        <span></span>
      </div>
    </div>
    <!-- 小时 -->
    <div class="v3c-content" v-show="tabActive == 3">
      <!-- 每一小时 -->
      <div>
        <el-radio label="1" v-model="state.hour.cronEvery">每一小时</el-radio>
      </div>
      <!-- 每隔多久 -->
      <div class="mt-15">
        <el-radio label="2" v-model="state.hour.cronEvery">每隔</el-radio>
        <el-input-number v-model="state.hour.incrementIncrement" :min="1" :max="24" controls-position="right" />
        <span class="ml-5 mr-5">小时执行,从</span>
        <el-input-number v-model="state.hour.incrementStart" :min="0" :max="23" controls-position="right" />
        <span>小时开始</span>
      </div>
      <!-- 具体小时数 -->
      <div class="mt-15">
        <el-radio label="3" v-model="state.hour.cronEvery">具体小时数(可多选)</el-radio>
        <el-select v-model="state.hour.specificSpecific" multiple clearable style="width: 140px">
          <el-option v-for="(item, index) in 24" :key="index" :label="index" :value="index" />
        </el-select>
      </div>
      <!-- 周期从 -->
      <div class="mt-15">
        <el-radio label="4" v-model="state.hour.cronEvery">周期从</el-radio>
        <el-input-number v-model="state.hour.rangeStart" :min="0" :max="23" controls-position="right" />
        <span></span><span class="ml-10 mr-5"></span>
        <el-input-number v-model="state.hour.rangeEnd" :min="0" :max="23" controls-position="right" />
        <span></span>
      </div>
    </div>
    <!---->
    <div class="v3c-content" v-show="tabActive == 4">
      <!-- 1 -->
      <div>
        <el-radio label="1" v-model="state.day.cronEvery">每一天</el-radio>
      </div>
      <!-- 2 -->
      <div class="mt-15">
        <el-radio label="2" v-model="state.day.cronEvery">每隔</el-radio>
        <el-input-number v-model="state.week.incrementIncrement" :min="1" :max="60" controls-position="right" />
        <span class="ml-5 mr-5">周执行,从</span>
        <el-input-number v-model="state.week.incrementStart" :min="1" :max="52" controls-position="right" />
        <span>周开始</span>
      </div>
      <!-- 3 -->
      <div class="mt-15">
        <el-radio label="3" v-model="state.day.cronEvery">每隔</el-radio>
        <el-input-number v-model="state.day.incrementIncrement" :min="1" :max="30" controls-position="right" />
        <span class="ml-5 mr-5">天执行,从</span>
        <el-input-number v-model="state.day.incrementStart" :min="1" :max="30" controls-position="right" />
        <span>天开始</span>
      </div>
      <!-- 4 -->
      <div class="mt-15">
        <el-radio label="4" v-model="state.day.cronEvery">具体星期几(可多选)</el-radio>
        <el-select v-model="state.week.specificSpecific" multiple clearable style="width: 140px">
          <el-option v-for="(item, index) in weekList" :key="index" :label="item.name" :value="item.value" />
        </el-select>
      </div>
      <!-- 5 -->
      <div class="mt-15">
        <el-radio label="5" v-model="state.day.cronEvery">具体天数(可多选)</el-radio>
        <el-select v-model="state.day.specificSpecific" multiple clearable style="width: 140px">
          <el-option v-for="(item, index) in 31" :key="index" :label="item" :value="item" />
        </el-select>
      </div>
      <!-- 6 -->
      <!-- <div class="mt-15">
        <el-radio label="6" v-model="state.day.cronEvery">在这个月的最后一天</el-radio>
      </div> -->
      <!-- 7 -->
      <!-- <div class="mt-15">
        <el-radio label="7" v-model="state.day.cronEvery">在这个月的最后一个工作日</el-radio>
      </div> -->
      <!-- 8 -->
      <!-- <div class="mt-15">
        <el-radio label="8" v-model="state.day.cronEvery">在这个月的最后一个</el-radio>
        <el-select v-model="state.day.cronLastSpecificDomDay" style="width: 140px">
          <el-option v-for="(item, index) in weekList" :key="index" :label="item.name" :value="item.val" />
        </el-select>
      </div> -->
      <!-- 9 -->
      <!-- <div class="mt-15">
          <el-radio label="9" v-model="state.day.cronEvery">{{ }}</el-radio>
          <el-input-number v-model="state.day.cronDaysBeforeEomMinus" :min="1" :max="31" controls-position="right" />
          <span>在本月底前</span>
      </div> -->
      <!-- 10 -->
      <!-- <div class="mt-15">
        <el-radio label="10" v-model="state.day.cronEvery">最近的工作日(周一至周五)至本月</el-radio>
        <el-input-number v-model="state.day.cronDaysNearestWeekday" :min="1" :max="31" controls-position="right" />
        <span></span>
      </div> -->
      <!-- 11 -->
      <!-- <div class="mt-15">
        <el-radio label="11" v-model="state.day.cronEvery">在这个月的第</el-radio>
        <el-input-number v-model="state.week.cronNthDayNth" :min="1" :max="5" controls-position="right" />
        <span></span>
        <el-select v-model="state.week.cronNthDayDay" style="width: 140px">
          <el-option v-for="(item, index) in weekList" :key="index" :label="item.name" :value="item.val" />
        </el-select>
      </div> -->
    </div>
    <!---->
    <div class="v3c-content" v-show="tabActive == 5">
      <!-- 1 -->
      <div>
        <el-radio label="1" v-model="state.month.cronEvery">每一月</el-radio>
      </div>
      <!-- 2 -->
      <div class="mt-15">
        <el-radio label="2" v-model="state.month.cronEvery">每隔</el-radio>
        <el-input-number v-model="state.month.incrementIncrement" :min="1" :max="12" controls-position="right" />
        <span class="ml-5 mr-5">月执行,从</span>
        <el-input-number v-model="state.month.incrementStart" :min="1" :max="12" controls-position="right" />
        <span>月开始</span>
      </div>
      <!-- 3 -->
      <div class="mt-15">
        <el-radio label="3" v-model="state.month.cronEvery">具体月数(可多选)</el-radio>
        <el-select multiple clearable v-model="state.month.specificSpecific" style="width: 140px">
          <el-option v-for="(item, index) in 12" :key="index" :label="item" :value="item" />
        </el-select>
      </div>
      <!-- 4 -->
      <div class="mt-15">
        <el-radio label="4" v-model="state.month.cronEvery">周期从</el-radio>
        <el-input-number v-model="state.month.rangeStart" :min="1" :max="12" controls-position="right" />
        <span></span><span class="ml-10 mr-5"></span>
        <el-input-number v-model="state.month.rangeEnd" :min="1" :max="12" controls-position="right" />
        <span></span>
      </div>
    </div>
    <!---->
    <div class="v3c-content" v-show="tabActive == 6">
      <!-- 1 -->
      <div>
        <el-radio label="1" v-model="state.year.cronEvery">每一年</el-radio>
      </div>
      <!-- 2 -->
      <div class="mt-15">
        <el-radio label="2" v-model="state.year.cronEvery">每隔</el-radio>
        <el-input-number v-model="state.year.incrementIncrement" :min="1" :max="99" controls-position="right" />
        <span class="ml-5 mr-5">年执行,从</span>
        <el-input-number v-model="state.year.incrementStart" :min="currYear" :max="currYear + 10"
          controls-position="right" style="width:100px;" />
        <span>年开始</span>
      </div>
      <!-- 3 -->
      <div class="mt-15">
        <el-radio label="3" v-model="state.year.cronEvery">具体年份(可多选)</el-radio>
        <el-select multiple clearable v-model="state.year.specificSpecific" style="width: 140px">
          <el-option v-for="(item, index) in 100" :key="index" :label="currYear + item" :value="currYear + item" />
        </el-select>
      </div>
      <!-- 4 -->
      <div class="mt-15">
        <el-radio label="4" v-model="state.year.cronEvery">周期从</el-radio>
        <el-input-number v-model="state.year.rangeStart" :min="currYear" :max="currYear + 10" controls-position="right"
          style="width:100px;" />
        <span></span><span class="ml-10 mr-5"></span>
        <el-input-number v-model="state.year.rangeEnd" :min="currYear" :max="currYear + 10" controls-position="right"
          style="width:100px;" />
        <span></span>
      </div>
    </div>
    <!-- 结果 -->
    <!-- <div class="v3c-footer">
      <div style="flex: 1">
        CRON &nbsp;: &nbsp;&nbsp;<span class="cron">{{ state.cron }}</span>
        &nbsp; &nbsp; &nbsp;
        <button class="btn-ok" @click.stop="handleChange">生成cron</button>
      </div>
    </div> -->
  </div>
</template>

<script>
import { reactive, computed, toRefs, defineComponent, ref, watch } from "vue";
// (默认是每一分钟一次)
export default defineComponent({
  name: "Vue3Cron",
  props: {
    maxHeight: String,
    change: Function,
    value: String,
  },
  setup(props, { emit }) {
    const weekList = ref([
      { name: '星期日', value: 'SUN', val: 1, },
      { name: '星期一', value: 'MON', val: 2, },
      { name: '星期二', value: 'TUE', val: 3, },
      { name: '星期三', value: 'WED', val: 4, },
      { name: '星期四', value: 'THU', val: 5, },
      { name: '星期五', value: 'FRI', val: 6, },
      { name: '星期六', value: 'SAT', val: 7, },
    ])

    const tabActive = ref(1);
    const currYear = ref(new Date().getFullYear());
    const onHandleTab = (index) => {
      tabActive.value = index;
    };

    // (默认是每一分钟一次)
    const state = reactive({
      second: {
        cronEvery: "1",
        incrementStart: 0,
        incrementIncrement: 1,
        rangeStart: 0,
        rangeEnd: 0,
        specificSpecific: [],
      },
      minute: {
        cronEvery: "1",
        incrementStart: 0,
        incrementIncrement: 1,
        rangeStart: 0,
        rangeEnd: 0,
        specificSpecific: [],
      },
      hour: {
        cronEvery: "1",
        incrementStart: 1,
        incrementIncrement: 1,
        rangeStart: 0,
        rangeEnd: 0,
        specificSpecific: [],
      },
      day: {
        cronEvery: "1",
        incrementStart: 1,
        incrementIncrement: 1,
        rangeStart: 0,
        rangeEnd: 0,
        specificSpecific: [],
        cronLastSpecificDomDay: 1,
        cronDaysBeforeEomMinus: 0,
        cronDaysNearestWeekday: 1,
      },
      week: {
        cronEvery: "1",
        incrementStart: 1,
        incrementIncrement: 1,
        specificSpecific: [],
        cronNthDayDay: 1,
        cronNthDayNth: 1,
      },
      month: {
        cronEvery: "1",
        incrementStart: 1,
        incrementIncrement: 1,
        rangeStart: 1,
        rangeEnd: 1,
        specificSpecific: [],
      },
      year: {
        cronEvery: "1",
        incrementStart: new Date().getFullYear(),
        incrementIncrement: 1,
        rangeStart: new Date().getFullYear(),
        rangeEnd: new Date().getFullYear(),
        specificSpecific: [],
      },
      output: {
        second: "",
        minute: "",
        hour: "",
        day: "",
        month: "",
        Week: "",
        year: "",
      },
      secondsText: computed(() => {
        let seconds = "";
        let cronEvery = state.second.cronEvery;
        switch (cronEvery?.toString()) {
          case "1":
            seconds = "*";
            break;
          case "2":
            seconds = state.second.incrementStart + "/" + state.second.incrementIncrement;
            break;
          case "3":
            state.second.specificSpecific.map((val) => {
              seconds += val + ",";
            });
            seconds = seconds.slice(0, -1);
            break;
          case "4":
            seconds = state.second.rangeStart + "-" + state.second.rangeEnd;
            break;
        }
        return seconds;
      }),
      minutesText: computed(() => {
        let minutes = "";
        let cronEvery = state.minute.cronEvery;
        switch (cronEvery?.toString()) {
          case "1":
            minutes = "*";
            break;
          case "2":
            minutes = state.minute.incrementStart + "/" + state.minute.incrementIncrement;
            break;
          case "3":
            state.minute.specificSpecific.map((val) => {
              minutes += val + ",";
            });
            minutes = minutes.slice(0, -1);
            break;
          case "4":
            minutes = state.minute.rangeStart + "-" + state.minute.rangeEnd;
            break;
        }
        return minutes;
      }),
      hoursText: computed(() => {
        let hours = "";
        let cronEvery = state.hour.cronEvery;
        switch (cronEvery?.toString()) {
          case "1":
            hours = "*";
            break;
          case "2":
            hours = state.hour.incrementStart + "/" + state.hour.incrementIncrement;
            break;
          case "3":
            state.hour.specificSpecific.map((val) => {
              hours += val + ",";
            });
            hours = hours.slice(0, -1);
            break;
          case "4":
            hours = state.hour.rangeStart + "-" + state.hour.rangeEnd;
            break;
        }
        return hours;
      }),
      daysText: computed(() => {
        let days = "";
        let cronEvery = state.day.cronEvery;
        switch (cronEvery?.toString()) {
          case "1":
            break;
          case "2":
          case "4":
          case "11":
            days = "?";
            break;
          case "3":
            days = state.day.incrementStart + "/" + state.day.incrementIncrement;
            break;
          case "5":
            state.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 = state.day.cronLastSpecificDomDay + "L";
            break;
          case "9":
            days = "L-" + state.day.cronDaysBeforeEomMinus;
            break;
          case "10":
            days = state.day.cronDaysNearestWeekday + "W";
            break;
        }
        return days;
      }),
      weeksText: computed(() => {
        let weeks = "";
        let cronEvery = state.day.cronEvery;
        switch (cronEvery?.toString()) {
          case "1":
          case "3":
          case "5":
            weeks = "?";
            break;
          case "2":
            weeks = state.week.incrementStart + "/" + state.week.incrementIncrement;
            break;
          case "4":
            state.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 = state.week.cronNthDayDay + "#" + state.week.cronNthDayNth;
            break;
        }
        return weeks;
      }),
      monthsText: computed(() => {
        let months = "";
        let cronEvery = state.month.cronEvery;
        switch (cronEvery?.toString()) {
          case "1":
            months = "*";
            break;
          case "2":
            months = state.month.incrementStart + "/" + state.month.incrementIncrement;
            break;
          case "3":
            state.month.specificSpecific.map((val) => {
              months += val + ",";
            });
            months = months.slice(0, -1);
            break;
          case "4":
            months = state.month.rangeStart + "-" + state.month.rangeEnd;
            break;
        }
        return months;
      }),
      yearsText: computed(() => {
        let years = "";
        // TODO,目前先不指定年份,注释以下代码
        let cronEvery = state.year.cronEvery;
        switch (cronEvery?.toString()) {
          case "1":
            years = "*";
            break;
          case "2":
            years = state.year.incrementStart + "/" + state.year.incrementIncrement;
            break;
          case "3":
            state.year.specificSpecific.map((val) => {
              years += val + ",";
            });
            years = years.slice(0, -1);
            break;
          case "4":
            years = state.year.rangeStart + "-" + state.year.rangeEnd;
            break;
        }
        return years;
      }),
      cron: computed(() => {
        return `${state.secondsText || "*"} ${state.minutesText || "*"} ${state.hoursText || "*"} ${state.daysText || "*"} ${state.monthsText || "*"} ${state.weeksText || "?"} ${state.yearsText || "*"}`;
      }),
    });

    const handleChange = () => {
      if (typeof state.cron !== "string") return false;
      emit("change", state.cron);
    };
    const rest = (data) => {
      for (let i in data) {
        if (data[i] instanceof Object) {
          this.rest(data[i]);
        } else {
          switch (typeof data[i]) {
            case "object":
              data[i] = [];
              break;
            case "string":
              data[i] = "";
              break;
          }
        }
      }
    };

    watch(
      () => state.cron,
      (value) => {
        if (typeof state.cron !== "string") return;
        emit("update:value", value);
      }
    );

    return {
      weekList,
      state,
      handleChange,
      rest,
      tabActive,
      onHandleTab,
      currYear,
    };
  },
});
</script>

<style lang="css" scoped>
:deep(.el-input-number) {
  width: 80px;
  margin-right: 5px;
}

:deep(.el-radio) {
  margin-right: 10px;
}

.v3c {
  width: auto;
  border: 1px solid #f5f7fa;
}

.v3c-tab {
  padding: 0;
  list-style: none;
  margin: 0;
  background-color: #f5f7fa;
  display: flex;
}

.v3c-tab-item {
  flex: 1;
  text-align: center;
  cursor: pointer;
  padding: 6px;
}

.v3c-tab-item.v3c-active {
  background-color: #409eff;
  color: #ffffff;
}

.v3c-lang-btn {
  background-color: #61ddaa;
  color: #ffffff;
  /* border-radius: 10px; */
}

.v3c-content {
  padding: 20px;
  max-height: v-bind(maxHeight);
  overflow: hidden;
  overflow-y: auto;
}

.p-20 {
  padding: 20px;
}

.v3c-footer {
  background-color: #f5f7fa;
  padding-top: 10px;
  padding-bottom: 10px;
  display: flex;
  text-align: center;
}

.v3c input[type="text"] {
  width: 80px;
}

.v3c input[type="number"] {
  width: 80px;
  height: 28px;
  border: 1px solid #d9d9d9;
}

.v3c select {
  width: 80px;
  height: 32px;
  border: 1px solid #d9d9d9;
}

.v3c select[multiple] {
  width: 80px;
  height: 100px;
  border: 1px solid #d9d9d9;
}

.btn-ok {
  line-height: 1.5715;
  position: relative;
  display: inline-block;
  font-weight: 400;
  white-space: nowrap;
  text-align: center;
  background-image: none;
  border: 1px solid transparent;
  box-shadow: 0 2px #00000004;
  cursor: pointer;
  transition: all 0.3s cubic-bezier(0.645, 0.045, 0.355, 1);
  -webkit-user-select: none;
  -moz-user-select: none;
  -ms-user-select: none;
  user-select: none;
  touch-action: manipulation;
  height: 32px;
  padding: 4px 15px;
  font-size: 14px;
  border-radius: 2px;

  color: #fff;
  background: #409eff;
  border-color: #409eff;
  text-shadow: 0 -1px 0 rgb(0 0 0 / 12%);
  box-shadow: 0 2px #0000000b;
}

.btn-close {
  line-height: 1.5715;
  position: relative;
  display: inline-block;
  font-weight: 400;
  white-space: nowrap;
  text-align: center;
  background-image: none;
  border: 1px solid transparent;
  box-shadow: 0 2px #00000004;
  cursor: pointer;
  transition: all 0.3s cubic-bezier(0.645, 0.045, 0.355, 1);
  -webkit-user-select: none;
  -moz-user-select: none;
  -ms-user-select: none;
  user-select: none;
  touch-action: manipulation;
  height: 32px;
  padding: 4px 15px;
  font-size: 14px;
  border-radius: 2px;

  color: #fff;
  background: #61ddaa;
  border-color: #61ddaa;
  text-shadow: 0 -1px 0 rgb(0 0 0 / 12%);
  box-shadow: 0 2px #0000000b;
}

.cron {
  background-color: #61ddaa;
  padding: 5px;
  padding-left: 10px;
  padding-right: 10px;
  color: #ffffff;
}
</style>

2、业务代码中使用vue3Cron/Index.vue

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
<template>
  <el-drawer :model-value="isShow" direction="rtl" :show-close="false" :destroy-on-close="true"
    :close-on-click-modal="false" :title="!!curRecord ? '编辑***' : '创建***'" @open="onOpen" @closed="onCancel"
    size="500px">
    <div class="pr-20">
      <el-form class="edit-form" :model="formData" ref="formRef" :rules="rules" label-width="100px">
        <el-form-item label="名称" prop="name">
          <el-input v-model="formData.name" placeholder="请输入****" />
        </el-form-item>
        <el-form-item label="cron表达式" prop="logicConfig">
          <el-input v-model="formData.logicConfig" placeholder="请输入cron表达式">
            <template #append>
              <el-tooltip content="配置cron表达式" placement="top">
                <el-button :icon="ArrowDown" @click="() => { isShowCronCore = !isShowCronCore }" />
              </el-tooltip>
            </template>
          </el-input>
        </el-form-item>
        <div style="width:100%;padding-left: 10px;margin-top: -5px;" v-show="isShowCronCore">
          <Vue3Cron @change="changeCron" v-model:value="formData.logicConfig" />
        </div>
      </el-form>
    </div>
    <template #footer>
      <span class="dialog-footer">
        <el-button @click="onCancel">取 消</el-button>
        <el-button type="primary" v-if="modalType != 'view'" :loading="submiting" @click="onSubmit">确 定</el-button>
      </span>
    </template>
  </el-drawer>
</template>
<script setup>
import { ref, reactive } from "vue";
import { ElMessage } from "element-plus";
import { ArrowDown } from '@element-plus/icons-vue'
import cronParse from 'cron-parser';
import triggerApi from '@/api/triggerApi';
import Vue3Cron from "@/components/vue3Cron/Index.vue";

// 其他代码省略*******// 定义数据
const isShowCronCore = ref(true); // 是否打开cron表达式配置框
const submiting = ref(false);     // 是否正在提交中
const formRef = ref(null);
const formData = reactive({  // 表单数据
  name: "", // 名称
  logicConfig: "* * * * * ? *", // cron表达式
});

const changeCron = (val) => {
  if (typeof val !== "string") return false;
  formData.logicConfig = val;
};

3、效果

例如:勾选配置为:每天10:30执行一次,输入框显示的表达式如下

注:目前还没做根据表达式回显秒分时天月年的配置项的功能,其实也很简单,只需要稍加理解一下cron表达式的规则,然后逐一解析即可。另外实际项目中根据情况判断需不需要显示年的选项

附上cron表达式基本介绍:

1、Cron表达式是一个字符串,字符串以5或6个空格隔开,分为6或7个域,每一个域代表一个含义,Cron有如下两种语法格式:

  (1)、秒 分 时 日 月 周 年

  (2)、秒 分 时 日 月 周

corn从左到右(用空格隔开):秒 分 小时 月份中的日期 月份 星期中的日期 年份

二、各字段的含义

字段

允许值

允许的特殊字符

秒(Seconds)

0~59的整数

, - * /    四个字符

分(Minutes)

0~59的整数

, - * /    四个字符

小时(Hours)

0~23的整数

, - * /    四个字符

日期(DayofMonth)

1~31的整数(但是你需要考虑你月的天数)

,- * ? / L W C     八个字符

月份(Month)

1~12的整数或者 JAN-DEC

, - * /    四个字符

星期(DayofWeek)

1~7的整数或者 SUN-SAT (1=SUN)

, - * ? / L C #     八个字符

年(可选,留空)(Year)

1970~2099

, - * /    四个字符

注意事项:

  每一个域都使用数字,但还可以出现如下特殊字符,它们的含义是:

  (1)*:表示匹配该域的任意值。假如在Minutes域使用*, 即表示每分钟都会触发事件。

  (2)?:只能用在DayofMonth和DayofWeek两个域。它也匹配域的任意值,但实际不会。因为DayofMonth和DayofWeek会相互影响。例如想在每月的20日触发调度,不管20日到底是星期几,则只能使用如下写法: 13 13 15 20 * ?, 其中最后一位只能用?,而不能使用*,如果使用*表示不管星期几都会触发,实际上并不是这样。

  (3)-:表示范围。例如在Minutes域使用5-20,表示从5分到20分钟每分钟触发一次 

  (4)/:表示起始时间开始触发,然后每隔固定时间触发一次。例如在Minutes域使用5/20,则意味着5分钟触发一次,而25,45等分别触发一次. 

  (5),:表示列出枚举值。例如:在Minutes域使用5,20,则意味着在5和20分每分钟触发一次。 

  (6)L:表示最后,只能出现在DayofWeek和DayofMonth域。如果在DayofWeek域使用5L,意味着在最后的一个星期四触发。 

  (7)W:表示有效工作日(周一到周五),只能出现在DayofMonth域,系统将在离指定日期的最近的有效工作日触发事件。例如:在 DayofMonth使用5W,如果5日是星期六,则将在最近的工作日:星期五,即4日触发。如果5日是星期天,则在6日(周一)触发;如果5日在星期一到星期五中的一天,则就在5日触发。另外一点,W的最近寻找不会跨过月份 。

  (8)LW:这两个字符可以连用,表示在某个月最后一个工作日,即最后一个星期五。 

  (9)#:用于确定每个月第几个星期几,只能出现在DayofMonth域。例如在4#2,表示某月的第二个星期三。

三、常用表达式例子

  (1)0 0 2 1 * ? *   表示在每月的1日的凌晨2点调整任务

  (2)0 15 10 ? * MON-FRI   表示周一到周五每天上午10:15执行作业

  (3)0 15 10 ? 6L 2002-2006   表示2002-2006年的每个月的最后一个星期五上午10:15执行作

  (4)0 0 10,14,16 * * ?   每天上午10点,下午2点,4点 

  (5)0 0/30 9-17 * * ?   朝九晚五工作时间内每半小时 

  (6)0 0 12 ? * WED    表示每个星期三中午12点 

  (7)0 0 12 * * ?   每天中午12点触发 

  (8)0 15 10 ? * *    每天上午10:15触发 

  (9)0 15 10 * * ?     每天上午10:15触发 

  (10)0 15 10 * * ? *    每天上午10:15触发 

  (11)0 15 10 * * ? 2005    2005年的每天上午10:15触发 

  (12)0 * 14 * * ?     在每天下午2点到下午2:59期间的每1分钟触发 

  (13)0 0/5 14 * * ?    在每天下午2点到下午2:55期间的每5分钟触发 

  (14)0 0/5 14,18 * * ?     在每天下午2点到2:55期间和下午6点到6:55期间的每5分钟触发 

  (15)0 0-5 14 * * ?    在每天下午2点到下午2:05期间的每1分钟触发 

  (16)0 10,44 14 ? 3 WED    每年三月的星期三的下午2:10和2:44触发 

  (17)0 15 10 ? * MON-FRI    周一至周五的上午10:15触发 

  (18)0 15 10 15 * ?    每月15日上午10:15触发 

  (19)0 15 10 L * ?    每月最后一日的上午10:15触发 

  (20)0 15 10 ? * 6L    每月的最后一个星期五上午10:15触发 

  (21)0 15 10 ? * 6L 2002-2005   2002年至2005年的每月的最后一个星期五上午10:15触发 

  (22)0 15 10 ? * 6#3   每月的第三个星期五上午10:15触发

注:

  (1)有些子表达式能包含一些范围或列表

  例如:子表达式(天(星期))可以为 “MON-FRI”,“MON,WED,FRI”,“MON-WED,SAT”

“*”字符代表所有可能的值

  因此,“*”在子表达式(月)里表示每个月的含义,“*”在子表达式(天(星期))表示星期的每一天

  “/”字符用来指定数值的增量    例如:在子表达式(分钟)里的“0/15”表示从第0分钟开始,每15分钟  在子表达式(分钟)里的“3/20”表示从第3分钟开始,每20分钟(它和“3,23,43”)的含义一样

  “?”字符仅被用于天(月)和天(星期)两个子表达式,表示不指定值    当2个子表达式其中之一被指定了值以后,为了避免冲突,需要将另一个子表达式的值设为“?”

  “L” 字符仅被用于天(月)和天(星期)两个子表达式,它是单词“last”的缩写    但是它在两个子表达式里的含义是不同的。    在天(月)子表达式中,“L”表示一个月的最后一天    在天(星期)自表达式中,“L”表示一个星期的最后一天,也就是SAT

  如果在“L”前有具体的内容,它就具有其他的含义了

  例如:“6L”表示这个月的倒数第6天,“FRIL”表示这个月的最一个星期五    注意:在使用“L”参数时,不要指定列表或范围,因为这会导致问题

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2022-12-16,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
暂无评论
推荐阅读
人事管理系统排名出炉!Moka等九大HR系统优缺点解析
在数字化浪潮的推动下,越来越多的企业开始采用人事管理系统来优化人力资源管理流程。从员工入职、考勤排班、薪酬核算,到绩效考核、培训发展,一个高效的HR系统不仅能降低人力成本,还能提升管理效率,帮助企业实现精细化人才管理。然而,市场上的HR软件种类繁多,功能各异,如何挑选最适合企业需求的系统成为HR们关注的焦点。
用户11311027
2025/03/13
3290
人事管理系统排名出炉!Moka等九大HR系统优缺点解析
2023爱分析·一体化HR SaaS市场厂商评估报告:北森
伴随数字化转型走向深入,企业人力资源数字化也进入快速发展阶段,人力资源的价值也得到了重新审视和定义。政策层面,《十四五规划和2035年远景目标纲要》、《“十四五”国家信息化规划》等一系列政策文件相继颁布,国家及各部委都在鼓励企业人力资源数字化“上云”发展,推动人力资源管理数字化持续升级。同时,受疫情因素影响,远程办公、线上招聘、视频面试、线上培训等新型办公模式相继涌现,加速了企业人力资源数字化进程。并且,面对外部复杂多变的商业环境,传统的人力资源管理已经无法快速、敏捷地适应企业的战略发展需求,企业亟需借助数字化技术手段打造柔性敏捷组织,以快速响应市场环境变化、有效解决企业经营难题。
爱分析ifenxi
2023/03/06
7630
【聚焦】从六大模块出发,RPA助力企业智能管理之人力资源篇
全球领先的信息技术研究和咨询公司Gartner已公布2020年度十大战略科技趋势。Gartner的2020年度十大战略科技趋势突出了企业在五年战略技术规划过程中需要考虑的趋势。
RPA小葵
2020/05/27
1.1K0
【聚焦】从六大模块出发,RPA助力企业智能管理之人力资源篇
易路|解锁连锁酒店行业人力资源管理变革的秘诀
2022年11月22日,由易路人力资源科技(以下简称易路)主办的以“智未来·效先行”为主题的2022易路人力科技趋势峰会正式举办。为助力企业应对不确定外部变化、保持持续竞争力。锦江酒店(中国区)人事管理部副总经理王述齐受邀参加本次峰会,对话易路联合创始人兼总裁缪青。他将从自身行业及企业出发,分享在快速变化、充满不确定的环境下,对于人力资源管理,锦江酒店是如何思考、规划并执行。
云上计算
2022/11/24
5890
易路|解锁连锁酒店行业人力资源管理变革的秘诀
当HR遇上大数据
一、人力资源管理的本土实践与挑战 “天下之物莫不有理,惟于理有未穷,故其知有不尽也。” 中国企业在改革开放一路坎坷走过三十多年的历程,在企业管理方面主要通过学习和借鉴西方管理哲学与理论,过程中也不断优化以适应中国商业环境和人文环境下运营管理的特殊性要求。人力资源作为其中一个管理模块,已经成为中国企业的日常管理中不可替代的职能,是企业战略落地的支撑要素。但在长期为中国企业,特别是民营企业提供管理咨询服务的过程中,我们认为民营企业人力资源管理的问题往往非常相似,如岗位职责不清、员工责任心不强、薪酬竞争力不足
CSDN技术头条
2018/02/09
2.2K1
当HR遇上大数据
肯耐珂萨沈健:数字化正重构人力资源管理,HR SaaS进入深水区 | 腾讯SaaS加速器·CEO说
来源:数字观察  作者:窦悦怡 ---- “从需求方来看,企业对于传统意义上的人力资源预算投入的增长幅度变小,而对HR SaaS软件预算投入的增长幅度开始加大。 这时候,客户的需求就发生了一些新的变化,他们不再要单点的产品,或者说对客户部分负责的产品,而是需要对结果负责的覆盖全生命周期流程的产品和服务体系。 从供应端来看,我认为整个行业进入了竞争热化的阶段。当前中国企业级服务市场正处于混战局面,不仅仅是领域玩家之间的竞争,还面临着越来越多的跨界对手,大家都因看好这个赛道蜂拥而至。玩家虽多,但面对客
腾讯SaaS加速器
2020/06/09
1.7K0
平衡计分卡 - 不仅是度量系统,更是战略管理工具
根据西方经济学的原理,企业的最终目的是实现股东价值最大化。股东价值就是企业未来自由现金流的折现,未来的自由现金流是要靠现在的投入以及通过核心能力不断增强创造的。然而,人们衡量股东价值的指标往往基本上是财务指标,包括销售收入增长、自由现金流、净利润率、投资报酬率、经济增加值等。这些指标有一个共同的特征,即它们都是企业的短期绩效指标。因此对上述财务绩效指标的依赖会使企业过度关注短期的财务绩效,妨碍企业增强创造未来经济价值的能力。那么企业未来的绩效是由什么因素驱动的?怎么度量?企业的绩效度量体系怎么从企业的愿景和战略中推导出来?它应当具有什么结构?这些问题,促进了平衡计分卡方法的形成。
段立功
2022/11/30
9290
平衡计分卡 - 不仅是度量系统,更是战略管理工具
HR SaaS市场竞争火热,肯耐珂萨缘何持续领跑? |爱分析调研
中国人力资源数字化市场规模快速增长,各路厂商云集,呈现百花齐放的态势。作为人力资源管理一体化云解决方案的龙头服务商,肯耐珂萨坚定执行价值导向的差异化竞争策略,15年引领行业创新,依托行业领先方法论支撑的一体化HR SaaS产品能力、深厚的技术积累、大量行业常模沉淀和敏捷创新能力,开创了一条特色化的HR SaaS发展路径,拒绝价格战、拒绝同质化,倡导回归到客户价值层面,以通过价值的创造和提升来实现可持续的高质量发展。2023年,对于中国HR SaaS行业,需要在“回归”中打开新的道路。
爱分析ifenxi
2023/05/10
3640
HR SaaS市场竞争火热,肯耐珂萨缘何持续领跑? |爱分析调研
企业人力资源数字化转型,装一个软件就够了吗?
一直以来大家对HR的工作可能都有个深深的误解,不就是招聘嘛,有什么难的。其实HR还真不“难”,你只需要会招聘、会统计、会分析、会谈判、懂法律、懂金融、懂管理、能哄人、能受气、能熬夜……基本上就可以做HR了。
云巴巴
2021/08/31
8150
企业人力资源数字化转型,装一个软件就够了吗?
HR必备的88个关键知识及管理工具
一、战略管理工具 1、Swot分析矩阵 它是指企业外部环境和内部条件分析,从而寻找二者最佳可行战略组合的一种分析工具。“S”代表企业的优势或长处(Strengths),“W”代表企业的劣势或弱点(We
用户1756920
2018/06/20
1.4K0
先易后难还是先难后易,HR SaaS厂商该如何选择?
HR SaaS作为中国SaaS市场份额最高的领域发展尤为迅速,但集中度却没有明显提升,这或许意味着HR SaaS领域的竞争马上将进入下一个阶段。 来源 / ToB行业头条 (ID:wwwqifu) 作者 / 樊航
ToB行业头条
2022/04/15
5170
肯耐珂萨沈健:智慧应变,人力资源管理的演进|腾讯SaaS加速器·CEO说
来源 |  腾讯SaaS加速器首期项目-肯耐珂萨 ---- 今年7月,肯耐珂萨在“助力企业人力资本管理数字化转型”这一使命基础上,进一步提出了新的价值主张“HR数字化提升组织效能”,这也是肯耐珂萨在数字化道路上探索客户价值的最新解读。 “我们为什么提出这个价值主张,就希望客户能够关注到最后的落脚点,不要为了上数字化而上数字化,因为数字化本身它只是手段,不是目的,目的是组织目标的实现”,沈健在专访中说道,“从需求端和整个风向来看,企业进行数字化已经是必须,人力资源也会通过数字化手段来发生革新,从而促进
腾讯SaaS加速器
2020/10/26
1.3K0
我被漂亮的hr小姐姐撩了……(有图)
腾讯金牛企业会员 上周已经正式上线 帮助广大想要做数字化转型或升级的中小企业 解决不敢转、不会转、没人教的问题 我们已经把上云所需的产品打包好了 云服务器、解析、域名、建站、证书、商标…… 只要你是金牛会员 这些产品通通免费挑选 今天 金牛会员产品家族迎来了新成员 人力资源管理数字化,解放双手! 与候选人前期沟通意向太耗时,招聘旺季压力山大? 新人指引、报道指引还在通过微信/邮箱手动发送? 线下Excel表管理绩效考核容易错漏? 请休假还在使用纸质单据? …… 使用腾讯HR助手,实现人力
腾讯云DNSPod团队
2021/08/30
2.6K0
为什么说coreHR模块是HR系统项目建设成败的关键?
作为经历过不同企业HR信息化、数字化的从业者,参与过各种HR系统建设的从业人员,今天想和大家聊聊HR系统建设中最重要却最容易被低估的模块COREHR。
用户7193158
2023/06/06
5170
德为 CTO 黄际雷:研发绩效管理的一种配方
文章原创首发于微信公众号「 TGO 鲲鹏会」,原文地址:德为 CTO 黄际雷:研发绩效管理的一种配方
TGO鲲鹏会
2018/06/01
3980
德为 CTO 黄际雷:研发绩效管理的一种配方
利用数据分析进行人力资源管理的优化
大家经常说:无工具不管理、无数据难决策。所以企业的人力资源管理,我们首先要考虑在目前大数据背景下如何开展人力资源数据的整理与分析。 当前,移动互联网、社交应用、大数据等技术浪潮凶猛来袭,正在加速驱动着
用户1756920
2018/06/21
1.2K0
【管理】数据分析下的人力资源管理优化与提升
大家经常说:无工具不管理、无数据难决策。所以企业的人力资源管理,我们首先要考虑在目前大数据背景下如何开展人力资源数据的整理与分析。 当前,移动互联网、社交应用、大数据等技术浪潮凶猛来袭,正在加速驱动着企业人力资源管理的信息化进程。 那么,到底如何有效迎接这一浪潮,如何以价值为导向,整理、分析,并发掘出关键信息加以分析利用,从而提升人力资源管理效益,是每一位管理者面临的问题。 如何通过建立人力资源数据库,完成全面的数据化分析,实现用数据说话,真正推动企业人力资源管理转型升级,支撑企业战略发展。 人
小莹莹
2018/04/20
2.3K0
敏捷绩效管理三剑客:OKR 、KPI、CFR
从第一次工业革命开始,人类经历了蒸汽时代、电气时代、信息时代,并正在迎接智能时代的到来。在蒸汽时代和电气时代,推动经济社会发展的核心资源是不可再生的物质能源和资本;而到了信息时代,知识和信息成为了企业的核心战略资源,员工必须具备较高知识和技能水平,才能较好地完成诸如软硬件研发等各种信息处理工作;进入智能时代后,创造力逐渐成为高效组织的一个必要条件,低技术含量的企业正逐渐被高创造性企业取代。
腾讯云 CODING
2021/06/15
1.3K0
敏捷绩效管理三剑客:OKR 、KPI、CFR
【愚公系列】2023年12月 智能制造理论篇-人力资源
人力资源是指一项组织或企业的所有员工,包括招聘、培训、绩效管理、员工福利、薪酬管理、员工关系等方面的管理。在西方,人力资源的管理强调员工的个性和价值,注重员工参与和沟通,以及强调员工与企业的关系是相互的,需要建立双向信任与共同成长。而在东方,人力资源的管理强调权威和等级制度,注重员工服从和执行,以及强调员工与企业的关系是属下与上级之间的单向关系。由于文化、教育、法律等方面的差异,西方和东方的人力资源管理方式存在一定的差距。
愚公搬代码
2023/12/10
4231
国企事业单位人力资源管理系统选型操作指南
2020年6月,国资委印发的《关于开展对标世界一流管理提升行动的通知》明确推动中央企业和地方国有重点企业基本形成系统完备、科学规范、运行高效的中国特色现代国有企业管理体系,而人力资源管理也成为本次管理提升行动中8大领域之一,人力资源数字化作为国有企业数字化转型的重要抓手,被视为国企深化改革的巨大动力和支持。近年来,数字政府逐渐成为政府建设的重要方向,随着管理体制改革深化,事业单位由公共行政向公共管理转变,事业单位也在加剧推动人力资源管理的数字化建设。 而国企事业单位人力资源管理数字化建设,除了内部自行开发人力资源管理系统外,就是从外部采购成熟的人力资源管理系统支持,今天主要就如何选择适合国企事业单位的人力资源管理系统,提供一些建议和经验。
用户7193158
2022/08/31
9980
推荐阅读
相关推荐
人事管理系统排名出炉!Moka等九大HR系统优缺点解析
更多 >
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档