This commit is contained in:
BianLzhaoMin 2026-01-30 15:15:52 +08:00
parent 602f75ceb4
commit 5a9237a137
11 changed files with 2231 additions and 4 deletions

View File

@ -0,0 +1,174 @@
<template>
<el-form>
<el-form-item>
<el-radio v-model='radioValue' :value="1">
允许的通配符[, - * ? / L W]
</el-radio>
</el-form-item>
<el-form-item>
<el-radio v-model='radioValue' :value="2">
不指定
</el-radio>
</el-form-item>
<el-form-item>
<el-radio v-model='radioValue' :value="3">
周期从
<el-input-number v-model='cycle01' :min="1" :max="30" /> -
<el-input-number v-model='cycle02' :min="cycle01 + 1" :max="31" />
</el-radio>
</el-form-item>
<el-form-item>
<el-radio v-model='radioValue' :value="4">
<el-input-number v-model='average01' :min="1" :max="30" /> 号开始
<el-input-number v-model='average02' :min="1" :max="31 - average01" /> 日执行一次
</el-radio>
</el-form-item>
<el-form-item>
<el-radio v-model='radioValue' :value="5">
每月
<el-input-number v-model='workday' :min="1" :max="31" /> 号最近的那个工作日
</el-radio>
</el-form-item>
<el-form-item>
<el-radio v-model='radioValue' :value="6">
本月最后一天
</el-radio>
</el-form-item>
<el-form-item>
<el-radio v-model='radioValue' :value="7">
指定
<el-select clearable v-model="checkboxList" placeholder="可多选" multiple :multiple-limit="10">
<el-option v-for="item in 31" :key="item" :label="item" :value="item" />
</el-select>
</el-radio>
</el-form-item>
</el-form>
</template>
<script setup>
const emit = defineEmits(['update'])
const props = defineProps({
cron: {
type: Object,
default: {
second: "*",
min: "*",
hour: "*",
day: "*",
month: "*",
week: "?",
year: "",
}
},
check: {
type: Function,
default: () => {
}
}
})
const radioValue = ref(1)
const cycle01 = ref(1)
const cycle02 = ref(2)
const average01 = ref(1)
const average02 = ref(1)
const workday = ref(1)
const checkboxList = ref([])
const checkCopy = ref([1])
const cycleTotal = computed(() => {
cycle01.value = props.check(cycle01.value, 1, 30)
cycle02.value = props.check(cycle02.value, cycle01.value + 1, 31)
return cycle01.value + '-' + cycle02.value
})
const averageTotal = computed(() => {
average01.value = props.check(average01.value, 1, 30)
average02.value = props.check(average02.value, 1, 31 - average01.value)
return average01.value + '/' + average02.value
})
const workdayTotal = computed(() => {
workday.value = props.check(workday.value, 1, 31)
return workday.value + 'W'
})
const checkboxString = computed(() => {
return checkboxList.value.join(',')
})
watch(() => props.cron.day, value => changeRadioValue(value))
watch([radioValue, cycleTotal, averageTotal, workdayTotal, checkboxString], () => onRadioChange())
function changeRadioValue(value) {
if (value === "*") {
radioValue.value = 1
} else if (value === "?") {
radioValue.value = 2
} else if (value.indexOf("-") > -1) {
const indexArr = value.split('-')
cycle01.value = Number(indexArr[0])
cycle02.value = Number(indexArr[1])
radioValue.value = 3
} else if (value.indexOf("/") > -1) {
const indexArr = value.split('/')
average01.value = Number(indexArr[0])
average02.value = Number(indexArr[1])
radioValue.value = 4
} else if (value.indexOf("W") > -1) {
const indexArr = value.split("W")
workday.value = Number(indexArr[0])
radioValue.value = 5
} else if (value === "L") {
radioValue.value = 6
} else {
checkboxList.value = [...new Set(value.split(',').map(item => Number(item)))]
radioValue.value = 7
}
}
//
function onRadioChange() {
if (radioValue.value === 2 && props.cron.week === '?') {
emit('update', 'week', '*', 'day')
}
if (radioValue.value !== 2 && props.cron.week !== '?') {
emit('update', 'week', '?', 'day')
}
switch (radioValue.value) {
case 1:
emit('update', 'day', '*', 'day')
break
case 2:
emit('update', 'day', '?', 'day')
break
case 3:
emit('update', 'day', cycleTotal.value, 'day')
break
case 4:
emit('update', 'day', averageTotal.value, 'day')
break
case 5:
emit('update', 'day', workdayTotal.value, 'day')
break
case 6:
emit('update', 'day', 'L', 'day')
break
case 7:
if (checkboxList.value.length === 0) {
checkboxList.value.push(checkCopy.value[0])
} else {
checkCopy.value = checkboxList.value
}
emit('update', 'day', checkboxString.value, 'day')
break
}
}
</script>
<style lang="scss" scoped>
.el-input-number--small, .el-select, .el-select--small {
margin: 0 0.2rem;
}
.el-select, .el-select--small {
width: 18.8rem;
}
</style>

View File

@ -0,0 +1,133 @@
<template>
<el-form>
<el-form-item>
<el-radio v-model='radioValue' :value="1">
小时允许的通配符[, - * /]
</el-radio>
</el-form-item>
<el-form-item>
<el-radio v-model='radioValue' :value="2">
周期从
<el-input-number v-model='cycle01' :min="0" :max="22" /> -
<el-input-number v-model='cycle02' :min="cycle01 + 1" :max="23" />
</el-radio>
</el-form-item>
<el-form-item>
<el-radio v-model='radioValue' :value="3">
<el-input-number v-model='average01' :min="0" :max="22" /> 时开始
<el-input-number v-model='average02' :min="1" :max="23 - average01" /> 小时执行一次
</el-radio>
</el-form-item>
<el-form-item>
<el-radio v-model='radioValue' :value="4">
指定
<el-select clearable v-model="checkboxList" placeholder="可多选" multiple :multiple-limit="10">
<el-option v-for="item in 24" :key="item" :label="item - 1" :value="item - 1" />
</el-select>
</el-radio>
</el-form-item>
</el-form>
</template>
<script setup>
const emit = defineEmits(['update'])
const props = defineProps({
cron: {
type: Object,
default: {
second: "*",
min: "*",
hour: "*",
day: "*",
month: "*",
week: "?",
year: "",
}
},
check: {
type: Function,
default: () => {
}
}
})
const radioValue = ref(1)
const cycle01 = ref(0)
const cycle02 = ref(1)
const average01 = ref(0)
const average02 = ref(1)
const checkboxList = ref([])
const checkCopy = ref([0])
const cycleTotal = computed(() => {
cycle01.value = props.check(cycle01.value, 0, 22)
cycle02.value = props.check(cycle02.value, cycle01.value + 1, 23)
return cycle01.value + '-' + cycle02.value
})
const averageTotal = computed(() => {
average01.value = props.check(average01.value, 0, 22)
average02.value = props.check(average02.value, 1, 23 - average01.value)
return average01.value + '/' + average02.value
})
const checkboxString = computed(() => {
return checkboxList.value.join(',')
})
watch(() => props.cron.hour, value => changeRadioValue(value))
watch([radioValue, cycleTotal, averageTotal, checkboxString], () => onRadioChange())
function changeRadioValue(value) {
if (props.cron.min === '*') {
emit('update', 'min', '0', 'hour')
}
if (props.cron.second === '*') {
emit('update', 'second', '0', 'hour')
}
if (value === '*') {
radioValue.value = 1
} else if (value.indexOf('-') > -1) {
const indexArr = value.split('-')
cycle01.value = Number(indexArr[0])
cycle02.value = Number(indexArr[1])
radioValue.value = 2
} else if (value.indexOf('/') > -1) {
const indexArr = value.split('/')
average01.value = Number(indexArr[0])
average02.value = Number(indexArr[1])
radioValue.value = 3
} else {
checkboxList.value = [...new Set(value.split(',').map(item => Number(item)))]
radioValue.value = 4
}
}
function onRadioChange() {
switch (radioValue.value) {
case 1:
emit('update', 'hour', '*', 'hour')
break
case 2:
emit('update', 'hour', cycleTotal.value, 'hour')
break
case 3:
emit('update', 'hour', averageTotal.value, 'hour')
break
case 4:
if (checkboxList.value.length === 0) {
checkboxList.value.push(checkCopy.value[0])
} else {
checkCopy.value = checkboxList.value
}
emit('update', 'hour', checkboxString.value, 'hour')
break
}
}
</script>
<style lang="scss" scoped>
.el-input-number--small, .el-select, .el-select--small {
margin: 0 0.2rem;
}
.el-select, .el-select--small {
width: 18.8rem;
}
</style>

