vue3 添加编辑页使用 cron 表达式生成

示例效果图
在这里插入图片描述

1、添加组件

<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>-->
<!--            &lt;!&ndash; 4 &ndash;&gt;-->
<!--            <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="mt-15">
            <el-input v-model="value"/>
        </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: '星期日', val: 'SUN', value: 1,},
            {name: '星期一', val: 'MON', value: 2,},
            {name: '星期二', val: 'TUE', value: 3,},
            {name: '星期三', val: 'WED', value: 4,},
            {name: '星期四', val: 'THU', value: 5,},
            {name: '星期五', val: 'FRI', value: 6,},
            {name: '星期六', val: 'SAT', value: 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(() => {
                console.log("------------")
                let weeks = "";
                let cronEvery = state.day.cronEvery;
                switch (cronEvery?.toString()) {
                    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 "5":
                        weeks = "?";
                        break;
                    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(() => {
                let secondsText = `${state.secondsText || "*"}`
                let minutesText = `${state.minutesText || "*"}`
                let hoursText = `${state.hoursText || "*"}`
                let daysText = `${state.daysText || "*"}`
                let monthsText = `${state.monthsText || "*"}`
                let weeksText = `${state.weeksText || "?"}`
                let yearsText = `${state.yearsText || "*"}`
                if (minutesText !== '*') {
                    secondsText = secondsText === '*' ? '0' : secondsText;
                }
                if (hoursText !== '*') {
                    secondsText = secondsText === '*' ? '0' : secondsText;
                    minutesText = minutesText === '*' ? '0' : minutesText;
                }
                if (daysText !== '*') {
                    secondsText = secondsText === '*' ? '0' : secondsText;
                    minutesText = minutesText === '*' ? '0' : minutesText;
                    hoursText = hoursText === '*' ? '0' : hoursText;
                }
                if (weeksText !== '?') {
                    secondsText = secondsText === '*' ? '0' : secondsText;
                    minutesText = minutesText === '*' ? '0' : minutesText;
                    hoursText = hoursText === '*' ? '0' : hoursText;
                }
                if (monthsText !== '*') {
                    secondsText = secondsText === '*' ? '0' : secondsText;
                    minutesText = minutesText === '*' ? '0' : minutesText;
                    hoursText = hoursText === '*' ? '0' : hoursText;
                    daysText = daysText === '*' ? '1' : daysText;
                }
                if (yearsText !== '*') {
                    secondsText = secondsText === '*' ? '0' : secondsText;
                    minutesText = minutesText === '*' ? '0' : minutesText;
                    hoursText = hoursText === '*' ? '0' : hoursText;
                    // daysText = daysText === '*' ? '1' : daysText;
                    // monthsText = monthsText === '*' ? '1' : monthsText;
                }
                return secondsText + " " + minutesText + " " + hoursText + " " + daysText + " " + monthsText + " " + weeksText + " " + yearsText;
            }),
        });


        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;
                    }
                }
            }
        };
        // 点击变更调用方数据
        const handleChange = () => {
            if (typeof state.cron !== "string") return false;
            emit("change", state.cron);
        };
        // 数据变化时变更调用方数据
        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-content > div {
    line-height: 50px;
}

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

.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;
}
</style>

2、使用组件

2.1、定义相关前置参数

