You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
RuoYi-Vue/ruoyi-ui-next/src/components/business/Crontab/index.vue

376 lines
9.6 KiB

<template>
<div>
<el-tabs type="border-card">
<el-tab-pane label="秒" v-if="shouldHide('second')">
<CrontabSecond
@update="updateCrontabValue"
:check="checkNumber"
ref="cronsecondRef"
/>
</el-tab-pane>
<el-tab-pane label="分钟" v-if="shouldHide('min')">
<CrontabMin
@update="updateCrontabValue"
:check="checkNumber"
ref="cronminRef"
/>
</el-tab-pane>
<el-tab-pane label="小时" v-if="shouldHide('hour')">
<CrontabHour
@update="updateCrontabValue"
:check="checkNumber"
ref="cronhourRef"
/>
</el-tab-pane>
<el-tab-pane label="日" v-if="shouldHide('day')">
<CrontabDay
@update="updateCrontabValue"
:check="checkNumber"
:cron="crontabValueObj"
ref="crondayRef"
/>
</el-tab-pane>
<el-tab-pane label="月" v-if="shouldHide('month')">
<CrontabMonth
@update="updateCrontabValue"
:check="checkNumber"
ref="cronmonthRef"
/>
</el-tab-pane>
<el-tab-pane label="周" v-if="shouldHide('week')">
<CrontabWeek
@update="updateCrontabValue"
:check="checkNumber"
:cron="crontabValueObj"
ref="cronweekRef"
/>
</el-tab-pane>
<el-tab-pane label="年" v-if="shouldHide('year')">
<CrontabYear
@update="updateCrontabValue"
:check="checkNumber"
ref="cronyearRef"
/>
</el-tab-pane>
</el-tabs>
<div class="popup-main">
<div class="popup-result">
<p class="title">时间表达式</p>
<table>
<thead>
<th v-for="item of tabTitles" :key="item" width="40">{{ item }}</th>
<th>Cron 表达式</th>
</thead>
<tbody>
<td><span>{{ crontabValueObj.second }}</span></td>
<td><span>{{ crontabValueObj.min }}</span></td>
<td><span>{{ crontabValueObj.hour }}</span></td>
<td><span>{{ crontabValueObj.day }}</span></td>
<td><span>{{ crontabValueObj.month }}</span></td>
<td><span>{{ crontabValueObj.week }}</span></td>
<td><span>{{ crontabValueObj.year }}</span></td>
<td><span>{{ crontabValueString }}</span></td>
</tbody>
</table>
</div>
<CrontabResult :ex="crontabValueString" />
<div class="pop_btn">
<el-button size="small" type="primary" @click="submitFill"></el-button>
<el-button size="small" type="warning" @click="clearCron"></el-button>
<el-button size="small" @click="hidePopup"></el-button>
</div>
</div>
</div>
</template>
<script setup lang="ts">
import { ref, computed, watch, onMounted } from 'vue'
import CrontabSecond from './second.vue'
import CrontabMin from './min.vue'
import CrontabHour from './hour.vue'
import CrontabDay from './day.vue'
import CrontabMonth from './month.vue'
import CrontabWeek from './week.vue'
import CrontabYear from './year.vue'
import CrontabResult from './result.vue'
import type { CrontabValueObj } from '@/types'
interface Props {
expression?: string
hideComponent?: string[]
}
const props = withDefaults(defineProps<Props>(), {
expression: '',
hideComponent: () => []
})
const emit = defineEmits<{
hide: []
fill: [value: string]
}>()
const tabTitles = ['秒', '分钟', '小时', '日', '月', '周', '年']
const crontabValueObj = ref<CrontabValueObj>({
second: '*',
min: '*',
hour: '*',
day: '*',
month: '*',
week: '?',
year: ''
})
const cronsecondRef = ref<any>(null)
const cronminRef = ref<any>(null)
const cronhourRef = ref<any>(null)
const crondayRef = ref<any>(null)
const cronmonthRef = ref<any>(null)
const cronweekRef = ref<any>(null)
const cronyearRef = ref<any>(null)
const crontabValueString = computed(() => {
const obj = crontabValueObj.value
return `${obj.second} ${obj.min} ${obj.hour} ${obj.day} ${obj.month} ${obj.week}${obj.year === '' ? '' : ' ' + obj.year}`
})
function shouldHide(key: string): boolean {
if (props.hideComponent && props.hideComponent.includes(key)) return false
return true
}
function checkNumber(value: number, minLimit: number, maxLimit: number): number {
value = Math.floor(value)
if (value < minLimit) value = minLimit
else if (value > maxLimit) value = maxLimit
return value
}
function updateCrontabValue(name: string, value: string, from?: string) {
crontabValueObj.value[name as keyof CrontabValueObj] = value
if (from && from !== name) {
changeRadio(name, value)
}
}
function changeRadio(name: string, value: string) {
const arr = ['second', 'min', 'hour', 'month']
const refName = 'cron' + name
const refMap: Record<string, any> = {
cronsecond: cronsecondRef.value,
cronmin: cronminRef.value,
cronhour: cronhourRef.value,
cronday: crondayRef.value,
cronmonth: cronmonthRef.value,
cronweek: cronweekRef.value,
cronyear: cronyearRef.value
}
const compRef = refMap[refName]
if (!compRef) return
let insValue = 1
if (arr.includes(name)) {
if (value === '*') {
insValue = 1
} else if (value.includes('-')) {
const indexArr = value.split('-')
compRef.cycle01 = isNaN(Number(indexArr[0])) ? 0 : Number(indexArr[0])
compRef.cycle02 = Number(indexArr[1])
insValue = 2
} else if (value.includes('/')) {
const indexArr = value.split('/')
compRef.average01 = isNaN(Number(indexArr[0])) ? 0 : Number(indexArr[0])
compRef.average02 = Number(indexArr[1])
insValue = 3
} else {
insValue = 4
compRef.checkboxList = value.split(',').map(Number)
}
} else if (name === 'day') {
if (value === '*') {
insValue = 1
} else if (value === '?') {
insValue = 2
} else if (value.includes('-')) {
const indexArr = value.split('-')
compRef.cycle01 = isNaN(Number(indexArr[0])) ? 0 : Number(indexArr[0])
compRef.cycle02 = Number(indexArr[1])
insValue = 3
} else if (value.includes('/')) {
const indexArr = value.split('/')
compRef.average01 = isNaN(Number(indexArr[0])) ? 0 : Number(indexArr[0])
compRef.average02 = Number(indexArr[1])
insValue = 4
} else if (value.includes('W')) {
const indexArr = value.split('W')
compRef.workday = isNaN(Number(indexArr[0])) ? 0 : Number(indexArr[0])
insValue = 5
} else if (value === 'L') {
insValue = 6
} else {
compRef.checkboxList = value.split(',').map(Number)
insValue = 7
}
} else if (name === 'week') {
if (value === '*') {
insValue = 1
} else if (value === '?') {
insValue = 2
} else if (value.includes('-')) {
const indexArr = value.split('-')
compRef.cycle01 = isNaN(Number(indexArr[0])) ? 0 : Number(indexArr[0])
compRef.cycle02 = Number(indexArr[1])
insValue = 3
} else if (value.includes('#')) {
const indexArr = value.split('#')
compRef.average01 = isNaN(Number(indexArr[0])) ? 1 : Number(indexArr[0])
compRef.average02 = Number(indexArr[1])
insValue = 4
} else if (value.includes('L')) {
const indexArr = value.split('L')
compRef.weekday = isNaN(Number(indexArr[0])) ? 1 : Number(indexArr[0])
insValue = 5
} else {
compRef.checkboxList = value.split(',')
insValue = 6
}
} else if (name === 'year') {
if (value === '') {
insValue = 1
} else if (value === '*') {
insValue = 2
} else if (value.includes('-')) {
insValue = 3
} else if (value.includes('/')) {
insValue = 4
} else {
compRef.checkboxList = value.split(',').map(Number)
insValue = 5
}
}
compRef.setRadioValue(insValue)
}
function resolveExp() {
if (props.expression) {
const arr = props.expression.split(' ')
if (arr.length >= 6) {
const obj = {
second: arr[0],
min: arr[1],
hour: arr[2],
day: arr[3],
month: arr[4],
week: arr[5],
year: arr[6] || ''
}
crontabValueObj.value = { ...obj }
for (const key in obj) {
if (obj[key as keyof typeof obj]) {
changeRadio(key, obj[key as keyof typeof obj])
}
}
}
} else {
clearCron()
}
}
function submitFill() {
emit('fill', crontabValueString.value)
hidePopup()
}
function clearCron() {
crontabValueObj.value = {
second: '*',
min: '*',
hour: '*',
day: '*',
month: '*',
week: '?',
year: ''
}
for (const key in crontabValueObj.value) {
changeRadio(key, crontabValueObj.value[key as keyof CrontabValueObj])
}
}
function hidePopup() {
emit('hide')
}
watch(() => props.expression, resolveExp)
onMounted(() => {
resolveExp()
})
</script>
<style scoped>
.pop_btn {
text-align: center;
margin-top: 20px;
}
.popup-main {
position: relative;
margin: 10px auto;
background: #fff;
border-radius: 5px;
font-size: 12px;
overflow: hidden;
}
.popup-result {
box-sizing: border-box;
line-height: 24px;
margin: 25px auto;
padding: 15px 10px 10px;
border: 1px solid #ccc;
position: relative;
}
.popup-result .title {
position: absolute;
top: -28px;
left: 50%;
width: 140px;
font-size: 14px;
margin-left: -70px;
text-align: center;
line-height: 30px;
background: #fff;
}
.popup-result table {
text-align: center;
width: 100%;
margin: 0 auto;
}
.popup-result table span {
display: block;
width: 100%;
font-family: arial;
line-height: 30px;
height: 30px;
white-space: nowrap;
overflow: hidden;
border: 1px solid #e8e8e8;
}
</style>