View File

@ -0,0 +1,647 @@
<template>
<div class="cron-simplified">
<!-- 周期选择 -->
<div class="period-section">
<div class="period-title">周期</div>
<div class="period-buttons">
<el-button
v-for="period in periodOptions"
:key="period.value"
:type="selectedPeriod === period.value ? 'primary' : ''"
@click="handlePeriodChange(period.value)"
class="period-btn"
>
{{ period.label }}
</el-button>
</div>
</div>
<!-- 时间输入区域 -->
<div class="time-input-section" v-if="showTimeInputs">
<div class="time-inputs">
<div class="time-input-item" v-if="showSecond">
<label></label>
<el-input-number
v-model="timeValues.second"
:min="0"
:max="59"
:controls="false"
size="default"
class="time-input"
/>
</div>
<div class="time-input-item" v-if="showMinute">
<label>分钟</label>
<el-input-number
v-model="timeValues.minute"
:min="0"
:max="59"
:controls="false"
size="default"
class="time-input"
/>
</div>
<div class="time-input-item" v-if="showHour">
<label>小时</label>
<el-input-number
v-model="timeValues.hour"
:min="0"
:max="23"
:controls="false"
size="default"
class="time-input"
/>
</div>
<div class="time-input-item" v-if="showDay">
<label>日期</label>
<el-input-number
v-model="timeValues.day"
:min="1"
:max="31"
:controls="false"
size="default"
class="time-input"
/>
</div>
<div class="time-input-item" v-if="showMonth">
<label>月份</label>
<el-input-number
v-model="timeValues.month"
:min="1"
:max="12"
:controls="false"
size="default"
class="time-input"
/>
</div>
</div>
</div>
<!-- 星期选择 -->
<div class="week-section" v-if="showWeek">
<div class="week-title">星期</div>
<div class="week-buttons">
<el-button
v-for="week in weekOptions"
:key="week.value"
:type="selectedWeek === week.value ? 'primary' : ''"
@click="handleWeekChange(week.value)"
class="week-btn"
>
{{ week.label }}
</el-button>
</div>
</div>
<!-- Cron表达式显示 -->
<div class="cron-result-section">
<div class="result-title">时间表达式</div>
<div class="cron-expression">{{ crontabValueString }}</div>
</div>
<!-- 最近5次运行时间 -->
<CrontabResult :ex="crontabValueString"></CrontabResult>
<!-- 操作按钮 -->
<div class="pop_btn">
<el-button type="primary" @click="submitFill">确定</el-button>
<el-button type="warning" @click="clearCron">重置</el-button>
<el-button @click="hidePopup">取消</el-button>
</div>
</div>
</template>
<script setup>
import { ref, computed, watch, getCurrentInstance, onMounted } from 'vue'
import CrontabResult from './result.vue'
const { proxy } = getCurrentInstance()
const emit = defineEmits(['hide', 'fill'])
const props = defineProps({
hideComponent: {
type: Array,
default: () => [],
},
expression: {
type: String,
default: '',
},
})
//
const periodOptions = [
{ label: '每秒', value: 'second' },
{ label: '每分钟', value: 'minute' },
{ label: '每小时', value: 'hour' },
{ label: '每天', value: 'day' },
{ label: '每周', value: 'week' },
{ label: '每月', value: 'month' },
{ label: '每年', value: 'year' },
]
//
const weekOptions = [
{ label: '日', value: 1 },
{ label: '一', value: 2 },
{ label: '二', value: 3 },
{ label: '三', value: 4 },
{ label: '四', value: 5 },
{ label: '五', value: 6 },
{ label: '六', value: 7 },
]
//
const selectedPeriod = ref('second')
//
const selectedWeek = ref(1)
//
const timeValues = ref({
second: 0,
minute: 0,
hour: 0,
day: 1,
month: 1,
})
// Cron
const crontabValueObj = ref({
second: '*',
min: '*',
hour: '*',
day: '*',
month: '*',
week: '?',
year: '',
})
//
const executionDesc = computed(() => {
const periodMap = {
second: '每秒执行',
minute: '每分钟执行',
hour: '每小时执行',
day: '每天执行',
week: '每周执行',
month: '每月执行',
year: '每年执行',
}
return periodMap[selectedPeriod.value] || '每秒执行'
})
//
const showTimeInputs = computed(() => {
return selectedPeriod.value !== 'second'
})
const showSecond = computed(() => {
return ['minute', 'hour', 'day', 'week', 'month', 'year'].includes(selectedPeriod.value)
})
const showMinute = computed(() => {
return ['hour', 'day', 'week', 'month', 'year'].includes(selectedPeriod.value)
})
const showHour = computed(() => {
return ['day', 'week', 'month', 'year'].includes(selectedPeriod.value)
})
const showDay = computed(() => {
return ['month', 'year'].includes(selectedPeriod.value)
})
const showMonth = computed(() => {
return selectedPeriod.value === 'year'
})
const showWeek = computed(() => {
return selectedPeriod.value === 'week'
})
// Cron
const crontabValueString = computed(() => {
const obj = crontabValueObj.value
return (
obj.second +
' ' +
obj.min +
' ' +
obj.hour +
' ' +
obj.day +
' ' +
obj.month +
' ' +
obj.week +
(obj.year === '' ? '' : ' ' + obj.year)
)
})
// Cron
watch(
[selectedPeriod, selectedWeek, timeValues],
() => {
updateCronExpression()
},
{ deep: true },
)
// Cron
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
}
}
//
function handlePeriodChange(period) {
selectedPeriod.value = period
updateCronExpression()
}
//
function handleWeekChange(week) {
selectedWeek.value = week
updateCronExpression()
}
//
function resolveExp() {
if (props.expression) {
const arr = props.expression.split(/\s+/)
if (arr.length >= 6) {
// 6
const obj = {
second: arr[0],
min: arr[1],
hour: arr[2],
day: arr[3],
month: arr[4],
week: arr[5],
year: arr[6] ? arr[6] : '',
}
crontabValueObj.value = { ...obj }
//
//
const isNumber = (str) => {
return /^\d+$/.test(str)
}
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'
}
}
} else {
clearCron()
}
}
//
function hidePopup() {
emit('hide')
}
//
function submitFill() {
emit('fill', crontabValueString.value)
hidePopup()
}
//
function clearCron() {
selectedPeriod.value = 'second'
selectedWeek.value = 1
timeValues.value = {
second: 0,
minute: 0,
hour: 0,
day: 1,
month: 1,
}
updateCronExpression()
}
//
watch(
() => props.expression,
() => {
resolveExp()
},
{ immediate: true },
)
onMounted(() => {
if (props.expression) {
resolveExp()
} else {
updateCronExpression()
}
})
</script>
<style lang="scss" scoped>
.cron-simplified {
padding: 20px;
background: #f5f5f5;
min-height: 400px;
}
.period-section {
background: #fff;
padding: 20px;
border-radius: 4px;
margin-bottom: 20px;
.period-title {
font-size: 14px;
font-weight: 500;
color: #333;
margin-bottom: 15px;
}
.period-buttons {
display: flex;
gap: 10px;
flex-wrap: wrap;
.period-btn {
min-width: 80px;
border-radius: 4px;
}
}
}
.execution-section {
background: #fff;
padding: 20px;
border-radius: 4px;
margin-bottom: 20px;
min-height: 60px;
.execution-desc {
font-size: 14px;
color: #666;
}
}
.time-input-section {
background: #fff;
padding: 20px;
border-radius: 4px;
margin-bottom: 20px;
.time-inputs {
display: flex;
gap: 20px;
flex-wrap: wrap;
align-items: flex-end;
.time-input-item {
display: flex;
flex-direction: column;
gap: 8px;
label {
font-size: 14px;
color: #333;
font-weight: 500;
}
.time-input {
width: 120px;
:deep(.el-input__inner) {
text-align: center;
}
}
}
}
}
.week-section {
background: #fff;
padding: 20px;
border-radius: 4px;
margin-bottom: 20px;
.week-title {
font-size: 14px;
font-weight: 500;
color: #333;
margin-bottom: 15px;
}
.week-buttons {
display: flex;
gap: 10px;
flex-wrap: wrap;
.week-btn {
min-width: 50px;
border-radius: 4px;
}
}
}
.cron-result-section {
background: #fff;
padding: 20px;
border-radius: 4px;
margin-bottom: 20px;
.result-title {
font-size: 14px;
font-weight: 500;
color: #333;
margin-bottom: 15px;
}
.cron-expression {
font-size: 14px;
color: #1677ff;
font-family: monospace;
padding: 10px;
background: #f0f9ff;
border-radius: 4px;
word-break: break-all;
border: 1px solid #d4e8ff;
}
}
.pop_btn {
text-align: center;
margin-top: 20px;
padding-top: 20px;
border-top: 1px solid #e8e8e8;
display: flex;
justify-content: center;
gap: 10px;
}
</style>

