diff --git a/package.json b/package.json index 83456b48..2269bac6 100644 --- a/package.json +++ b/package.json @@ -28,6 +28,7 @@ "animate.css": "^4.1.1", "axios": "^0.27.2", "codemirror": "^6.0.1", + "cron-parser": "^4.9.0", "crypto-js": "^4.2.0", "dayjs": "^1.11.4", "echarts": "^5.4.2", diff --git a/src/components/GenCron/CronForm/component/day-form.vue b/src/components/GenCron/CronForm/component/day-form.vue new file mode 100644 index 00000000..32c4237c --- /dev/null +++ b/src/components/GenCron/CronForm/component/day-form.vue @@ -0,0 +1,88 @@ + + + diff --git a/src/components/GenCron/CronForm/component/hour-form.vue b/src/components/GenCron/CronForm/component/hour-form.vue new file mode 100644 index 00000000..9c361622 --- /dev/null +++ b/src/components/GenCron/CronForm/component/hour-form.vue @@ -0,0 +1,60 @@ + + + diff --git a/src/components/GenCron/CronForm/component/minute-form.vue b/src/components/GenCron/CronForm/component/minute-form.vue new file mode 100644 index 00000000..9d18ca9a --- /dev/null +++ b/src/components/GenCron/CronForm/component/minute-form.vue @@ -0,0 +1,60 @@ + + + diff --git a/src/components/GenCron/CronForm/component/month-form.vue b/src/components/GenCron/CronForm/component/month-form.vue new file mode 100644 index 00000000..6a74bc6b --- /dev/null +++ b/src/components/GenCron/CronForm/component/month-form.vue @@ -0,0 +1,60 @@ + + + diff --git a/src/components/GenCron/CronForm/component/second-form.vue b/src/components/GenCron/CronForm/component/second-form.vue new file mode 100644 index 00000000..ce363e3d --- /dev/null +++ b/src/components/GenCron/CronForm/component/second-form.vue @@ -0,0 +1,60 @@ + + + diff --git a/src/components/GenCron/CronForm/component/use-mixin.ts b/src/components/GenCron/CronForm/component/use-mixin.ts new file mode 100644 index 00000000..2fb84578 --- /dev/null +++ b/src/components/GenCron/CronForm/component/use-mixin.ts @@ -0,0 +1,220 @@ +import { computed, reactive, ref, unref, watch } from 'vue' + +// 类型定义 +export enum TypeEnum { + unset = 'UNSET', + every = 'EVERY', + range = 'RANGE', + loop = 'LOOP', + work = 'WORK', + last = 'LAST', + specify = 'SPECIFY' +} + +// 周定义 +export const WEEK_MAP: any = { + 1: '周日', + 2: '周一', + 3: '周二', + 4: '周三', + 5: '周四', + 6: '周五', + 7: '周六' +} + +// use 公共 props +export function useFormProps(options: any) { + const defaultValue = options?.defaultValue ?? '?' + return { + modelValue: { + type: String, + default: defaultValue + }, + disabled: { + type: Boolean, + default: false + }, + ...options?.props + } +} + +// use 公共 emits +export function useFromEmits() { + return ['change', 'update:modelValue'] +} + +// use 公共 setup +export function useFormSetup(props: any, context: any, options: any) { + const { emit } = context + const defaultValue = ref(options?.defaultValue ?? '?') + // 类型 + const type = ref(options.defaultType ?? TypeEnum.every) + const valueList = ref([]) + // 对于不同的类型, 所定义的值也有所不同 + const valueRange = reactive(options.valueRange) + const valueLoop = reactive(options.valueLoop) + const valueWork = ref(options.valueWork) + const maxValue = ref(options.maxValue) + const minValue = ref(options.minValue) + + // 根据不同的类型计算出的 value + const computeValue = computed(() => { + const valueArray: any[] = [] + switch (type.value) { + case TypeEnum.unset: + valueArray.push('?') + break + case TypeEnum.every: + valueArray.push('*') + break + case TypeEnum.range: + valueArray.push(`${valueRange.start}-${valueRange.end}`) + break + case TypeEnum.loop: + valueArray.push(`${valueLoop.start}/${valueLoop.interval}`) + break + case TypeEnum.work: + valueArray.push(`${valueWork.value}W`) + break + case TypeEnum.last: + valueArray.push('L') + break + case TypeEnum.specify: + if (valueList.value.length === 0) { + valueList.value.push(minValue.value) + } + valueArray.push(valueList.value.join(',')) + break + default: + valueArray.push(defaultValue.value) + break + } + return valueArray.length > 0 ? valueArray.join('') : defaultValue.value + }) + + // 指定值范围区间, 介于最小值和最大值之间 + const specifyRange = computed(() => { + const range: number[] = [] + if (maxValue.value != null) { + for (let i = minValue.value; i <= maxValue.value; i++) { + range.push(i) + } + } + return range + }) + + // 更新值 + const updateValue = (value: any) => { + emit('change', value) + emit('update:modelValue', value) + } + + // 解析值 + const parseValue = (value: any) => { + if (value === computeValue.value) { + return + } + try { + if (!value || value === defaultValue.value) { + type.value = TypeEnum.every + } else if (value.includes('?')) { + type.value = TypeEnum.unset + } else if (value.includes('-')) { + type.value = TypeEnum.range + const values = value.split('-') + if (values.length >= 2) { + valueRange.start = Number.parseInt(values[0]) + valueRange.end = Number.parseInt(values[1]) + } + } else if (value.includes('/')) { + type.value = TypeEnum.loop + const values = value.split('/') + if (values.length >= 2) { + valueLoop.start = value[0] === '*' ? 0 : Number.parseInt(values[0]) + valueLoop.interval = Number.parseInt(values[1]) + } + } else if (value.includes('W')) { + type.value = TypeEnum.work + const values = value.split('W') + if (!values[0] && !Number.isNaN(values[0])) { + valueWork.value = Number.parseInt(values[0]) + } + } else if (value.includes('L')) { + type.value = TypeEnum.last + } else if (value.includes(',') || !Number.isNaN(value)) { + type.value = TypeEnum.specify + valueList.value = value.split(',').map((item: any) => Number.parseInt(item)) + } else { + type.value = TypeEnum.every + } + } catch (e) { + type.value = TypeEnum.every + } + } + + // 更新值 + watch(() => props.modelValue, (val) => { + if (val !== computeValue.value) { + parseValue(val) + } + }, { immediate: true }) + + // 更新值 + watch(computeValue, (v) => updateValue(v)) + + // 单选框属性 + const beforeRadioAttrs = computed(() => ({ + class: ['choice'], + disabled: props.disabled || unref(options.disabled), + size: 'small' + })) + + // 输入框属性 + const inputNumberAttrs = computed(() => ({ + max: maxValue.value, + min: minValue.value, + precision: 0, + size: 'small', + hideButton: true, + class: 'w60' + })) + + // 区间属性 + const typeRangeAttrs = computed(() => ({ + disabled: type.value !== TypeEnum.range || props.disabled || unref(options.disabled), + ...inputNumberAttrs.value + })) + + // 间隔属性 + const typeLoopAttrs = computed(() => ({ + disabled: type.value !== TypeEnum.loop || props.disabled || unref(options.disabled), + ...inputNumberAttrs.value + })) + + // 指定属性 + const typeSpecifyAttrs = computed(() => ({ + disabled: type.value !== TypeEnum.specify || props.disabled || unref(options.disabled), + class: ['list-check-item'], + size: 'small' + })) + + return { + type, + TypeEnum, + defaultValue, + valueRange, + valueLoop, + valueList, + valueWork, + maxValue, + minValue, + computeValue, + specifyRange, + updateValue, + beforeRadioAttrs, + inputNumberAttrs, + typeRangeAttrs, + typeLoopAttrs, + typeSpecifyAttrs + } +} diff --git a/src/components/GenCron/CronForm/component/week-form.vue b/src/components/GenCron/CronForm/component/week-form.vue new file mode 100644 index 00000000..98404010 --- /dev/null +++ b/src/components/GenCron/CronForm/component/week-form.vue @@ -0,0 +1,108 @@ + + + diff --git a/src/components/GenCron/CronForm/component/year-form.vue b/src/components/GenCron/CronForm/component/year-form.vue new file mode 100644 index 00000000..4782ae6a --- /dev/null +++ b/src/components/GenCron/CronForm/component/year-form.vue @@ -0,0 +1,46 @@ + + + diff --git a/src/components/GenCron/CronForm/index.vue b/src/components/GenCron/CronForm/index.vue new file mode 100644 index 00000000..2b27032d --- /dev/null +++ b/src/components/GenCron/CronForm/index.vue @@ -0,0 +1,378 @@ + + + + + + + diff --git a/src/components/GenCron/CronForm/type.ts b/src/components/GenCron/CronForm/type.ts new file mode 100644 index 00000000..4ee28fc1 --- /dev/null +++ b/src/components/GenCron/CronForm/type.ts @@ -0,0 +1,9 @@ +// cron 参数类型 +export interface CronPropType { + modelValue: string + disabled: boolean + hideSecond: boolean + hideYear: boolean + placeholder: string + callback: (expression: string, timestamp: number, validated: boolean) => void +} diff --git a/src/components/GenCron/CronModel/index.vue b/src/components/GenCron/CronModel/index.vue new file mode 100644 index 00000000..145b10a9 --- /dev/null +++ b/src/components/GenCron/CronModel/index.vue @@ -0,0 +1,67 @@ + + + + + + + diff --git a/src/components/GiCell/GiCellTag.vue b/src/components/GiCell/GiCellTag.vue index dae70dc5..1b10c34d 100644 --- a/src/components/GiCell/GiCellTag.vue +++ b/src/components/GiCell/GiCellTag.vue @@ -11,18 +11,15 @@ diff --git a/src/views/schedule/job/index.vue b/src/views/schedule/job/index.vue index e0ccc53d..becf5052 100644 --- a/src/views/schedule/job/index.vue +++ b/src/views/schedule/job/index.vue @@ -36,7 +36,14 @@