cron表达式可视化配置替换成自定义组件
This commit is contained in:
330
src/components/CronExpressionEditor.vue
Normal file
330
src/components/CronExpressionEditor.vue
Normal file
@@ -0,0 +1,330 @@
|
|||||||
|
<template>
|
||||||
|
<div class="cron-expression-editor">
|
||||||
|
<el-input
|
||||||
|
v-model="cronExpression"
|
||||||
|
placeholder="请输入标准Unix 5位cron表达式,如: 0 0 * * *"
|
||||||
|
readonly
|
||||||
|
>
|
||||||
|
<template #append>
|
||||||
|
<el-button @click="openCronDialog">可视化配置</el-button>
|
||||||
|
</template>
|
||||||
|
</el-input>
|
||||||
|
|
||||||
|
<el-dialog
|
||||||
|
v-model="showCronDialog"
|
||||||
|
title="可视化配置Cron表达式"
|
||||||
|
width="600px"
|
||||||
|
:before-close="handleCronDialogClose"
|
||||||
|
>
|
||||||
|
<div class="cron-dialog-content">
|
||||||
|
<el-form :model="cronConfig" label-width="100px">
|
||||||
|
<!-- 分 -->
|
||||||
|
<el-form-item label="分">
|
||||||
|
<el-select
|
||||||
|
v-model="cronConfig.minute"
|
||||||
|
placeholder="请选择分钟"
|
||||||
|
clearable
|
||||||
|
filterable
|
||||||
|
allow-create
|
||||||
|
default-first-option
|
||||||
|
>
|
||||||
|
<el-option label="*" value="*">
|
||||||
|
<span>*</span>
|
||||||
|
<span class="option-desc">每分钟</span>
|
||||||
|
</el-option>
|
||||||
|
<el-option label="*/5" value="*/5">
|
||||||
|
<span>*/5</span>
|
||||||
|
<span class="option-desc">每隔5分钟</span>
|
||||||
|
</el-option>
|
||||||
|
<el-option label="*/10" value="*/10">
|
||||||
|
<span>*/10</span>
|
||||||
|
<span class="option-desc">每隔10分钟</span>
|
||||||
|
</el-option>
|
||||||
|
<el-option label="*/15" value="*/15">
|
||||||
|
<span>*/15</span>
|
||||||
|
<span class="option-desc">每隔15分钟</span>
|
||||||
|
</el-option>
|
||||||
|
<el-option label="*/30" value="*/30">
|
||||||
|
<span>*/30</span>
|
||||||
|
<span class="option-desc">每隔30分钟</span>
|
||||||
|
</el-option>
|
||||||
|
<el-option
|
||||||
|
v-for="minute in 60"
|
||||||
|
:key="minute-1"
|
||||||
|
:label="minute-1"
|
||||||
|
:value="(minute-1).toString()"
|
||||||
|
>
|
||||||
|
<span>{{ minute-1 }}</span>
|
||||||
|
<span class="option-desc">第{{ minute-1 }}分钟</span>
|
||||||
|
</el-option>
|
||||||
|
</el-select>
|
||||||
|
</el-form-item>
|
||||||
|
|
||||||
|
<!-- 时 -->
|
||||||
|
<el-form-item label="时">
|
||||||
|
<el-select
|
||||||
|
v-model="cronConfig.hour"
|
||||||
|
placeholder="请选择小时"
|
||||||
|
clearable
|
||||||
|
filterable
|
||||||
|
allow-create
|
||||||
|
default-first-option
|
||||||
|
>
|
||||||
|
<el-option label="*" value="*">
|
||||||
|
<span>*</span>
|
||||||
|
<span class="option-desc">每小时</span>
|
||||||
|
</el-option>
|
||||||
|
<el-option label="*/2" value="*/2">
|
||||||
|
<span>*/2</span>
|
||||||
|
<span class="option-desc">每隔2小时</span>
|
||||||
|
</el-option>
|
||||||
|
<el-option label="*/3" value="*/3">
|
||||||
|
<span>*/3</span>
|
||||||
|
<span class="option-desc">每隔3小时</span>
|
||||||
|
</el-option>
|
||||||
|
<el-option label="*/6" value="*/6">
|
||||||
|
<span>*/6</span>
|
||||||
|
<span class="option-desc">每隔6小时</span>
|
||||||
|
</el-option>
|
||||||
|
<el-option label="*/12" value="*/12">
|
||||||
|
<span>*/12</span>
|
||||||
|
<span class="option-desc">每隔12小时</span>
|
||||||
|
</el-option>
|
||||||
|
<el-option
|
||||||
|
v-for="hour in 24"
|
||||||
|
:key="hour-1"
|
||||||
|
:label="hour-1"
|
||||||
|
:value="(hour-1).toString()"
|
||||||
|
>
|
||||||
|
<span>{{ hour-1 }}</span>
|
||||||
|
<span class="option-desc">{{ hour-1 }}点</span>
|
||||||
|
</el-option>
|
||||||
|
</el-select>
|
||||||
|
</el-form-item>
|
||||||
|
|
||||||
|
<!-- 日 -->
|
||||||
|
<el-form-item label="日">
|
||||||
|
<el-select
|
||||||
|
v-model="cronConfig.day"
|
||||||
|
placeholder="请选择日期"
|
||||||
|
clearable
|
||||||
|
filterable
|
||||||
|
allow-create
|
||||||
|
default-first-option
|
||||||
|
>
|
||||||
|
<el-option label="*" value="*">
|
||||||
|
<span>*</span>
|
||||||
|
<span class="option-desc">每天</span>
|
||||||
|
</el-option>
|
||||||
|
<el-option label="*/2" value="*/2">
|
||||||
|
<span>*/2</span>
|
||||||
|
<span class="option-desc">每隔2天</span>
|
||||||
|
</el-option>
|
||||||
|
<el-option label="*/7" value="*/7">
|
||||||
|
<span>*/7</span>
|
||||||
|
<span class="option-desc">每隔7天</span>
|
||||||
|
</el-option>
|
||||||
|
<el-option label="*/15" value="*/15">
|
||||||
|
<span>*/15</span>
|
||||||
|
<span class="option-desc">每隔15天</span>
|
||||||
|
</el-option>
|
||||||
|
<el-option
|
||||||
|
v-for="day in 31"
|
||||||
|
:key="day"
|
||||||
|
:label="day"
|
||||||
|
:value="day.toString()"
|
||||||
|
>
|
||||||
|
<span>{{ day }}</span>
|
||||||
|
<span class="option-desc">每月{{ day }}日</span>
|
||||||
|
</el-option>
|
||||||
|
</el-select>
|
||||||
|
</el-form-item>
|
||||||
|
|
||||||
|
<!-- 月 -->
|
||||||
|
<el-form-item label="月">
|
||||||
|
<el-select
|
||||||
|
v-model="cronConfig.month"
|
||||||
|
placeholder="请选择月份"
|
||||||
|
clearable
|
||||||
|
filterable
|
||||||
|
allow-create
|
||||||
|
default-first-option
|
||||||
|
>
|
||||||
|
<el-option label="*" value="*">
|
||||||
|
<span>*</span>
|
||||||
|
<span class="option-desc">每月</span>
|
||||||
|
</el-option>
|
||||||
|
<el-option label="*/2" value="*/2">
|
||||||
|
<span>*/2</span>
|
||||||
|
<span class="option-desc">每隔2个月</span>
|
||||||
|
</el-option>
|
||||||
|
<el-option label="*/3" value="*/3">
|
||||||
|
<span>*/3</span>
|
||||||
|
<span class="option-desc">每隔3个月</span>
|
||||||
|
</el-option>
|
||||||
|
<el-option label="*/6" value="*/6">
|
||||||
|
<span>*/6</span>
|
||||||
|
<span class="option-desc">每隔6个月</span>
|
||||||
|
</el-option>
|
||||||
|
<el-option
|
||||||
|
v-for="month in 12"
|
||||||
|
:key="month"
|
||||||
|
:label="month"
|
||||||
|
:value="month.toString()"
|
||||||
|
>
|
||||||
|
<span>{{ month }}</span>
|
||||||
|
<span class="option-desc">第{{ month }}月</span>
|
||||||
|
</el-option>
|
||||||
|
</el-select>
|
||||||
|
</el-form-item>
|
||||||
|
|
||||||
|
<!-- 周 -->
|
||||||
|
<el-form-item label="周">
|
||||||
|
<el-select
|
||||||
|
v-model="cronConfig.week"
|
||||||
|
placeholder="请选择星期"
|
||||||
|
clearable
|
||||||
|
filterable
|
||||||
|
allow-create
|
||||||
|
default-first-option
|
||||||
|
>
|
||||||
|
<el-option label="*" value="*">
|
||||||
|
<span>*</span>
|
||||||
|
<span class="option-desc">每周</span>
|
||||||
|
</el-option>
|
||||||
|
<el-option label="1-5" value="1-5">
|
||||||
|
<span>1-5</span>
|
||||||
|
<span class="option-desc">工作日</span>
|
||||||
|
</el-option>
|
||||||
|
<el-option
|
||||||
|
v-for="(week, index) in weekOptions"
|
||||||
|
:key="index"
|
||||||
|
:label="week.label"
|
||||||
|
:value="index.toString()"
|
||||||
|
>
|
||||||
|
<span>{{ week.label }}</span>
|
||||||
|
<span class="option-desc">{{ week.desc }}</span>
|
||||||
|
</el-option>
|
||||||
|
</el-select>
|
||||||
|
</el-form-item>
|
||||||
|
</el-form>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<template #footer>
|
||||||
|
<div class="dialog-footer">
|
||||||
|
<el-button @click="handleCronDialogClose">取消</el-button>
|
||||||
|
<el-button type="primary" @click="confirmCronExpression">确认</el-button>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
</el-dialog>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import { ref, computed, watch, reactive } from 'vue'
|
||||||
|
|
||||||
|
export default {
|
||||||
|
name: 'CronExpressionEditor',
|
||||||
|
props: {
|
||||||
|
modelValue: {
|
||||||
|
type: String,
|
||||||
|
default: ''
|
||||||
|
}
|
||||||
|
},
|
||||||
|
emits: ['update:modelValue'],
|
||||||
|
setup(props, { emit }) {
|
||||||
|
// 是否显示Cron表达式配置对话框
|
||||||
|
const showCronDialog = ref(false)
|
||||||
|
|
||||||
|
// 星期选项
|
||||||
|
const weekOptions = [
|
||||||
|
{ label: '日', desc: '星期日' },
|
||||||
|
{ label: '一', desc: '星期一' },
|
||||||
|
{ label: '二', desc: '星期二' },
|
||||||
|
{ label: '三', desc: '星期三' },
|
||||||
|
{ label: '四', desc: '星期四' },
|
||||||
|
{ label: '五', desc: '星期五' },
|
||||||
|
{ label: '六', desc: '星期六' }
|
||||||
|
]
|
||||||
|
|
||||||
|
// cron配置
|
||||||
|
const cronConfig = reactive({
|
||||||
|
minute: '*',
|
||||||
|
hour: '*',
|
||||||
|
day: '*',
|
||||||
|
month: '*',
|
||||||
|
week: '*'
|
||||||
|
})
|
||||||
|
|
||||||
|
// 计算属性:cron表达式
|
||||||
|
const cronExpression = computed({
|
||||||
|
get: () => props.modelValue,
|
||||||
|
set: (value) => emit('update:modelValue', value)
|
||||||
|
})
|
||||||
|
|
||||||
|
// 打开Cron对话框
|
||||||
|
const openCronDialog = () => {
|
||||||
|
// 解析当前的cron表达式
|
||||||
|
if (cronExpression.value) {
|
||||||
|
const parts = cronExpression.value.split(' ')
|
||||||
|
if (parts.length === 5) {
|
||||||
|
cronConfig.minute = parts[0]
|
||||||
|
cronConfig.hour = parts[1]
|
||||||
|
cronConfig.day = parts[2]
|
||||||
|
cronConfig.month = parts[3]
|
||||||
|
cronConfig.week = parts[4]
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// 默认值
|
||||||
|
cronConfig.minute = '*'
|
||||||
|
cronConfig.hour = '*'
|
||||||
|
cronConfig.day = '*'
|
||||||
|
cronConfig.month = '*'
|
||||||
|
cronConfig.week = '*'
|
||||||
|
}
|
||||||
|
showCronDialog.value = true
|
||||||
|
}
|
||||||
|
|
||||||
|
// 确认Cron表达式
|
||||||
|
const confirmCronExpression = () => {
|
||||||
|
cronExpression.value = `${cronConfig.minute} ${cronConfig.hour} ${cronConfig.day} ${cronConfig.month} ${cronConfig.week}`
|
||||||
|
showCronDialog.value = false
|
||||||
|
}
|
||||||
|
|
||||||
|
// 处理Cron对话框关闭
|
||||||
|
const handleCronDialogClose = () => {
|
||||||
|
showCronDialog.value = false
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
showCronDialog,
|
||||||
|
cronConfig,
|
||||||
|
cronExpression,
|
||||||
|
weekOptions,
|
||||||
|
openCronDialog,
|
||||||
|
confirmCronExpression,
|
||||||
|
handleCronDialogClose
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
.cron-expression-editor {
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.cron-dialog-content {
|
||||||
|
padding: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.dialog-footer {
|
||||||
|
text-align: right;
|
||||||
|
}
|
||||||
|
|
||||||
|
.option-desc {
|
||||||
|
float: right;
|
||||||
|
color: #8492a6;
|
||||||
|
font-size: 13px;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
@@ -57,15 +57,10 @@
|
|||||||
label="执行频率"
|
label="执行频率"
|
||||||
prop="cron_expression"
|
prop="cron_expression"
|
||||||
v-if="formData.execution_type === 'automatic'">
|
v-if="formData.execution_type === 'automatic'">
|
||||||
<el-input
|
<cron-expression-editor
|
||||||
v-model="formData.cron_expression"
|
v-model="formData.cron_expression"
|
||||||
placeholder="请输入cron表达式,如:0 0 6 * * *"
|
/>
|
||||||
>
|
<div class="form-item-tip">Cron表达式格式:分 时 日 月 周</div>
|
||||||
<template #append>
|
|
||||||
<el-button @click="showCronDialog = true">可视化配置</el-button>
|
|
||||||
</template>
|
|
||||||
</el-input>
|
|
||||||
<div class="form-item-tip">Cron表达式格式:秒 分 时 日 月 周</div>
|
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
</el-form>
|
</el-form>
|
||||||
|
|
||||||
@@ -81,35 +76,17 @@
|
|||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
</el-dialog>
|
</el-dialog>
|
||||||
|
|
||||||
<!-- Cron表达式可视化配置对话框 -->
|
|
||||||
<el-dialog
|
|
||||||
v-model="showCronDialog"
|
|
||||||
title="可视化配置执行频率"
|
|
||||||
width="800px"
|
|
||||||
:before-close="handleCronDialogClose"
|
|
||||||
>
|
|
||||||
<div style="padding: 10px 20px;">
|
|
||||||
<vue3-cron-plus-picker
|
|
||||||
@fill="handleCronFill"
|
|
||||||
@hide="handleCronDialogClose"
|
|
||||||
:expression="tempCronExpression"
|
|
||||||
:hide-year="true"
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
</el-dialog>
|
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import { ref, reactive, computed, watch } from 'vue';
|
import { ref, reactive, computed, watch } from 'vue';
|
||||||
import { ElMessage } from 'element-plus';
|
import { ElMessage } from 'element-plus';
|
||||||
import { Vue3CronPlusPicker } from 'vue3-cron-plus-picker';
|
import CronExpressionEditor from './CronExpressionEditor.vue';
|
||||||
import 'vue3-cron-plus-picker/style.css';
|
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: 'PlanForm',
|
name: 'PlanForm',
|
||||||
components: {
|
components: {
|
||||||
Vue3CronPlusPicker
|
CronExpressionEditor
|
||||||
},
|
},
|
||||||
props: {
|
props: {
|
||||||
visible: {
|
visible: {
|
||||||
@@ -133,12 +110,6 @@ export default {
|
|||||||
// 加载状态
|
// 加载状态
|
||||||
const loading = ref(false);
|
const loading = ref(false);
|
||||||
|
|
||||||
// 是否显示Cron表达式配置对话框
|
|
||||||
const showCronDialog = ref(false);
|
|
||||||
|
|
||||||
// 临时存储cron表达式
|
|
||||||
const tempCronExpression = ref('');
|
|
||||||
|
|
||||||
// 表单数据
|
// 表单数据
|
||||||
const formData = reactive({
|
const formData = reactive({
|
||||||
id: null,
|
id: null,
|
||||||
@@ -183,18 +154,6 @@ export default {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
// 处理Cron表达式填充
|
|
||||||
const handleCronFill = (cronExpression) => {
|
|
||||||
formData.cron_expression = cronExpression;
|
|
||||||
tempCronExpression.value = cronExpression;
|
|
||||||
showCronDialog.value = false;
|
|
||||||
};
|
|
||||||
|
|
||||||
// 处理Cron对话框关闭
|
|
||||||
const handleCronDialogClose = () => {
|
|
||||||
showCronDialog.value = false;
|
|
||||||
};
|
|
||||||
|
|
||||||
// 关闭对话框
|
// 关闭对话框
|
||||||
const handleClose = () => {
|
const handleClose = () => {
|
||||||
emit('update:visible', false);
|
emit('update:visible', false);
|
||||||
@@ -239,9 +198,6 @@ export default {
|
|||||||
formData[key] = newVal[key];
|
formData[key] = newVal[key];
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
// 初始化临时cron表达式
|
|
||||||
tempCronExpression.value = newVal.cron_expression || '';
|
|
||||||
} else {
|
} else {
|
||||||
// 重置表单数据
|
// 重置表单数据
|
||||||
Object.keys(formData).forEach(key => {
|
Object.keys(formData).forEach(key => {
|
||||||
@@ -253,21 +209,16 @@ export default {
|
|||||||
});
|
});
|
||||||
// 默认值
|
// 默认值
|
||||||
formData.execution_type = 'automatic';
|
formData.execution_type = 'automatic';
|
||||||
tempCronExpression.value = '';
|
|
||||||
}
|
}
|
||||||
}, { immediate: true });
|
}, { immediate: true });
|
||||||
|
|
||||||
return {
|
return {
|
||||||
formRef,
|
formRef,
|
||||||
loading,
|
loading,
|
||||||
showCronDialog,
|
|
||||||
tempCronExpression,
|
|
||||||
formData,
|
formData,
|
||||||
rules,
|
rules,
|
||||||
title,
|
title,
|
||||||
handleExecutionTypeChange,
|
handleExecutionTypeChange,
|
||||||
handleCronFill,
|
|
||||||
handleCronDialogClose,
|
|
||||||
handleClose,
|
handleClose,
|
||||||
handleSubmit
|
handleSubmit
|
||||||
};
|
};
|
||||||
|
|||||||
Reference in New Issue
Block a user