View File

@ -0,0 +1,126 @@
<template>
<el-form>
<el-form-item>
<el-radio v-model='radioValue' :value="1">
分钟允许的通配符[, - * /]
</el-radio>
</el-form-item>
<el-form-item>
<el-radio v-model='radioValue' :value="2">
周期从
<el-input-number v-model='cycle01' :min="0" :max="58" /> -
<el-input-number v-model='cycle02' :min="cycle01 + 1" :max="59" /> 分钟
</el-radio>
</el-form-item>
<el-form-item>
<el-radio v-model='radioValue' :value="3">
<el-input-number v-model='average01' :min="0" :max="58" /> 分钟开始
<el-input-number v-model='average02' :min="1" :max="59 - average01" /> 分钟执行一次
</el-radio>
</el-form-item>
<el-form-item>
<el-radio v-model='radioValue' :value="4">
指定
<el-select clearable v-model="checkboxList" placeholder="可多选" multiple :multiple-limit="10">
<el-option v-for="item in 60" :key="item" :label="item - 1" :value="item - 1" />
</el-select>
</el-radio>
</el-form-item>
</el-form>
</template>
<script setup>
const emit = defineEmits(['update'])
const props = defineProps({
cron: {
type: Object,
default: {
second: "*",
min: "*",
hour: "*",
day: "*",
month: "*",
week: "?",
year: "",
}
},
check: {
type: Function,
default: () => {
}
}
})
const radioValue = ref(1)
const cycle01 = ref(0)
const cycle02 = ref(1)
const average01 = ref(0)
const average02 = ref(1)
const checkboxList = ref([])
const checkCopy = ref([0])
const cycleTotal = computed(() => {
cycle01.value = props.check(cycle01.value, 0, 58)
cycle02.value = props.check(cycle02.value, cycle01.value + 1, 59)
return cycle01.value + '-' + cycle02.value
})
const averageTotal = computed(() => {
average01.value = props.check(average01.value, 0, 58)
average02.value = props.check(average02.value, 1, 59 - average01.value)
return average01.value + '/' + average02.value
})
const checkboxString = computed(() => {
return checkboxList.value.join(',')
})
watch(() => props.cron.min, value => changeRadioValue(value))
watch([radioValue, cycleTotal, averageTotal, checkboxString], () => onRadioChange())
function changeRadioValue(value) {
if (value === '*') {
radioValue.value = 1
} else if (value.indexOf('-') > -1) {
const indexArr = value.split('-')
cycle01.value = Number(indexArr[0])
cycle02.value = Number(indexArr[1])
radioValue.value = 2
} else if (value.indexOf('/') > -1) {
const indexArr = value.split('/')
average01.value = Number(indexArr[0])
average02.value = Number(indexArr[1])
radioValue.value = 3
} else {
checkboxList.value = [...new Set(value.split(',').map(item => Number(item)))]
radioValue.value = 4
}
}
function onRadioChange() {
switch (radioValue.value) {
case 1:
emit('update', 'min', '*', 'min')
break
case 2:
emit('update', 'min', cycleTotal.value, 'min')
break
case 3:
emit('update', 'min', averageTotal.value, 'min')
break
case 4:
if (checkboxList.value.length === 0) {
checkboxList.value.push(checkCopy.value[0])
} else {
checkCopy.value = checkboxList.value
}
emit('update', 'min', checkboxString.value, 'min')
break
}
}
</script>
<style lang="scss" scoped>
.el-input-number--small, .el-select, .el-select--small {
margin: 0 0.2rem;
}
.el-select, .el-select--small {
width: 19.8rem;
}
</style>

