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

news2024/12/23 4:25:20

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

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);
    }

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

智能优化算法应用:基于蝙蝠算法3D无线传感器网络(WSN)覆盖优化 - 附代码

智能优化算法应用&#xff1a;基于蝙蝠算法3D无线传感器网络(WSN)覆盖优化 - 附代码 文章目录 智能优化算法应用&#xff1a;基于蝙蝠算法3D无线传感器网络(WSN)覆盖优化 - 附代码1.无线传感网络节点模型2.覆盖数学模型及分析3.蝙蝠算法4.实验参数设定5.算法结果6.参考文献7.MA…

【MQ】Rocketmq如何保证消息不丢失

文章目录 前言一、前言二、消息什么情况会丢失&#xff1f;三、如何保障消息不丢失&#xff1f;3.1、生产者端3.2、Broker端3.3、消费者端 四、总结 前言 一、前言 RocketMQ可以理解成一个特殊的存储系统&#xff0c;这个存储系统特殊之处数据是一般只会被使用一次&#xff0…

Mysql安装教程(zip版)

去官网下载&#xff1a; 我这有个5.7.9的版本&#xff1a; 链接&#xff1a;https://pan.baidu.com/s/1H6Qs2mP0vzBklmD_ID7VLg 提取码&#xff1a;8xnk 管理员cmd 到mysql安装目录的bin下面 1、mysqld --initialize-insecure --usermysql //初始化执行成功之后会生…

四六级高频词组3

目录 词组 参考链接 词组 101. by chance&#xff08;accidentally&#xff0c; by accident&#xff09;偶然 102. for a change换换环境&#xff08;花样等&#xff09; 103. charge sb. with …控告某人犯有… 104. in charge of &#xff08;responsible for&#xff…

小程序商城免费搭建之b2b2c o2o 多商家入驻商城 直播带货商城 电子商务b2b2c o2o 多商家入驻商城 直播带货商城 电子商务 鸿鹄云商

1. 涉及平台 平台管理、商家端&#xff08;PC端、手机端&#xff09;、买家平台&#xff08;H5/公众号、小程序、APP端&#xff08;IOS/Android&#xff09;、微服务平台&#xff08;业务服务&#xff09; 2. 核心架构 Spring Cloud、Spring Boot、Mybatis、Redis 3. 前端框架…

音视频技术开发周刊 | 323

每周一期&#xff0c;纵览音视频技术领域的干货。 新闻投稿&#xff1a;contributelivevideostack.com。 Meta牵头组建开源「AI复仇者联盟」&#xff0c;AMD等盟友800亿美元力战OpenAI英伟达 超过50家科技大厂名校和机构&#xff0c;共同成立了全新的人工智能联盟。以开源为旗号…

c++ multimap

multimap创建 multimap<string , string> m; m.insert(make_pair("12","3234")); m.insert(make_pair("12","3234")); m.insert(make_pair("12","3234"));遍历 multimap<string , string> m; m.inser…

Nacos配置管理-nacos集群搭建

一、集群结构图 其中包含3个nacos节点&#xff0c;然后一个负载均衡器代理3个Nacos。这里负载均衡器可以使用 nginx。 二、 计划实现 --计划架构-- 3个Nacos节点&#xff1b; 3个mysql库&#xff1b; --计划节点地址-- 三、集群搭建 3.1 基本步骤 &#xff08;1&#…

Camunda 7.x 系列【60】流程分类

有道无术,术尚可求,有术无道,止于术。 本系列Spring Boot 版本 2.7.9 本系列Camunda 版本 7.19.0 源码地址:https://gitee.com/pearl-organization/camunda-study-demo 文章目录 1. 前言2. 案例演示2.1 后端2.2 前端2.3 测试1. 前言 钉钉中的OA审批分类: 企业级的业务…

SQL自学通之函数 :对数据的进一步处理

目录 一、目标 二、汇总函数 COUNT SUM AVG MAX MIN VARIANCE STDDEV 三、日期/时间函数 ADD_MONTHS LAST_DAY MONTHS_BETWEEN NEW_TIME NEXT_DAY SYSDATE 四、数学函数 ABS CEIL 和FLOOR COS、 COSH 、SIN 、SINH、 TAN、 TANH EXP LN and LOG MOD POW…

