vue3的定时器cron组件详解
作者:不想长胖的可乐鸭
该文章介绍了如何在Vue3和Antd-Vue中实现一个定时任务调度组件,该组件支持每日定时任务,并返回cron格式的字符串,父组件调用该组件后,会得到一个cron格式的时间字符串,表示任务的执行时间,例如,“000009***”表示每天的9点
先看图
仅适用于vue3+antd-vue,仅对业务需求,每日定时。
实现功能如下:


话不多说,上组件代码
组件代码如下,如需改动,找ai就完事
<!-- src/components/CronEditor.vue -->
<template>
<div class="cron-editor">
<a-form-item label="推送频率" :labelCol="{ span: 4 }">
<a-radio-group v-model:value="cronType" @change="onTypeChange">
<a-radio value="daily">每天</a-radio>
<a-radio value="weekly">每周</a-radio>
</a-radio-group>
</a-form-item>
<a-form-item v-if="cronType === 'daily'" label="推送时间" :labelCol="{ span: 4 }">
<a-time-picker
:value="dailyTime"
format="HH:mm"
value-format="HH:mm"
@change="onDailyTimeChange"
/>
</a-form-item>
<template v-if="cronType === 'weekly'">
<a-form-item label="选择星期" :labelCol="{ span: 4 }">
<a-checkbox-group v-model:value="selectedWeekdays" @change="onWeekdaysChange">
<a-checkbox v-for="day in weekdays" :key="day.value" :value="day.value">
{{ day.label }}
</a-checkbox>
</a-checkbox-group>
</a-form-item>
<a-form-item label="推送时间" :labelCol="{ span: 4 }">
<a-time-picker
:value="weeklyTime"
format="HH:mm"
value-format="HH:mm"
@change="onWeeklyTimeChange"
/>
</a-form-item>
</template>
</div>
</template>
<script setup lang="ts">
import { ref, watch } from 'vue'
const props = defineProps<{
modelValue?: string
}>()
const emit = defineEmits<{(e: 'update:modelValue', value: string): void}>()
// Cron 类型:每天或每周
const cronType = ref<'daily' | 'weekly'>('daily')
// 每天推送的时间
const dailyTime = ref<string>('09:00')
// 每周推送的星期选择
const selectedWeekdays = ref<number[]>([1]) // 默认周一
// 每周推送的时间
const weeklyTime = ref<string>('09:00')
// 星期选项
const weekdays = [
{ value: 1, label: '周一' },
{ value: 2, label: '周二' },
{ value: 3, label: '周三' },
{ value: 4, label: '周四' },
{ value: 5, label: '周五' },
{ value: 6, label: '周六' },
{ value: 7, label: '周日' }
]
// 当类型改变时重置时间
const onTypeChange = () => {
if (cronType.value === 'daily') {
generateDailyCron()
} else {
generateWeeklyCron()
}
}
// 处理每天时间变化
const onDailyTimeChange = (time: string | string[], timeString: string) => {
dailyTime.value = timeString
generateDailyCron()
}
// 处理每周时间变化
const onWeeklyTimeChange = (time: string | string[], timeString: string) => {
weeklyTime.value = timeString
generateWeeklyCron()
}
// 处理星期选择变化
const onWeekdaysChange = (values: number[]) => {
selectedWeekdays.value = values
generateWeeklyCron()
}
// 生成每天的 cron 表达式
const generateDailyCron = () => {
const time = dailyTime.value || '09:00'
const [hour, minute] = time.split(':')
const cron = `00 ${minute} ${hour} * * *`
emit('update:modelValue', cron)
}
// 生成每周的 cron 表达式
const generateWeeklyCron = () => {
if (selectedWeekdays.value.length === 0) return
const time = weeklyTime.value || '09:00'
const [hour, minute] = time.split(':')
// 如果选择了所有星期(周一到周日),则生成每天的cron表达式
if (selectedWeekdays.value.length === 7) {
const cron = `00 ${minute} ${hour} * * *`
emit('update:modelValue', cron)
} else {
const days = selectedWeekdays.value.sort().join(',')
const cron = `00 ${minute} ${hour} * * ${days}`
emit('update:modelValue', cron)
}
}
// 解析传入的 cron 表达式
const parseCronExpression = (cron: string) => {
if (!cron) return
const parts = cron.split(' ')
// 现在期望接收6个部分(包含秒)而不是5个部分
if (parts.length !== 6) return
// 解构出秒字段,但我们在解析时忽略它
const [second, minute, hour, dayOfMonth, month, dayOfWeek] = parts
// 判断是每天还是每周
if (dayOfMonth === '*' && month === '*' && dayOfWeek === '*') {
// 每天
// cronType.value = 'daily'
dailyTime.value = `${hour}:${minute}`
} else if (dayOfMonth === '*' && month === '*' && dayOfWeek !== '*') {
// 每周
cronType.value = 'weekly'
weeklyTime.value = `${hour}:${minute}`
selectedWeekdays.value = dayOfWeek.split(',').map(Number)
}
}
// 监听 modelValue 变化
watch(() => props.modelValue, (newVal) => {
if (newVal) {
parseCronExpression(newVal)
}
}, { immediate: true })
// 初始化生成 cron 表达式
generateDailyCron()
</script>
<style scoped>
.cron-editor {
width: 100%;
}
</style>
父组件调用:
<CronEditor v-model="time" /> import CronEditor from './CronEditor.vue'
组件调用会直接回传cron格式的string类型数据。周选择选择完毕默认为每天。
例如每天的九点:"00 00 09 * * *"
总结
以上为个人经验,希望能给大家一个参考,也希望大家多多支持脚本之家。