View File

@ -0,0 +1,141 @@
<template>
<el-form>
<el-form-item>
<el-radio v-model='radioValue' :value="1">
允许的通配符[, - * /]
</el-radio>
</el-form-item>
<el-form-item>
<el-radio v-model='radioValue' :value="2">
周期从
<el-input-number v-model='cycle01' :min="1" :max="11" /> -
<el-input-number v-model='cycle02' :min="cycle01 + 1" :max="12" />
</el-radio>
</el-form-item>
<el-form-item>
<el-radio v-model='radioValue' :value="3">
<el-input-number v-model='average01' :min="1" :max="11" /> 月开始
<el-input-number v-model='average02' :min="1" :max="12 - average01" /> 月月执行一次
</el-radio>
</el-form-item>
<el-form-item>
<el-radio v-model='radioValue' :value="4">
指定
<el-select clearable v-model="checkboxList" placeholder="可多选" multiple :multiple-limit="8">
<el-option v-for="item in monthList" :key="item.key" :label="item.value" :value="item.key" />
</el-select>
</el-radio>
</el-form-item>
</el-form>
</template>
<script setup>
const emit = defineEmits(['update'])
const props = defineProps({
cron: {
type: Object,
default: {
second: "*",
min: "*",
hour: "*",
day: "*",
month: "*",
week: "?",
year: "",
}
},
check: {
type: Function,
default: () => {
}
}
})
const radioValue = ref(1)
const cycle01 = ref(1)
const cycle02 = ref(2)
const average01 = ref(1)
const average02 = ref(1)
const checkboxList = ref([])
const checkCopy = ref([1])
const monthList = ref([
{key: 1, value: '一月'},
{key: 2, value: '二月'},
{key: 3, value: '三月'},
{key: 4, value: '四月'},
{key: 5, value: '五月'},
{key: 6, value: '六月'},
{key: 7, value: '七月'},
{key: 8, value: '八月'},
{key: 9, value: '九月'},
{key: 10, value: '十月'},
{key: 11, value: '十一月'},
{key: 12, value: '十二月'}
])
const cycleTotal = computed(() => {
cycle01.value = props.check(cycle01.value, 1, 11)
cycle02.value = props.check(cycle02.value, cycle01.value + 1, 12)
return cycle01.value + '-' + cycle02.value
})
const averageTotal = computed(() => {
average01.value = props.check(average01.value, 1, 11)
average02.value = props.check(average02.value, 1, 12 - average01.value)
return average01.value + '/' + average02.value
})
const checkboxString = computed(() => {
return checkboxList.value.join(',')
})
watch(() => props.cron.month, value => changeRadioValue(value))
watch([radioValue, cycleTotal, averageTotal, checkboxString], () => onRadioChange())
function changeRadioValue(value) {
if (value === '*') {
radioValue.value = 1
} else if (value.indexOf('-') > -1) {
const indexArr = value.split('-')
cycle01.value = Number(indexArr[0])
cycle02.value = Number(indexArr[1])
radioValue.value = 2
} else if (value.indexOf('/') > -1) {
const indexArr = value.split('/')
average01.value = Number(indexArr[0])
average02.value = Number(indexArr[1])
radioValue.value = 3
} else {
checkboxList.value = [...new Set(value.split(',').map(item => Number(item)))]
radioValue.value = 4
}
}
function onRadioChange() {
switch (radioValue.value) {
case 1:
emit('update', 'month', '*', 'month')
break
case 2:
emit('update', 'month', cycleTotal.value, 'month')
break
case 3:
emit('update', 'month', averageTotal.value, 'month')
break
case 4:
if (checkboxList.value.length === 0) {
checkboxList.value.push(checkCopy.value[0])
} else {
checkCopy.value = checkboxList.value
}
emit('update', 'month', checkboxString.value, 'month')
break
}
}
</script>
<style lang="scss" scoped>
.el-input-number--small, .el-select, .el-select--small {
margin: 0 0.2rem;
}
.el-select, .el-select--small {
width: 18.8rem;
}
</style>

View File

