2
0
mirror of https://github.com/acepanel/panel.git synced 2026-02-04 09:13:49 +08:00

feat: 新的Cron表达式生成器

This commit is contained in:
2025-12-31 17:38:08 +08:00
parent b86fc187d7
commit 80fde60526
4 changed files with 430 additions and 14 deletions

View File

@@ -0,0 +1,260 @@
<script setup lang="ts">
import { useGettext } from 'vue3-gettext'
import CronPreview from './CronPreview.vue'
const { $gettext } = useGettext()
// 生成的 Cron 表达式值
const value = defineModel<string>('value', {
type: String,
required: true
})
// 当前选择的周期类型
const selectedOption = ref<string>('every-n-minutes')
// 表单数据
const formData = ref({
// Every N 系列
nMinutes: 30, // 每 N 分钟
nHours: 2, // 每 N 小时
nDays: 3, // 每 N 天
// 时间配置
minute: 30, // 分钟
hour: 1, // 小时
day: 3, // 日期1-31
month: 1, // 月份1-12
weekday: 1, // 星期0-60=周日)
// 自定义表达式
customCron: '* * * * *'
})
// 周期选项
const options = [
{ label: $gettext('Every N Minutes'), value: 'every-n-minutes' },
{ label: $gettext('Every N Hours'), value: 'every-n-hours' },
{ label: $gettext('Every N Days'), value: 'every-n-days' },
{ label: $gettext('Hourly'), value: 'every-hour' },
{ label: $gettext('Daily'), value: 'every-day' },
{ label: $gettext('Weekly'), value: 'every-week' },
{ label: $gettext('Monthly'), value: 'every-month' },
{ label: $gettext('Yearly'), value: 'every-year' },
{ label: $gettext('Custom'), value: 'custom' }
]
// 星期选项
const weekdayOptions = [
{ label: $gettext('Sunday'), value: 0 },
{ label: $gettext('Monday'), value: 1 },
{ label: $gettext('Tuesday'), value: 2 },
{ label: $gettext('Wednesday'), value: 3 },
{ label: $gettext('Thursday'), value: 4 },
{ label: $gettext('Friday'), value: 5 },
{ label: $gettext('Saturday'), value: 6 }
]
// 月份选项
const monthOptions = Array.from({ length: 12 }, (_, i) => ({
label: $gettext('Month %{month}', { month: String(i + 1) }),
value: i + 1
}))
// 生成 Cron 表达式
const generateCron = (): string => {
const { minute, hour, day, month, weekday, nMinutes, nHours, nDays, customCron } = formData.value
switch (selectedOption.value) {
case 'every-n-minutes':
// 每 N 分钟:*/N * * * *
return `*/${nMinutes} * * * *`
case 'every-n-hours':
// 每 N 小时的第 M 分钟M */N * * *
return `${minute} */${nHours} * * *`
case 'every-n-days':
// 每 N 天的 H 时 M 分M H */N * *
return `${minute} ${hour} */${nDays} * *`
case 'every-hour':
// 每小时的第 M 分钟M * * * *
return `${minute} * * * *`
case 'every-day':
// 每天 H 时 M 分M H * * *
return `${minute} ${hour} * * *`
case 'every-week':
// 每周几的 H 时 M 分M H * * W
return `${minute} ${hour} * * ${weekday}`
case 'every-month':
// 每月 D 日 H 时 M 分M H D * *
return `${minute} ${hour} ${day} * *`
case 'every-year':
// 每年 Mon 月 D 日 H 时 M 分M H D Mon *
return `${minute} ${hour} ${day} ${month} *`
case 'custom':
return customCron
default:
return '* * * * *'
}
}
// 监听变化,更新 Cron 表达式
watch(
[selectedOption, formData],
() => {
value.value = generateCron()
},
{ deep: true, immediate: true }
)
// 判断是否显示某个输入框
const showMonth = computed(() => selectedOption.value === 'every-year')
const showDay = computed(() =>
['every-n-days', 'every-month', 'every-year'].includes(selectedOption.value)
)
const showWeekday = computed(() => selectedOption.value === 'every-week')
const showHour = computed(() =>
['every-n-days', 'every-day', 'every-week', 'every-month', 'every-year'].includes(
selectedOption.value
)
)
const showMinute = computed(() =>
[
'every-n-minutes',
'every-n-hours',
'every-n-days',
'every-hour',
'every-day',
'every-week',
'every-month',
'every-year'
].includes(selectedOption.value)
)
const showNDays = computed(() => selectedOption.value === 'every-n-days')
const showNHours = computed(() => selectedOption.value === 'every-n-hours')
const showNMinutes = computed(() => selectedOption.value === 'every-n-minutes')
const showCustom = computed(() => selectedOption.value === 'custom')
</script>
<template>
<n-flex vertical :size="12">
<n-flex align="center" :wrap="false">
<!-- 周期类型选择 -->
<n-select
v-model:value="selectedOption"
:options="options"
:style="{ width: '160px', flexShrink: 0 }"
/>
<!-- N 分钟 -->
<n-input-number
v-if="showNMinutes"
v-model:value="formData.nMinutes"
:min="1"
:max="59"
:style="{ width: '140px' }"
>
<template #suffix>{{ $gettext('Minutes') }}</template>
</n-input-number>
<!-- N 小时 -->
<n-input-number
v-if="showNHours"
v-model:value="formData.nHours"
:min="1"
:max="23"
:style="{ width: '140px' }"
>
<template #suffix>{{ $gettext('Hours') }}</template>
</n-input-number>
<!-- N -->
<n-input-number
v-if="showNDays"
v-model:value="formData.nDays"
:min="1"
:max="31"
:style="{ width: '140px' }"
>
<template #suffix>{{ $gettext('Days') }}</template>
</n-input-number>
<!-- 月份选择每年 -->
<n-select
v-if="showMonth"
v-model:value="formData.month"
:options="monthOptions"
:style="{ width: '140px' }"
/>
<!-- 日期选择每月每年 -->
<n-input-number
v-if="showDay && !showNDays"
v-model:value="formData.day"
:min="1"
:max="31"
:style="{ width: '140px' }"
>
<template #suffix>{{ $gettext('Day') }}</template>
</n-input-number>
<!-- 星期选择每周 -->
<n-select
v-if="showWeekday"
v-model:value="formData.weekday"
:options="weekdayOptions"
:style="{ width: '140px' }"
/>
<!-- 小时选择 -->
<n-input-number
v-if="showHour"
v-model:value="formData.hour"
:min="0"
:max="23"
:style="{ width: '140px' }"
>
<template #suffix>{{ $gettext('Hour') }}</template>
</n-input-number>
<!-- 分钟选择 -->
<n-input-number
v-if="showMinute && !showNMinutes"
v-model:value="formData.minute"
:min="0"
:max="59"
:style="{ width: '140px' }"
>
<template #suffix>{{ $gettext('Minute') }}</template>
</n-input-number>
<!-- 自定义 Cron 表达式 -->
<n-input
v-if="showCustom"
v-model:value="formData.customCron"
:placeholder="$gettext('Enter Cron expression')"
:style="{ width: '240px' }"
/>
</n-flex>
<!-- 预览 -->
<n-text depth="3">
<cron-preview :cron="value" />
</n-text>
</n-flex>
</template>
<style scoped lang="scss"></style>