|
76 | 76 | shadow="never" |
77 | 77 | class="card-never mt-16 w-full" |
78 | 78 | > |
79 | | - <p style="margin-top: -8px">{{ $t('views.trigger.triggerCycle.title') }}</p> |
| 79 | + <div class="flex-between"> |
| 80 | + <p style="margin-top: -8px"> |
| 81 | + {{ |
| 82 | + form.trigger_setting.schedule_type === 'cron' |
| 83 | + ? 'Cron表达式' |
| 84 | + : $t('views.trigger.triggerCycle.title') |
| 85 | + }} |
| 86 | + </p> |
| 87 | + <el-tooltip |
| 88 | + :content=" |
| 89 | + form.trigger_setting.schedule_type === 'cron' |
| 90 | + ? '切换为触发周期' |
| 91 | + : '切换为Cron表达式' |
| 92 | + " |
| 93 | + placement="top" |
| 94 | + effect="light" |
| 95 | + > |
| 96 | + <el-button text @click.stop="switchScheduleType"> |
| 97 | + <el-icon><Switch /></el-icon> |
| 98 | + </el-button> |
| 99 | + </el-tooltip> |
| 100 | + </div> |
80 | 101 |
|
81 | 102 | <el-cascader |
| 103 | + v-if="form.trigger_setting.schedule_type !== 'cron'" |
82 | 104 | v-model="scheduled" |
83 | 105 | :options="triggerCycleOptions" |
84 | 106 | @change="handleChangeScheduled" |
85 | 107 | style="width: 100%" |
86 | 108 | /> |
| 109 | + <el-input |
| 110 | + v-else |
| 111 | + v-model="form.trigger_setting.cron_expression" |
| 112 | + placeholder="请输入Cron表达式(如:0 0 1 * *)" |
| 113 | + clearable |
| 114 | + @blur="validateCron" |
| 115 | + @input="validateCron" |
| 116 | + /> |
| 117 | + <div v-if="cronError" class="el-form-item__error">{{ cronError }}</div> |
87 | 118 | </el-card> |
88 | 119 | </el-card> |
89 | 120 | <el-card |
@@ -500,6 +531,8 @@ import { triggerCycleOptions } from '@/utils/trigger.ts' |
500 | 531 | import { t } from '@/locales' |
501 | 532 | import { type FormInstance } from 'element-plus' |
502 | 533 | import { useRoute } from 'vue-router' |
| 534 | +import { cloneDeep } from 'lodash' |
| 535 | +import { isValidCron } from 'cron-validator' |
503 | 536 | import Result from '@/request/Result' |
504 | 537 | import { hasPermission } from '@/utils/permission' |
505 | 538 | import permissionMap from '@/permission' |
@@ -577,6 +610,52 @@ const event_url = computed(() => { |
577 | 610 | return `${window.origin}${window.MaxKB.prefix}/api/trigger/v1/webhook/${form.value.id}` |
578 | 611 | }) |
579 | 612 |
|
| 613 | +const lastPresetSetting = ref<any>(null) |
| 614 | +const cronError = ref('') |
| 615 | +
|
| 616 | +const validateCron = () => { |
| 617 | + const cron = form.value.trigger_setting.cron_expression?.trim() |
| 618 | + if (!cron) { |
| 619 | + cronError.value = '' |
| 620 | + return |
| 621 | + } |
| 622 | + const fields = cron.split(/\s+/) |
| 623 | + if (fields.length !== 5 || !isValidCron(cron)) { |
| 624 | + cronError.value = 'Cron表达式不合法' |
| 625 | + } else { |
| 626 | + cronError.value = '' |
| 627 | + } |
| 628 | +} |
| 629 | +
|
| 630 | +function switchScheduleType() { |
| 631 | + const currentType = form.value.trigger_setting.schedule_type || 'daily' |
| 632 | + const isCron = currentType === 'cron' |
| 633 | +
|
| 634 | + if (!isCron) { |
| 635 | + lastPresetSetting.value = cloneDeep({ |
| 636 | + schedule_type: form.value.trigger_setting.schedule_type, |
| 637 | + interval_unit: form.value.trigger_setting.interval_unit, |
| 638 | + interval_value: form.value.trigger_setting.interval_value, |
| 639 | + days: form.value.trigger_setting.days, |
| 640 | + time: form.value.trigger_setting.time, |
| 641 | + }) |
| 642 | +
|
| 643 | + form.value.trigger_setting.schedule_type = 'cron' |
| 644 | + form.value.trigger_setting.interval_unit = undefined |
| 645 | + form.value.trigger_setting.interval_value = undefined |
| 646 | + form.value.trigger_setting.days = undefined |
| 647 | + form.value.trigger_setting.time = undefined |
| 648 | + return |
| 649 | + } |
| 650 | + cronError.value = '' |
| 651 | + const backup = lastPresetSetting.value |
| 652 | + form.value.trigger_setting.schedule_type = backup?.schedule_type || 'daily' |
| 653 | + form.value.trigger_setting.interval_unit = backup?.interval_unit |
| 654 | + form.value.trigger_setting.interval_value = backup?.interval_value |
| 655 | + form.value.trigger_setting.days = backup?.days |
| 656 | + form.value.trigger_setting.time = backup?.time |
| 657 | +} |
| 658 | +
|
580 | 659 | const addParameter = () => { |
581 | 660 | form.value.trigger_setting.body.push({ field: '', type: '' }) |
582 | 661 | } |
@@ -779,12 +858,21 @@ const open = (trigger_id?: string, source_type?: string, source_id?: string) => |
779 | 858 | } |
780 | 859 |
|
781 | 860 | const close = () => { |
| 861 | + cronError.value = '' |
782 | 862 | current_source_id.value = undefined |
783 | 863 | current_source_type.value = undefined |
784 | 864 | drawer.value = false |
785 | 865 | form.value = getDefaultValue() |
786 | 866 | } |
787 | 867 | const submit = () => { |
| 868 | + if ( |
| 869 | + form.value.trigger_type === 'SCHEDULED' && |
| 870 | + form.value.trigger_setting.schedule_type === 'cron' |
| 871 | + ) { |
| 872 | + validateCron() |
| 873 | + if (cronError.value) return |
| 874 | + } |
| 875 | +
|
788 | 876 | Promise.all([ |
789 | 877 | ...(toolParameterRef.value ? toolParameterRef.value.map((item) => item.validate()) : []), |
790 | 878 | ...(applicationParameterRef.value |
|
0 commit comments