@ -0,0 +1,540 @@
<template>
<div class="popup-result">
<p class="title">最近5次运行时间</p>
<ul class="popup-result-scroll">
<template v-if='isShow'>
<li v-for='item in resultList' :key="item">{{item}}</li>
</template>
<li v-else>计算结果中...</li>
</ul>
</div>
</template>
<script setup>
const props = defineProps({
ex: {
type: String,
default: ''
}
})
const dayRule = ref('')
const dayRuleSup = ref('')
const dateArr = ref([])
const resultList = ref([])
const isShow = ref(false)
watch(() => props.ex, () => expressionChange())
//
function expressionChange() {
// -
isShow.value = false
// [0123456]
let ruleArr = props.ex.split(' ')
//
let nums = 0
//
let resultArr = []
// []
let nTime = new Date()
let nYear = nTime.getFullYear()
let nMonth = nTime.getMonth() + 1
let nDay = nTime.getDate()
let nHour = nTime.getHours()
let nMin = nTime.getMinutes()
let nSecond = nTime.getSeconds()
// 100
getSecondArr(ruleArr[0])
getMinArr(ruleArr[1])
getHourArr(ruleArr[2])
getDayArr(ruleArr[3])
getMonthArr(ruleArr[4])
getWeekArr(ruleArr[5])
getYearArr(ruleArr[6], nYear)
// -便使
let sDate = dateArr.value[0]
let mDate = dateArr.value[1]
let hDate = dateArr.value[2]
let DDate = dateArr.value[3]
let MDate = dateArr.value[4]
let YDate = dateArr.value[5]
//
let sIdx = getIndex(sDate, nSecond)
let mIdx = getIndex(mDate, nMin)
let hIdx = getIndex(hDate, nHour)
let DIdx = getIndex(DDate, nDay)
let MIdx = getIndex(MDate, nMonth)
let YIdx = getIndex(YDate, nYear)
// ()
const resetSecond = function () {
sIdx = 0
nSecond = sDate[sIdx]
}
const resetMin = function () {
mIdx = 0
nMin = mDate[mIdx]
resetSecond()
}
const resetHour = function () {
hIdx = 0
nHour = hDate[hIdx]
resetMin()
}
const resetDay = function () {
DIdx = 0
nDay = DDate[DIdx]
resetHour()
}
const resetMonth = function () {
MIdx = 0
nMonth = MDate[MIdx]
resetDay()
}
//
if (nYear !== YDate[YIdx]) {
resetMonth()
}
//
if (nMonth !== MDate[MIdx]) {
resetDay()
}
//
if (nDay !== DDate[DIdx]) {
resetHour()
}
//
if (nHour !== hDate[hIdx]) {
resetMin()
}
//
if (nMin !== mDate[mIdx]) {
resetSecond()
}
//
goYear: for (let Yi = YIdx; Yi < YDate.length; Yi++) {
let YY = YDate[Yi]
//
if (nMonth > MDate[MDate.length - 1]) {
resetMonth()
continue
}
//
goMonth: for (let Mi = MIdx; Mi < MDate.length; Mi++) {
// 便
let MM = MDate[Mi];
MM = MM < 10 ? '0' + MM : MM
//
if (nDay > DDate[DDate.length - 1]) {
resetDay()
if (Mi === MDate.length - 1) {
resetMonth()
continue goYear
}
continue
}
//
goDay: for (let Di = DIdx; Di < DDate.length; Di++) {
// 便
let DD = DDate[Di]
let thisDD = DD < 10 ? '0' + DD : DD
//
if (nHour > hDate[hDate.length - 1]) {
resetHour()
if (Di === DDate.length - 1) {
resetDay()
if (Mi === MDate.length - 1) {
resetMonth()
continue goYear
}
continue goMonth
}
continue
}
//
if (checkDate(YY + '-' + MM + '-' + thisDD + ' 00:00:00') !== true && dayRule.value !== 'workDay' && dayRule.value !== 'lastWeek' && dayRule.value !== 'lastDay') {
resetDay()
continue goMonth
}
//
if (dayRule.value === 'lastDay') {
//
if (checkDate(YY + '-' + MM + '-' + thisDD + ' 00:00:00') !== true) {
while (DD > 0 && checkDate(YY + '-' + MM + '-' + thisDD + ' 00:00:00') !== true) {
DD--
thisDD = DD < 10 ? '0' + DD : DD
}
}
} else if (dayRule.value === 'workDay') {
// 230
if (checkDate(YY + '-' + MM + '-' + thisDD + ' 00:00:00') !== true) {
while (DD > 0 && checkDate(YY + '-' + MM + '-' + thisDD + ' 00:00:00') !== true) {
DD--
thisDD = DD < 10 ? '0' + DD : DD
}
}
// X
let thisWeek = formatDate(new Date(YY + '-' + MM + '-' + thisDD + ' 00:00:00'), 'week')
//
if (thisWeek === 1) {
//
DD++
thisDD = DD < 10 ? '0' + DD : DD
//
if (checkDate(YY + '-' + MM + '-' + thisDD + ' 00:00:00') !== true) {
DD -= 3
}
} else if (thisWeek === 7) {
// 61
if (dayRuleSup.value !== 1) {
DD--
} else {
DD += 2
}
}
} else if (dayRule.value === 'weekDay') {
//
//
let thisWeek = formatDate(new Date(YY + '-' + MM + '-' + DD + ' 00:00:00'), 'week')
// dayRuleSup
if (dayRuleSup.value.indexOf(thisWeek) < 0) {
//
if (Di === DDate.length - 1) {
resetDay()
if (Mi === MDate.length - 1) {
resetMonth()
continue goYear
}
continue goMonth
}
continue
}
} else if (dayRule.value === 'assWeek') {
//
// 1
let thisWeek = formatDate(new Date(YY + '-' + MM + '-' + DD + ' 00:00:00'), 'week')
if (dayRuleSup.value[1] >= thisWeek) {
DD = (dayRuleSup.value[0] - 1) * 7 + dayRuleSup.value[1] - thisWeek + 1
} else {
DD = dayRuleSup.value[0] * 7 + dayRuleSup.value[1] - thisWeek + 1
}
} else if (dayRule.value === 'lastWeek') {
//
// 230
if (checkDate(YY + '-' + MM + '-' + thisDD + ' 00:00:00') !== true) {
while (DD > 0 && checkDate(YY + '-' + MM + '-' + thisDD + ' 00:00:00') !== true) {
DD--
thisDD = DD < 10 ? '0' + DD : DD
}
}
//
let thisWeek = formatDate(new Date(YY + '-' + MM + '-' + thisDD + ' 00:00:00'), 'week')
//
if (dayRuleSup.value < thisWeek) {
DD -= thisWeek - dayRuleSup.value
} else if (dayRuleSup.value > thisWeek) {
DD -= 7 - (dayRuleSup.value - thisWeek)
}
}
// 1005
DD = DD < 10 ? '0' + DD : DD
//
goHour: for (let hi = hIdx; hi < hDate.length; hi++) {
let hh = hDate[hi] < 10 ? '0' + hDate[hi] : hDate[hi]
//
if (nMin > mDate[mDate.length - 1]) {
resetMin()
if (hi === hDate.length - 1) {
resetHour()
if (Di === DDate.length - 1) {
resetDay()
if (Mi === MDate.length - 1) {
resetMonth()
continue goYear
}
continue goMonth
}
continue goDay
}
continue
}
// ""
goMin: for (let mi = mIdx; mi < mDate.length; mi++) {
let mm = mDate[mi] < 10 ? '0' + mDate[mi] : mDate[mi]
//
if (nSecond > sDate[sDate.length - 1]) {
resetSecond()
if (mi === mDate.length - 1) {
resetMin()
if (hi === hDate.length - 1) {
resetHour()
if (Di === DDate.length - 1) {
resetDay()
if (Mi === MDate.length - 1) {
resetMonth()
continue goYear
}
continue goMonth
}
continue goDay
}
continue goHour
}
continue
}
// ""
goSecond: for (let si = sIdx; si <= sDate.length - 1; si++) {
let ss = sDate[si] < 10 ? '0' + sDate[si] : sDate[si]
//
if (MM !== '00' && DD !== '00') {
resultArr.push(YY + '-' + MM + '-' + DD + ' ' + hh + ':' + mm + ':' + ss)
nums++
}
// 退
if (nums === 5) break goYear
//
if (si === sDate.length - 1) {
resetSecond()
if (mi === mDate.length - 1) {
resetMin()
if (hi === hDate.length - 1) {
resetHour()
if (Di === DDate.length - 1) {
resetDay()
if (Mi === MDate.length - 1) {
resetMonth()
continue goYear
}
continue goMonth
}
continue goDay
}
continue goHour
}
continue goMin
}
} //goSecond
} //goMin
}//goHour
}//goDay
}//goMonth
}
// 100
if (resultArr.length === 0) {
resultList.value = ['没有达到条件的结果!']
} else {
resultList.value = resultArr
if (resultArr.length !== 5) {
resultList.value.push('最近100年内只有上面' + resultArr.length + '条结果!')
}
}
// -
isShow.value = true
}
//
function getIndex(arr, value) {
if (value <= arr[0] || value > arr[arr.length - 1]) {
return 0
} else {
for (let i = 0; i < arr.length - 1; i++) {
if (value > arr[i] && value <= arr[i + 1]) {
return i + 1
}
}
}
}
// ""
function getYearArr(rule, year) {
dateArr.value[5] = getOrderArr(year, year + 100)
if (rule !== undefined) {
if (rule.indexOf('-') >= 0) {
dateArr.value[5] = getCycleArr(rule, year + 100, false)
} else if (rule.indexOf('/') >= 0) {
dateArr.value[5] = getAverageArr(rule, year + 100)
} else if (rule !== '*') {
dateArr.value[5] = getAssignArr(rule)
}
}
}
// ""
function getMonthArr(rule) {
dateArr.value[4] = getOrderArr(1, 12)
if (rule.indexOf('-') >= 0) {
dateArr.value[4] = getCycleArr(rule, 12, false)
} else if (rule.indexOf('/') >= 0) {
dateArr.value[4] = getAverageArr(rule, 12)
} else if (rule !== '*') {
dateArr.value[4] = getAssignArr(rule)
}
}
// ""-
function getWeekArr(rule) {
//
if (dayRule.value === '' && dayRuleSup.value === '') {
if (rule.indexOf('-') >= 0) {
dayRule.value = 'weekDay'
dayRuleSup.value = getCycleArr(rule, 7, false)
} else if (rule.indexOf('#') >= 0) {
dayRule.value = 'assWeek'
let matchRule = rule.match(/[0-9]{1}/g)
dayRuleSup.value = [Number(matchRule[1]), Number(matchRule[0])]
dateArr.value[3] = [1]
if (dayRuleSup.value[1] === 7) {
dayRuleSup.value[1] = 0
}
} else if (rule.indexOf('L') >= 0) {
dayRule.value = 'lastWeek'
dayRuleSup.value = Number(rule.match(/[0-9]{1,2}/g)[0])
dateArr.value[3] = [31]
if (dayRuleSup.value === 7) {
dayRuleSup.value = 0
}
} else if (rule !== '*' && rule !== '?') {
dayRule.value = 'weekDay'
dayRuleSup.value = getAssignArr(rule)
}
}
}
// ""-
function getDayArr(rule) {
dateArr.value[3] = getOrderArr(1, 31)
dayRule.value = ''
dayRuleSup.value = ''
if (rule.indexOf('-') >= 0) {
dateArr.value[3] = getCycleArr(rule, 31, false)
dayRuleSup.value = 'null'
} else if (rule.indexOf('/') >= 0) {
dateArr.value[3] = getAverageArr(rule, 31)
dayRuleSup.value = 'null'
} else if (rule.indexOf('W') >= 0) {
dayRule.value = 'workDay'
dayRuleSup.value = Number(rule.match(/[0-9]{1,2}/g)[0])
dateArr.value[3] = [dayRuleSup.value]
} else if (rule.indexOf('L') >= 0) {
dayRule.value = 'lastDay'
dayRuleSup.value = 'null'
dateArr.value[3] = [31]
} else if (rule !== '*' && rule !== '?') {
dateArr.value[3] = getAssignArr(rule)
dayRuleSup.value = 'null'
} else if (rule === '*') {
dayRuleSup.value = 'null'
}
}
// ""
function getHourArr(rule) {
dateArr.value[2] = getOrderArr(0, 23)
if (rule.indexOf('-') >= 0) {
dateArr.value[2] = getCycleArr(rule, 24, true)
} else if (rule.indexOf('/') >= 0) {
dateArr.value[2] = getAverageArr(rule, 23)
} else if (rule !== '*') {
dateArr.value[2] = getAssignArr(rule)
}
}
// ""
function getMinArr(rule) {
dateArr.value[1] = getOrderArr(0, 59)
if (rule.indexOf('-') >= 0) {
dateArr.value[1] = getCycleArr(rule, 60, true)
} else if (rule.indexOf('/') >= 0) {
dateArr.value[1] = getAverageArr(rule, 59)
} else if (rule !== '*') {
dateArr.value[1] = getAssignArr(rule)
}
}
// ""
function getSecondArr(rule) {
dateArr.value[0] = getOrderArr(0, 59)
if (rule.indexOf('-') >= 0) {
dateArr.value[0] = getCycleArr(rule, 60, true)
} else if (rule.indexOf('/') >= 0) {
dateArr.value[0] = getAverageArr(rule, 59)
} else if (rule !== '*') {
dateArr.value[0] = getAssignArr(rule)
}
}
// min-max
function getOrderArr(min, max) {
let arr = []
for (let i = min; i <= max; i++) {
arr.push(i)
}
return arr
}
//
function getAssignArr(rule) {
let arr = []
let assiginArr = rule.split(',')
for (let i = 0; i < assiginArr.length; i++) {
arr[i] = Number(assiginArr[i])
}
arr.sort(compare)
return arr
}
//
function getAverageArr(rule, limit) {
let arr = []
let agArr = rule.split('/')
let min = Number(agArr[0])
let step = Number(agArr[1])
while (min <= limit) {
arr.push(min)
min += step
}
return arr
}
//
function getCycleArr(rule, limit, status) {
// status--01
let arr = []
let cycleArr = rule.split('-')
let min = Number(cycleArr[0])
let max = Number(cycleArr[1])
if (min > max) {
max += limit
}
for (let i = min; i <= max; i++) {
let add = 0
if (status === false && i % limit === 0) {
add = limit
}
arr.push(Math.round(i % limit + add))
}
arr.sort(compare)
return arr
}
// Array.sort
function compare(value1, value2) {
if (value2 - value1 > 0) {
return -1
} else {
return 1
}
}
// 2017-9-19 18:04:33
function formatDate(value, type) {
//
let time = typeof value == 'number' ? new Date(value) : value
let Y = time.getFullYear()
let M = time.getMonth() + 1
let D = time.getDate()
let h = time.getHours()
let m = time.getMinutes()
let s = time.getSeconds()
let week = time.getDay()
// type
if (type === undefined) {
return Y + '-' + (M < 10 ? '0' + M : M) + '-' + (D < 10 ? '0' + D : D) + ' ' + (h < 10 ? '0' + h : h) + ':' + (m < 10 ? '0' + m : m) + ':' + (s < 10 ? '0' + s : s)
} else if (type === 'week') {
// quartz 1
return week + 1
}
}
//
function checkDate(value) {
let time = new Date(value)
let format = formatDate(time)
return value === format
}
onMounted(() => {
expressionChange()
})
</script>