软件测试之缺陷管理

一、软件缺陷的基本概念 1、软件缺陷的基本概念主要分为&#xff1a;缺陷、故障、失效这三种。 &#xff08;1&#xff09;缺陷&#xff08;defect&#xff09;&#xff1a;存在于软件之中的偏差&#xff0c;可被激活&#xff0c;以静态的形式存在于软件内部&#xff0c;相当…

输电线路故障监测系统:实现电力传输的智能化管理

随着科技的不断发展&#xff0c;电力系统的安全稳定运行对于国家经济和人民生活至关重要。为了提高电力系统的运行效率和安全性&#xff0c;恒峰智慧科技研发的输电线路故障监测系统HFP-GZS2000应运而生。本文将介绍输电线路分布式故障定位及隐患监测装置的技术原理、功能特点以…

洗衣行业在线下单小程序源码系统:上门取货,轻松操作,简单便捷 带完整的安装部署教程

传统洗衣行业存在一些问题&#xff0c;如店面覆盖范围有限、取送时间较长、服务水平参差不齐等。随着消费升级和移动互联网技术的发展&#xff0c;消费者对于洗衣服务的需求也在发生变化。他们需要更便捷、高效、优质的服务方式。因此&#xff0c;开发一款基于移动互联网技术的…

vscode 远程连接内网服务器和通过跳板机远程连接外网服务器

1.打开vscode congfig文件&#xff0c;输入相应信息如下图 若本地没有id_rsa文件&#xff0c;可打开cmd进入.ssh目录下输入命令&#xff1a;ssh-keygen&#xff0c;创建该文件&#xff0c;会提示输入该文件保存地址以及设置秘钥密码&#xff08;最好不要设置密码&#xff0c;不…

Java EE 多线程之多线程案例

文章目录 1. 多线程案例1.1 单例模式1.1.1 饿汉模式1.1.2 懒汉模式1.1.3 多线程下的单例模式 1.2 阻塞队列1.2.1 阻塞队列定义1.2.2 生产者消费者模型的意义1.2.4 标准库中的阻塞队列1.2.5 实现阻塞队列1.2.6 用阻塞队列实现生产者消费者模型 1.3 实现定时器1.3.1 标准库中的定…

在接触新的游戏引擎的时候,如何能快速地熟悉并开发出一款新游戏?

引言 大家好&#xff0c;今天分享点个人经验。 有一定编程经验或者游戏开发经验的小伙伴&#xff0c;在接触新的游戏引擎的时候&#xff0c;如何能快速地熟悉并开发出一款新游戏&#xff1f; 利用现成开发框架。 1.什么是开发框架&#xff1f; 开发框架&#xff0c;顾名思…

Slice和MB

Slice 编码帧或场分割成若干个slice独立编码,各Slice之间相互独立,Slice中又有多个宏块构成,各Slice中的宏块个数不一定要一致,可以有以下几种Slice的划分方式: 一个picture一个Slice一个picture多个Slice,每个Slice的宏块数目一致一个picture多个Slice,每个Slice的宏块…

注意力机制和自注意力机制

有很多自己的理解&#xff0c;仅供参考 Attention注意力机制 对于一张图片&#xff0c;我们第一眼看上去&#xff0c;眼睛会首先注意到一些重点的区域&#xff0c;因为这些区域可能包含更多或更重要的信息&#xff0c;这就是注意力机制&#xff0c;我们会把我们的焦点聚焦在比…

cadence中如何在更新原理图封装

cadence中如何在更新原理图封装 一、更改原理图封装 当原理图画好后&#xff0c;如果我们发现某个封装错了&#xff0c;需要改动&#xff0c;需要找到你最初画Library中器件封装文件打开&#xff0c;进行修改&#xff0c;修改好后保存。 二、更新封装 保存好后&#xff0c;…

性能测试:方法、工具与最佳实践

目录 前言 1. 为什么进行性能测试&#xff1f; 2. 性能测试方法 3. 性能测试工具 Apache JMeter: LoadRunner: Gatling: Apache ab (Apache Benchmark): Locust: Tsung: BlazeMeter: K6: Neoload: WebLOAD: 4. 最佳实践 设定明确的性能测试目标&#xff1a; 模…