Commit fbebcc446737a74adcfa63f765b86d349e7bf63d

Authored by 芋道源码
Committed by Gitee
2 parents 75c7b88b 8d82cfbb

!236 refactor: Job crontab components

Merge pull request !236 from xingyu/master
yudao-ui-admin-vue3/package.json
1 { 1 {
2 "name": "ruoyi-vue-pro-vue3", 2 "name": "ruoyi-vue-pro-vue3",
3 - "version": "1.6.2.1601", 3 + "version": "1.6.3.1601",
4 "description": "基于vue3、element-plus、typesScript、vite3", 4 "description": "基于vue3、element-plus、typesScript、vite3",
5 "author": "xingyu", 5 "author": "xingyu",
6 "private": false, 6 "private": false,
yudao-ui-admin-vue3/src/api/bpm/task/index.ts
@@ -11,22 +11,22 @@ export const getDoneTaskPage = async (params) => { @@ -11,22 +11,22 @@ export const getDoneTaskPage = async (params) => {
11 } 11 }
12 12
13 export const completeTask = async (data) => { 13 export const completeTask = async (data) => {
14 - return await request.put({ url: '/bpm/task/complete', data: data }) 14 + return await request.put({ url: '/bpm/task/complete', data })
15 } 15 }
16 16
17 export const approveTask = async (data) => { 17 export const approveTask = async (data) => {
18 - return await request.put({ url: '/bpm/task/approve', data: data }) 18 + return await request.put({ url: '/bpm/task/approve', data })
19 } 19 }
20 20
21 export const rejectTask = async (data) => { 21 export const rejectTask = async (data) => {
22 - return await request.put({ url: '/bpm/task/reject', data: data }) 22 + return await request.put({ url: '/bpm/task/reject', data })
23 } 23 }
24 export const backTask = async (data) => { 24 export const backTask = async (data) => {
25 - return await request.put({ url: '/bpm/task/back', data: data }) 25 + return await request.put({ url: '/bpm/task/back', data })
26 } 26 }
27 27
28 export const updateTaskAssignee = async (data) => { 28 export const updateTaskAssignee = async (data) => {
29 - return await request.put({ url: '/bpm/task/update-assignee', data: data }) 29 + return await request.put({ url: '/bpm/task/update-assignee', data })
30 } 30 }
31 31
32 export const getTaskListByProcessInstanceId = async (processInstanceId) => { 32 export const getTaskListByProcessInstanceId = async (processInstanceId) => {
yudao-ui-admin-vue3/src/api/infra/job/index.ts
@@ -19,8 +19,8 @@ export const createJobApi = (data: JobVO) => { @@ -19,8 +19,8 @@ export const createJobApi = (data: JobVO) => {
19 } 19 }
20 20
21 // 修改定时任务调度 21 // 修改定时任务调度
22 -export const updateJobApi = (params: JobVO) => {  
23 - return request.put({ url: '/infra/job/update', params }) 22 +export const updateJobApi = (data: JobVO) => {
  23 + return request.put({ url: '/infra/job/update', data })
24 } 24 }
25 25
26 // 删除定时任务调度 26 // 删除定时任务调度
@@ -35,11 +35,11 @@ export const exportJobApi = (params) => { @@ -35,11 +35,11 @@ export const exportJobApi = (params) => {
35 35
36 // 任务状态修改 36 // 任务状态修改
37 export const updateJobStatusApi = (id: number, status: number) => { 37 export const updateJobStatusApi = (id: number, status: number) => {
38 - const data = { 38 + const params = {
39 id, 39 id,
40 status 40 status
41 } 41 }
42 - return request.put({ url: '/infra/job/update-status', data: data }) 42 + return request.put({ url: '/infra/job/update-status', params })
43 } 43 }
44 44
45 // 定时任务立即执行一次 45 // 定时任务立即执行一次
yudao-ui-admin-vue3/src/api/infra/job/types.ts
@@ -8,5 +8,4 @@ export type JobVO = { @@ -8,5 +8,4 @@ export type JobVO = {
8 retryCount: number 8 retryCount: number
9 retryInterval: number 9 retryInterval: number
10 monitorTimeout: number 10 monitorTimeout: number
11 - createTime: string  
12 } 11 }
yudao-ui-admin-vue3/src/components/Crontab/index.ts
1 -import Crontab from './src/index.vue'  
2 - 1 +import Crontab from './src/Crontab.vue'
3 export { Crontab } 2 export { Crontab }
yudao-ui-admin-vue3/src/components/Crontab/src/Crontab.vue 0 → 100644
  1 +<!--
  2 + * @Descripttion: cron规则生成器
  3 + * @version: 1.0
  4 + * @Author: sakuya
  5 + * @Date: 2021年12月29日15:23:54
  6 + * @LastEditors:
  7 + * @LastEditTime:
  8 +-->
  9 +<script setup lang="ts">
  10 +import {
  11 + ElInput,
  12 + ElInputNumber,
  13 + ElDropdown,
  14 + ElDropdownMenu,
  15 + ElDropdownItem,
  16 + ElDialog,
  17 + ElTabs,
  18 + ElTabPane,
  19 + ElSelect,
  20 + ElOption,
  21 + ElForm,
  22 + ElFormItem,
  23 + ElRadioGroup,
  24 + ElRadioButton,
  25 + ElMessage
  26 +} from 'element-plus'
  27 +import { ref, computed, onMounted, reactive, watch, PropType } from 'vue'
  28 +interface shortcutsType {
  29 + text: string
  30 + value: string
  31 +}
  32 +const props = defineProps({
  33 + modelValue: { type: String, default: '* * * * * ?' },
  34 + shortcuts: { type: Array as PropType<shortcutsType[]>, default: () => [] }
  35 +})
  36 +const defaultValue = ref('')
  37 +const dialogVisible = ref(false)
  38 +const getYear = () => {
  39 + let v: number[] = []
  40 + let y = new Date().getFullYear()
  41 + for (let i = 0; i < 11; i++) {
  42 + v.push(y + i)
  43 + }
  44 + return v
  45 +}
  46 +const cronValue = reactive({
  47 + second: {
  48 + type: '0',
  49 + range: {
  50 + start: 1,
  51 + end: 2
  52 + },
  53 + loop: {
  54 + start: 0,
  55 + end: 1
  56 + },
  57 + appoint: [] as string[]
  58 + },
  59 + minute: {
  60 + type: '0',
  61 + range: {
  62 + start: 1,
  63 + end: 2
  64 + },
  65 + loop: {
  66 + start: 0,
  67 + end: 1
  68 + },
  69 + appoint: [] as string[]
  70 + },
  71 + hour: {
  72 + type: '0',
  73 + range: {
  74 + start: 1,
  75 + end: 2
  76 + },
  77 + loop: {
  78 + start: 0,
  79 + end: 1
  80 + },
  81 + appoint: [] as string[]
  82 + },
  83 + day: {
  84 + type: '0',
  85 + range: {
  86 + start: 1,
  87 + end: 2
  88 + },
  89 + loop: {
  90 + start: 1,
  91 + end: 1
  92 + },
  93 + appoint: [] as string[]
  94 + },
  95 + month: {
  96 + type: '0',
  97 + range: {
  98 + start: 1,
  99 + end: 2
  100 + },
  101 + loop: {
  102 + start: 1,
  103 + end: 1
  104 + },
  105 + appoint: [] as string[]
  106 + },
  107 + week: {
  108 + type: '5',
  109 + range: {
  110 + start: '2',
  111 + end: '3'
  112 + },
  113 + loop: {
  114 + start: 0,
  115 + end: '2'
  116 + },
  117 + last: '2',
  118 + appoint: [] as string[]
  119 + },
  120 + year: {
  121 + type: '-1',
  122 + range: {
  123 + start: getYear()[0],
  124 + end: getYear()[1]
  125 + },
  126 + loop: {
  127 + start: getYear()[0],
  128 + end: 1
  129 + },
  130 + appoint: [] as string[]
  131 + }
  132 +})
  133 +const data = reactive({
  134 + second: ['0', '5', '15', '20', '25', '30', '35', '40', '45', '50', '55', '59'],
  135 + minute: ['0', '5', '15', '20', '25', '30', '35', '40', '45', '50', '55', '59'],
  136 + hour: [
  137 + '0',
  138 + '1',
  139 + '2',
  140 + '3',
  141 + '4',
  142 + '5',
  143 + '6',
  144 + '7',
  145 + '8',
  146 + '9',
  147 + '10',
  148 + '11',
  149 + '12',
  150 + '13',
  151 + '14',
  152 + '15',
  153 + '16',
  154 + '17',
  155 + '18',
  156 + '19',
  157 + '20',
  158 + '21',
  159 + '22',
  160 + '23'
  161 + ],
  162 + day: [
  163 + '1',
  164 + '2',
  165 + '3',
  166 + '4',
  167 + '5',
  168 + '6',
  169 + '7',
  170 + '8',
  171 + '9',
  172 + '10',
  173 + '11',
  174 + '12',
  175 + '13',
  176 + '14',
  177 + '15',
  178 + '16',
  179 + '17',
  180 + '18',
  181 + '19',
  182 + '20',
  183 + '21',
  184 + '22',
  185 + '23',
  186 + '24',
  187 + '25',
  188 + '26',
  189 + '27',
  190 + '28',
  191 + '29',
  192 + '30',
  193 + '31'
  194 + ],
  195 + month: ['1', '2', '3', '4', '5', '6', '7', '8', '9', '10', '11', '12'],
  196 + week: [
  197 + {
  198 + value: '1',
  199 + label: '周日'
  200 + },
  201 + {
  202 + value: '2',
  203 + label: '周一'
  204 + },
  205 + {
  206 + value: '3',
  207 + label: '周二'
  208 + },
  209 + {
  210 + value: '4',
  211 + label: '周三'
  212 + },
  213 + {
  214 + value: '5',
  215 + label: '周四'
  216 + },
  217 + {
  218 + value: '6',
  219 + label: '周五'
  220 + },
  221 + {
  222 + value: '7',
  223 + label: '周六'
  224 + }
  225 + ],
  226 + year: getYear()
  227 +})
  228 +
  229 +const value_second = computed(() => {
  230 + let v = cronValue.second
  231 + if (v.type == '0') {
  232 + return '*'
  233 + } else if (v.type == '1') {
  234 + return v.range.start + '-' + v.range.end
  235 + } else if (v.type == '2') {
  236 + return v.loop.start + '/' + v.loop.end
  237 + } else if (v.type == '3') {
  238 + return v.appoint.length > 0 ? v.appoint.join(',') : '*'
  239 + } else {
  240 + return '*'
  241 + }
  242 +})
  243 +const value_minute = computed(() => {
  244 + let v = cronValue.minute
  245 + if (v.type == '0') {
  246 + return '*'
  247 + } else if (v.type == '1') {
  248 + return v.range.start + '-' + v.range.end
  249 + } else if (v.type == '2') {
  250 + return v.loop.start + '/' + v.loop.end
  251 + } else if (v.type == '3') {
  252 + return v.appoint.length > 0 ? v.appoint.join(',') : '*'
  253 + } else {
  254 + return '*'
  255 + }
  256 +})
  257 +const value_hour = computed(() => {
  258 + let v = cronValue.hour
  259 + if (v.type == '0') {
  260 + return '*'
  261 + } else if (v.type == '1') {
  262 + return v.range.start + '-' + v.range.end
  263 + } else if (v.type == '2') {
  264 + return v.loop.start + '/' + v.loop.end
  265 + } else if (v.type == '3') {
  266 + return v.appoint.length > 0 ? v.appoint.join(',') : '*'
  267 + } else {
  268 + return '*'
  269 + }
  270 +})
  271 +const value_day = computed(() => {
  272 + let v = cronValue.day
  273 + if (v.type == '0') {
  274 + return '*'
  275 + } else if (v.type == '1') {
  276 + return v.range.start + '-' + v.range.end
  277 + } else if (v.type == '2') {
  278 + return v.loop.start + '/' + v.loop.end
  279 + } else if (v.type == '3') {
  280 + return v.appoint.length > 0 ? v.appoint.join(',') : '*'
  281 + } else if (v.type == '4') {
  282 + return 'L'
  283 + } else if (v.type == '5') {
  284 + return '?'
  285 + } else {
  286 + return '*'
  287 + }
  288 +})
  289 +const value_month = computed(() => {
  290 + let v = cronValue.month
  291 + if (v.type == '0') {
  292 + return '*'
  293 + } else if (v.type == '1') {
  294 + return v.range.start + '-' + v.range.end
  295 + } else if (v.type == '2') {
  296 + return v.loop.start + '/' + v.loop.end
  297 + } else if (v.type == '3') {
  298 + return v.appoint.length > 0 ? v.appoint.join(',') : '*'
  299 + } else {
  300 + return '*'
  301 + }
  302 +})
  303 +const value_week = computed(() => {
  304 + let v = cronValue.week
  305 + if (v.type == '0') {
  306 + return '*'
  307 + } else if (v.type == '1') {
  308 + return v.range.start + '-' + v.range.end
  309 + } else if (v.type == '2') {
  310 + return v.loop.end + '#' + v.loop.start
  311 + } else if (v.type == '3') {
  312 + return v.appoint.length > 0 ? v.appoint.join(',') : '*'
  313 + } else if (v.type == '4') {
  314 + return v.last + 'L'
  315 + } else if (v.type == '5') {
  316 + return '?'
  317 + } else {
  318 + return '*'
  319 + }
  320 +})
  321 +const value_year = computed(() => {
  322 + let v = cronValue.year
  323 + if (v.type == '-1') {
  324 + return ''
  325 + } else if (v.type == '0') {
  326 + return '*'
  327 + } else if (v.type == '1') {
  328 + return v.range.start + '-' + v.range.end
  329 + } else if (v.type == '2') {
  330 + return v.loop.start + '/' + v.loop.end
  331 + } else if (v.type == '3') {
  332 + return v.appoint.length > 0 ? v.appoint.join(',') : ''
  333 + } else {
  334 + return ''
  335 + }
  336 +})
  337 +watch(
  338 + () => cronValue.week.type,
  339 + (val) => {
  340 + if (val != '5') {
  341 + cronValue.day.type = '5'
  342 + }
  343 + }
  344 +)
  345 +watch(
  346 + () => cronValue.day.type,
  347 + (val) => {
  348 + if (val != '5') {
  349 + cronValue.week.type = '5'
  350 + }
  351 + }
  352 +)
  353 +watch(
  354 + () => props.modelValue,
  355 + () => {
  356 + defaultValue.value = props.modelValue
  357 + }
  358 +)
  359 +onMounted(() => {
  360 + defaultValue.value = props.modelValue
  361 +})
  362 +const emit = defineEmits(['update:modelValue'])
  363 +const handleShortcuts = (command) => {
  364 + if (command == 'custom') {
  365 + open()
  366 + } else {
  367 + defaultValue.value = command
  368 + emit('update:modelValue', defaultValue.value)
  369 + }
  370 +}
  371 +const open = () => {
  372 + set()
  373 + dialogVisible.value = true
  374 +}
  375 +const set = () => {
  376 + defaultValue.value = props.modelValue
  377 + let arr = (props.modelValue || '* * * * * ?').split(' ')
  378 + //简单检查
  379 + if (arr.length < 6) {
  380 + ElMessage.warning('cron表达式错误,已转换为默认表达式')
  381 + arr = '* * * * * ?'.split(' ')
  382 + }
  383 +
  384 + //秒
  385 + if (arr[0] == '*') {
  386 + cronValue.second.type = '0'
  387 + } else if (arr[0].includes('-')) {
  388 + cronValue.second.type = '1'
  389 + cronValue.second.range.start = Number(arr[0].split('-')[0])
  390 + cronValue.second.range.end = Number(arr[0].split('-')[1])
  391 + } else if (arr[0].includes('/')) {
  392 + cronValue.second.type = '2'
  393 + cronValue.second.loop.start = Number(arr[0].split('/')[0])
  394 + cronValue.second.loop.end = Number(arr[0].split('/')[1])
  395 + } else {
  396 + cronValue.second.type = '3'
  397 + cronValue.second.appoint = arr[0].split(',')
  398 + }
  399 + //分
  400 + if (arr[1] == '*') {
  401 + cronValue.minute.type = '0'
  402 + } else if (arr[1].includes('-')) {
  403 + cronValue.minute.type = '1'
  404 + cronValue.minute.range.start = Number(arr[1].split('-')[0])
  405 + cronValue.minute.range.end = Number(arr[1].split('-')[1])
  406 + } else if (arr[1].includes('/')) {
  407 + cronValue.minute.type = '2'
  408 + cronValue.minute.loop.start = Number(arr[1].split('/')[0])
  409 + cronValue.minute.loop.end = Number(arr[1].split('/')[1])
  410 + } else {
  411 + cronValue.minute.type = '3'
  412 + cronValue.minute.appoint = arr[1].split(',')
  413 + }
  414 + //小时
  415 + if (arr[2] == '*') {
  416 + cronValue.hour.type = '0'
  417 + } else if (arr[2].includes('-')) {
  418 + cronValue.hour.type = '1'
  419 + cronValue.hour.range.start = Number(arr[2].split('-')[0])
  420 + cronValue.hour.range.end = Number(arr[2].split('-')[1])
  421 + } else if (arr[2].includes('/')) {
  422 + cronValue.hour.type = '2'
  423 + cronValue.hour.loop.start = Number(arr[2].split('/')[0])
  424 + cronValue.hour.loop.end = Number(arr[2].split('/')[1])
  425 + } else {
  426 + cronValue.hour.type = '3'
  427 + cronValue.hour.appoint = arr[2].split(',')
  428 + }
  429 + //日
  430 + if (arr[3] == '*') {
  431 + cronValue.day.type = '0'
  432 + } else if (arr[3] == 'L') {
  433 + cronValue.day.type = '4'
  434 + } else if (arr[3] == '?') {
  435 + cronValue.day.type = '5'
  436 + } else if (arr[3].includes('-')) {
  437 + cronValue.day.type = '1'
  438 + cronValue.day.range.start = Number(arr[3].split('-')[0])
  439 + cronValue.day.range.end = Number(arr[3].split('-')[1])
  440 + } else if (arr[3].includes('/')) {
  441 + cronValue.day.type = '2'
  442 + cronValue.day.loop.start = Number(arr[3].split('/')[0])
  443 + cronValue.day.loop.end = Number(arr[3].split('/')[1])
  444 + } else {
  445 + cronValue.day.type = '3'
  446 + cronValue.day.appoint = arr[3].split(',')
  447 + }
  448 + //月
  449 + if (arr[4] == '*') {
  450 + cronValue.month.type = '0'
  451 + } else if (arr[4].includes('-')) {
  452 + cronValue.month.type = '1'
  453 + cronValue.month.range.start = Number(arr[4].split('-')[0])
  454 + cronValue.month.range.end = Number(arr[4].split('-')[1])
  455 + } else if (arr[4].includes('/')) {
  456 + cronValue.month.type = '2'
  457 + cronValue.month.loop.start = Number(arr[4].split('/')[0])
  458 + cronValue.month.loop.end = Number(arr[4].split('/')[1])
  459 + } else {
  460 + cronValue.month.type = '3'
  461 + cronValue.month.appoint = arr[4].split(',')
  462 + }
  463 + //周
  464 + if (arr[5] == '*') {
  465 + cronValue.week.type = '0'
  466 + } else if (arr[5] == '?') {
  467 + cronValue.week.type = '5'
  468 + } else if (arr[5].includes('-')) {
  469 + cronValue.week.type = '1'
  470 + cronValue.week.range.start = arr[5].split('-')[0]
  471 + cronValue.week.range.end = arr[5].split('-')[1]
  472 + } else if (arr[5].includes('#')) {
  473 + cronValue.week.type = '2'
  474 + cronValue.week.loop.start = Number(arr[5].split('#')[1])
  475 + cronValue.week.loop.end = arr[5].split('#')[0]
  476 + } else if (arr[5].includes('L')) {
  477 + cronValue.week.type = '4'
  478 + cronValue.week.last = arr[5].split('L')[0]
  479 + } else {
  480 + cronValue.week.type = '3'
  481 + cronValue.week.appoint = arr[5].split(',')
  482 + }
  483 + //年
  484 + if (!arr[6]) {
  485 + cronValue.year.type = '-1'
  486 + } else if (arr[6] == '*') {
  487 + cronValue.year.type = '0'
  488 + } else if (arr[6].includes('-')) {
  489 + cronValue.year.type = '1'
  490 + cronValue.year.range.start = Number(arr[6].split('-')[0])
  491 + cronValue.year.range.end = Number(arr[6].split('-')[1])
  492 + } else if (arr[6].includes('/')) {
  493 + cronValue.year.type = '2'
  494 + cronValue.year.loop.start = Number(arr[6].split('/')[1])
  495 + cronValue.year.loop.end = Number(arr[6].split('/')[0])
  496 + } else {
  497 + cronValue.year.type = '3'
  498 + cronValue.year.appoint = arr[6].split(',')
  499 + }
  500 +}
  501 +const submit = () => {
  502 + let year = value_year.value ? ' ' + value_year.value : ''
  503 + defaultValue.value =
  504 + value_second.value +
  505 + ' ' +
  506 + value_minute.value +
  507 + ' ' +
  508 + value_hour.value +
  509 + ' ' +
  510 + value_day.value +
  511 + ' ' +
  512 + value_month.value +
  513 + ' ' +
  514 + value_week.value +
  515 + year
  516 + emit('update:modelValue', defaultValue.value)
  517 + dialogVisible.value = false
  518 +}
  519 +</script>
  520 +<template>
  521 + <el-input v-model="defaultValue" v-bind="$attrs">
  522 + <template #append>
  523 + <el-dropdown split-button trigger="click" @command="handleShortcuts">
  524 + 生成器
  525 + <template #dropdown>
  526 + <el-dropdown-menu>
  527 + <el-dropdown-item command="0 * * * * ?">每分钟</el-dropdown-item>
  528 + <el-dropdown-item command="0 0 * * * ?">每小时</el-dropdown-item>
  529 + <el-dropdown-item command="0 0 0 * * ?">每天零点</el-dropdown-item>
  530 + <el-dropdown-item command="0 0 0 1 * ?">每月一号零点</el-dropdown-item>
  531 + <el-dropdown-item command="0 0 0 L * ?">每月最后一天零点</el-dropdown-item>
  532 + <el-dropdown-item command="0 0 0 ? * 1">每周星期日零点</el-dropdown-item>
  533 + <el-dropdown-item
  534 + v-for="(item, index) in shortcuts"
  535 + :key="item.value"
  536 + :divided="index == 0"
  537 + :command="item.value"
  538 + >
  539 + {{ item.text }}
  540 + </el-dropdown-item>
  541 + <el-dropdown-item divided command="custom">
  542 + <Icon icon="ep:menu" />自定义
  543 + </el-dropdown-item>
  544 + </el-dropdown-menu>
  545 + </template>
  546 + </el-dropdown>
  547 + </template>
  548 + </el-input>
  549 +
  550 + <el-dialog
  551 + title="cron规则生成器"
  552 + v-model="dialogVisible"
  553 + :width="580"
  554 + destroy-on-close
  555 + append-to-body
  556 + >
  557 + <div class="sc-cron">
  558 + <el-tabs>
  559 + <el-tab-pane>
  560 + <template #label>
  561 + <div class="sc-cron-num">
  562 + <h2>秒</h2>
  563 + <h4>{{ value_second }}</h4>
  564 + </div>
  565 + </template>
  566 + <el-form>
  567 + <el-form-item label="类型">
  568 + <el-radio-group v-model="cronValue.second.type">
  569 + <el-radio-button label="0">任意值</el-radio-button>
  570 + <el-radio-button label="1">范围</el-radio-button>
  571 + <el-radio-button label="2">间隔</el-radio-button>
  572 + <el-radio-button label="3">指定</el-radio-button>
  573 + </el-radio-group>
  574 + </el-form-item>
  575 + <el-form-item label="范围" v-if="cronValue.second.type == '1'">
  576 + <el-input-number
  577 + v-model="cronValue.second.range.start"
  578 + :min="0"
  579 + :max="59"
  580 + controls-position="right"
  581 + />
  582 + <span style="padding: 0 15px">-</span>
  583 + <el-input-number
  584 + v-model="cronValue.second.range.end"
  585 + :min="0"
  586 + :max="59"
  587 + controls-position="right"
  588 + />
  589 + </el-form-item>
  590 + <el-form-item label="间隔" v-if="cronValue.second.type == '2'">
  591 + <el-input-number
  592 + v-model="cronValue.second.loop.start"
  593 + :min="0"
  594 + :max="59"
  595 + controls-position="right"
  596 + />
  597 + 秒开始,每
  598 + <el-input-number
  599 + v-model="cronValue.second.loop.end"
  600 + :min="0"
  601 + :max="59"
  602 + controls-position="right"
  603 + />
  604 + 秒执行一次
  605 + </el-form-item>
  606 + <el-form-item label="指定" v-if="cronValue.second.type == '3'">
  607 + <el-select v-model="cronValue.second.appoint" multiple style="width: 100%">
  608 + <el-option
  609 + v-for="(item, index) in data.second"
  610 + :key="index"
  611 + :label="item"
  612 + :value="item"
  613 + />
  614 + </el-select>
  615 + </el-form-item>
  616 + </el-form>
  617 + </el-tab-pane>
  618 + <el-tab-pane>
  619 + <template #label>
  620 + <div class="sc-cron-num">
  621 + <h2>分钟</h2>
  622 + <h4>{{ value_minute }}</h4>
  623 + </div>
  624 + </template>
  625 + <el-form>
  626 + <el-form-item label="类型">
  627 + <el-radio-group v-model="cronValue.minute.type">
  628 + <el-radio-button label="0">任意值</el-radio-button>
  629 + <el-radio-button label="1">范围</el-radio-button>
  630 + <el-radio-button label="2">间隔</el-radio-button>
  631 + <el-radio-button label="3">指定</el-radio-button>
  632 + </el-radio-group>
  633 + </el-form-item>
  634 + <el-form-item label="范围" v-if="cronValue.minute.type == '1'">
  635 + <el-input-number
  636 + v-model="cronValue.minute.range.start"
  637 + :min="0"
  638 + :max="59"
  639 + controls-position="right"
  640 + />
  641 + <span style="padding: 0 15px">-</span>
  642 + <el-input-number
  643 + v-model="cronValue.minute.range.end"
  644 + :min="0"
  645 + :max="59"
  646 + controls-position="right"
  647 + />
  648 + </el-form-item>
  649 + <el-form-item label="间隔" v-if="cronValue.minute.type == '2'">
  650 + <el-input-number
  651 + v-model="cronValue.minute.loop.start"
  652 + :min="0"
  653 + :max="59"
  654 + controls-position="right"
  655 + />
  656 + 分钟开始,每
  657 + <el-input-number
  658 + v-model="cronValue.minute.loop.end"
  659 + :min="0"
  660 + :max="59"
  661 + controls-position="right"
  662 + />
  663 + 分钟执行一次
  664 + </el-form-item>
  665 + <el-form-item label="指定" v-if="cronValue.minute.type == '3'">
  666 + <el-select v-model="cronValue.minute.appoint" multiple style="width: 100%">
  667 + <el-option
  668 + v-for="(item, index) in data.minute"
  669 + :key="index"
  670 + :label="item"
  671 + :value="item"
  672 + />
  673 + </el-select>
  674 + </el-form-item>
  675 + </el-form>
  676 + </el-tab-pane>
  677 + <el-tab-pane>
  678 + <template #label>
  679 + <div class="sc-cron-num">
  680 + <h2>小时</h2>
  681 + <h4>{{ value_hour }}</h4>
  682 + </div>
  683 + </template>
  684 + <el-form>
  685 + <el-form-item label="类型">
  686 + <el-radio-group v-model="cronValue.hour.type">
  687 + <el-radio-button label="0">任意值</el-radio-button>
  688 + <el-radio-button label="1">范围</el-radio-button>
  689 + <el-radio-button label="2">间隔</el-radio-button>
  690 + <el-radio-button label="3">指定</el-radio-button>
  691 + </el-radio-group>
  692 + </el-form-item>
  693 + <el-form-item label="范围" v-if="cronValue.hour.type == '1'">
  694 + <el-input-number
  695 + v-model="cronValue.hour.range.start"
  696 + :min="0"
  697 + :max="23"
  698 + controls-position="right"
  699 + />
  700 + <span style="padding: 0 15px">-</span>
  701 + <el-input-number
  702 + v-model="cronValue.hour.range.end"
  703 + :min="0"
  704 + :max="23"
  705 + controls-position="right"
  706 + />
  707 + </el-form-item>
  708 + <el-form-item label="间隔" v-if="cronValue.hour.type == '2'">
  709 + <el-input-number
  710 + v-model="cronValue.hour.loop.start"
  711 + :min="0"
  712 + :max="23"
  713 + controls-position="right"
  714 + />
  715 + 小时开始,每
  716 + <el-input-number
  717 + v-model="cronValue.hour.loop.end"
  718 + :min="0"
  719 + :max="23"
  720 + controls-position="right"
  721 + />
  722 + 小时执行一次
  723 + </el-form-item>
  724 + <el-form-item label="指定" v-if="cronValue.hour.type == '3'">
  725 + <el-select v-model="cronValue.hour.appoint" multiple style="width: 100%">
  726 + <el-option
  727 + v-for="(item, index) in data.hour"
  728 + :key="index"
  729 + :label="item"
  730 + :value="item"
  731 + />
  732 + </el-select>
  733 + </el-form-item>
  734 + </el-form>
  735 + </el-tab-pane>
  736 + <el-tab-pane>
  737 + <template #label>
  738 + <div class="sc-cron-num">
  739 + <h2>日</h2>
  740 + <h4>{{ value_day }}</h4>
  741 + </div>
  742 + </template>
  743 + <el-form>
  744 + <el-form-item label="类型">
  745 + <el-radio-group v-model="cronValue.day.type">
  746 + <el-radio-button label="0">任意值</el-radio-button>
  747 + <el-radio-button label="1">范围</el-radio-button>
  748 + <el-radio-button label="2">间隔</el-radio-button>
  749 + <el-radio-button label="3">指定</el-radio-button>
  750 + <el-radio-button label="4">本月最后一天</el-radio-button>
  751 + <el-radio-button label="5">不指定</el-radio-button>
  752 + </el-radio-group>
  753 + </el-form-item>
  754 + <el-form-item label="范围" v-if="cronValue.day.type == '1'">
  755 + <el-input-number
  756 + v-model="cronValue.day.range.start"
  757 + :min="1"
  758 + :max="31"
  759 + controls-position="right"
  760 + />
  761 + <span style="padding: 0 15px">-</span>
  762 + <el-input-number
  763 + v-model="cronValue.day.range.end"
  764 + :min="1"
  765 + :max="31"
  766 + controls-position="right"
  767 + />
  768 + </el-form-item>
  769 + <el-form-item label="间隔" v-if="cronValue.day.type == '2'">
  770 + <el-input-number
  771 + v-model="cronValue.day.loop.start"
  772 + :min="1"
  773 + :max="31"
  774 + controls-position="right"
  775 + />
  776 + 号开始,每
  777 + <el-input-number
  778 + v-model="cronValue.day.loop.end"
  779 + :min="1"
  780 + :max="31"
  781 + controls-position="right"
  782 + />
  783 + 天执行一次
  784 + </el-form-item>
  785 + <el-form-item label="指定" v-if="cronValue.day.type == '3'">
  786 + <el-select v-model="cronValue.day.appoint" multiple style="width: 100%">
  787 + <el-option
  788 + v-for="(item, index) in data.day"
  789 + :key="index"
  790 + :label="item"
  791 + :value="item"
  792 + />
  793 + </el-select>
  794 + </el-form-item>
  795 + </el-form>
  796 + </el-tab-pane>
  797 + <el-tab-pane>
  798 + <template #label>
  799 + <div class="sc-cron-num">
  800 + <h2>月</h2>
  801 + <h4>{{ value_month }}</h4>
  802 + </div>
  803 + </template>
  804 + <el-form>
  805 + <el-form-item label="类型">
  806 + <el-radio-group v-model="cronValue.month.type">
  807 + <el-radio-button label="0">任意值</el-radio-button>
  808 + <el-radio-button label="1">范围</el-radio-button>
  809 + <el-radio-button label="2">间隔</el-radio-button>
  810 + <el-radio-button label="3">指定</el-radio-button>
  811 + </el-radio-group>
  812 + </el-form-item>
  813 + <el-form-item label="范围" v-if="cronValue.month.type == '1'">
  814 + <el-input-number
  815 + v-model="cronValue.month.range.start"
  816 + :min="1"
  817 + :max="12"
  818 + controls-position="right"
  819 + />
  820 + <span style="padding: 0 15px">-</span>
  821 + <el-input-number
  822 + v-model="cronValue.month.range.end"
  823 + :min="1"
  824 + :max="12"
  825 + controls-position="right"
  826 + />
  827 + </el-form-item>
  828 + <el-form-item label="间隔" v-if="cronValue.month.type == '2'">
  829 + <el-input-number
  830 + v-model="cronValue.month.loop.start"
  831 + :min="1"
  832 + :max="12"
  833 + controls-position="right"
  834 + />
  835 + 月开始,每
  836 + <el-input-number
  837 + v-model="cronValue.month.loop.end"
  838 + :min="1"
  839 + :max="12"
  840 + controls-position="right"
  841 + />
  842 + 月执行一次
  843 + </el-form-item>
  844 + <el-form-item label="指定" v-if="cronValue.month.type == '3'">
  845 + <el-select v-model="cronValue.month.appoint" multiple style="width: 100%">
  846 + <el-option
  847 + v-for="(item, index) in data.month"
  848 + :key="index"
  849 + :label="item"
  850 + :value="item"
  851 + />
  852 + </el-select>
  853 + </el-form-item>
  854 + </el-form>
  855 + </el-tab-pane>
  856 + <el-tab-pane>
  857 + <template #label>
  858 + <div class="sc-cron-num">
  859 + <h2>周</h2>
  860 + <h4>{{ value_week }}</h4>
  861 + </div>
  862 + </template>
  863 + <el-form>
  864 + <el-form>
  865 + <el-form-item label="类型">
  866 + <el-radio-group v-model="cronValue.week.type">
  867 + <el-radio-button label="0">任意值</el-radio-button>
  868 + <el-radio-button label="1">范围</el-radio-button>
  869 + <el-radio-button label="2">间隔</el-radio-button>
  870 + <el-radio-button label="3">指定</el-radio-button>
  871 + <el-radio-button label="4">本月最后一周</el-radio-button>
  872 + <el-radio-button label="5">不指定</el-radio-button>
  873 + </el-radio-group>
  874 + </el-form-item>
  875 + <el-form-item label="范围" v-if="cronValue.week.type == '1'">
  876 + <el-select v-model="cronValue.week.range.start">
  877 + <el-option
  878 + v-for="(item, index) in data.week"
  879 + :key="index"
  880 + :label="item.label"
  881 + :value="item.value"
  882 + />
  883 + </el-select>
  884 + <span style="padding: 0 15px">-</span>
  885 + <el-select v-model="cronValue.week.range.end">
  886 + <el-option
  887 + v-for="(item, index) in data.week"
  888 + :key="index"
  889 + :label="item.label"
  890 + :value="item.value"
  891 + />
  892 + </el-select>
  893 + </el-form-item>
  894 + <el-form-item label="间隔" v-if="cronValue.week.type == '2'">
  895 + 第
  896 + <el-input-number
  897 + v-model="cronValue.week.loop.start"
  898 + :min="1"
  899 + :max="4"
  900 + controls-position="right"
  901 + />
  902 + 周的星期
  903 + <el-select v-model="cronValue.week.loop.end">
  904 + <el-option
  905 + v-for="(item, index) in data.week"
  906 + :key="index"
  907 + :label="item.label"
  908 + :value="item.value"
  909 + />
  910 + </el-select>
  911 + 执行一次
  912 + </el-form-item>
  913 + <el-form-item label="指定" v-if="cronValue.week.type == '3'">
  914 + <el-select v-model="cronValue.week.appoint" multiple style="width: 100%">
  915 + <el-option
  916 + v-for="(item, index) in data.week"
  917 + :key="index"
  918 + :label="item.label"
  919 + :value="item.value"
  920 + />
  921 + </el-select>
  922 + </el-form-item>
  923 + <el-form-item label="最后一周" v-if="cronValue.week.type == '4'">
  924 + <el-select v-model="cronValue.week.last">
  925 + <el-option
  926 + v-for="(item, index) in data.week"
  927 + :key="index"
  928 + :label="item.label"
  929 + :value="item.value"
  930 + />
  931 + </el-select>
  932 + </el-form-item>
  933 + </el-form>
  934 + </el-form>
  935 + </el-tab-pane>
  936 + <el-tab-pane>
  937 + <template #label>
  938 + <div class="sc-cron-num">
  939 + <h2>年</h2>
  940 + <h4>{{ value_year }}</h4>
  941 + </div>
  942 + </template>
  943 + <el-form>
  944 + <el-form-item label="类型">
  945 + <el-radio-group v-model="cronValue.year.type">
  946 + <el-radio-button label="-1">忽略</el-radio-button>
  947 + <el-radio-button label="0">任意值</el-radio-button>
  948 + <el-radio-button label="1">范围</el-radio-button>
  949 + <el-radio-button label="2">间隔</el-radio-button>
  950 + <el-radio-button label="3">指定</el-radio-button>
  951 + </el-radio-group>
  952 + </el-form-item>
  953 + <el-form-item label="范围" v-if="cronValue.year.type == '1'">
  954 + <el-input-number v-model="cronValue.year.range.start" controls-position="right" />
  955 + <span style="padding: 0 15px">-</span>
  956 + <el-input-number v-model="cronValue.year.range.end" controls-position="right" />
  957 + </el-form-item>
  958 + <el-form-item label="间隔" v-if="cronValue.year.type == '2'">
  959 + <el-input-number v-model="cronValue.year.loop.start" controls-position="right" />
  960 + 年开始,每
  961 + <el-input-number
  962 + v-model="cronValue.year.loop.end"
  963 + :min="1"
  964 + controls-position="right"
  965 + />
  966 + 年执行一次
  967 + </el-form-item>
  968 + <el-form-item label="指定" v-if="cronValue.year.type == '3'">
  969 + <el-select v-model="cronValue.year.appoint" multiple style="width: 100%">
  970 + <el-option
  971 + v-for="(item, index) in data.year"
  972 + :key="index"
  973 + :label="item"
  974 + :value="item"
  975 + />
  976 + </el-select>
  977 + </el-form-item>
  978 + </el-form>
  979 + </el-tab-pane>
  980 + </el-tabs>
  981 + </div>
  982 +
  983 + <template #footer>
  984 + <el-button @click="dialogVisible = false">取 消</el-button>
  985 + <el-button type="primary" @click="submit()">确 认</el-button>
  986 + </template>
  987 + </el-dialog>
  988 +</template>
  989 +
  990 +<style scoped>
  991 +.sc-cron:deep(.el-tabs__item) {
  992 + height: auto;
  993 + line-height: 1;
  994 + padding: 0 7px;
  995 + vertical-align: bottom;
  996 +}
  997 +.sc-cron-num {
  998 + text-align: center;
  999 + margin-bottom: 15px;
  1000 + width: 100%;
  1001 +}
  1002 +.sc-cron-num h2 {
  1003 + font-size: 12px;
  1004 + margin-bottom: 15px;
  1005 + font-weight: normal;
  1006 +}
  1007 +.sc-cron-num h4 {
  1008 + display: block;
  1009 + height: 32px;
  1010 + line-height: 30px;
  1011 + width: 100%;
  1012 + font-size: 12px;
  1013 + padding: 0 15px;
  1014 + background: var(--el-color-primary-light-9);
  1015 + border-radius: 4px;
  1016 +}
  1017 +.sc-cron:deep(.el-tabs__item.is-active) .sc-cron-num h4 {
  1018 + background: var(--el-color-primary);
  1019 + color: #fff;
  1020 +}
  1021 +
  1022 +[data-theme='dark'] .sc-cron-num h4 {
  1023 + background: var(--el-color-white);
  1024 +}
  1025 +</style>
yudao-ui-admin-vue3/src/components/Crontab/src/components/day.vue deleted
1 -<script setup lang="ts">  
2 -import { computed, ref, watch } from 'vue'  
3 -import { ElForm, ElFormItem, ElRadio, ElSelect, ElOption, ElInputNumber } from 'element-plus'  
4 -const props = defineProps({  
5 - check: {  
6 - type: Function,  
7 - required: true  
8 - },  
9 - cron: {  
10 - type: Object  
11 - }  
12 -})  
13 -  
14 -const emits = defineEmits(['update'])  
15 -  
16 -const radioValue = ref(1)  
17 -const workday = ref(1)  
18 -const cycle01 = ref(1)  
19 -const cycle02 = ref(2)  
20 -const average01 = ref(1)  
21 -const average02 = ref(1)  
22 -  
23 -const checkboxList = ref([])  
24 -  
25 -defineExpose({  
26 - radioValue,  
27 - workday,  
28 - cycle01,  
29 - cycle02,  
30 - average01,  
31 - average02,  
32 - checkboxList  
33 -})  
34 -  
35 -/**  
36 - * 计算两个周期值  
37 - * @type {ComputedRef<string>}  
38 - */  
39 -const cycleTotal = computed(() => {  
40 - const cycle1 = props.check(cycle01.value, 1, 30)  
41 - const cycle2 = props.check(cycle02.value, cycle1 ? cycle1 + 1 : 2, 31, 31)  
42 - return cycle1 + '-' + cycle2  
43 -})  
44 -  
45 -/**  
46 - * 计算平均用到的值  
47 - */  
48 -const averageTotal = computed(() => {  
49 - const average1 = props.check(average01.value, 1, 30)  
50 - const average2 = props.check(average02.value, 1, 31 - average1 || 0)  
51 - return average1 + '/' + average2  
52 -})  
53 -  
54 -/**  
55 - * 计算工作日格式  
56 - */  
57 -const workdayCheck = computed(() => props.check(workday, 1, 31))  
58 -  
59 -/**  
60 - * 计算勾选的checkbox值合集  
61 - */  
62 -const checkboxString = computed(() => {  
63 - const str = checkboxList.value.join()  
64 - return str.length === 0 ? '*' : str  
65 -})  
66 -  
67 -watch(radioValue, () => {  
68 - if (parseInt(radioValue.value.toString()) !== 2 && props.cron?.week !== '?') {  
69 - emits('update', 'week', '?', 'day')  
70 - }  
71 -  
72 - switch (parseInt(radioValue.value.toString())) {  
73 - case 1:  
74 - emits('update', 'day', '*')  
75 - break  
76 - case 2:  
77 - emits('update', 'day', '?')  
78 - break  
79 - case 3:  
80 - emits('update', 'day', cycleTotal)  
81 - break  
82 - case 4:  
83 - emits('update', 'day', averageTotal)  
84 - break  
85 - case 5:  
86 - emits('update', 'day', workday.value + 'W')  
87 - break  
88 - case 6:  
89 - emits('update', 'day', 'L')  
90 - break  
91 - case 7:  
92 - emits('update', 'day', checkboxString)  
93 - break  
94 - }  
95 -})  
96 -  
97 -watch(cycleTotal, () => {  
98 - if (parseInt(radioValue.value.toString()) === 3) {  
99 - emits('update', 'day', cycleTotal)  
100 - }  
101 -})  
102 -  
103 -watch(averageTotal, () => {  
104 - if (parseInt(radioValue.value.toString()) === 4) {  
105 - emits('update', 'day', averageTotal)  
106 - }  
107 -})  
108 -  
109 -watch(workdayCheck, () => {  
110 - if (parseInt(radioValue.value.toString()) === 5) {  
111 - emits('update', 'day', workdayCheck.value + 'W')  
112 - }  
113 -})  
114 -  
115 -watch(checkboxString, () => {  
116 - if (parseInt(radioValue.value.toString()) === 7) {  
117 - emits('update', 'day', checkboxString)  
118 - }  
119 -})  
120 -</script>  
121 -<template>  
122 - <el-form>  
123 - <el-form-item>  
124 - <el-radio v-model="radioValue" :label="1"> 日,允许的通配符[, - * ? / L W] </el-radio>  
125 - </el-form-item>  
126 -  
127 - <el-form-item>  
128 - <el-radio v-model="radioValue" :label="2"> 不指定 </el-radio>  
129 - </el-form-item>  
130 -  
131 - <el-form-item>  
132 - <el-radio v-model="radioValue" :label="3">  
133 - 周期从  
134 - <el-input-number v-model="cycle01" :min="1" :max="30" /> -  
135 - <el-input-number v-model="cycle02" :min="cycle01 ? cycle01 + 1 : 2" :max="31" /> 日  
136 - </el-radio>  
137 - </el-form-item>  
138 -  
139 - <el-form-item>  
140 - <el-radio v-model="radioValue" :label="4">  
141 - 从  
142 - <el-input-number v-model="average01" :min="1" :max="30" /> 号开始,每  
143 - <el-input-number v-model="average02" :min="1" :max="31 - average01 || 1" /> 日执行一次  
144 - </el-radio>  
145 - </el-form-item>  
146 -  
147 - <el-form-item>  
148 - <el-radio v-model="radioValue" :label="5">  
149 - 每月  
150 - <el-input-number v-model="workday" :min="1" :max="31" /> 号最近的那个工作日  
151 - </el-radio>  
152 - </el-form-item>  
153 -  
154 - <el-form-item>  
155 - <el-radio v-model="radioValue" :label="6"> 本月最后一天 </el-radio>  
156 - </el-form-item>  
157 -  
158 - <el-form-item>  
159 - <el-radio v-model="radioValue" :label="7">  
160 - 指定  
161 - <el-select  
162 - clearable  
163 - v-model="checkboxList"  
164 - placeholder="可多选"  
165 - multiple  
166 - style="width: 100%"  
167 - >  
168 - <el-option v-for="item in 31" :key="item" :value="item">{{ item }}</el-option>  
169 - </el-select>  
170 - </el-radio>  
171 - </el-form-item>  
172 - </el-form>  
173 -</template>  
yudao-ui-admin-vue3/src/components/Crontab/src/components/hour.vue deleted
1 -<script setup lang="ts">  
2 -import { computed, ref, watch } from 'vue'  
3 -import { ElForm, ElFormItem, ElRadio, ElSelect, ElOption, ElInputNumber } from 'element-plus'  
4 -const props = defineProps({  
5 - check: {  
6 - type: Function,  
7 - required: true  
8 - },  
9 - cron: {  
10 - type: Object  
11 - }  
12 -})  
13 -const emits = defineEmits(['update'])  
14 -  
15 -const radioValue = ref(1)  
16 -const cycle01 = ref(0)  
17 -const cycle02 = ref(1)  
18 -const average01 = ref(0)  
19 -const average02 = ref(1)  
20 -const checkboxList = ref([])  
21 -  
22 -defineExpose({  
23 - radioValue,  
24 - cycle01,  
25 - cycle02,  
26 - average01,  
27 - average02,  
28 - checkboxList  
29 -})  
30 -  
31 -const cycleTotal = computed(() => {  
32 - const cycle1 = props.check(cycle01.value, 0, 22)  
33 - const cycle2 = props.check(cycle02.value, cycle1 ? cycle1 + 1 : 1, 23)  
34 - return cycle1 + '-' + cycle2  
35 -})  
36 -  
37 -watch(cycleTotal, () => {  
38 - if (parseInt(radioValue.value.toString()) === 2) {  
39 - emits('update', 'hour', cycleTotal)  
40 - }  
41 -})  
42 -  
43 -const averageTotal = computed(() => {  
44 - const average1 = props.check(average01.value, 0, 22)  
45 - const average2 = props.check(average02.value, 1, 23 - average1 || 0)  
46 - return average1 + '/' + average2  
47 -})  
48 -  
49 -watch(averageTotal, () => {  
50 - if (parseInt(radioValue.value.toString()) === 3) {  
51 - emits('update', 'hour', averageTotal)  
52 - }  
53 -})  
54 -  
55 -const checkboxString = computed(() => {  
56 - let str = checkboxList.value.join()  
57 - return str.length === 0 ? '*' : str  
58 -})  
59 -  
60 -watch(checkboxString, () => {  
61 - if (parseInt(radioValue.value.toString()) === 4) {  
62 - emits('update', 'hour', checkboxString)  
63 - }  
64 -})  
65 -  
66 -watch(radioValue, () => {  
67 - switch (parseInt(radioValue.value.toString())) {  
68 - case 1:  
69 - emits('update', 'hour', '*')  
70 - break  
71 - case 2:  
72 - emits('update', 'hour', cycleTotal)  
73 - break  
74 - case 3:  
75 - emits('update', 'hour', averageTotal)  
76 - break  
77 - case 4:  
78 - emits('update', 'hour', checkboxString)  
79 - break  
80 - }  
81 -})  
82 -</script>  
83 -<template>  
84 - <el-form>  
85 - <el-form-item>  
86 - <el-radio v-model="radioValue" :label="1"> 小时,允许的通配符[, - * /] </el-radio>  
87 - </el-form-item>  
88 -  
89 - <el-form-item>  
90 - <el-radio v-model="radioValue" :label="2">  
91 - 周期从  
92 - <el-input-number v-model="cycle01" :min="0" :max="22" /> -  
93 - <el-input-number v-model="cycle02" :min="cycle01 ? cycle01 + 1 : 1" :max="23" /> 小时  
94 - </el-radio>  
95 - </el-form-item>  
96 -  
97 - <el-form-item>  
98 - <el-radio v-model="radioValue" :label="3">  
99 - 从  
100 - <el-input-number v-model="average01" :min="0" :max="22" /> 小时开始,每  
101 - <el-input-number v-model="average02" :min="1" :max="23 - average01 || 0" /> 小时执行一次  
102 - </el-radio>  
103 - </el-form-item>  
104 -  
105 - <el-form-item>  
106 - <el-radio v-model="radioValue" :label="4">  
107 - 指定  
108 - <el-select  
109 - clearable  
110 - v-model="checkboxList"  
111 - placeholder="可多选"  
112 - multiple  
113 - style="width: 100%"  
114 - >  
115 - <el-option v-for="item in 24" :key="item" :value="item - 1">{{ item - 1 }}</el-option>  
116 - </el-select>  
117 - </el-radio>  
118 - </el-form-item>  
119 - </el-form>  
120 -</template>  
yudao-ui-admin-vue3/src/components/Crontab/src/components/index.ts deleted
1 -import CrontabSecond from './second.vue'  
2 -import CrontabMin from './min.vue'  
3 -import CrontabHour from './hour.vue'  
4 -import CrontabDay from './day.vue'  
5 -import CrontabMonth from './month.vue'  
6 -import CrontabWeek from './week.vue'  
7 -import CrontabYear from './year.vue'  
8 -import CrontabResult from './result.vue'  
9 -  
10 -export {  
11 - CrontabSecond,  
12 - CrontabMin,  
13 - CrontabHour,  
14 - CrontabDay,  
15 - CrontabMonth,  
16 - CrontabWeek,  
17 - CrontabYear,  
18 - CrontabResult  
19 -}  
yudao-ui-admin-vue3/src/components/Crontab/src/components/min.vue deleted
1 -<script setup lang="ts">  
2 -import { computed, ref, watch } from 'vue'  
3 -import { ElForm, ElFormItem, ElRadio, ElSelect, ElOption, ElInputNumber } from 'element-plus'  
4 -const props = defineProps({  
5 - check: {  
6 - type: Function,  
7 - required: true  
8 - },  
9 - cron: {  
10 - type: Object  
11 - }  
12 -})  
13 -const emits = defineEmits(['update'])  
14 -  
15 -const radioValue = ref(1)  
16 -const cycle01 = ref(0)  
17 -const cycle02 = ref(1)  
18 -const average01 = ref(0)  
19 -const average02 = ref(1)  
20 -const checkboxList = ref([])  
21 -  
22 -defineExpose({  
23 - radioValue,  
24 - cycle01,  
25 - cycle02,  
26 - average01,  
27 - average02,  
28 - checkboxList  
29 -})  
30 -  
31 -const cycleTotal = computed(() => {  
32 - const cycle1 = props.check(cycle01.value, 0, 58)  
33 - const cycle2 = props.check(cycle02.value, cycle1 ? cycle1 + 1 : 1, 59)  
34 - return cycle1 + '-' + cycle2  
35 -})  
36 -  
37 -watch(cycleTotal, () => {  
38 - if (parseInt(radioValue.value.toString()) === 2) {  
39 - emits('update', 'min', cycleTotal, 'min')  
40 - }  
41 -})  
42 -  
43 -const averageTotal = computed(() => {  
44 - const average1 = props.check(average01.value, 0, 58)  
45 - const average2 = props.check(average02.value, 1, 59 - average1 || 0)  
46 - return average1 + '/' + average2  
47 -})  
48 -  
49 -watch(averageTotal, () => {  
50 - if (parseInt(radioValue.value.toString()) === 3) {  
51 - emits('update', 'min', averageTotal, 'min')  
52 - }  
53 -})  
54 -  
55 -const checkboxString = computed(() => {  
56 - let str = checkboxList.value.join()  
57 - return str.length === 0 ? '*' : str  
58 -})  
59 -  
60 -watch(checkboxString, () => {  
61 - if (parseInt(radioValue.value.toString()) === 4) {  
62 - emits('update', 'min', checkboxString, 'min')  
63 - }  
64 -})  
65 -  
66 -watch(radioValue, () => {  
67 - switch (parseInt(radioValue.value.toString())) {  
68 - case 1:  
69 - emits('update', 'min', '*', 'min')  
70 - break  
71 - case 2:  
72 - emits('update', 'min', cycleTotal, 'min')  
73 - break  
74 - case 3:  
75 - emits('update', 'min', averageTotal, 'min')  
76 - break  
77 - case 4:  
78 - emits('update', 'min', checkboxString, 'min')  
79 - break  
80 - }  
81 -})  
82 -</script>  
83 -<template>  
84 - <el-form>  
85 - <el-form-item>  
86 - <el-radio v-model="radioValue" :label="1"> 分钟,允许的通配符[, - * /] </el-radio>  
87 - </el-form-item>  
88 -  
89 - <el-form-item>  
90 - <el-radio v-model="radioValue" :label="2">  
91 - 周期从  
92 - <el-input-number v-model="cycle01" :min="0" :max="58" /> -  
93 - <el-input-number v-model="cycle02" :min="cycle01 ? cycle01 + 1 : 1" :max="59" /> 分钟  
94 - </el-radio>  
95 - </el-form-item>  
96 -  
97 - <el-form-item>  
98 - <el-radio v-model="radioValue" :label="3">  
99 - 从  
100 - <el-input-number v-model="average01" :min="0" :max="58" /> 分钟开始,每  
101 - <el-input-number v-model="average02" :min="1" :max="59 - average01 || 0" /> 分钟执行一次  
102 - </el-radio>  
103 - </el-form-item>  
104 -  
105 - <el-form-item>  
106 - <el-radio v-model="radioValue" :label="4">  
107 - 指定  
108 - <el-select  
109 - clearable  
110 - v-model="checkboxList"  
111 - placeholder="可多选"  
112 - multiple  
113 - style="width: 100%"  
114 - >  
115 - <el-option v-for="item in 60" :key="item" :value="item - 1">{{ item - 1 }}</el-option>  
116 - </el-select>  
117 - </el-radio>  
118 - </el-form-item>  
119 - </el-form>  
120 -</template>  
yudao-ui-admin-vue3/src/components/Crontab/src/components/month.vue deleted
1 -<script setup lang="ts">  
2 -import { computed, ref, watch } from 'vue'  
3 -import { ElForm, ElFormItem, ElRadio, ElSelect, ElOption, ElInputNumber } from 'element-plus'  
4 -const props = defineProps({  
5 - check: {  
6 - type: Function,  
7 - required: true  
8 - },  
9 - cron: {  
10 - type: Object  
11 - }  
12 -})  
13 -const emits = defineEmits(['update'])  
14 -  
15 -const radioValue = ref(1)  
16 -const cycle01 = ref(1)  
17 -const cycle02 = ref(2)  
18 -const average01 = ref(1)  
19 -const average02 = ref(1)  
20 -const checkboxList = ref([])  
21 -  
22 -defineExpose({  
23 - radioValue,  
24 - cycle01,  
25 - cycle02,  
26 - average01,  
27 - average02,  
28 - checkboxList  
29 -})  
30 -  
31 -const cycleTotal = computed(() => {  
32 - const cycle1 = props.check(cycle01.value, 1, 11)  
33 - const cycle2 = props.check(cycle02.value, cycle1 ? cycle1 + 1 : 2, 12)  
34 - return cycle1 + '-' + cycle2  
35 -})  
36 -  
37 -watch(cycleTotal, () => {  
38 - if (parseInt(radioValue.value.toString()) === 2) {  
39 - emits('update', 'month', cycleTotal)  
40 - }  
41 -})  
42 -  
43 -const averageTotal = computed(() => {  
44 - const average1 = props.check(average01.value, 1, 11)  
45 - const average2 = props.check(average02.value, 1, 12 - average1 || 0)  
46 - return average1 + '/' + average2  
47 -})  
48 -  
49 -watch(averageTotal, () => {  
50 - if (parseInt(radioValue.value.toString()) === 3) {  
51 - emits('update', 'month', averageTotal)  
52 - }  
53 -})  
54 -  
55 -const checkboxString = computed(() => {  
56 - let str = checkboxList.value.join()  
57 - return str.length === 0 ? '*' : str  
58 -})  
59 -  
60 -watch(checkboxString, () => {  
61 - if (parseInt(radioValue.value.toString()) === 4) {  
62 - emits('update', 'month', checkboxString)  
63 - }  
64 -})  
65 -  
66 -watch(radioValue, () => {  
67 - switch (parseInt(radioValue.value.toString())) {  
68 - case 1:  
69 - emits('update', 'month', '*')  
70 - break  
71 - case 2:  
72 - emits('update', 'month', cycleTotal)  
73 - break  
74 - case 3:  
75 - emits('update', 'month', averageTotal)  
76 - break  
77 - case 4:  
78 - emits('update', 'month', checkboxString)  
79 - break  
80 - }  
81 -})  
82 -</script>  
83 -<template>  
84 - <el-form>  
85 - <el-form-item>  
86 - <el-radio v-model="radioValue" :label="1"> 月,允许的通配符[, - * /] </el-radio>  
87 - </el-form-item>  
88 -  
89 - <el-form-item>  
90 - <el-radio v-model="radioValue" :label="2">  
91 - 周期从  
92 - <el-input-number v-model="cycle01" :min="1" :max="11" /> -  
93 - <el-input-number v-model="cycle02" :min="cycle01 ? cycle01 + 1 : 2" :max="12" /> 月  
94 - </el-radio>  
95 - </el-form-item>  
96 -  
97 - <el-form-item>  
98 - <el-radio v-model="radioValue" :label="3">  
99 - 从  
100 - <el-input-number v-model="average01" :min="1" :max="11" /> 月开始,每  
101 - <el-input-number v-model="average02" :min="1" :max="12 - average01 || 0" /> 月月执行一次  
102 - </el-radio>  
103 - </el-form-item>  
104 -  
105 - <el-form-item>  
106 - <el-radio v-model="radioValue" :label="4">  
107 - 指定  
108 - <el-select  
109 - clearable  
110 - v-model="checkboxList"  
111 - placeholder="可多选"  
112 - multiple  
113 - style="width: 100%"  
114 - >  
115 - <el-option v-for="item in 12" :key="item" :value="item">{{ item }}</el-option>  
116 - </el-select>  
117 - </el-radio>  
118 - </el-form-item>  
119 - </el-form>  
120 -</template>  
yudao-ui-admin-vue3/src/components/Crontab/src/components/result.vue deleted
1 -<script setup lang="ts">  
2 -import { onMounted, ref, watch } from 'vue'  
3 -  
4 -const props = defineProps({  
5 - ex: {  
6 - type: String,  
7 - required: true  
8 - }  
9 -})  
10 -  
11 -watch(() => props.ex, expressionChange)  
12 -  
13 -onMounted(() => {  
14 - expressionChange()  
15 -})  
16 -  
17 -const dayRule = ref('')  
18 -const dayRuleSup = ref<string | number | any[]>([])  
19 -const dateArr = ref<any[][]>([])  
20 -const resultList = ref<string[]>([])  
21 -const isShow = ref(false)  
22 -  
23 -function expressionChange() {  
24 - // 计算开始-隐藏结果  
25 - isShow.value = false  
26 - // 获取规则数组[0秒、1分、2时、3日、4月、5星期、6年]  
27 - let ruleArr = props.ex.split(' ')  
28 - // 用于记录进入循环的次数  
29 - let nums = 0  
30 - // 用于暂时存符号时间规则结果的数组  
31 - let resultArr: string[] = []  
32 - // 获取当前时间精确至[年、月、日、时、分、秒]  
33 - let nTime = new Date()  
34 - let nYear = nTime.getFullYear()  
35 - let nMonth = nTime.getMonth() + 1  
36 - let nDay = nTime.getDate()  
37 - let nHour = nTime.getHours()  
38 - let nMin = nTime.getMinutes()  
39 - let nSecond = nTime.getSeconds()  
40 - // 根据规则获取到近100年可能年数组、月数组等等  
41 - getSecondArr(ruleArr[0])  
42 - getMinArr(ruleArr[1])  
43 - getHourArr(ruleArr[2])  
44 - getDayArr(ruleArr[3])  
45 - getMonthArr(ruleArr[4])  
46 - getWeekArr(ruleArr[5])  
47 - getYearArr(ruleArr[6], nYear)  
48 - // 将获取到的数组赋值-方便使用  
49 - let sDate = dateArr.value[0]  
50 - let mDate = dateArr.value[1]  
51 - let hDate = dateArr.value[2]  
52 - let DDate = dateArr.value[3]  
53 - let MDate = dateArr.value[4]  
54 - let YDate = dateArr.value[5]  
55 - // 获取当前时间在数组中的索引  
56 - let sIdx = getIndex(sDate, nSecond)  
57 - let mIdx = getIndex(mDate, nMin)  
58 - let hIdx = getIndex(hDate, nHour)  
59 - let DIdx = getIndex(DDate, nDay)  
60 - let MIdx = getIndex(MDate, nMonth)  
61 - let YIdx = getIndex(YDate, nYear)  
62 - // 重置月日时分秒的函数(后面用的比较多)  
63 - const resetSecond = function () {  
64 - sIdx = 0  
65 - nSecond = sDate[sIdx]  
66 - }  
67 - const resetMin = function () {  
68 - mIdx = 0  
69 - nMin = mDate[mIdx]  
70 - resetSecond()  
71 - }  
72 - const resetHour = function () {  
73 - hIdx = 0  
74 - nHour = hDate[hIdx]  
75 - resetMin()  
76 - }  
77 - const resetDay = function () {  
78 - DIdx = 0  
79 - nDay = DDate[DIdx]  
80 - resetHour()  
81 - }  
82 - const resetMonth = function () {  
83 - MIdx = 0  
84 - nMonth = MDate[MIdx]  
85 - resetDay()  
86 - }  
87 - // 如果当前年份不为数组中当前值  
88 - if (nYear !== YDate[YIdx]) {  
89 - resetMonth()  
90 - }  
91 - // 如果当前月份不为数组中当前值  
92 - if (nMonth !== MDate[MIdx]) {  
93 - resetDay()  
94 - }  
95 - // 如果当前“日”不为数组中当前值  
96 - if (nDay !== DDate[DIdx]) {  
97 - resetHour()  
98 - }  
99 - // 如果当前“时”不为数组中当前值  
100 - if (nHour !== hDate[hIdx]) {  
101 - resetMin()  
102 - }  
103 - // 如果当前“分”不为数组中当前值  
104 - if (nMin !== mDate[mIdx]) {  
105 - resetSecond()  
106 - }  
107 -  
108 - // 循环年份数组  
109 - goYear: for (let Yi = YIdx; Yi < YDate.length; Yi++) {  
110 - let YY = YDate[Yi]  
111 - // 如果到达最大值时  
112 - if (nMonth > MDate[MDate.length - 1]) {  
113 - resetMonth()  
114 - continue  
115 - }  
116 - // 循环月份数组  
117 - goMonth: for (let Mi = MIdx; Mi < MDate.length; Mi++) {  
118 - // 赋值、方便后面运算  
119 - let MM = MDate[Mi]  
120 - MM = MM < 10 ? '0' + MM : MM  
121 - // 如果到达最大值时  
122 - if (nDay > DDate[DDate.length - 1]) {  
123 - resetDay()  
124 - if (Mi == MDate.length - 1) {  
125 - resetMonth()  
126 - continue goYear  
127 - }  
128 - continue  
129 - }  
130 - // 循环日期数组  
131 - goDay: for (let Di = DIdx; Di < DDate.length; Di++) {  
132 - // 赋值、方便后面运算  
133 - let DD = DDate[Di]  
134 - let thisDD = DD < 10 ? '0' + DD : DD  
135 -  
136 - // 如果到达最大值时  
137 - if (nHour > hDate[hDate.length - 1]) {  
138 - resetHour()  
139 - if (Di == DDate.length - 1) {  
140 - resetDay()  
141 - if (Mi == MDate.length - 1) {  
142 - resetMonth()  
143 - continue goYear  
144 - }  
145 - continue goMonth  
146 - }  
147 - continue  
148 - }  
149 -  
150 - // 判断日期的合法性,不合法的话也是跳出当前循环  
151 - if (  
152 - checkDate(YY + '-' + MM + '-' + thisDD + ' 00:00:00') !== true &&  
153 - dayRule.value !== 'workDay' &&  
154 - dayRule.value !== 'lastWeek' &&  
155 - dayRule.value !== 'lastDay'  
156 - ) {  
157 - resetDay()  
158 - continue goMonth  
159 - }  
160 - // 如果日期规则中有值时  
161 - if (dayRule.value == 'lastDay') {  
162 - // 如果不是合法日期则需要将前将日期调到合法日期即月末最后一天  
163 -  
164 - if (checkDate(YY + '-' + MM + '-' + thisDD + ' 00:00:00') !== true) {  
165 - while (DD > 0 && checkDate(YY + '-' + MM + '-' + thisDD + ' 00:00:00') !== true) {  
166 - DD--  
167 -  
168 - thisDD = DD < 10 ? '0' + DD : DD  
169 - }  
170 - }  
171 - } else if (dayRule.value == 'workDay') {  
172 - // 校验并调整如果是2月30号这种日期传进来时需调整至正常月底  
173 - if (checkDate(YY + '-' + MM + '-' + thisDD + ' 00:00:00') !== true) {  
174 - while (DD > 0 && checkDate(YY + '-' + MM + '-' + thisDD + ' 00:00:00') !== true) {  
175 - DD--  
176 - thisDD = DD < 10 ? '0' + DD : DD  
177 - }  
178 - }  
179 - // 获取达到条件的日期是星期X  
180 - let thisWeek = formatDate(new Date(YY + '-' + MM + '-' + thisDD + ' 00:00:00'), 'week')  
181 - // 当星期日时  
182 - if (thisWeek == 1) {  
183 - // 先找下一个日,并判断是否为月底  
184 - DD++  
185 - thisDD = DD < 10 ? '0' + DD : DD  
186 - // 判断下一日已经不是合法日期  
187 - if (checkDate(YY + '-' + MM + '-' + thisDD + ' 00:00:00') !== true) {  
188 - DD -= 3  
189 - }  
190 - } else if (thisWeek == 7) {  
191 - // 当星期6时只需判断不是1号就可进行操作  
192 - if (dayRuleSup.value !== 1) {  
193 - DD--  
194 - } else {  
195 - DD += 2  
196 - }  
197 - }  
198 - } else if (dayRule.value == 'weekDay') {  
199 - // 如果指定了是星期几  
200 - // 获取当前日期是属于星期几  
201 - let thisWeek = formatDate(new Date(YY + '-' + MM + '-' + DD + ' 00:00:00'), 'week')  
202 - // 校验当前星期是否在星期池(dayRuleSup)中  
203 - if ((dayRuleSup.value as any[]).indexOf(thisWeek) < 0) {  
204 - // 如果到达最大值时  
205 - if (Di == DDate.length - 1) {  
206 - resetDay()  
207 - if (Mi == MDate.length - 1) {  
208 - resetMonth()  
209 - continue goYear  
210 - }  
211 - continue goMonth  
212 - }  
213 - continue  
214 - }  
215 - } else if (dayRule.value == 'assWeek') {  
216 - // 如果指定了是第几周的星期几  
217 - // 获取每月1号是属于星期几  
218 - let thisWeek = formatDate(new Date(YY + '-' + MM + '-' + DD + ' 00:00:00'), 'week')  
219 - if (dayRuleSup.value[1] >= thisWeek) {  
220 - DD = (dayRuleSup.value[0] - 1) * 7 + dayRuleSup.value[1] - thisWeek + 1  
221 - } else {  
222 - DD = dayRuleSup.value[0] * 7 + dayRuleSup.value[1] - thisWeek + 1  
223 - }  
224 - } else if (dayRule.value == 'lastWeek') {  
225 - // 如果指定了每月最后一个星期几  
226 - // 校验并调整如果是2月30号这种日期传进来时需调整至正常月底  
227 - if (checkDate(YY + '-' + MM + '-' + thisDD + ' 00:00:00') !== true) {  
228 - while (DD > 0 && checkDate(YY + '-' + MM + '-' + thisDD + ' 00:00:00') !== true) {  
229 - DD--  
230 - thisDD = DD < 10 ? '0' + DD : DD  
231 - }  
232 - }  
233 - // 获取月末最后一天是星期几  
234 - let thisWeek = formatDate(new Date(YY + '-' + MM + '-' + thisDD + ' 00:00:00'), 'week')  
235 - // 找到要求中最近的那个星期几  
236 - if (dayRuleSup.value < thisWeek) {  
237 - DD -= thisWeek - (dayRuleSup.value as number)  
238 - } else if (dayRuleSup.value > thisWeek) {  
239 - DD -= 7 - ((dayRuleSup.value as number) - thisWeek)  
240 - }  
241 - }  
242 - // 判断时间值是否小于10置换成“05”这种格式  
243 - DD = DD < 10 ? '0' + DD : DD  
244 -  
245 - // 循环“时”数组  
246 - goHour: for (let hi = hIdx; hi < hDate.length; hi++) {  
247 - let hh = hDate[hi] < 10 ? '0' + hDate[hi] : hDate[hi]  
248 -  
249 - // 如果到达最大值时  
250 - if (nMin > mDate[mDate.length - 1]) {  
251 - resetMin()  
252 - if (hi == hDate.length - 1) {  
253 - resetHour()  
254 - if (Di == DDate.length - 1) {  
255 - resetDay()  
256 - if (Mi == MDate.length - 1) {  
257 - resetMonth()  
258 - continue goYear  
259 - }  
260 - continue goMonth  
261 - }  
262 - continue goDay  
263 - }  
264 - continue  
265 - }  
266 - // 循环"分"数组  
267 - goMin: for (let mi = mIdx; mi < mDate.length; mi++) {  
268 - let mm = mDate[mi] < 10 ? '0' + mDate[mi] : mDate[mi]  
269 -  
270 - // 如果到达最大值时  
271 - if (nSecond > sDate[sDate.length - 1]) {  
272 - resetSecond()  
273 - if (mi == mDate.length - 1) {  
274 - resetMin()  
275 - if (hi == hDate.length - 1) {  
276 - resetHour()  
277 - if (Di == DDate.length - 1) {  
278 - resetDay()  
279 - if (Mi == MDate.length - 1) {  
280 - resetMonth()  
281 - continue goYear  
282 - }  
283 - continue goMonth  
284 - }  
285 - continue goDay  
286 - }  
287 - continue goHour  
288 - }  
289 - continue  
290 - }  
291 - // 循环"秒"数组  
292 - goSecond: for (let si = sIdx; si <= sDate.length - 1; si++) {  
293 - let ss = sDate[si] < 10 ? '0' + sDate[si] : sDate[si]  
294 - // 添加当前时间(时间合法性在日期循环时已经判断)  
295 - if (MM !== '00' && DD !== '00') {  
296 - resultArr.push(YY + '-' + MM + '-' + DD + ' ' + hh + ':' + mm + ':' + ss)  
297 - nums++  
298 - }  
299 - // 如果条数满了就退出循环  
300 - if (nums == 5) break goYear  
301 - // 如果到达最大值时  
302 - if (si == sDate.length - 1) {  
303 - resetSecond()  
304 - if (mi == mDate.length - 1) {  
305 - resetMin()  
306 - if (hi == hDate.length - 1) {  
307 - resetHour()  
308 - if (Di == DDate.length - 1) {  
309 - resetDay()  
310 - if (Mi == MDate.length - 1) {  
311 - resetMonth()  
312 - continue goYear  
313 - }  
314 - continue goMonth  
315 - }  
316 - continue goDay  
317 - }  
318 - continue goHour  
319 - }  
320 - continue goMin  
321 - }  
322 - } //goSecond  
323 - } //goMin  
324 - } //goHour  
325 - } //goDay  
326 - } //goMonth  
327 - }  
328 - // 判断100年内的结果条数  
329 - if (resultArr.length == 0) {  
330 - resultList.value = ['没有达到条件的结果!']  
331 - } else {  
332 - resultList.value = resultArr  
333 - if (resultArr.length !== 5) {  
334 - resultList.value.push('最近100年内只有上面' + resultArr.length + '条结果!')  
335 - }  
336 - }  
337 - // 计算完成-显示结果  
338 - isShow.value = true  
339 -}  
340 -  
341 -/**  
342 - * 用于计算某位数字在数组中的索引  
343 - */  
344 -function getIndex(arr, value): number {  
345 - if (value <= arr[0] || value > arr[arr.length - 1]) {  
346 - return 0  
347 - } else {  
348 - for (let i = 0; i < arr.length - 1; i++) {  
349 - if (value > arr[i] && value <= arr[i + 1]) {  
350 - return i + 1  
351 - }  
352 - }  
353 - }  
354 - return 0  
355 -}  
356 -  
357 -function getYearArr(rule, year) {  
358 - dateArr.value[5] = getOrderArr(year, year + 100)  
359 - if (rule !== undefined) {  
360 - if (rule.indexOf('-') >= 0) {  
361 - dateArr.value[5] = getCycleArr(rule, year + 100, false)  
362 - } else if (rule.indexOf('/') >= 0) {  
363 - dateArr.value[5] = getAverageArr(rule, year + 100)  
364 - } else if (rule !== '*') {  
365 - dateArr.value[5] = getAssignArr(rule)  
366 - }  
367 - }  
368 -}  
369 -  
370 -function getMonthArr(rule) {  
371 - dateArr.value[4] = getOrderArr(1, 12)  
372 - if (rule.indexOf('-') >= 0) {  
373 - dateArr.value[4] = getCycleArr(rule, 12, false)  
374 - } else if (rule.indexOf('/') >= 0) {  
375 - dateArr.value[4] = getAverageArr(rule, 12)  
376 - } else if (rule !== '*') {  
377 - dateArr.value[4] = getAssignArr(rule)  
378 - }  
379 -}  
380 -  
381 -function getWeekArr(rule) {  
382 - // 只有当日期规则的两个值均为“”时则表达日期是有选项的  
383 - if (dayRule.value === '' && dayRuleSup.value === '') {  
384 - if (rule.indexOf('-') >= 0) {  
385 - dayRule.value = 'weekDay'  
386 - dayRuleSup.value = getCycleArr(rule, 7, false)  
387 - } else if (rule.indexOf('#') >= 0) {  
388 - dayRule.value = 'assWeek'  
389 - let matchRule = rule.match(/[0-9]{1}/g)  
390 - dayRuleSup.value = [Number(matchRule[1]), Number(matchRule[0])]  
391 - dateArr.value[3] = [1]  
392 - if (dayRuleSup.value[1] == 7) {  
393 - dayRuleSup.value[1] = 0  
394 - }  
395 - } else if (rule.indexOf('L') >= 0) {  
396 - dayRule.value = 'lastWeek'  
397 - dayRuleSup.value = Number(rule.match(/[0-9]{1,2}/g)[0])  
398 - dateArr.value[3] = [31]  
399 - if (dayRuleSup.value == 7) {  
400 - dayRuleSup.value = 0  
401 - }  
402 - } else if (rule !== '*' && rule !== '?') {  
403 - dayRule.value = 'weekDay'  
404 - dayRuleSup.value = getAssignArr(rule)  
405 - }  
406 - }  
407 -}  
408 -  
409 -function getDayArr(rule) {  
410 - dateArr.value[3] = getOrderArr(1, 31)  
411 - dayRule.value = ''  
412 - dayRuleSup.value = ''  
413 - if (rule.indexOf('-') >= 0) {  
414 - dateArr.value[3] = getCycleArr(rule, 31, false)  
415 - dayRuleSup.value = 'null'  
416 - } else if (rule.indexOf('/') >= 0) {  
417 - dateArr.value[3] = getAverageArr(rule, 31)  
418 - dayRuleSup.value = 'null'  
419 - } else if (rule.indexOf('W') >= 0) {  
420 - dayRule.value = 'workDay'  
421 - dayRuleSup.value = Number(rule.match(/[0-9]{1,2}/g)[0])  
422 - dateArr.value[3] = [dayRuleSup.value]  
423 - } else if (rule.indexOf('L') >= 0) {  
424 - dayRule.value = 'lastDay'  
425 - dayRuleSup.value = 'null'  
426 - dateArr.value[3] = [31]  
427 - } else if (rule !== '*' && rule !== '?') {  
428 - dateArr.value[3] = getAssignArr(rule)  
429 - dayRuleSup.value = 'null'  
430 - } else if (rule == '*') {  
431 - dayRuleSup.value = 'null'  
432 - }  
433 -}  
434 -  
435 -function getHourArr(rule) {  
436 - dateArr.value[2] = getOrderArr(0, 23)  
437 - if (rule.indexOf('-') >= 0) {  
438 - dateArr.value[2] = getCycleArr(rule, 24, true)  
439 - } else if (rule.indexOf('/') >= 0) {  
440 - dateArr.value[2] = getAverageArr(rule, 23)  
441 - } else if (rule !== '*') {  
442 - dateArr.value[2] = getAssignArr(rule)  
443 - }  
444 -}  
445 -  
446 -function getMinArr(rule) {  
447 - dateArr.value[1] = getOrderArr(0, 59)  
448 - if (rule.indexOf('-') >= 0) {  
449 - dateArr.value[1] = getCycleArr(rule, 60, true)  
450 - } else if (rule.indexOf('/') >= 0) {  
451 - dateArr.value[1] = getAverageArr(rule, 59)  
452 - } else if (rule !== '*') {  
453 - dateArr.value[1] = getAssignArr(rule)  
454 - }  
455 -}  
456 -  
457 -function getSecondArr(rule) {  
458 - dateArr.value[0] = getOrderArr(0, 59)  
459 - if (rule.indexOf('-') >= 0) {  
460 - dateArr.value[0] = getCycleArr(rule, 60, true)  
461 - } else if (rule.indexOf('/') >= 0) {  
462 - dateArr.value[0] = getAverageArr(rule, 59)  
463 - } else if (rule !== '*') {  
464 - dateArr.value[0] = getAssignArr(rule)  
465 - }  
466 -}  
467 -  
468 -function getOrderArr(min: number, max: number): number[] {  
469 - let arr: number[] = []  
470 - for (let i = min; i <= max; i++) {  
471 - arr.push(i)  
472 - }  
473 - return arr  
474 -}  
475 -  
476 -function getAssignArr(rule) {  
477 - let arr: number[] = []  
478 - let assiginArr = rule.split(',')  
479 - for (let i = 0; i < assiginArr.length; i++) {  
480 - arr[i] = Number(assiginArr[i])  
481 - }  
482 - arr.sort(compare)  
483 - return arr  
484 -}  
485 -  
486 -function compare(value1, value2) {  
487 - if (value2 - value1 > 0) {  
488 - return -1  
489 - } else {  
490 - return 1  
491 - }  
492 -}  
493 -  
494 -function getAverageArr(rule, limit): number[] {  
495 - let arr: number[] = []  
496 - let agArr = rule.split('/')  
497 - let min = Number(agArr[0])  
498 - let step = Number(agArr[1])  
499 - while (min <= limit) {  
500 - arr.push(min)  
501 - min += step  
502 - }  
503 - return arr  
504 -}  
505 -  
506 -function getCycleArr(rule, limit: number, status): number[] {  
507 - // status--表示是否从0开始(则从1开始)  
508 - let arr: number[] = []  
509 - let cycleArr = rule.split('-')  
510 - let min = Number(cycleArr[0])  
511 - let max = Number(cycleArr[1])  
512 - if (min > max) {  
513 - max += limit  
514 - }  
515 - for (let i = min; i <= max; i++) {  
516 - let add = 0  
517 - if (status == false && i % limit == 0) {  
518 - add = limit  
519 - }  
520 - arr.push(Math.round((i % limit) + add))  
521 - }  
522 - arr.sort(compare)  
523 - return arr  
524 -}  
525 -  
526 -function formatDate(value, type?) {  
527 - // 计算日期相关值  
528 - let time = typeof value == 'number' ? new Date(value) : value  
529 - let Y = time.getFullYear()  
530 - let M = time.getMonth() + 1  
531 - let D = time.getDate()  
532 - let h = time.getHours()  
533 - let m = time.getMinutes()  
534 - let s = time.getSeconds()  
535 - let week = time.getDay()  
536 - // 如果传递了type的话  
537 - if (type == undefined) {  
538 - return (  
539 - Y +  
540 - '-' +  
541 - (M < 10 ? '0' + M : M) +  
542 - '-' +  
543 - (D < 10 ? '0' + D : D) +  
544 - ' ' +  
545 - (h < 10 ? '0' + h : h) +  
546 - ':' +  
547 - (m < 10 ? '0' + m : m) +  
548 - ':' +  
549 - (s < 10 ? '0' + s : s)  
550 - )  
551 - } else if (type == 'week') {  
552 - // 在quartz中 1为星期日  
553 - return week + 1  
554 - }  
555 -}  
556 -  
557 -function checkDate(value) {  
558 - let time = new Date(value)  
559 - let format = formatDate(time)  
560 - return value === format  
561 -}  
562 -</script>  
563 -<template>  
564 - <div class="popup-result">  
565 - <p class="title">最近5次运行时间</p>  
566 - <ul class="popup-result-scroll">  
567 - <template v-if="isShow">  
568 - <li v-for="item in resultList" :key="item">{{ item }}</li>  
569 - </template>  
570 - <li v-else>计算结果中...</li>  
571 - </ul>  
572 - </div>  
573 -</template>  
yudao-ui-admin-vue3/src/components/Crontab/src/components/second.vue deleted
1 -<script setup lang="ts">  
2 -import { computed, ref, watch } from 'vue'  
3 -import { ElForm, ElFormItem, ElRadio, ElSelect, ElOption, ElInputNumber } from 'element-plus'  
4 -const props = defineProps({  
5 - check: {  
6 - type: Function,  
7 - required: true  
8 - },  
9 - cron: {  
10 - type: Object  
11 - }  
12 -})  
13 -const emits = defineEmits(['update'])  
14 -  
15 -const radioValue = ref(1)  
16 -const cycle01 = ref(1)  
17 -const cycle02 = ref(2)  
18 -const average01 = ref(0)  
19 -const average02 = ref(1)  
20 -const checkboxList = ref([])  
21 -  
22 -defineExpose({  
23 - radioValue,  
24 - cycle01,  
25 - cycle02,  
26 - average01,  
27 - average02,  
28 - checkboxList  
29 -})  
30 -  
31 -const cycleTotal = computed(() => {  
32 - const cycle1 = props.check(cycle01.value, 0, 58)  
33 - const cycle2 = props.check(cycle02.value, cycle1 ? cycle1 + 1 : 1, 59)  
34 - return cycle1 + '-' + cycle2  
35 -})  
36 -  
37 -watch(cycleTotal, () => {  
38 - if (parseInt(radioValue.value.toString()) === 2) {  
39 - emits('update', 'second', cycleTotal)  
40 - }  
41 -})  
42 -  
43 -const averageTotal = computed(() => {  
44 - const average1 = props.check(average01.value, 0, 58)  
45 - const average2 = props.check(average02.value, 1, 59 - average1 || 0)  
46 - return average1 + '/' + average2  
47 -})  
48 -  
49 -watch(averageTotal, () => {  
50 - if (parseInt(radioValue.value.toString()) === 3) {  
51 - emits('update', 'second', averageTotal)  
52 - }  
53 -})  
54 -  
55 -const checkboxString = computed(() => {  
56 - let str = checkboxList.value.join()  
57 - return str.length === 0 ? '*' : str  
58 -})  
59 -  
60 -watch(checkboxString, () => {  
61 - if (parseInt(radioValue.value.toString()) === 4) {  
62 - emits('update', 'second', checkboxString)  
63 - }  
64 -})  
65 -  
66 -watch(radioValue, () => {  
67 - switch (parseInt(radioValue.value.toString())) {  
68 - case 1:  
69 - emits('update', 'second', '*', 'second')  
70 - break  
71 - case 2:  
72 - emits('update', 'second', cycleTotal)  
73 - break  
74 - case 3:  
75 - emits('update', 'second', averageTotal)  
76 - break  
77 - case 4:  
78 - emits('update', 'second', checkboxString)  
79 - break  
80 - }  
81 -})  
82 -</script>  
83 -<template>  
84 - <el-form>  
85 - <el-form-item>  
86 - <el-radio v-model="radioValue" :label="1"> 秒,允许的通配符[, - * /] </el-radio>  
87 - </el-form-item>  
88 -  
89 - <el-form-item>  
90 - <el-radio v-model="radioValue" :label="2">  
91 - 周期从  
92 - <el-input-number v-model="cycle01" :min="0" :max="58" /> -  
93 - <el-input-number v-model="cycle02" :min="cycle01 ? cycle01 + 1 : 1" :max="59" /> 秒  
94 - </el-radio>  
95 - </el-form-item>  
96 -  
97 - <el-form-item>  
98 - <el-radio v-model="radioValue" :label="3">  
99 - 从  
100 - <el-input-number v-model="average01" :min="0" :max="58" /> 秒开始,每  
101 - <el-input-number v-model="average02" :min="1" :max="59 - average01 || 0" /> 秒执行一次  
102 - </el-radio>  
103 - </el-form-item>  
104 -  
105 - <el-form-item>  
106 - <el-radio v-model="radioValue" :label="4">  
107 - 指定  
108 - <el-select  
109 - clearable  
110 - v-model="checkboxList"  
111 - placeholder="可多选"  
112 - multiple  
113 - style="width: 100%"  
114 - >  
115 - <el-option v-for="item in 60" :key="item" :value="item - 1">{{ item - 1 }}</el-option>  
116 - </el-select>  
117 - </el-radio>  
118 - </el-form-item>  
119 - </el-form>  
120 -</template>  
yudao-ui-admin-vue3/src/components/Crontab/src/components/week.vue deleted
1 -<script setup lang="ts">  
2 -import { computed, ref, watch } from 'vue'  
3 -import { ElForm, ElFormItem, ElRadio, ElSelect, ElOption, ElInputNumber } from 'element-plus'  
4 -const props = defineProps({  
5 - check: {  
6 - type: Function,  
7 - required: true  
8 - },  
9 - cron: {  
10 - type: Object  
11 - }  
12 -})  
13 -const emits = defineEmits(['update'])  
14 -  
15 -const radioValue = ref<number>(2)  
16 -const weekday = ref<number>(2)  
17 -const cycle01 = ref<number>(2)  
18 -const cycle02 = ref<number>(3)  
19 -const average01 = ref<number>(1)  
20 -const average02 = ref<number>(2)  
21 -const checkboxList = ref([])  
22 -const weekList = ref([  
23 - {  
24 - key: 2,  
25 - value: '星期一'  
26 - },  
27 - {  
28 - key: 3,  
29 - value: '星期二'  
30 - },  
31 - {  
32 - key: 4,  
33 - value: '星期三'  
34 - },  
35 - {  
36 - key: 5,  
37 - value: '星期四'  
38 - },  
39 - {  
40 - key: 6,  
41 - value: '星期五'  
42 - },  
43 - {  
44 - key: 7,  
45 - value: '星期六'  
46 - },  
47 - {  
48 - key: 1,  
49 - value: '星期日'  
50 - }  
51 -])  
52 -  
53 -defineExpose({  
54 - radioValue,  
55 - weekday,  
56 - cycle01,  
57 - cycle02,  
58 - average01,  
59 - average02,  
60 - checkboxList  
61 -})  
62 -  
63 -const cycleTotal = computed(() => {  
64 - const cycle1 = props.check(cycle01.value, 1, 7)  
65 - const cycle2 = props.check(cycle02.value, 1, 7)  
66 - return cycle1 + '-' + cycle2  
67 -})  
68 -  
69 -watch(cycleTotal, () => {  
70 - if (parseInt(radioValue.value.toString()) === 3) {  
71 - emits('update', 'month', cycleTotal)  
72 - }  
73 -})  
74 -  
75 -const averageTotal = computed(() => {  
76 - const average1 = props.check(average01.value, 1, 4)  
77 - const average2 = props.check(average02.value, 1, 7)  
78 - return average1 + '#' + average2  
79 -})  
80 -  
81 -watch(averageTotal, () => {  
82 - if (parseInt(radioValue.value.toString()) === 4) {  
83 - emits('update', 'month', averageTotal)  
84 - }  
85 -})  
86 -  
87 -const weekdayCheck = computed(() => {  
88 - return props.check(weekday.value, 1, 7)  
89 -})  
90 -  
91 -watch(weekdayCheck, () => {  
92 - if (parseInt(radioValue.value.toString()) === 5) {  
93 - emits('update', 'week', weekday.value + 'L')  
94 - }  
95 -})  
96 -  
97 -const checkboxString = computed(() => {  
98 - let str = checkboxList.value.join()  
99 - return str.length === 0 ? '*' : str  
100 -})  
101 -  
102 -watch(checkboxString, () => {  
103 - if (parseInt(radioValue.value.toString()) === 6) {  
104 - emits('update', 'month', checkboxString)  
105 - }  
106 -})  
107 -  
108 -watch(radioValue, () => {  
109 - if (parseInt(radioValue.value.toString()) !== 2 && radioValue.value.toString() !== '?') {  
110 - emits('update', 'day', '?', 'week')  
111 - }  
112 - switch (parseInt(radioValue.value.toString())) {  
113 - case 1:  
114 - emits('update', 'week', '*')  
115 - break  
116 - case 2:  
117 - emits('update', 'week', '?')  
118 - break  
119 - case 3:  
120 - emits('update', 'week', cycleTotal)  
121 - break  
122 - case 4:  
123 - emits('update', 'week', averageTotal)  
124 - break  
125 - case 5:  
126 - emits('update', 'week', weekdayCheck.value + 'L')  
127 - break  
128 - case 6:  
129 - emits('update', 'week', checkboxString)  
130 - break  
131 - }  
132 -})  
133 -</script>  
134 -<template>  
135 - <el-form>  
136 - <el-form-item>  
137 - <el-radio v-model="radioValue" :label="1"> 周,允许的通配符[, - * ? / L #] </el-radio>  
138 - </el-form-item>  
139 -  
140 - <el-form-item>  
141 - <el-radio v-model="radioValue" :label="2"> 不指定 </el-radio>  
142 - </el-form-item>  
143 -  
144 - <el-form-item>  
145 - <el-radio v-model="radioValue" :label="3">  
146 - 周期从星期  
147 - <el-select clearable v-model="cycle01">  
148 - <el-option  
149 - v-for="(item, index) of weekList"  
150 - :key="index"  
151 - :label="item.value"  
152 - :value="item.key"  
153 - :disabled="item.key === 1"  
154 - >{{ item.value }}</el-option  
155 - >  
156 - </el-select>  
157 - -  
158 - <el-select clearable v-model="cycle02">  
159 - <el-option  
160 - v-for="(item, index) of weekList"  
161 - :key="index"  
162 - :label="item.value"  
163 - :value="item.key"  
164 - :disabled="item.key < cycle01 && item.key !== 1"  
165 - >{{ item.value }}</el-option  
166 - >  
167 - </el-select>  
168 - </el-radio>  
169 - </el-form-item>  
170 -  
171 - <el-form-item>  
172 - <el-radio v-model="radioValue" :label="4">  
173 - 第  
174 - <el-input-number v-model="average01" :min="1" :max="4" /> 周的星期  
175 - <el-select clearable v-model="average02">  
176 - <el-option  
177 - v-for="(item, index) of weekList"  
178 - :key="index"  
179 - :label="item.value"  
180 - :value="item.key"  
181 - >{{ item.value }}</el-option  
182 - >  
183 - </el-select>  
184 - </el-radio>  
185 - </el-form-item>  
186 -  
187 - <el-form-item>  
188 - <el-radio v-model="radioValue" :label="5">  
189 - 本月最后一个星期  
190 - <el-select clearable v-model="weekday">  
191 - <el-option  
192 - v-for="(item, index) of weekList"  
193 - :key="index"  
194 - :label="item.value"  
195 - :value="item.key"  
196 - >{{ item.value }}</el-option  
197 - >  
198 - </el-select>  
199 - </el-radio>  
200 - </el-form-item>  
201 -  
202 - <el-form-item>  
203 - <el-radio v-model="radioValue" :label="6">  
204 - 指定  
205 - <el-select  
206 - clearable  
207 - v-model="checkboxList"  
208 - placeholder="可多选"  
209 - multiple  
210 - style="width: 100%"  
211 - >  
212 - <el-option  
213 - v-for="(item, index) of weekList"  
214 - :key="index"  
215 - :label="item.value"  
216 - :value="String(item.key)"  
217 - >{{ item.value }}</el-option  
218 - >  
219 - </el-select>  
220 - </el-radio>  
221 - </el-form-item>  
222 - </el-form>  
223 -</template>  
yudao-ui-admin-vue3/src/components/Crontab/src/components/year.vue deleted
1 -<script setup lang="ts">  
2 -import { computed, onMounted, ref, watch } from 'vue'  
3 -import { ElForm, ElFormItem, ElRadio, ElSelect, ElOption, ElInputNumber } from 'element-plus'  
4 -const props = defineProps({  
5 - check: {  
6 - type: Function,  
7 - required: true  
8 - },  
9 - cron: {  
10 - type: Object  
11 - }  
12 -})  
13 -const emits = defineEmits(['update'])  
14 -  
15 -const fullYear = ref<number>(0)  
16 -const radioValue = ref<number>(1)  
17 -const cycle01 = ref<number>(0)  
18 -const cycle02 = ref<number>(0)  
19 -const average01 = ref<number>(0)  
20 -const average02 = ref<number>(1)  
21 -const checkboxList = ref([])  
22 -  
23 -defineExpose({  
24 - fullYear,  
25 - radioValue,  
26 - cycle01,  
27 - cycle02,  
28 - average01,  
29 - average02,  
30 - checkboxList  
31 -})  
32 -  
33 -const cycleTotal = computed(() => {  
34 - const cycle1 = props.check(cycle01.value, fullYear.value, 2098)  
35 - const cycle2 = props.check(cycle02.value, cycle1 ? cycle1 + 1 : fullYear.value, 2099)  
36 - return cycle1 + '-' + cycle2  
37 -})  
38 -  
39 -watch(cycleTotal, () => {  
40 - if (parseInt(radioValue.value.toString()) === 3) {  
41 - emits('update', 'year', cycleTotal)  
42 - }  
43 -})  
44 -  
45 -const averageTotal = computed(() => {  
46 - const average1 = props.check(average01.value, fullYear.value, 2098)  
47 - const average2 = props.check(average02.value, 1, 2099 - average1 || fullYear.value)  
48 - return average1 + '/' + average2  
49 -})  
50 -  
51 -watch(averageTotal, () => {  
52 - if (parseInt(radioValue.value.toString()) === 4) {  
53 - emits('update', 'year', averageTotal)  
54 - }  
55 -})  
56 -  
57 -const checkboxString = computed(() => {  
58 - let str = checkboxList.value.join()  
59 - return str.length === 0 ? '*' : str  
60 -})  
61 -  
62 -watch(checkboxString, () => {  
63 - if (parseInt(radioValue.value.toString()) === 5) {  
64 - emits('update', 'year', checkboxString)  
65 - }  
66 -})  
67 -  
68 -watch(radioValue, () => {  
69 - switch (parseInt(radioValue.value.toString())) {  
70 - case 1:  
71 - emits('update', 'year', '')  
72 - break  
73 - case 2:  
74 - emits('update', 'year', '*')  
75 - break  
76 - case 3:  
77 - emits('update', 'year', cycleTotal, 'min')  
78 - break  
79 - case 4:  
80 - emits('update', 'year', averageTotal, 'min')  
81 - break  
82 - case 5:  
83 - emits('update', 'year', checkboxString, 'min')  
84 - break  
85 - }  
86 -})  
87 -  
88 -onMounted(() => {  
89 - fullYear.value = Number(new Date().getFullYear())  
90 - cycle01.value = fullYear.value  
91 - average01.value = fullYear.value  
92 -})  
93 -</script>  
94 -<template>  
95 - <el-form>  
96 - <el-form-item>  
97 - <el-radio label="1" v-model="radioValue"> 不填,允许的通配符[, - * /] </el-radio>  
98 - </el-form-item>  
99 -  
100 - <el-form-item>  
101 - <el-radio label="2" v-model="radioValue"> 每年 </el-radio>  
102 - </el-form-item>  
103 -  
104 - <el-form-item>  
105 - <el-radio label="3" v-model="radioValue">  
106 - 周期从  
107 - <el-input-number v-model="cycle01" :min="fullYear" :max="2098" /> -  
108 - <el-input-number  
109 - v-model="cycle02"  
110 - :min="cycle01 ? cycle01 + 1 : fullYear + 1"  
111 - :max="2099"  
112 - />  
113 - </el-radio>  
114 - </el-form-item>  
115 -  
116 - <el-form-item>  
117 - <el-radio label="4" v-model="radioValue">  
118 - 从  
119 - <el-input-number v-model="average01" :min="fullYear" :max="2098" /> 年开始,每  
120 - <el-input-number v-model="average02" :min="1" :max="2099 - average01 || fullYear" />  
121 - 年执行一次  
122 - </el-radio>  
123 - </el-form-item>  
124 -  
125 - <el-form-item>  
126 - <el-radio label="5" v-model="radioValue">  
127 - 指定  
128 - <el-select clearable v-model="checkboxList" placeholder="可多选" multiple>  
129 - <el-option  
130 - v-for="item in 9"  
131 - :key="item"  
132 - :value="item - 1 + fullYear"  
133 - :label="item - 1 + fullYear"  
134 - />  
135 - </el-select>  
136 - </el-radio>  
137 - </el-form-item>  
138 - </el-form>  
139 -</template>  
yudao-ui-admin-vue3/src/components/Crontab/src/index.vue deleted
1 -<script setup lang="ts">  
2 -import {  
3 - CrontabSecond,  
4 - CrontabMin,  
5 - CrontabHour,  
6 - CrontabDay,  
7 - CrontabMonth,  
8 - CrontabWeek,  
9 - CrontabYear,  
10 - CrontabResult  
11 -} from './components'  
12 -import { ElTabs, ElTabPane } from 'element-plus'  
13 -import { computed, defineEmits, defineProps, onMounted, Ref, ref, watch } from 'vue'  
14 -  
15 -const cronsecond = ref(null)  
16 -const cronmin = ref(null)  
17 -const cronhour = ref(null)  
18 -const cronday = ref(null)  
19 -const cronmonth = ref(null)  
20 -const cronweek = ref(null)  
21 -const cronyear = ref(null)  
22 -  
23 -const refs = ref<Record<string, Ref>>({})  
24 -onMounted(() => {  
25 - refs.value.cronsecond = cronsecond  
26 - refs.value.cronmin = cronmin  
27 - refs.value.cronhour = cronhour  
28 - refs.value.cronday = cronday  
29 - refs.value.cronmonth = cronmonth  
30 - refs.value.cronweek = cronweek  
31 - refs.value.cronyear = cronyear  
32 -})  
33 -  
34 -const props = defineProps({  
35 - expression: {  
36 - type: String,  
37 - required: false  
38 - },  
39 - hideComponent: {  
40 - type: Array  
41 - }  
42 -})  
43 -  
44 -const emit = defineEmits(['hide', 'fill'])  
45 -  
46 -const tabTitles = ['秒', '分钟', '小时', '日', '月', '周', '年']  
47 -  
48 -const crontabValueObj = ref({  
49 - second: '*',  
50 - min: '*',  
51 - hour: '*',  
52 - day: '*',  
53 - month: '*',  
54 - week: '?',  
55 - year: ''  
56 -})  
57 -  
58 -function shouldHide(key) {  
59 - return !(props.hideComponent && props.hideComponent.includes(key))  
60 -}  
61 -  
62 -function resolveExp() {  
63 - // 反解析 表达式  
64 - if (props.expression) {  
65 - let arr = props.expression.split(' ')  
66 - if (arr.length >= 6) {  
67 - //6 位以上是合法表达式  
68 - let obj = {  
69 - second: arr[0],  
70 - min: arr[1],  
71 - hour: arr[2],  
72 - day: arr[3],  
73 - month: arr[4],  
74 - week: arr[5],  
75 - year: arr[6] ? arr[6] : ''  
76 - }  
77 - crontabValueObj.value = {  
78 - ...obj  
79 - }  
80 - for (let i in obj) {  
81 - if (obj[i]) {  
82 - changeRadio(i, obj[i])  
83 - }  
84 - }  
85 - }  
86 - } else {  
87 - // 没有传入的表达式 则还原  
88 - clearCron()  
89 - }  
90 -}  
91 -  
92 -// 由子组件触发,更改表达式组成的字段值  
93 -function updateCrontabValue(name, value, from) {  
94 - crontabValueObj.value[name] = value  
95 - if (from && from !== name) {  
96 - console.log(`来自组件 ${from} 改变了 ${name} ${value}`)  
97 - changeRadio(name, value)  
98 - }  
99 -}  
100 -// 赋值到组件  
101 -function changeRadio(name, value) {  
102 - let arr = ['second', 'min', 'hour', 'month'],  
103 - refName = 'cron' + name,  
104 - insValue  
105 -  
106 - if (!refs.value[refName]) return  
107 -  
108 - if (arr.includes(name)) {  
109 - if (value === '*') {  
110 - insValue = 1  
111 - } else if (value.indexOf('-') > -1) {  
112 - let indexArr = value.split('-')  
113 - isNaN(indexArr[0])  
114 - ? (refs.value[refName].cycle01 = 0)  
115 - : (refs.value[refName].cycle01 = indexArr[0])  
116 - refs.value[refName].cycle02 = indexArr[1]  
117 - insValue = 2  
118 - } else if (value.indexOf('/') > -1) {  
119 - let indexArr = value.split('/')  
120 - isNaN(indexArr[0])  
121 - ? (refs.value[refName].average01 = 0)  
122 - : (refs.value[refName].average01 = indexArr[0])  
123 - refs.value[refName].average02 = indexArr[1]  
124 - insValue = 3  
125 - } else {  
126 - insValue = 4  
127 - refs.value[refName].checkboxList = value.split(',')  
128 - }  
129 - } else if (name == 'day') {  
130 - if (value === '*') {  
131 - insValue = 1  
132 - } else if (value == '?') {  
133 - insValue = 2  
134 - } else if (value.indexOf('-') > -1) {  
135 - let indexArr = value.split('-')  
136 - isNaN(indexArr[0])  
137 - ? (refs.value[refName].cycle01 = 0)  
138 - : (refs.value[refName].cycle01 = indexArr[0])  
139 - refs.value[refName].cycle02 = indexArr[1]  
140 - insValue = 3  
141 - } else if (value.indexOf('/') > -1) {  
142 - let indexArr = value.split('/')  
143 - isNaN(indexArr[0])  
144 - ? (refs.value[refName].average01 = 0)  
145 - : (refs.value[refName].average01 = indexArr[0])  
146 - refs.value[refName].average02 = indexArr[1]  
147 - insValue = 4  
148 - } else if (value.indexOf('W') > -1) {  
149 - let indexArr = value.split('W')  
150 - isNaN(indexArr[0])  
151 - ? (refs.value[refName].workday = 0)  
152 - : (refs.value[refName].workday = indexArr[0])  
153 - insValue = 5  
154 - } else if (value === 'L') {  
155 - insValue = 6  
156 - } else {  
157 - refs.value[refName].checkboxList = value.split(',')  
158 - insValue = 7  
159 - }  
160 - } else if (name == 'week') {  
161 - if (value === '*') {  
162 - insValue = 1  
163 - } else if (value == '?') {  
164 - insValue = 2  
165 - } else if (value.indexOf('-') > -1) {  
166 - let indexArr = value.split('-')  
167 - isNaN(indexArr[0])  
168 - ? (refs.value[refName].cycle01 = 0)  
169 - : (refs.value[refName].cycle01 = indexArr[0])  
170 - refs.value[refName].cycle02 = indexArr[1]  
171 - insValue = 3  
172 - } else if (value.indexOf('#') > -1) {  
173 - let indexArr = value.split('#')  
174 - isNaN(indexArr[0])  
175 - ? (refs.value[refName].average01 = 1)  
176 - : (refs.value[refName].average01 = indexArr[0])  
177 - refs.value[refName].average02 = indexArr[1]  
178 - insValue = 4  
179 - } else if (value.indexOf('L') > -1) {  
180 - let indexArr = value.split('L')  
181 - isNaN(indexArr[0])  
182 - ? (refs.value[refName].weekday = 1)  
183 - : (refs.value[refName].weekday = indexArr[0])  
184 - insValue = 5  
185 - } else {  
186 - refs.value[refName].checkboxList = value.split(',')  
187 - insValue = 6  
188 - }  
189 - } else if (name == 'year') {  
190 - if (value == '') {  
191 - insValue = 1  
192 - } else if (value == '*') {  
193 - insValue = 2  
194 - } else if (value.indexOf('-') > -1) {  
195 - insValue = 3  
196 - } else if (value.indexOf('/') > -1) {  
197 - insValue = 4  
198 - } else {  
199 - refs.value[refName].checkboxList = value.split(',')  
200 - insValue = 5  
201 - }  
202 - }  
203 - refs.value[refName].radioValue = insValue  
204 -}  
205 -  
206 -// 表单选项的子组件校验数字格式(通过-props传递)  
207 -function checkNumber(value, minLimit, maxLimit) {  
208 - // 检查必须为整数  
209 - value = Math.floor(value)  
210 - if (value < minLimit) {  
211 - value = minLimit  
212 - } else if (value > maxLimit) {  
213 - value = maxLimit  
214 - }  
215 - return value  
216 -}  
217 -  
218 -// 隐藏弹窗  
219 -function hidePopup() {  
220 - emit('hide')  
221 -}  
222 -  
223 -// 填充表达式  
224 -function submitFill() {  
225 - emit('fill', crontabValueString)  
226 - hidePopup()  
227 -}  
228 -  
229 -const crontabValueString = computed(() => {  
230 - let obj = crontabValueObj.value  
231 - return (  
232 - obj.second +  
233 - ' ' +  
234 - obj.min +  
235 - ' ' +  
236 - obj.hour +  
237 - ' ' +  
238 - obj.day +  
239 - ' ' +  
240 - obj.month +  
241 - ' ' +  
242 - obj.week +  
243 - (obj.year === '' ? '' : ' ' + obj.year)  
244 - )  
245 -})  
246 -  
247 -function clearCron() {  
248 - // 还原选择项  
249 - crontabValueObj.value = {  
250 - second: '*',  
251 - min: '*',  
252 - hour: '*',  
253 - day: '*',  
254 - month: '*',  
255 - week: '?',  
256 - year: ''  
257 - }  
258 - for (let j in crontabValueObj.value) {  
259 - changeRadio(j, crontabValueObj.value[j])  
260 - }  
261 -}  
262 -  
263 -watch(() => props.expression, resolveExp)  
264 -</script>  
265 -<template>  
266 - <div>  
267 - <el-tabs type="border-card">  
268 - <el-tab-pane label="秒" v-if="shouldHide('second')">  
269 - <CrontabSecond  
270 - @update="updateCrontabValue"  
271 - :check="checkNumber"  
272 - :cron="crontabValueObj"  
273 - ref="cronsecond"  
274 - />  
275 - </el-tab-pane>  
276 -  
277 - <el-tab-pane label="分钟" v-if="shouldHide('min')">  
278 - <CrontabMin  
279 - @update="updateCrontabValue"  
280 - :check="checkNumber"  
281 - :cron="crontabValueObj"  
282 - ref="cronmin"  
283 - />  
284 - </el-tab-pane>  
285 -  
286 - <el-tab-pane label="小时" v-if="shouldHide('hour')">  
287 - <CrontabHour  
288 - @update="updateCrontabValue"  
289 - :check="checkNumber"  
290 - :cron="crontabValueObj"  
291 - ref="cronhour"  
292 - />  
293 - </el-tab-pane>  
294 -  
295 - <el-tab-pane label="日" v-if="shouldHide('day')">  
296 - <CrontabDay  
297 - @update="updateCrontabValue"  
298 - :check="checkNumber"  
299 - :cron="crontabValueObj"  
300 - ref="cronday"  
301 - />  
302 - </el-tab-pane>  
303 -  
304 - <el-tab-pane label="月" v-if="shouldHide('month')">  
305 - <CrontabMonth  
306 - @update="updateCrontabValue"  
307 - :check="checkNumber"  
308 - :cron="crontabValueObj"  
309 - ref="cronmonth"  
310 - />  
311 - </el-tab-pane>  
312 -  
313 - <el-tab-pane label="周" v-if="shouldHide('week')">  
314 - <CrontabWeek  
315 - @update="updateCrontabValue"  
316 - :check="checkNumber"  
317 - :cron="crontabValueObj"  
318 - ref="cronweek"  
319 - />  
320 - </el-tab-pane>  
321 -  
322 - <el-tab-pane label="年" v-if="shouldHide('year')">  
323 - <CrontabYear  
324 - @update="updateCrontabValue"  
325 - :check="checkNumber"  
326 - :cron="crontabValueObj"  
327 - ref="cronyear"  
328 - />  
329 - </el-tab-pane>  
330 - </el-tabs>  
331 -  
332 - <div class="popup-main">  
333 - <div class="popup-result">  
334 - <p class="title">时间表达式</p>  
335 - <table>  
336 - <thead>  
337 - <th v-for="item of tabTitles" width="40" :key="item">{{ item }}</th>  
338 - <th>Cron 表达式</th>  
339 - </thead>  
340 - <tbody>  
341 - <td>  
342 - <span>{{ crontabValueObj.second }}</span>  
343 - </td>  
344 - <td>  
345 - <span>{{ crontabValueObj.min }}</span>  
346 - </td>  
347 - <td>  
348 - <span>{{ crontabValueObj.hour }}</span>  
349 - </td>  
350 - <td>  
351 - <span>{{ crontabValueObj.day }}</span>  
352 - </td>  
353 - <td>  
354 - <span>{{ crontabValueObj.month }}</span>  
355 - </td>  
356 - <td>  
357 - <span>{{ crontabValueObj.week }}</span>  
358 - </td>  
359 - <td>  
360 - <span>{{ crontabValueObj.year }}</span>  
361 - </td>  
362 - <td>  
363 - <span>{{ crontabValueString }}</span>  
364 - </td>  
365 - </tbody>  
366 - </table>  
367 - </div>  
368 - <CrontabResult :ex="crontabValueString" />  
369 -  
370 - <div class="pop_btn">  
371 - <el-button type="primary" @click="submitFill">确定</el-button>  
372 - <el-button type="warning" @click="clearCron">重置</el-button>  
373 - <el-button @click="hidePopup">取消</el-button>  
374 - </div>  
375 - </div>  
376 - </div>  
377 -</template>  
378 -<style scoped>  
379 -.pop_btn {  
380 - text-align: center;  
381 - margin-top: 20px;  
382 -}  
383 -.popup-main {  
384 - position: relative;  
385 - margin: 10px auto;  
386 - background: #fff;  
387 - border-radius: 5px;  
388 - font-size: 12px;  
389 - overflow: hidden;  
390 -}  
391 -.popup-title {  
392 - overflow: hidden;  
393 - line-height: 34px;  
394 - padding-top: 6px;  
395 - background: #f2f2f2;  
396 -}  
397 -.popup-result {  
398 - box-sizing: border-box;  
399 - line-height: 24px;  
400 - margin: 25px auto;  
401 - padding: 15px 10px 10px;  
402 - border: 1px solid #ccc;  
403 - position: relative;  
404 -}  
405 -.popup-result .title {  
406 - position: absolute;  
407 - top: -28px;  
408 - left: 50%;  
409 - width: 140px;  
410 - font-size: 14px;  
411 - margin-left: -70px;  
412 - text-align: center;  
413 - line-height: 30px;  
414 - background: #fff;  
415 -}  
416 -.popup-result table {  
417 - text-align: center;  
418 - width: 100%;  
419 - margin: 0 auto;  
420 -}  
421 -.popup-result table span {  
422 - display: block;  
423 - width: 100%;  
424 - font-family: arial;  
425 - line-height: 30px;  
426 - height: 30px;  
427 - white-space: nowrap;  
428 - overflow: hidden;  
429 - border: 1px solid #e8e8e8;  
430 -}  
431 -.popup-result-scroll {  
432 - font-size: 12px;  
433 - line-height: 24px;  
434 - height: 10em;  
435 - overflow-y: auto;  
436 -}  
437 -</style>  
yudao-ui-admin-vue3/src/views/infra/job/index.vue
1 <script lang="ts" setup> 1 <script lang="ts" setup>
  2 +import { Crontab } from '@/components/Crontab'
2 import { ref, unref } from 'vue' 3 import { ref, unref } from 'vue'
3 import DictTag from '@/components/DictTag/src/DictTag.vue' 4 import DictTag from '@/components/DictTag/src/DictTag.vue'
4 import * as JobApi from '@/api/infra/job' 5 import * as JobApi from '@/api/infra/job'
@@ -11,6 +12,7 @@ import { FormExpose } from &#39;@/components/Form&#39; @@ -11,6 +12,7 @@ import { FormExpose } from &#39;@/components/Form&#39;
11 import { rules, allSchemas } from './job.data' 12 import { rules, allSchemas } from './job.data'
12 import { useRouter } from 'vue-router' 13 import { useRouter } from 'vue-router'
13 import { useMessage } from '@/hooks/web/useMessage' 14 import { useMessage } from '@/hooks/web/useMessage'
  15 +import { InfraJobStatusEnum } from '@/utils/constants'
14 const message = useMessage() 16 const message = useMessage()
15 const { t } = useI18n() // 国际化 17 const { t } = useI18n() // 国际化
16 const { push } = useRouter() 18 const { push } = useRouter()
@@ -28,7 +30,13 @@ const actionType = ref(&#39;&#39;) // 操作按钮的类型 @@ -28,7 +30,13 @@ const actionType = ref(&#39;&#39;) // 操作按钮的类型
28 const dialogVisible = ref(false) // 是否显示弹出层 30 const dialogVisible = ref(false) // 是否显示弹出层
29 const dialogTitle = ref('edit') // 弹出层标题 31 const dialogTitle = ref('edit') // 弹出层标题
30 const formRef = ref<FormExpose>() // 表单 Ref 32 const formRef = ref<FormExpose>() // 表单 Ref
31 - 33 +const cronExpression = ref('')
  34 +const shortcuts = ref([
  35 + {
  36 + text: '每天8点和12点 (自定义追加)',
  37 + value: '0 0 8,12 * * ?'
  38 + }
  39 +])
32 // 设置标题 40 // 设置标题
33 const setDialogTile = (type: string) => { 41 const setDialogTile = (type: string) => {
34 dialogTitle.value = t('action.' + type) 42 dialogTitle.value = t('action.' + type)
@@ -38,6 +46,7 @@ const setDialogTile = (type: string) =&gt; { @@ -38,6 +46,7 @@ const setDialogTile = (type: string) =&gt; {
38 46
39 // 新增操作 47 // 新增操作
40 const handleCreate = () => { 48 const handleCreate = () => {
  49 + cronExpression.value = ''
41 setDialogTile('create') 50 setDialogTile('create')
42 // 重置表单 51 // 重置表单
43 unref(formRef)?.getElFormRef()?.resetFields() 52 unref(formRef)?.getElFormRef()?.resetFields()
@@ -48,8 +57,31 @@ const handleUpdate = async (row: JobVO) =&gt; { @@ -48,8 +57,31 @@ const handleUpdate = async (row: JobVO) =&gt; {
48 setDialogTile('update') 57 setDialogTile('update')
49 // 设置数据 58 // 设置数据
50 const res = await JobApi.getJobApi(row.id) 59 const res = await JobApi.getJobApi(row.id)
  60 + cronExpression.value = res.cronExpression
51 unref(formRef)?.setValues(res) 61 unref(formRef)?.setValues(res)
52 } 62 }
  63 +const handleChangeStatus = async (row: JobVO) => {
  64 + const text = row.status === InfraJobStatusEnum.STOP ? '开启' : '关闭'
  65 + const status =
  66 + row.status === InfraJobStatusEnum.STOP ? InfraJobStatusEnum.NORMAL : InfraJobStatusEnum.STOP
  67 + message
  68 + .confirm('确认要' + text + '定时任务编号为"' + row.id + '"的数据项?', t('common.reminder'))
  69 + .then(async () => {
  70 + row.status =
  71 + row.status === InfraJobStatusEnum.NORMAL
  72 + ? InfraJobStatusEnum.NORMAL
  73 + : InfraJobStatusEnum.STOP
  74 + await JobApi.updateJobStatusApi(row.id, status)
  75 + message.success(text + '成功')
  76 + await getList()
  77 + })
  78 + .catch(() => {
  79 + row.status =
  80 + row.status === InfraJobStatusEnum.NORMAL
  81 + ? InfraJobStatusEnum.STOP
  82 + : InfraJobStatusEnum.NORMAL
  83 + })
  84 +}
53 // 执行日志 85 // 执行日志
54 const handleJobLog = (row: JobVO) => { 86 const handleJobLog = (row: JobVO) => {
55 if (row.id) { 87 if (row.id) {
@@ -72,6 +104,7 @@ const submitForm = async () =&gt; { @@ -72,6 +104,7 @@ const submitForm = async () =&gt; {
72 // 提交请求 104 // 提交请求
73 try { 105 try {
74 const data = unref(formRef)?.formModel as JobVO 106 const data = unref(formRef)?.formModel as JobVO
  107 + data.cronExpression = cronExpression.value
75 if (actionType.value === 'create') { 108 if (actionType.value === 'create') {
76 await JobApi.createJobApi(data) 109 await JobApi.createJobApi(data)
77 message.success(t('common.createSuccess')) 110 message.success(t('common.createSuccess'))
@@ -144,6 +177,15 @@ getList() @@ -144,6 +177,15 @@ getList()
144 <el-button link type="primary" v-hasPermi="['infra:job:update']" @click="handleUpdate(row)"> 177 <el-button link type="primary" v-hasPermi="['infra:job:update']" @click="handleUpdate(row)">
145 <Icon icon="ep:edit" class="mr-1px" /> {{ t('action.edit') }} 178 <Icon icon="ep:edit" class="mr-1px" /> {{ t('action.edit') }}
146 </el-button> 179 </el-button>
  180 + <el-button
  181 + link
  182 + type="primary"
  183 + v-hasPermi="['infra:job:update']"
  184 + @click="handleChangeStatus(row)"
  185 + >
  186 + <Icon icon="ep:edit" class="mr-1px" />
  187 + {{ row.status === InfraJobStatusEnum.STOP ? '开启' : '暂停' }}
  188 + </el-button>
147 <el-button link type="primary" v-hasPermi="['infra:job:query']" @click="handleDetail(row)"> 189 <el-button link type="primary" v-hasPermi="['infra:job:query']" @click="handleDetail(row)">
148 <Icon icon="ep:view" class="mr-1px" /> {{ t('action.detail') }} 190 <Icon icon="ep:view" class="mr-1px" /> {{ t('action.detail') }}
149 </el-button> 191 </el-button>
@@ -171,7 +213,11 @@ getList() @@ -171,7 +213,11 @@ getList()
171 :schema="allSchemas.formSchema" 213 :schema="allSchemas.formSchema"
172 :rules="rules" 214 :rules="rules"
173 ref="formRef" 215 ref="formRef"
174 - /> 216 + >
  217 + <template #cronExpression>
  218 + <Crontab v-model="cronExpression" :shortcuts="shortcuts" />
  219 + </template>
  220 + </Form>
175 <!-- 对话框(详情) --> 221 <!-- 对话框(详情) -->
176 <Descriptions 222 <Descriptions
177 v-if="actionType === 'detail'" 223 v-if="actionType === 'detail'"
yudao-ui-admin-vue3/src/views/infra/job/job.data.ts
@@ -36,7 +36,13 @@ const crudSchemas = reactive&lt;CrudSchema[]&gt;([ @@ -36,7 +36,13 @@ const crudSchemas = reactive&lt;CrudSchema[]&gt;([
36 { 36 {
37 label: t('common.status'), 37 label: t('common.status'),
38 field: 'status', 38 field: 'status',
39 - dictType: DICT_TYPE.INFRA_JOB_STATUS 39 + dictType: DICT_TYPE.INFRA_JOB_STATUS,
  40 + form: {
  41 + show: false
  42 + },
  43 + detail: {
  44 + show: false
  45 + }
40 }, 46 },
41 { 47 {
42 label: '处理器的名字', 48 label: '处理器的名字',