View File

@ -0,0 +1,128 @@
<template>
<el-form>
<el-form-item>
<el-radio v-model='radioValue' :value="1">
允许的通配符[, - * /]
</el-radio>
</el-form-item>
<el-form-item>
<el-radio v-model='radioValue' :value="2">
周期从
<el-input-number v-model='cycle01' :min="0" :max="58" /> -
<el-input-number v-model='cycle02' :min="cycle01 + 1" :max="59" />
</el-radio>
</el-form-item>
<el-form-item>
<el-radio v-model='radioValue' :value="3">
<el-input-number v-model='average01' :min="0" :max="58" /> 秒开始
<el-input-number v-model='average02' :min="1" :max="59 - average01" /> 秒执行一次
</el-radio>
</el-form-item>
<el-form-item>
<el-radio v-model='radioValue' :value="4">
指定
<el-select clearable v-model="checkboxList" placeholder="可多选" multiple :multiple-limit="10">
<el-option v-for="item in 60" :key="item" :label="item - 1" :value="item - 1" />
</el-select>
</el-radio>
</el-form-item>
</el-form>
</template>
<script setup>
const emit = defineEmits(['update'])
const props = defineProps({
cron: {
type: Object,
default: {
second: "*",
min: "*",
hour: "*",
day: "*",
month: "*",
week: "?",
year: "",
}
},
check: {
type: Function,
default: () => {
}
}
})
const radioValue = ref(1)
const cycle01 = ref(0)
const cycle02 = ref(1)
const average01 = ref(0)
const average02 = ref(1)
const checkboxList = ref([])
const checkCopy = ref([0])
const cycleTotal = computed(() => {
cycle01.value = props.check(cycle01.value, 0, 58)
cycle02.value = props.check(cycle02.value, cycle01.value + 1, 59)
return cycle01.value + '-' + cycle02.value
})
const averageTotal = computed(() => {
average01.value = props.check(average01.value, 0, 58)
average02.value = props.check(average02.value, 1, 59 - average01.value)
return average01.value + '/' + average02.value
})
const checkboxString = computed(() => {
return checkboxList.value.join(',')
})
watch(() => props.cron.second, value => changeRadioValue(value))
watch([radioValue, cycleTotal, averageTotal, checkboxString], () => onRadioChange())
function changeRadioValue(value) {
if (value === '*') {
radioValue.value = 1
} else if (value.indexOf('-') > -1) {
const indexArr = value.split('-')
cycle01.value = Number(indexArr[0])
cycle02.value = Number(indexArr[1])
radioValue.value = 2
} else if (value.indexOf('/') > -1) {
const indexArr = value.split('/')
average01.value = Number(indexArr[0])
average02.value = Number(indexArr[1])
radioValue.value = 3
} else {
checkboxList.value = [...new Set(value.split(',').map(item => Number(item)))]
radioValue.value = 4
}
}
//
function onRadioChange() {
switch (radioValue.value) {
case 1:
emit('update', 'second', '*', 'second')
break
case 2:
emit('update', 'second', cycleTotal.value, 'second')
break
case 3:
emit('update', 'second', averageTotal.value, 'second')
break
case 4:
if (checkboxList.value.length === 0) {
checkboxList.value.push(checkCopy.value[0])
} else {
checkCopy.value = checkboxList.value
}
emit('update', 'second', checkboxString.value, 'second')
break
}
}
</script>
<style lang="scss" scoped>
.el-input-number--small, .el-select, .el-select--small {
margin: 0 0.2rem;
}
.el-select, .el-select--small {
width: 18.8rem;
}
</style>

