From 400a11fc7ee0df9b24ec56e74dd1e6aa0a922f2f Mon Sep 17 00:00:00 2001 From: BianLzhaoMin <11485688+bianliangzhaomin123@user.noreply.gitee.com> Date: Tue, 10 Feb 2026 14:59:14 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BC=98=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../sMsSendManage/loopSend/Crontab/index.vue | 276 +++++++----------- src/views/sMsSendManage/loopSend/edit.vue | 63 ++-- 2 files changed, 143 insertions(+), 196 deletions(-) diff --git a/src/views/sMsSendManage/loopSend/Crontab/index.vue b/src/views/sMsSendManage/loopSend/Crontab/index.vue index ec72b32..1a3a190 100644 --- a/src/views/sMsSendManage/loopSend/Crontab/index.vue +++ b/src/views/sMsSendManage/loopSend/Crontab/index.vue @@ -64,17 +64,6 @@ class="time-input" /> -
- - -
@@ -137,7 +126,6 @@ const periodOptions = [ { label: '每天', value: 'day' }, { label: '每小时', value: 'hour' }, { label: '每分钟', value: 'minute' }, - { label: '每秒', value: 'second' }, ] // 星期选项 @@ -152,34 +140,30 @@ const weekOptions = [ ] // 选中的周期 -const selectedPeriod = ref('second') +const selectedPeriod = ref('minute') // 选中的星期(用于每周) const selectedWeek = ref(1) // 时间值 const timeValues = ref({ - second: 0, minute: 0, hour: 0, day: 1, month: 1, }) -// Cron表达式对象 +// Cron表达式对象(5位标准格式:分钟 小时 日 月 星期) const crontabValueObj = ref({ - second: '*', min: '*', hour: '*', day: '*', month: '*', week: '?', - year: '', }) // 执行描述 const executionDesc = computed(() => { const periodMap = { - second: '每秒执行', minute: '每分钟执行', hour: '每小时执行', day: '每天执行', @@ -187,16 +171,12 @@ const executionDesc = computed(() => { month: '每月执行', year: '每年执行', } - return periodMap[selectedPeriod.value] || '每秒执行' + return periodMap[selectedPeriod.value] || '每分钟执行' }) // 显示控制 const showTimeInputs = computed(() => { - return selectedPeriod.value !== 'second' -}) - -const showSecond = computed(() => { - return ['minute', 'hour', 'day', 'week', 'month', 'year'].includes(selectedPeriod.value) + return selectedPeriod.value !== 'minute' }) const showMinute = computed(() => { @@ -219,23 +199,10 @@ const showWeek = computed(() => { return selectedPeriod.value === 'week' }) -// Cron表达式字符串 +// Cron表达式字符串(6位格式:秒 分钟 小时 日 月 星期,秒固定为0) const crontabValueString = computed(() => { const obj = crontabValueObj.value - return ( - obj.second + - ' ' + - obj.min + - ' ' + - obj.hour + - ' ' + - obj.day + - ' ' + - obj.month + - ' ' + - obj.week + - (obj.year === '' ? '' : ' ' + obj.year) - ) + return '0 ' + obj.min + ' ' + obj.hour + ' ' + obj.day + ' ' + obj.month + ' ' + obj.week }) // 监听时间值变化,更新Cron表达式 @@ -247,91 +214,67 @@ watch( { deep: true }, ) -// 更新Cron表达式 +// 更新Cron表达式(生成6位格式:秒固定为0,分钟 小时 日 月 星期) function updateCronExpression() { switch (selectedPeriod.value) { - case 'second': - // 每秒:* * * * * ? * - crontabValueObj.value = { - second: '*', - min: '*', - hour: '*', - day: '*', - month: '*', - week: '?', - year: '', - } - break case 'minute': - // 每分钟:指定秒 * * * * ? * + // 每分钟:* * * * ? crontabValueObj.value = { - second: String(timeValues.value.second), min: '*', hour: '*', day: '*', month: '*', week: '?', - year: '', } break case 'hour': - // 每小时:指定秒 指定分钟 * * * ? * + // 每小时:指定分钟 * * * ? crontabValueObj.value = { - second: String(timeValues.value.second), min: String(timeValues.value.minute), hour: '*', day: '*', month: '*', week: '?', - year: '', } break case 'day': - // 每天:指定秒 指定分钟 指定小时 * * ? * + // 每天:指定分钟 指定小时 * * ? crontabValueObj.value = { - second: String(timeValues.value.second), min: String(timeValues.value.minute), hour: String(timeValues.value.hour), day: '*', month: '*', week: '?', - year: '', } break case 'week': - // 每周:指定秒 指定分钟 指定小时 ? * 指定星期 * + // 每周:指定分钟 指定小时 ? * 指定星期 crontabValueObj.value = { - second: String(timeValues.value.second), min: String(timeValues.value.minute), hour: String(timeValues.value.hour), day: '?', month: '*', week: String(selectedWeek.value), - year: '', } break case 'month': - // 每月:指定秒 指定分钟 指定小时 指定日期 * ? * + // 每月:指定分钟 指定小时 指定日期 * ? crontabValueObj.value = { - second: String(timeValues.value.second), min: String(timeValues.value.minute), hour: String(timeValues.value.hour), day: String(timeValues.value.day), month: '*', week: '?', - year: '', } break case 'year': - // 每年:指定秒 指定分钟 指定小时 指定日期 指定月份 ? * + // 每年:指定分钟 指定小时 指定日期 指定月份 ? crontabValueObj.value = { - second: String(timeValues.value.second), min: String(timeValues.value.minute), hour: String(timeValues.value.hour), day: String(timeValues.value.day), month: String(timeValues.value.month), week: '?', - year: '', } break } @@ -349,115 +292,109 @@ function handleWeekChange(week) { updateCronExpression() } -// 解析表达式 +// 解析表达式(支持5位和6位格式,生成时统一为6位格式:0 分钟 小时 日 月 星期) function resolveExp() { if (props.expression) { const arr = props.expression.split(/\s+/) - if (arr.length >= 6) { - // 6位以上是合法表达式 - const obj = { - second: arr[0], + let obj = {} + + // 判断是5位还是6位表达式 + if (arr.length === 5) { + // 5位格式:分钟 小时 日 月 星期(兼容旧数据) + obj = { + min: arr[0], + hour: arr[1], + day: arr[2], + month: arr[3], + week: arr[4], + } + } else if (arr.length >= 6) { + // 6位或7位格式:秒 分钟 小时 日 月 星期 [年] + // 秒字段(arr[0])固定为0,忽略它,使用分钟作为第一位 + obj = { min: arr[1], hour: arr[2], day: arr[3], month: arr[4], week: arr[5], - year: arr[6] ? arr[6] : '', } - crontabValueObj.value = { ...obj } + } else { + clearCron() + return + } - // 根据表达式反推周期选择 - // 判断是否为数字(简单判断) - const isNumber = (str) => { - return /^\d+$/.test(str) - } + crontabValueObj.value = { ...obj } - if ( - obj.second === '*' && - obj.min === '*' && - obj.hour === '*' && - obj.day === '*' && - obj.month === '*' && - obj.week === '?' - ) { - selectedPeriod.value = 'second' - } else if ( - isNumber(obj.second) && - obj.min === '*' && - obj.hour === '*' && - obj.day === '*' && - obj.month === '*' && - obj.week === '?' - ) { - selectedPeriod.value = 'minute' - timeValues.value.second = parseInt(obj.second) || 0 - } else if ( - isNumber(obj.second) && - isNumber(obj.min) && - obj.hour === '*' && - obj.day === '*' && - obj.month === '*' && - obj.week === '?' - ) { - selectedPeriod.value = 'hour' - timeValues.value.second = parseInt(obj.second) || 0 - timeValues.value.minute = parseInt(obj.min) || 0 - } else if ( - isNumber(obj.second) && - isNumber(obj.min) && - isNumber(obj.hour) && - obj.day === '*' && - obj.month === '*' && - obj.week === '?' - ) { - selectedPeriod.value = 'day' - timeValues.value.second = parseInt(obj.second) || 0 - timeValues.value.minute = parseInt(obj.min) || 0 - timeValues.value.hour = parseInt(obj.hour) || 0 - } else if ( - isNumber(obj.second) && - isNumber(obj.min) && - isNumber(obj.hour) && - obj.day === '?' && - obj.month === '*' && - isNumber(obj.week) - ) { - selectedPeriod.value = 'week' - timeValues.value.second = parseInt(obj.second) || 0 - timeValues.value.minute = parseInt(obj.min) || 0 - timeValues.value.hour = parseInt(obj.hour) || 0 - selectedWeek.value = parseInt(obj.week) || 1 - } else if ( - isNumber(obj.second) && - isNumber(obj.min) && - isNumber(obj.hour) && - isNumber(obj.day) && - obj.month === '*' && - obj.week === '?' - ) { - selectedPeriod.value = 'month' - timeValues.value.second = parseInt(obj.second) || 0 - timeValues.value.minute = parseInt(obj.min) || 0 - timeValues.value.hour = parseInt(obj.hour) || 0 - timeValues.value.day = parseInt(obj.day) || 1 - } else if ( - isNumber(obj.second) && - isNumber(obj.min) && - isNumber(obj.hour) && - isNumber(obj.day) && - isNumber(obj.month) && - obj.week === '?' - ) { - selectedPeriod.value = 'year' - timeValues.value.second = parseInt(obj.second) || 0 - timeValues.value.minute = parseInt(obj.min) || 0 - timeValues.value.hour = parseInt(obj.hour) || 0 - timeValues.value.day = parseInt(obj.day) || 1 - timeValues.value.month = parseInt(obj.month) || 1 - } else { - // 如果无法匹配,默认使用每秒 - selectedPeriod.value = 'second' - } + // 根据表达式反推周期选择 + // 判断是否为数字(简单判断) + const isNumber = (str) => { + return /^\d+$/.test(str) + } + + if ( + obj.min === '*' && + obj.hour === '*' && + obj.day === '*' && + obj.month === '*' && + obj.week === '?' + ) { + selectedPeriod.value = 'minute' + } else if ( + isNumber(obj.min) && + obj.hour === '*' && + obj.day === '*' && + obj.month === '*' && + obj.week === '?' + ) { + selectedPeriod.value = 'hour' + timeValues.value.minute = parseInt(obj.min) || 0 + } else if ( + isNumber(obj.min) && + isNumber(obj.hour) && + obj.day === '*' && + obj.month === '*' && + obj.week === '?' + ) { + selectedPeriod.value = 'day' + timeValues.value.minute = parseInt(obj.min) || 0 + timeValues.value.hour = parseInt(obj.hour) || 0 + } else if ( + isNumber(obj.min) && + isNumber(obj.hour) && + obj.day === '?' && + obj.month === '*' && + isNumber(obj.week) + ) { + selectedPeriod.value = 'week' + timeValues.value.minute = parseInt(obj.min) || 0 + timeValues.value.hour = parseInt(obj.hour) || 0 + selectedWeek.value = parseInt(obj.week) || 1 + } else if ( + isNumber(obj.min) && + isNumber(obj.hour) && + isNumber(obj.day) && + obj.month === '*' && + obj.week === '?' + ) { + selectedPeriod.value = 'month' + timeValues.value.minute = parseInt(obj.min) || 0 + timeValues.value.hour = parseInt(obj.hour) || 0 + timeValues.value.day = parseInt(obj.day) || 1 + } else if ( + isNumber(obj.min) && + isNumber(obj.hour) && + isNumber(obj.day) && + isNumber(obj.month) && + obj.week === '?' + ) { + selectedPeriod.value = 'year' + timeValues.value.minute = parseInt(obj.min) || 0 + timeValues.value.hour = parseInt(obj.hour) || 0 + timeValues.value.day = parseInt(obj.day) || 1 + timeValues.value.month = parseInt(obj.month) || 1 + } else { + // 如果无法匹配,默认使用每分钟 + selectedPeriod.value = 'minute' } } else { clearCron() @@ -477,10 +414,9 @@ function submitFill() { // 重置 function clearCron() { - selectedPeriod.value = 'second' + selectedPeriod.value = 'minute' selectedWeek.value = 1 timeValues.value = { - second: 0, minute: 0, hour: 0, day: 1, diff --git a/src/views/sMsSendManage/loopSend/edit.vue b/src/views/sMsSendManage/loopSend/edit.vue index eefa129..4ca632a 100644 --- a/src/views/sMsSendManage/loopSend/edit.vue +++ b/src/views/sMsSendManage/loopSend/edit.vue @@ -452,9 +452,29 @@ const parseCronToChinese = (cronExpression) => { if (!cronExpression) return '' const parts = cronExpression.trim().split(/\s+/) - if (parts.length < 6) return '' + if (parts.length < 5) return '' - const [second, minute, hour, day, month, week, year] = parts + // 判断是5位格式(分钟 小时 日 月 星期)还是6/7位格式(秒 分钟 小时 日 月 星期 [年]) + let second, minute, hour, day, month, week, year + if (parts.length === 5) { + // 5位格式:分钟 小时 日 月 星期,秒默认为0 + second = '0' + minute = parts[0] + hour = parts[1] + day = parts[2] + month = parts[3] + week = parts[4] + year = '' + } else { + // 6位或7位格式:秒 分钟 小时 日 月 星期 [年] + second = parts[0] + minute = parts[1] + hour = parts[2] + day = parts[3] + month = parts[4] + week = parts[5] + year = parts[6] || '' + } // 格式化时间(时分秒) const formatTime = (h, m, s) => { @@ -539,7 +559,6 @@ const parseCronToChinese = (cronExpression) => { // 特殊情况1:每天固定时间执行(最常用) if ( - second !== '?' && minute !== '?' && hour !== '?' && day === '*' && @@ -547,11 +566,11 @@ const parseCronToChinese = (cronExpression) => { week === '?' && (!year || year === '*') ) { - const s = getSingleValue(second) + const s = second === '?' ? '0' : getSingleValue(second) const m = getSingleValue(minute) const h = getSingleValue(hour) - if (!hasStep(second) && !hasStep(minute) && !hasStep(hour)) { + if (!hasStep(minute) && !hasStep(hour)) { let result = `每天${formatTime(h, m, s)}执行` // 清理所有可能的*符号 result = result.replace(/(\d)\*/g, '$10').replace(/\*/g, '0') @@ -561,7 +580,6 @@ const parseCronToChinese = (cronExpression) => { // 特殊情况2:每周固定时间执行 if ( - second !== '?' && minute !== '?' && hour !== '?' && day === '?' && @@ -570,12 +588,12 @@ const parseCronToChinese = (cronExpression) => { week !== '*' && (!year || year === '*') ) { - const s = getSingleValue(second) + const s = second === '?' ? '0' : getSingleValue(second) const m = getSingleValue(minute) const h = getSingleValue(hour) const weekDesc = parseWeek(week) - if (!hasStep(second) && !hasStep(minute) && !hasStep(hour)) { + if (!hasStep(minute) && !hasStep(hour)) { let result = `${weekDesc},${formatTime(h, m, s)}执行` // 清理所有可能的*符号 result = result.replace(/(\d)\*/g, '$10').replace(/\*/g, '0') @@ -585,7 +603,6 @@ const parseCronToChinese = (cronExpression) => { // 特殊情况3:每月固定日期执行 if ( - second !== '?' && minute !== '?' && hour !== '?' && day !== '*' && @@ -594,12 +611,12 @@ const parseCronToChinese = (cronExpression) => { week === '?' && (!year || year === '*') ) { - const s = getSingleValue(second) + const s = second === '?' ? '0' : getSingleValue(second) const m = getSingleValue(minute) const h = getSingleValue(hour) const dayDesc = parseDay(day) - if (!hasStep(second) && !hasStep(minute) && !hasStep(hour)) { + if (!hasStep(minute) && !hasStep(hour)) { let result = `${dayDesc},${formatTime(h, m, s)}执行` // 清理所有可能的*符号 result = result.replace(/(\d)\*/g, '$10').replace(/\*/g, '0') @@ -609,7 +626,6 @@ const parseCronToChinese = (cronExpression) => { // 特殊情况4:每年固定日期时间执行 if ( - second !== '?' && minute !== '?' && hour !== '?' && day !== '*' && @@ -618,13 +634,13 @@ const parseCronToChinese = (cronExpression) => { week === '?' && (!year || year === '*' || year === '') ) { - const s = getSingleValue(second) + const s = second === '?' ? '0' : getSingleValue(second) const m = getSingleValue(minute) const h = getSingleValue(hour) const dayDesc = parseDay(day, true) // 每年模式,不显示"每月" const monthDesc = parseMonth(month) - if (!hasStep(second) && !hasStep(minute) && !hasStep(hour)) { + if (!hasStep(minute) && !hasStep(hour)) { let result = `每年${monthDesc}${dayDesc},${formatTime(h, m, s)}执行` // 清理所有可能的*符号 result = result.replace(/(\d)\*/g, '$10').replace(/\*/g, '0') @@ -679,11 +695,12 @@ const parseCronToChinese = (cronExpression) => { timeParts.push('**') } - if (second !== '*' && !hasStep(second)) { + // 秒字段:如果是5位格式或秒为?,默认为00 + if (second && second !== '*' && second !== '?' && !hasStep(second)) { const s = getSingleValue(second) timeParts.push(s.padStart(2, '0')) } else { - timeParts.push('**') + timeParts.push('00') // 默认秒为00 } // 如果时间部分有具体值,添加到描述中 @@ -704,22 +721,16 @@ const parseCronToChinese = (cronExpression) => { const step = minute.split('/')[1] partsDesc.push(`每${step}分钟`) } - if (second.includes('/') && second.split('/')[0] === '*') { + // 秒的步长表达式只在6/7位格式中处理 + if (second && second.includes('/') && second.split('/')[0] === '*') { const step = second.split('/')[1] partsDesc.push(`每${step}秒`) } // 构建最终描述 if (partsDesc.length === 0) { - if ( - second === '*' && - minute === '*' && - hour === '*' && - day === '*' && - month === '*' && - week === '?' - ) { - return '每秒执行' + if (minute === '*' && hour === '*' && day === '*' && month === '*' && week === '?') { + return '每分钟执行' } return `Cron表达式:${cronExpression}` }