import {defineAsyncComponent} from "vue";
export default {
    components: {
        Vue3Cron: defineAsyncComponent(() => import('@/components/vue3-cron/cron.vue')),
    },
    data() {
        return {
            // 表单参数
            obj: {},
            // 定义弹窗开关字段
            cronDialogVisible: false,
            cronTimes: [],
            uri: {
                // 定义预览 uri 的接口地址
                temporalPrediction: "/api/admin/dispatch/dispatchTask/temporalPrediction",
            }
        }
    },
    methods: {
        // 获取调度的预计执行时间
        temporalPrediction(cron, startTime, endTime) {
            this.crud.get(this.uri.temporalPrediction, {cron: cron, startTime: startTime, endTime: endTime}).then(res => {
                this.cronTimes = res.data.data;
            })
        }, 
    }   
  

2.2、 添加插槽 (添加/编辑页中)

<!-- cron 表达式插槽 -->
<template #cron="{size,row,index}">
    <!-- 展示当前cron 表达式-->
    <el-input v-model="this.obj.cron" placeholder=""/>
    <!-- 打开 cron 生成弹窗,详见定义弹窗中的内容  -->
    <el-button type="primary" style="margin-top: 10px;margin-bottom: 10px" @click="cronDialogVisible=true">cron 生成</el-button>
    <!-- 时间预测-- 与预览 (当前页面中)   -->
    <el-button type="primary" style="margin-top: 10px;margin-bottom: 10px" @click="temporalPrediction(this.obj.cron,this.obj.startTime,this.obj.endTime) ">时间预测</el-button>
    <div v-for="(item,index) in cronTimes">
        {{ item }}
    </div>
</template>
  

2.3、定义弹窗 (添加/编辑页中)

 <!--  cron 是弹窗 -->
 <el-dialog title="cron 生成" v-if="cronDialogVisible" v-model="cronDialogVisible">
     <!--  选择 -->
     <Vue3Cron  v-model:value="this.obj.cron"/>
     <!-- 时间预测-- 与预览 (弹窗中)   -->
     <el-button type="primary" style="margin-top: 10px;margin-bottom: 10px" @click="temporalPrediction(this.obj.cron) ">获取最近运行时间</el-button>
     <div v-for="(item,index) in cronTimes">
         {{ item }}
     </div>
 </el-dialog>

后端部分 ( java)

pom.xml

  <!-- quartz -->
        <dependency>
            <groupId>org.quartz-scheduler</groupId>
            <artifactId>quartz</artifactId>
            <version>2.2.1</version>
        </dependency>
        <dependency>
            <groupId>org.quartz-scheduler</groupId>
            <artifactId>quartz-jobs</artifactId>
            <version>2.2.1</version>
        </dependency>
        <dependency>
            <groupId>com.cronutils</groupId>
            <artifactId>cron-utils</artifactId>
            <version>9.1.0</version>
        </dependency>

接口 controller

  @GetMapping(value = "/temporalPrediction")
    @ApiOperation(value = "时间预测")
    public Result<List<String>> temporalPrediction(@RequestParam String cron,String startTime,String endTime) {
        return Result.success(baseService.temporalPrediction( cron, startTime, endTime));
    }

接口 service

   /**
     * 时间预测
     *
     * @param cron cron
     * @param startTime 开始时间
     * @param endTime 结束时间
     * @return {@link List}<{@link String}>
     */
    List<String> temporalPrediction(String cron, String startTime, String endTime);


    @Override
    public List<String> temporalPrediction(String cron, String startTime, String endTime) {
        List<String> nextExecuteTimes = null;
        try {
            if (StringUtils.isBlank(startTime) && StringUtils.isBlank(endTime)) {
                nextExecuteTimes = QuartzUtil.getNextExecuteTimes(cron, 10);
            } else {
                nextExecuteTimes = QuartzUtil.getNextExecuteTimesByTimeRange(cron, startTime, endTime, 10);
            }
        } catch (Exception e) {
            throw new ErrorException("cron 表达式解析失败");
        }
        return nextExecuteTimes;
    }

QuartzUtil 工具

 /**
     * 根据时间范围获取新的cron表达式
     *
     * @param cronExpression 现有的 cron 表达式
     * @param startTimeStr 开始时间
     * @param startTimeStr 结束时间
     * @return {@link String} 时间范围
     */
    public static String getNewCronByTimeRange(String cronExpression, String startTimeStr, String endTimeStr) {
        LocalDateTime startTime = LocalDateTimeUtil.parse("2021-01-01 " + startTimeStr);
        LocalDateTime endTime = LocalDateTimeUtil.parse("2021-01-01 " + endTimeStr);
        if (LocalDateTimeUtil.isAfter(startTime, endTime)) {
            throw new ErrorException("开始时间不能小于结束时间");
        }
        long minutes = LocalDateTimeUtil.betweenTwoTime(startTime, endTime, ChronoUnit.MINUTES);
        if (minutes == 0) {
            // 差值为0, cron 表达式结果不变
            return cronExpression;
        }
        // 随机分钟数
        long randomLong = RandomUtil.randomLong(minutes);
        // 随机秒数
        long second = RandomUtil.randomLong(59);
        LocalDateTime time = LocalDateTimeUtil.plus(startTime, randomLong, ChronoUnit.MINUTES);
        // System.out.println("随机数:" + randomLong+ " 随机时间:" + time.getHour() +":" + time.getMinute()  +":"+ second);
        String[] cronExpressionArray = cronExpression.split(" ");
        cronExpressionArray[0] = second + "";
        cronExpressionArray[1] = time.getMinute() + "";
        cronExpressionArray[2] = time.getHour() + "";
        return String.join(" ", cronExpressionArray);
    }

    /**
     * 列出接下来的 n次 执行时间 (根据 cron 表达式)
     *
     * @param cronExpression cron表达式
     * @param num 预测次数
     * @throws ParseException 解析异常 (cron 表达式不规范需返回异常,调用方需主动处理该错误)
     */
    public static List<String> getNextExecuteTimes(String cronExpression, int num) {
        List<String> dates = new ArrayList<>();
        CronExpression cron = null;
        try {
            cron = new CronExpression(cronExpression);
        } catch (ParseException e) {
            throw new RuntimeException(e);
        }
        Date currentDate = new Date();
        for (int i = 0; i < num; i++) {
            Date nextFireTime = cron.getNextValidTimeAfter(currentDate);
            currentDate = nextFireTime;
            dates.add(formatDate(nextFireTime));
        }
        return dates;
    }

    /**
     * 列出接下来的 n次 执行时间 (根据 cron 表达式+ 时间范围)
     *
     * @param cronExpression cron表达式
     * @param num 预测次数
     * @throws ParseException 解析异常 (cron 表达式不规范需返回异常,调用方需主动处理该错误)
     */
    public static List<String> getNextExecuteTimesByTimeRange(String cronExpression, String startTimeStr, String endTimeStr, int num) {
        List<String> dates = new ArrayList<>();
        for (int i = 0; i < num; i++) {
            String newCron = getNewCronByTimeRange(cronExpression, startTimeStr, endTimeStr);
            CronExpression cron = null;
            try {
                // 每次获取为 i 的最后一次的执行来保证 年月日 单位的执行日期, 时分秒日期每次 i 循环时修改获得
                cron = new CronExpression(newCron);
            } catch (ParseException e) {
                throw new RuntimeException(e);
            }
            Date currentDate = new Date();
            for (int j = 0; j <= i; j++) {
                Date nextFireTime = cron.getNextValidTimeAfter(currentDate);
                currentDate = nextFireTime;
                if (j == i) {
                    dates.add(formatDate(nextFireTime));
                }
            }
        }
        return dates;
    }


    /**
     * 格式化时间日期
     *
     * @param date 日期
     * @return {@link String}
     */
    private static String formatDate(Date date) {
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        return sdf.format(date);
    }

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/247728.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

【Linux系统编程二十一】:(进程通信3)--消息队列/信号量(system v标准的内核数据结构的设计模式)

【Linux系统编程二十】&#xff1a;消息队列/信号量(system v标准的内核数据结构的设计模式&#xff09; 一.消息队列二.system v标准的内核数据结构的设计三.四个概念(互斥/临界)四.信号量1.多线程并发访问2.计数器3.原子的4.总结 一.消息队列 一个叫做a进程啊&#xff0c;一个…

乐益达教育网页

目录 一、网页效果 二、html代码 三、CSS代码 四、JS代码 一、网页效果 二、html代码 <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><meta name"viewport" content"widthdevice-width, in…

Milesight VPN server.js 任意文件读取漏洞(CVE-2023-23907)

0x01 产品简介 MilesightVPN 是一款软件&#xff0c;一个 Milesight 产品的 VPN 通道设置过程更加完善&#xff0c;并可通过网络服务器界面连接状态。 0x02 漏洞概述 MilesightVPN server.js接口处存在文件读取漏洞&#xff0c;攻击者可通过该漏洞读取系统重要文件&#xff…

LeetCode-42. 接雨水【栈 数组 双指针 动态规划 单调栈】

LeetCode-42. 接雨水【栈 数组 双指针 动态规划 单调栈】 题目描述&#xff1a;解题思路一&#xff1a;单调栈&#xff0c;维护一个单调递减栈。每当遇到当前元素大于栈顶元素就出栈&#xff0c;在出栈时更新答案。当遇到出栈的情况&#xff0c;若单调栈栈左边有一个元素则必有…

Java医院信息化建设云HIS系统源码

云HIS提供标准化、信息化、可共享的医疗信息管理系统&#xff0c;实现医患事务管理和临床诊疗管理等标准医疗管理信息系统的功能。优化就医、管理流程&#xff0c;提升患者满意度、基层首诊率&#xff0c;通过信息共享、辅助诊疗等手段&#xff0c;提高基层医生的服务能力构建和…

Ubuntu20.04 下编译安装 ffmpeg 和 ffplay

Ubuntu20.04 下编译安装 ffmpeg 和 ffplay 一、下载源码包二、安装依赖库三、编译四、添加环境变量五、验证是否成功六、问题 一、下载源码包 1.1 官方下载链接&#xff1a;http://ffmpeg.org/download.html 最新版本为6.1&#xff0c;点击 Download Source Code下载即可 &…

【深度学习】强化学习(二)马尔可夫决策过程

文章目录 一、强化学习问题1、交互的对象2、强化学习的基本要素3、策略&#xff08;Policy&#xff09;4、马尔可夫决策过程1. 基本元素2. 交互过程的表示3. 马尔可夫过程&#xff08;Markov Process&#xff09;4. 马尔可夫决策过程&#xff08;MDP&#xff09;5. 轨迹的概率计…

监控pod 容器外网请求网络带宽,过滤掉内网、基于k8spacket开发、prometheus开发export

首先安装k8spacket 安装k8spacket遇到问题&#xff0c;下载插件一直能不能下载成功&#xff0c;pod不能启动。所有手动下载处理。 helm repo add k8spacket https://k8spacket.github.io/k8spacket-helm-chart helm pull k8spacket/k8spacket打开values.yaml 文件 手动下载插…

Axure元件库的介绍以及个人简介和登录界面案例展示

目录 一. 元件介绍 二. 基本元件的使用 2.1 形状元件 2.2 图片元件 2.3 占位符 2.4 文本 2.5 线段元件 2.6 热区文件 三. 表单元件的使用 3.1 文本框 3.2 文本域 3.3 下拉列表 3.4 列表框 3.5 复选框 3.6 单选按钮 四. 菜单与表格元件的使用 4.1 树 4.2 表格…

【CSS】用 CSS 写一个渐变色边框的输入框

Using_CSS_gradients MDN 多渐变色输入框&#xff0c;群友问了下&#xff0c;就试着写了下&#xff0c;看了看 css 渐变色 MDN 文档&#xff0c;其实很简单&#xff0c;代码记录下&#xff1a; <!DOCTYPE html> <html lang"en"><head><meta ch…

2024美赛备战-美赛必备技能(matlab 和SPSS入门必备)

( 一 )Matlab 1.数值计算和符号计算功能 Matlab 以矩阵作为数据操作的基本单位&#xff0c;它的指令表达式与数学、工程中 常用的符号、表达式十分相似&#xff0c;故用Matlab 来解算问题要比用C、FORTRAN 等 语 言完成相同的事情简捷得多&#xff0c;使学者易于学习和掌握…

python如何发送企业微信群消息

一、创建机器人&#xff0c;并获取webhook 1.1 进入企业微信中&#xff0c;添加群机器人&#xff0c;添加完成后可以获取到一个webhook的地址 1.2 群机器人企业微信接口的调用可以参考这个文件 https://developer.work.weixin.qq.com/document/path/99110#%E5%A6%82%E4%BD%…

【UE5.2】从零开始控制角色移动、游泳、下潜、上浮

目录 效果 步骤 一、项目准备 二、控制角色移动 三、控制角色游泳 四、实现角色潜水、上浮 五、解决在水面上浮的Bug 效果 步骤 一、项目准备 1. 新建一个空白工程&#xff0c;创建一个Basic关卡&#xff0c;添加第三人称游戏资源到内容浏览器 2. 在插件中启用“W…

[C++]——学习模板

了解模板——初阶 前言&#xff1a;一、模板1.1 什么是模板1.2 模板的概念1.3 模板可以做什么1.4 泛型模板 二、函数模板2.1 函数模板概念和格式2.2 函数模板原理2.3 函数模板实例化2.3.1 隐式实例化2.3.2 显式实例化 2.4 模板参数的匹配原则2.5 函数模板声明定义分离 三、类模…

YOLOv8改进 | 2023Neck篇 | 轻量级跨尺度特征融合模块CCFM(附yaml文件+添加教程)

一、本文介绍 本文给大家带来的改进机制是轻量级跨尺度特征融合模块CCFM&#xff08;Cross-Scale Feature Fusion Module&#xff09;其主要原理是&#xff1a;将不同尺度的特征通过融合操作整合起来&#xff0c;以增强模型对于尺度变化的适应性和对小尺度对象的检测能力。我将…

电子学会C/C++编程等级考试2021年03月(六级)真题解析

C/C++等级考试(1~8级)全部真题・点这里 第1题:生日相同 2.0 在一个有180人的大班级中,存在两个人生日相同的概率非常大,现给出每个学生的名字,出生月日。试找出所有生日相同的学生。 时间限制:1000 内存限制:65536输入 第一行为整数n,表示有n个学生,n ≤ 180。此后每…

Linux中的fork()函数

目录 1.现象 2.如何实现的&#xff1f; 1.现象 1.fork()函数是用来创建一个字进程的&#xff1a; 如果这个进程是子进程&#xff0c;那么返回值返回0&#xff0c;如果是父进程的话&#xff0c;那么返回子进程的pid&#xff0c;以便父进程找到子进程&#xff0c;因为子进程的p…

理解数字化转型:3个阶段、2个分类和3类价值

导读&#xff1a;数字化转型是基于IT技术提供业务所需要的支持&#xff0c;让业务和技术真正产生交互而诞生的。我们可以从概念及内涵、分类、价值等多个维度来理解企业数字化转型。 01 数字化转型的概念及内涵 数字化转型运用5G、人工智能、大数据、云计算等新一代数字技术&a…

【信息学奥赛】拼在起跑线上,想入道就别落下自己!

编程无难事&#xff0c;只怕有心人&#xff0c;学就是了&#xff01; 文章目录 1 信息学奥赛简介2 信息学竞赛的经验回顾3 优秀参考图书推荐《信息学奥赛一本通关》4 高质量技术圈开放 1 信息学奥赛简介 信息学奥赛&#xff0c;作为全国中学生学科奥林匹克“五大学科竞赛”之一…

狗dog目标检测数据集VOC+YOLO格式1W+张

狗&#xff0c;是食肉目犬科 [11]犬属 [13]哺乳动物 [12]&#xff0c;别称犬&#xff0c;与马、牛、羊、猪、鸡并称“六畜” [13]。狗的体型大小、毛色因品种不同而不同&#xff0c;体格匀称&#xff1b;鼻吻部较长&#xff1b;眼呈卵圆形&#xff1b;两耳或竖或垂&#xff1b;…