View File

@ -0,0 +1,197 @@
<template>
<el-form>
<el-form-item>
<el-radio v-model='radioValue' :value="1">
允许的通配符[, - * ? / L #]
</el-radio>
</el-form-item>
<el-form-item>
<el-radio v-model='radioValue' :value="2">
不指定
</el-radio>
</el-form-item>
<el-form-item>
<el-radio v-model='radioValue' :value="3">
周期从
<el-select clearable v-model="cycle01">
<el-option
v-for="(item,index) of weekList"
:key="index"
:label="item.value"
:value="item.key"
:disabled="item.key === 7"
>{{item.value}}</el-option>
</el-select>
-
<el-select clearable v-model="cycle02">
<el-option
v-for="(item,index) of weekList"
:key="index"
:label="item.value"
:value="item.key"
:disabled="item.key <= cycle01"
>{{item.value}}</el-option>
</el-select>
</el-radio>
</el-form-item>
<el-form-item>
<el-radio v-model='radioValue' :value="4">
<el-input-number v-model='average01' :min="1" :max="4" /> 周的
<el-select clearable v-model="average02">
<el-option v-for="item in weekList" :key="item.key" :label="item.value" :value="item.key" />
</el-select>
</el-radio>
</el-form-item>
<el-form-item>
<el-radio v-model='radioValue' :value="5">
本月最后一个
<el-select clearable v-model="weekday">
<el-option v-for="item in weekList" :key="item.key" :label="item.value" :value="item.key" />
</el-select>
</el-radio>
</el-form-item>
<el-form-item>
<el-radio v-model='radioValue' :value="6">
指定
<el-select class="multiselect" clearable v-model="checkboxList" placeholder="可多选" multiple :multiple-limit="6">
<el-option v-for="item in weekList" :key="item.key" :label="item.value" :value="item.key" />
</el-select>
</el-radio>
</el-form-item>
</el-form>
</template>
<script setup>
const emit = defineEmits(['update'])
const props = defineProps({
cron: {
type: Object,
default: {
second: "*",
min: "*",
hour: "*",
day: "*",
month: "*",
week: "?",
year: ""
}
},
check: {
type: Function,
default: () => {
}
}
})
const radioValue = ref(2)
const cycle01 = ref(2)
const cycle02 = ref(3)
const average01 = ref(1)
const average02 = ref(2)
const weekday = ref(2)
const checkboxList = ref([])
const checkCopy = ref([2])
const weekList = ref([
{key: 1, value: '星期日'},
{key: 2, value: '星期一'},
{key: 3, value: '星期二'},
{key: 4, value: '星期三'},
{key: 5, value: '星期四'},
{key: 6, value: '星期五'},
{key: 7, value: '星期六'}
])
const cycleTotal = computed(() => {
cycle01.value = props.check(cycle01.value, 1, 6)
cycle02.value = props.check(cycle02.value, cycle01.value + 1, 7)
return cycle01.value + '-' + cycle02.value
})
const averageTotal = computed(() => {
average01.value = props.check(average01.value, 1, 4)
average02.value = props.check(average02.value, 1, 7)
return average02.value + '#' + average01.value
})
const weekdayTotal = computed(() => {
weekday.value = props.check(weekday.value, 1, 7)
return weekday.value + 'L'
})
const checkboxString = computed(() => {
return checkboxList.value.join(',')
})
watch(() => props.cron.week, value => changeRadioValue(value))
watch([radioValue, cycleTotal, averageTotal, weekdayTotal, checkboxString], () => onRadioChange())
function changeRadioValue(value) {
if (value === "*") {
radioValue.value = 1
} else if (value === "?") {
radioValue.value = 2
} else if (value.indexOf("-") > -1) {
const indexArr = value.split('-')
cycle01.value = Number(indexArr[0])
cycle02.value = Number(indexArr[1])
radioValue.value = 3
} else if (value.indexOf("#") > -1) {
const indexArr = value.split('#')
average01.value = Number(indexArr[1])
average02.value = Number(indexArr[0])
radioValue.value = 4
} else if (value.indexOf("L") > -1) {
const indexArr = value.split("L")
weekday.value = Number(indexArr[0])
radioValue.value = 5
} else {
checkboxList.value = [...new Set(value.split(',').map(item => Number(item)))]
radioValue.value = 6
}
}
function onRadioChange() {
if (radioValue.value === 2 && props.cron.day === '?') {
emit('update', 'day', '*', 'week')
}
if (radioValue.value !== 2 && props.cron.day !== '?') {
emit('update', 'day', '?', 'week')
}
switch (radioValue.value) {
case 1:
emit('update', 'week', '*', 'week')
break
case 2:
emit('update', 'week', '?', 'week')
break
case 3:
emit('update', 'week', cycleTotal.value, 'week')
break
case 4:
emit('update', 'week', averageTotal.value, 'week')
break
case 5:
emit('update', 'week', weekdayTotal.value, 'week')
break
case 6:
if (checkboxList.value.length === 0) {
checkboxList.value.push(checkCopy.value[0])
} else {
checkCopy.value = checkboxList.value
}
emit('update', 'week', checkboxString.value, 'week')
break
}
}
</script>
<style lang="scss" scoped>
.el-input-number--small, .el-select, .el-select--small {
margin: 0 0.5rem;
}
.el-select, .el-select--small {
width: 8rem;
}
.el-select.multiselect, .el-select--small.multiselect {
width: 17.8rem;
}
</style>

View File

@ -0,0 +1,143 @@
<template>
<el-form>
<el-form-item>
<el-radio :value="1" v-model='radioValue'>
不填允许的通配符[, - * /]
</el-radio>
</el-form-item>
<el-form-item>
<el-radio :value="2" v-model='radioValue'>
每年
</el-radio>
</el-form-item>
<el-form-item>
<el-radio :value="3" v-model='radioValue'>
周期从
<el-input-number v-model='cycle01' :min='fullYear' :max="2098"/> -
<el-input-number v-model='cycle02' :min="cycle01 ? cycle01 + 1 : fullYear + 1" :max="2099"/>
</el-radio>
</el-form-item>
<el-form-item>
<el-radio :value="4" v-model='radioValue'>
<el-input-number v-model='average01' :min='fullYear' :max="2098"/> 年开始
<el-input-number v-model='average02' :min="1" :max="2099 - average01 || fullYear"/> 年执行一次
</el-radio>
</el-form-item>
<el-form-item>
<el-radio :value="5" v-model='radioValue'>
指定
<el-select clearable v-model="checkboxList" placeholder="可多选" multiple :multiple-limit="8">
<el-option v-for="item in 9" :key="item" :value="item - 1 + fullYear" :label="item -1 + fullYear" />
</el-select>
</el-radio>
</el-form-item>
</el-form>
</template>
<script setup>
const emit = defineEmits(['update'])
const props = defineProps({
cron: {
type: Object,
default: {
second: "*",
min: "*",
hour: "*",
day: "*",
month: "*",
week: "?",
year: ""
}
},
check: {
type: Function,
default: () => {
}
}
})
const fullYear = Number(new Date().getFullYear())
const maxFullYear = fullYear + 10
const radioValue = ref(1)
const cycle01 = ref(fullYear)
const cycle02 = ref(fullYear + 1)
const average01 = ref(fullYear)
const average02 = ref(1)
const checkboxList = ref([])
const checkCopy = ref([fullYear])
const cycleTotal = computed(() => {
cycle01.value = props.check(cycle01.value, fullYear, maxFullYear - 1)
cycle02.value = props.check(cycle02.value, cycle01.value + 1, maxFullYear)
return cycle01.value + '-' + cycle02.value
})
const averageTotal = computed(() => {
average01.value = props.check(average01.value, fullYear, maxFullYear - 1)
average02.value = props.check(average02.value, 1, 10)
return average01.value + '/' + average02.value
})
const checkboxString = computed(() => {
return checkboxList.value.join(',')
})
watch(() => props.cron.year, value => changeRadioValue(value))
watch([radioValue, cycleTotal, averageTotal, checkboxString], () => onRadioChange())
function changeRadioValue(value) {
if (value === '') {
radioValue.value = 1
} else if (value === "*") {
radioValue.value = 2
} else if (value.indexOf("-") > -1) {
const indexArr = value.split('-')
cycle01.value = Number(indexArr[0])
cycle02.value = Number(indexArr[1])
radioValue.value = 3
} else if (value.indexOf("/") > -1) {
const indexArr = value.split('/')
average01.value = Number(indexArr[0])
average02.value = Number(indexArr[1])
radioValue.value = 4
} else {
checkboxList.value = [...new Set(value.split(',').map(item => Number(item)))]
radioValue.value = 5
}
}
function onRadioChange() {
switch (radioValue.value) {
case 1:
emit('update', 'year', '', 'year')
break
case 2:
emit('update', 'year', '*', 'year')
break
case 3:
emit('update', 'year', cycleTotal.value, 'year')
break
case 4:
emit('update', 'year', averageTotal.value, 'year')
break
case 5:
if (checkboxList.value.length === 0) {
checkboxList.value.push(checkCopy.value[0])
} else {
checkCopy.value = checkboxList.value
}
emit('update', 'year', checkboxString.value, 'year')
break
}
}
</script>
<style lang="scss" scoped>
.el-input-number--small, .el-select, .el-select--small {
margin: 0 0.2rem;
}
.el-select, .el-select--small {
width: 18.8rem;
}
</style>

View File

@ -199,7 +199,7 @@
import { ref, reactive, computed, getCurrentInstance, nextTick, onMounted, watch } from 'vue'
import { useRoute, useRouter } from 'vue-router'
import { Clock } from '@element-plus/icons-vue'
import Crontab from '@/components/Crontab'
import Crontab from './Crontab/index.vue'
import {
addLoopSendAPI,
updateLoopSendAPI,
@ -235,7 +235,7 @@ const taskStatus = ref('')
const cronDialogConfig = reactive({
outerVisible: false,
outerTitle: 'Cron表达式生成器',
outerWidth: '800px',
outerWidth: '70%',
minHeight: '500px',
maxHeight: '80vh',
})

View File

@ -63,7 +63,6 @@ import { bus, BUS_EVENTS } from '@/utils/bus'
const router = useRouter()
const { proxy } = getCurrentInstance()
const { tableColumns, buildFormColumns } = config
const comTableRef = ref(null)
const sendDetailsRef = ref(null)
@ -89,7 +88,6 @@ const actionColumns = [
label: '详情',
type: 'primary',
link: true,
handler: (row) => {
router.push({
path: '/sms/loopSendEdit/index',