Переглянути джерело

😍修改cron表达式组件

zuohuaijun 2 роки тому
батько
коміт
efc441b2e8

+ 1 - 0
Web/package.json

@@ -37,6 +37,7 @@
 		"screenfull": "^6.0.2",
 		"sortablejs": "^1.15.0",
 		"splitpanes": "^3.1.5",
+		"vcrontab-3": "^3.3.22",
 		"vform3-builds": "^3.0.10",
 		"vue": "^3.3.4",
 		"vue-clipboard3": "^2.0.0",

+ 58 - 0
Web/pnpm-lock.yaml

@@ -86,6 +86,9 @@ dependencies:
   splitpanes:
     specifier: ^3.1.5
     version: 3.1.5
+  vcrontab-3:
+    specifier: ^3.3.22
+    version: 3.3.22
   vform3-builds:
     specifier: ^3.0.10
     version: 3.0.10
@@ -933,6 +936,7 @@ packages:
 
   /@interactjs/types@1.10.17:
     resolution: {integrity: sha512-X2JpoM7xUw0p9Me0tMaI0HNfcF/Hd07ZZlzpnpEMpGerUZOLoyeThrV9P+CrBHxZrluWJrigJbcdqXliFd0YMA==}
+    requiresBuild: true
     dev: false
 
   /@interactjs/utils@1.10.17:
@@ -1013,6 +1017,7 @@ packages:
   /@mapbox/node-pre-gyp@1.0.11:
     resolution: {integrity: sha512-Yhlar6v9WQgUp/He7BdgzOz8lqMQ8sU+jkCq7Wx8Myc5YFJLbEe7lgui/V7G1qB1DJykHSGwreceSaD60Y0PUQ==}
     hasBin: true
+    requiresBuild: true
     dependencies:
       detect-libc: 2.0.2
       https-proxy-agent: 5.0.1
@@ -1641,6 +1646,7 @@ packages:
 
   /abbrev@1.1.1:
     resolution: {integrity: sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==}
+    requiresBuild: true
     dev: false
     optional: true
 
@@ -1682,6 +1688,7 @@ packages:
   /agent-base@6.0.2:
     resolution: {integrity: sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==}
     engines: {node: '>= 6.0.0'}
+    requiresBuild: true
     dependencies:
       debug: 4.3.4
     transitivePeerDependencies:
@@ -1730,12 +1737,14 @@ packages:
 
   /aproba@2.0.0:
     resolution: {integrity: sha512-lYe4Gx7QT+MKGbDsA+Z+he/Wtef0BiwDOlK/XkBrdfsh9J/jPPXbX0tE9x9cl27Tmu5gg3QUbUrQYa/y+KOHPQ==}
+    requiresBuild: true
     dev: false
     optional: true
 
   /are-we-there-yet@2.0.0:
     resolution: {integrity: sha512-Ci/qENmwHnsYo9xKIcUJN5LeDKdJ6R1Z1j9V/J5wyq8nh/mYPEpIKJbBZXtZjG04HiK7zV/p6Vs9952MrMeUIw==}
     engines: {node: '>=10'}
+    requiresBuild: true
     dependencies:
       delegates: 1.0.0
       readable-stream: 3.6.2
@@ -1918,6 +1927,7 @@ packages:
   /chownr@2.0.0:
     resolution: {integrity: sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ==}
     engines: {node: '>=10'}
+    requiresBuild: true
     dev: false
     optional: true
 
@@ -1966,6 +1976,7 @@ packages:
   /color-support@1.1.3:
     resolution: {integrity: sha512-qiBjkpbMLO/HL68y+lh4q0/O1MZFj2RX6X/KmMa3+gJD3z+WwI1ZzDHysvqHGS3mP6mznPckpXmw1nI9cJjyRg==}
     hasBin: true
+    requiresBuild: true
     dev: false
     optional: true
 
@@ -1993,6 +2004,7 @@ packages:
 
   /console-control-strings@1.1.0:
     resolution: {integrity: sha512-ty/fTekppD2fIwRvnZAVdeOiGd1c7YXEixbgJTNzqcxJWKQnjJ/V1bNEEE6hygpM3WjwHFUVK6HTjWSzV4a8sQ==}
+    requiresBuild: true
     dev: false
     optional: true
 
@@ -2062,6 +2074,7 @@ packages:
 
   /debug@3.2.7:
     resolution: {integrity: sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==}
+    requiresBuild: true
     peerDependencies:
       supports-color: '*'
     peerDependenciesMeta:
@@ -2086,6 +2099,7 @@ packages:
   /decompress-response@4.2.1:
     resolution: {integrity: sha512-jOSne2qbyE+/r8G1VU+G/82LBs2Fs4LAsTiLSHOCOMZQl2OKZ6i8i4IyHemTe+/yIXOtTcRQMzPcgyhoFlqPkw==}
     engines: {node: '>=8'}
+    requiresBuild: true
     dependencies:
       mimic-response: 2.1.0
     dev: false
@@ -2106,12 +2120,14 @@ packages:
 
   /delegates@1.0.0:
     resolution: {integrity: sha512-bd2L678uiWATM6m5Z1VzNCErI3jiGzt6HGY8OVICs40JQq/HALfbyNJmp0UDakEY4pMMaN0Ly5om/B1VI/+xfQ==}
+    requiresBuild: true
     dev: false
     optional: true
 
   /detect-libc@2.0.2:
     resolution: {integrity: sha512-UX6sGumvvqSaXgdKGUsgZWqcUyIXZ/vZTrlRT/iobiKhGL0zL4d3osHj3uqllWJK+i+sixDS/3COVEOFbupFyw==}
     engines: {node: '>=8'}
+    requiresBuild: true
     dev: false
     optional: true
 
@@ -2203,6 +2219,7 @@ packages:
 
   /emoji-regex@8.0.0:
     resolution: {integrity: sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==}
+    requiresBuild: true
     dev: false
     optional: true
 
@@ -2563,6 +2580,7 @@ packages:
   /fs-minipass@2.1.0:
     resolution: {integrity: sha512-V/JgOLFCS+R6Vcq0slCuaeWEdNC3ouDlJMNIsacH2VtALiu9mV4LPrHc5cDl8k5aw6J8jwgWWpiTo5RYhmIzvg==}
     engines: {node: '>= 8'}
+    requiresBuild: true
     dependencies:
       minipass: 3.3.6
     dev: false
@@ -2586,6 +2604,7 @@ packages:
   /gauge@3.0.2:
     resolution: {integrity: sha512-+5J6MS/5XksCuXq++uFRsnUd7Ovu1XenbeuIuNRJxYWjgQbPuFhT14lAvsWfqfAmnwluf1OwMjz39HjfLPci0Q==}
     engines: {node: '>=10'}
+    requiresBuild: true
     dependencies:
       aproba: 2.0.0
       color-support: 1.1.3
@@ -2697,6 +2716,7 @@ packages:
 
   /has-unicode@2.0.1:
     resolution: {integrity: sha512-8Rf9Y83NBReMnx0gFzA8JImQACstCYWUplepDa9xprwwtmgEZUF0h/i5xSA625zB/I37EtrswSST6OXxwaaIJQ==}
+    requiresBuild: true
     dev: false
     optional: true
 
@@ -2727,6 +2747,7 @@ packages:
   /https-proxy-agent@5.0.1:
     resolution: {integrity: sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==}
     engines: {node: '>= 6'}
+    requiresBuild: true
     dependencies:
       agent-base: 6.0.2
       debug: 4.3.4
@@ -2744,6 +2765,7 @@ packages:
   /iconv-lite@0.6.3:
     resolution: {integrity: sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==}
     engines: {node: '>=0.10.0'}
+    requiresBuild: true
     dependencies:
       safer-buffer: 2.1.2
     dev: true
@@ -2807,6 +2829,7 @@ packages:
   /is-fullwidth-code-point@3.0.0:
     resolution: {integrity: sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==}
     engines: {node: '>=8'}
+    requiresBuild: true
     dev: false
     optional: true
 
@@ -3052,6 +3075,7 @@ packages:
   /make-dir@3.1.0:
     resolution: {integrity: sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw==}
     engines: {node: '>=8'}
+    requiresBuild: true
     dependencies:
       semver: 6.3.1
     dev: false
@@ -3107,6 +3131,7 @@ packages:
   /mimic-response@2.1.0:
     resolution: {integrity: sha512-wXqjST+SLt7R009ySCglWBCFpjUygmCIfD790/kVbiGmUgfYGuB14PiTd5DwVxSV4NcYHjzMkoj5LjQZwTQLEA==}
     engines: {node: '>=8'}
+    requiresBuild: true
     dev: false
     optional: true
 
@@ -3118,6 +3143,7 @@ packages:
   /minipass@3.3.6:
     resolution: {integrity: sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==}
     engines: {node: '>=8'}
+    requiresBuild: true
     dependencies:
       yallist: 4.0.0
     dev: false
@@ -3126,12 +3152,14 @@ packages:
   /minipass@5.0.0:
     resolution: {integrity: sha512-3FnjYuehv9k6ovOEbyOswadCDPX1piCfhV8ncmYtHOjuPwylVWsghTLo7rabjC3Rx5xD4HDx8Wm1xnMF7S5qFQ==}
     engines: {node: '>=8'}
+    requiresBuild: true
     dev: false
     optional: true
 
   /minizlib@2.1.2:
     resolution: {integrity: sha512-bAxsR8BVfj60DWXHE3u30oHzfl4G7khkSuPW+qvpd7jFRHm7dLxOjUk1EHACJ/hxLY8phGJ0YhYHZo7jil7Qdg==}
     engines: {node: '>= 8'}
+    requiresBuild: true
     dependencies:
       minipass: 3.3.6
       yallist: 4.0.0
@@ -3150,6 +3178,7 @@ packages:
     resolution: {integrity: sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==}
     engines: {node: '>=10'}
     hasBin: true
+    requiresBuild: true
     dev: false
     optional: true
 
@@ -3166,6 +3195,7 @@ packages:
 
   /nan@2.17.0:
     resolution: {integrity: sha512-2ZTgtl0nJsO0KQCjEpxcIr5D+Yv90plTitZt9JBfQvVJDS5seMl3FOvsh3+9CoYWXf/1l5OaZzzF6nDm4cagaQ==}
+    requiresBuild: true
     dev: false
     optional: true
 
@@ -3220,6 +3250,7 @@ packages:
     resolution: {integrity: sha512-Tbj67rffqceeLpcRXrT7vKAN8CwfPeIBgM7E6iBkmKLV7bEMwpGgYLGv0jACUsECaa/vuxP0IjEont6umdMgtQ==}
     engines: {node: '>=6'}
     hasBin: true
+    requiresBuild: true
     dependencies:
       abbrev: 1.1.1
     dev: false
@@ -3236,6 +3267,7 @@ packages:
 
   /npmlog@5.0.1:
     resolution: {integrity: sha512-AqZtDUWOMKs1G/8lwylVjrdYgqA4d9nu8hc+0gzRxlDb1I10+FHBGMXs6aiQHFdCUUlqH99MUMuLfzWDNDtfxw==}
+    requiresBuild: true
     dependencies:
       are-we-there-yet: 2.0.0
       console-control-strings: 1.1.0
@@ -3261,6 +3293,7 @@ packages:
   /object-assign@4.1.1:
     resolution: {integrity: sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==}
     engines: {node: '>=0.10.0'}
+    requiresBuild: true
     dev: false
     optional: true
 
@@ -3363,6 +3396,7 @@ packages:
   /pify@4.0.1:
     resolution: {integrity: sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==}
     engines: {node: '>=6'}
+    requiresBuild: true
     dev: true
     optional: true
 
@@ -3436,6 +3470,7 @@ packages:
 
   /prr@1.0.1:
     resolution: {integrity: sha512-yPw4Sng1gWghHQWj0B3ZggWUm4qVbPwPFcRG8KyxiU7J2OHFSoEHKS+EZ3fv5l1t9CyCiop6l/ZYeWbrgoQejw==}
+    requiresBuild: true
     dev: true
     optional: true
 
@@ -3475,6 +3510,7 @@ packages:
   /readable-stream@3.6.2:
     resolution: {integrity: sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==}
     engines: {node: '>= 6'}
+    requiresBuild: true
     dependencies:
       inherits: 2.0.4
       string_decoder: 1.3.0
@@ -3554,11 +3590,13 @@ packages:
 
   /safe-buffer@5.2.1:
     resolution: {integrity: sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==}
+    requiresBuild: true
     dev: false
     optional: true
 
   /safer-buffer@2.1.2:
     resolution: {integrity: sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==}
+    requiresBuild: true
     dev: true
     optional: true
 
@@ -3574,6 +3612,7 @@ packages:
 
   /sax@1.2.4:
     resolution: {integrity: sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw==}
+    requiresBuild: true
     dev: true
     optional: true
 
@@ -3595,6 +3634,7 @@ packages:
   /semver@5.7.2:
     resolution: {integrity: sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==}
     hasBin: true
+    requiresBuild: true
     dev: true
     optional: true
 
@@ -3611,6 +3651,7 @@ packages:
 
   /set-blocking@2.0.0:
     resolution: {integrity: sha512-KiKBS8AnWGEyLzofFfmvKwpdPzqiy16LvQfK3yv/fVH7Bj13/wl3JSR1J+rfgRE9q7xUJK4qvgS8raSOeLUehw==}
+    requiresBuild: true
     dev: false
     optional: true
 
@@ -3640,6 +3681,7 @@ packages:
 
   /signal-exit@3.0.7:
     resolution: {integrity: sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==}
+    requiresBuild: true
     dev: false
     optional: true
 
@@ -3649,11 +3691,13 @@ packages:
 
   /simple-concat@1.0.1:
     resolution: {integrity: sha512-cSFtAPtRhljv69IK0hTVZQ+OfE9nePi/rtJmw5UjHeVyVroEqJXP1sFztKUy1qU+xvz3u/sfYJLa947b7nAN2Q==}
+    requiresBuild: true
     dev: false
     optional: true
 
   /simple-get@3.1.1:
     resolution: {integrity: sha512-CQ5LTKGfCpvE1K0n2us+kuMPbk/q0EKl82s4aheV9oXjFEz6W/Y7oQFVJuU6QG77hRT4Ghb5RURteF5vnWjupA==}
+    requiresBuild: true
     dependencies:
       decompress-response: 4.2.1
       once: 1.4.0
@@ -3752,6 +3796,7 @@ packages:
   /string-width@4.2.3:
     resolution: {integrity: sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==}
     engines: {node: '>=8'}
+    requiresBuild: true
     dependencies:
       emoji-regex: 8.0.0
       is-fullwidth-code-point: 3.0.0
@@ -3761,6 +3806,7 @@ packages:
 
   /string_decoder@1.3.0:
     resolution: {integrity: sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==}
+    requiresBuild: true
     dependencies:
       safe-buffer: 5.2.1
     dev: false
@@ -3803,6 +3849,7 @@ packages:
   /tar@6.1.15:
     resolution: {integrity: sha512-/zKt9UyngnxIT/EAGYuxaMYgOIJiP81ab9ZfkILq4oNLPFX50qyYmu7jRj9qeXoxmJHjGlbH0+cm2uy1WCs10A==}
     engines: {node: '>=10'}
+    requiresBuild: true
     dependencies:
       chownr: 2.0.0
       fs-minipass: 2.1.0
@@ -3936,6 +3983,16 @@ packages:
       base64-arraybuffer: 1.0.2
     dev: false
 
+  /vcrontab-3@3.3.22:
+    resolution: {integrity: sha512-+0MzE2loqap7hJ2+bTDRJn4nsEXAoxECZodv8N+2DjVDkUGSRPGw76BXZbAUesBtUa6pRboK/d5/tIsSW2HmoA==}
+    dependencies:
+      '@element-plus/icons-vue': 2.1.0(vue@3.3.4)
+      element-plus: 2.3.8(vue@3.3.4)
+      vue: 3.3.4
+    transitivePeerDependencies:
+      - '@vue/composition-api'
+    dev: false
+
   /vform3-builds@3.0.10:
     resolution: {integrity: sha512-sULNk72Z6NG94X9MMgpBwinaIOYjtl7Bn5jZbV9iZaglSYr2SHm/wpXPAjl8F8OW6SzOOJgIpRek+NvOvN7wsg==}
     dev: false
@@ -4155,6 +4212,7 @@ packages:
 
   /wide-align@1.1.5:
     resolution: {integrity: sha512-eDMORYaPNZ4sQIuuYPDHdQvf4gyCF9rEEV/yPxGfwPkRodwEgiMUUXTx/dex+Me0wxx53S+NgUHaP7y3MGlDmg==}
+    requiresBuild: true
     dependencies:
       string-width: 4.2.3
     dev: false

+ 1 - 0
Web/src/types/global.d.ts

@@ -8,6 +8,7 @@ declare module 'js-table2excel';
 declare module 'qs';
 declare module 'sortablejs';
 declare module 'vue-plugin-hiprint';
+declare module 'vcrontab-3';
 
 // 声明一个模块,防止引入文件时报错
 declare module '*.json';

+ 0 - 175
Web/src/views/system/job/component/cronTab/day.vue

@@ -1,175 +0,0 @@
-<template>
-  <el-form size="small">
-    <el-form-item>
-      <el-radio v-model="radioValue" :label="1"> 日,允许的通配符[, - * ? / L W] </el-radio>
-    </el-form-item>
-
-    <el-form-item>
-      <el-radio v-model="radioValue" :label="2"> 不指定 </el-radio>
-    </el-form-item>
-
-    <el-form-item>
-      <el-radio v-model="radioValue" :label="3">
-        周期从
-        <el-input-number v-model="cycle01" :min="1" :max="30" /> - <el-input-number v-model="cycle02" :min="cycle01 + 1" :max="31" /> 日
-      </el-radio>
-    </el-form-item>
-
-    <el-form-item>
-      <el-radio v-model="radioValue" :label="4">
-        从
-        <el-input-number v-model="average01" :min="1" :max="30" /> 号开始,每
-        <el-input-number v-model="average02" :min="1" :max="31 - average01" /> 日执行一次
-      </el-radio>
-    </el-form-item>
-
-    <el-form-item>
-      <el-radio v-model="radioValue" :label="5">
-        每月
-        <el-input-number v-model="workday" :min="1" :max="31" /> 号最近的那个工作日
-      </el-radio>
-    </el-form-item>
-
-    <el-form-item>
-      <el-radio v-model="radioValue" :label="6"> 本月最后一天 </el-radio>
-    </el-form-item>
-
-    <el-form-item>
-      <el-radio v-model="radioValue" :label="7">
-        指定
-        <el-select clearable v-model="checkboxList" placeholder="可多选" multiple :multiple-limit="10">
-          <el-option v-for="item in 31" :key="item" :label="item" :value="item" />
-        </el-select>
-      </el-radio>
-    </el-form-item>
-  </el-form>
-</template>
-<script setup lang="ts">
-import { computed, ref, watch } from 'vue';
-
-const emit = defineEmits(['update'])
-const props = defineProps({
-  cron: {
-    type: Object,
-    default: {
-      second: '*',
-      min: '*',
-      hour: '*',
-      day: '*',
-      month: '*',
-      week: '?',
-      year: ''
-    }
-  },
-  check: {
-    type: Function,
-    default: () => {}
-  }
-})
-const radioValue = ref(1)
-const cycle01 = ref(1)
-const cycle02 = ref(2)
-const average01 = ref(1)
-const average02 = ref(1)
-const workday = ref(1)
-const checkboxList = ref([])
-const checkCopy = ref([1])
-const cycleTotal = computed(() => {
-  cycle01.value = props.check(cycle01.value, 1, 30)
-  cycle02.value = props.check(cycle02.value, cycle01.value + 1, 31)
-  return cycle01.value + '-' + cycle02.value
-})
-const averageTotal = computed(() => {
-  average01.value = props.check(average01.value, 1, 30)
-  average02.value = props.check(average02.value, 1, 31 - average01.value)
-  return average01.value + '/' + average02.value
-})
-const workdayTotal = computed(() => {
-  workday.value = props.check(workday.value, 1, 31)
-  return workday.value + 'W'
-})
-const checkboxString = computed(() => {
-  return checkboxList.value.join(',')
-})
-watch(
-  () => props.cron.day,
-  (value) => changeRadioValue(value)
-)
-watch([radioValue, cycleTotal, averageTotal, workdayTotal, checkboxString], () => onRadioChange())
-function changeRadioValue(value) {
-  if (value === '*') {
-    radioValue.value = 1
-  } else if (value === '?') {
-    radioValue.value = 2
-  } else if (value.indexOf('-') > -1) {
-    const indexArr = value.split('-')
-    cycle01.value = Number(indexArr[0])
-    cycle02.value = Number(indexArr[1])
-    radioValue.value = 3
-  } else if (value.indexOf('/') > -1) {
-    const indexArr = value.split('/')
-    average01.value = Number(indexArr[0])
-    average02.value = Number(indexArr[1])
-    radioValue.value = 4
-  } else if (value.indexOf('W') > -1) {
-    const indexArr = value.split('W')
-    workday.value = Number(indexArr[0])
-    radioValue.value = 5
-  } else if (value === 'L') {
-    radioValue.value = 6
-  } else {
-    checkboxList.value = [...new Set(value.split(',').map((item) => Number(item)))]
-    radioValue.value = 7
-  }
-}
-// 单选按钮值变化时
-function onRadioChange() {
-  if (radioValue.value === 2 && props.cron.week === '?') {
-    emit('update', 'week', '*', 'day')
-  }
-  if (radioValue.value !== 2 && props.cron.week !== '?') {
-    emit('update', 'week', '?', 'day')
-  }
-  switch (radioValue.value) {
-    case 1:
-      emit('update', 'day', '*', 'day')
-      break
-    case 2:
-      emit('update', 'day', '?', 'day')
-      break
-    case 3:
-      emit('update', 'day', cycleTotal.value, 'day')
-      break
-    case 4:
-      emit('update', 'day', averageTotal.value, 'day')
-      break
-    case 5:
-      emit('update', 'day', workdayTotal.value, 'day')
-      break
-    case 6:
-      emit('update', 'day', 'L', 'day')
-      break
-    case 7:
-      if (checkboxList.value.length === 0) {
-        checkboxList.value.push(checkCopy.value[0])
-      } else {
-        checkCopy.value = checkboxList.value
-      }
-      emit('update', 'day', checkboxString.value, 'day')
-      break
-  }
-}
-</script>
-
-<style lang="scss" scoped>
-.el-input-number--small,
-.el-input-number--small,
-.el-select,
-.el-select--small {
-  margin: 0 0.2rem;
-}
-.el-select,
-.el-select--small {
-  width: 18.8rem;
-}
-</style>

+ 0 - 132
Web/src/views/system/job/component/cronTab/hour.vue

@@ -1,132 +0,0 @@
-<template>
-  <el-form size="small">
-    <el-form-item>
-      <el-radio v-model="radioValue" :label="1"> 小时,允许的通配符[, - * /] </el-radio>
-    </el-form-item>
-
-    <el-form-item>
-      <el-radio v-model="radioValue" :label="2">
-        周期从
-        <el-input-number v-model="cycle01" :min="0" :max="22" /> - <el-input-number v-model="cycle02" :min="cycle01 + 1" :max="23" /> 时
-      </el-radio>
-    </el-form-item>
-
-    <el-form-item>
-      <el-radio v-model="radioValue" :label="3">
-        从
-        <el-input-number v-model="average01" :min="0" :max="22" /> 时开始,每
-        <el-input-number v-model="average02" :min="1" :max="23 - average01" /> 小时执行一次
-      </el-radio>
-    </el-form-item>
-
-    <el-form-item>
-      <el-radio v-model="radioValue" :label="4">
-        指定
-        <el-select clearable v-model="checkboxList" placeholder="可多选" multiple :multiple-limit="10">
-          <el-option v-for="item in 24" :key="item" :label="item - 1" :value="item - 1" />
-        </el-select>
-      </el-radio>
-    </el-form-item>
-  </el-form>
-</template>
-
-<script setup lang="ts">
-import { computed, ref, watch } from 'vue';
-
-const emit = defineEmits(['update'])
-const props = defineProps({
-  cron: {
-    type: Object,
-    default: {
-      second: '*',
-      min: '*',
-      hour: '*',
-      day: '*',
-      month: '*',
-      week: '?',
-      year: ''
-    }
-  },
-  check: {
-    type: Function,
-    default: () => {}
-  }
-})
-const radioValue = ref(1)
-const cycle01 = ref(0)
-const cycle02 = ref(1)
-const average01 = ref(0)
-const average02 = ref(1)
-const checkboxList = ref([])
-const checkCopy = ref([0])
-const cycleTotal = computed(() => {
-  cycle01.value = props.check(cycle01.value, 0, 22)
-  cycle02.value = props.check(cycle02.value, cycle01.value + 1, 23)
-  return cycle01.value + '-' + cycle02.value
-})
-const averageTotal = computed(() => {
-  average01.value = props.check(average01.value, 0, 22)
-  average02.value = props.check(average02.value, 1, 23 - average01.value)
-  return average01.value + '/' + average02.value
-})
-const checkboxString = computed(() => {
-  return checkboxList.value.join(',')
-})
-watch(
-  () => props.cron.hour,
-  (value) => changeRadioValue(value)
-)
-watch([radioValue, cycleTotal, averageTotal, checkboxString], () => onRadioChange())
-function changeRadioValue(value) {
-  if (value === '*') {
-    radioValue.value = 1
-  } else if (value.indexOf('-') > -1) {
-    const indexArr = value.split('-')
-    cycle01.value = Number(indexArr[0])
-    cycle02.value = Number(indexArr[1])
-    radioValue.value = 2
-  } else if (value.indexOf('/') > -1) {
-    const indexArr = value.split('/')
-    average01.value = Number(indexArr[0])
-    average02.value = Number(indexArr[1])
-    radioValue.value = 3
-  } else {
-    checkboxList.value = [...new Set(value.split(',').map((item) => Number(item)))]
-    radioValue.value = 4
-  }
-}
-function onRadioChange() {
-  switch (radioValue.value) {
-    case 1:
-      emit('update', 'hour', '*', 'hour')
-      break
-    case 2:
-      emit('update', 'hour', cycleTotal.value, 'hour')
-      break
-    case 3:
-      emit('update', 'hour', averageTotal.value, 'hour')
-      break
-    case 4:
-      if (checkboxList.value.length === 0) {
-        checkboxList.value.push(checkCopy.value[0])
-      } else {
-        checkCopy.value = checkboxList.value
-      }
-      emit('update', 'hour', checkboxString.value, 'hour')
-      break
-  }
-}
-</script>
-
-<style lang="scss" scoped>
-.el-input-number--small,
-.el-input-number--small,
-.el-select,
-.el-select--small {
-  margin: 0 0.2rem;
-}
-.el-select,
-.el-select--small {
-  width: 18.8rem;
-}
-</style>

+ 0 - 285
Web/src/views/system/job/component/cronTab/index.vue

@@ -1,285 +0,0 @@
-<template>
-  <div>
-    <el-tabs type="border-card">
-      <el-tab-pane label="秒" v-if="shouldHide('second')">
-        <CrontabSecond @update="updateCrontabValue" :check="checkNumber" :cron="crontabValueObj" ref="cronsecond" />
-      </el-tab-pane>
-
-      <el-tab-pane label="分钟" v-if="shouldHide('min')">
-        <CrontabMin @update="updateCrontabValue" :check="checkNumber" :cron="crontabValueObj" ref="cronmin" />
-      </el-tab-pane>
-
-      <el-tab-pane label="小时" v-if="shouldHide('hour')">
-        <CrontabHour @update="updateCrontabValue" :check="checkNumber" :cron="crontabValueObj" ref="cronhour" />
-      </el-tab-pane>
-
-      <el-tab-pane label="日" v-if="shouldHide('day')">
-        <CrontabDay @update="updateCrontabValue" :check="checkNumber" :cron="crontabValueObj" ref="cronday" />
-      </el-tab-pane>
-
-      <el-tab-pane label="月" v-if="shouldHide('month')">
-        <CrontabMonth @update="updateCrontabValue" :check="checkNumber" :cron="crontabValueObj" ref="cronmonth" />
-      </el-tab-pane>
-
-      <el-tab-pane label="周" v-if="shouldHide('week')">
-        <CrontabWeek @update="updateCrontabValue" :check="checkNumber" :cron="crontabValueObj" ref="cronweek" />
-      </el-tab-pane>
-
-      <el-tab-pane label="年" v-if="shouldHide('year')">
-        <CrontabYear @update="updateCrontabValue" :check="checkNumber" :cron="crontabValueObj" ref="cronyear" />
-      </el-tab-pane>
-    </el-tabs>
-
-    <div class="popup-main">
-      <div class="popup-result">
-        <p class="title">时间表达式</p>
-        <table>
-          <thead>
-            <th v-for="item of tabTitles" :key="item">{{ item }}</th>
-            <th>Cron 表达式</th>
-          </thead>
-          <tbody>
-            <td>
-              <span v-if="crontabValueObj.second.length < 10">{{ crontabValueObj.second }}</span>
-              <el-tooltip v-else :content="crontabValueObj.second" placement="top"
-                ><span>{{ crontabValueObj.second }}</span></el-tooltip
-              >
-            </td>
-            <td>
-              <span v-if="crontabValueObj.min.length < 10">{{ crontabValueObj.min }}</span>
-              <el-tooltip v-else :content="crontabValueObj.min" placement="top"
-                ><span>{{ crontabValueObj.min }}</span></el-tooltip
-              >
-            </td>
-            <td>
-              <span v-if="crontabValueObj.hour.length < 10">{{ crontabValueObj.hour }}</span>
-              <el-tooltip v-else :content="crontabValueObj.hour" placement="top"
-                ><span>{{ crontabValueObj.hour }}</span></el-tooltip
-              >
-            </td>
-            <td>
-              <span v-if="crontabValueObj.day.length < 10">{{ crontabValueObj.day }}</span>
-              <el-tooltip v-else :content="crontabValueObj.day" placement="top"
-                ><span>{{ crontabValueObj.day }}</span></el-tooltip
-              >
-            </td>
-            <td>
-              <span v-if="crontabValueObj.month.length < 10">{{ crontabValueObj.month }}</span>
-              <el-tooltip v-else :content="crontabValueObj.month" placement="top"
-                ><span>{{ crontabValueObj.month }}</span></el-tooltip
-              >
-            </td>
-            <td>
-              <span v-if="crontabValueObj.week.length < 10">{{ crontabValueObj.week }}</span>
-              <el-tooltip v-else :content="crontabValueObj.week" placement="top"
-                ><span>{{ crontabValueObj.week }}</span></el-tooltip
-              >
-            </td>
-            <td>
-              <span v-if="crontabValueObj.year.length < 10">{{ crontabValueObj.year }}</span>
-              <el-tooltip v-else :content="crontabValueObj.year" placement="top"
-                ><span>{{ crontabValueObj.year }}</span></el-tooltip
-              >
-            </td>
-            <td class="result">
-              <span v-if="crontabValueString.length < 90">{{ crontabValueString }}</span>
-              <el-tooltip v-else :content="crontabValueString" placement="top"
-                ><span>{{ crontabValueString }}</span></el-tooltip
-              >
-            </td>
-          </tbody>
-        </table>
-      </div>
-      <CrontabResult :ex="crontabValueString"></CrontabResult>
-
-      <div class="pop_btn">
-        <el-button @click="hidePopup">取消</el-button>
-        <el-button type="warning" @click="clearCron">重置</el-button>
-        <el-button type="primary" @click="submitFill">确定</el-button>
-      </div>
-    </div>
-  </div>
-</template>
-
-<script setup lang="ts">
-import { computed, onMounted, ref, watch } from 'vue'
-import CrontabSecond from './second.vue'
-import CrontabMin from './min.vue'
-import CrontabHour from './hour.vue'
-import CrontabDay from './day.vue'
-import CrontabMonth from './month.vue'
-import CrontabWeek from './week.vue'
-import CrontabYear from './year.vue'
-import CrontabResult from './result.vue'
-// const { proxy } = getCurrentInstance()
-const emit = defineEmits(['hide', 'fill'])
-const props = defineProps({
-  hideComponent: {
-    type: Array,
-    default: () => []
-  },
-  expression: {
-    type: String,
-    default: ''
-  }
-})
-const tabTitles = ref(['秒', '分钟', '小时', '日', '月', '周', '年'])
-const tabActive = ref(0)
-const hideComponent = ref([])
-const expression = ref('')
-const crontabValueObj = ref({
-  second: '*',
-  min: '*',
-  hour: '*',
-  day: '*',
-  month: '*',
-  week: '?',
-  year: ''
-})
-const crontabValueString = computed(() => {
-  const obj = crontabValueObj.value
-  return obj.second + ' ' + obj.min + ' ' + obj.hour + ' ' + obj.day + ' ' + obj.month + ' ' + obj.week + (obj.year === '' ? '' : ' ' + obj.year)
-})
-watch(
-	() => props.expression,
-	(newValue) => (expression.value = newValue)
-);
-watch(expression, () => resolveExp())
-function shouldHide(key: any) {
-  return !(hideComponent.value && hideComponent.value.includes(key))
-}
-function resolveExp() {
-  // 反解析 表达式
-  if (expression.value) {
-    const arr = expression.value.split(/\s+/)
-    if (arr.length >= 6) {
-      //6 位以上是合法表达式
-      let obj = {
-        second: arr[0],
-        min: arr[1],
-        hour: arr[2],
-        day: arr[3],
-        month: arr[4],
-        week: arr[5],
-        year: arr[6] ? arr[6] : ''
-      }
-      crontabValueObj.value = {
-        ...obj
-      }
-    }
-  } else {
-    // 没有传入的表达式 则还原
-    clearCron()
-  }
-}
-// tab切换值
-function tabCheck(index: number) {
-  tabActive.value = index
-}
-// 由子组件触发,更改表达式组成的字段值
-function updateCrontabValue(name: string | number, value: any, from: any) {
-  crontabValueObj.value[name] = value
-}
-// 表单选项的子组件校验数字格式(通过-props传递)
-function checkNumber(value: number, minLimit: number, maxLimit: number) {
-  // 检查必须为整数
-  value = Math.floor(value)
-  if (value < minLimit) {
-    value = minLimit
-  } else if (value > maxLimit) {
-    value = maxLimit
-  }
-  return value
-}
-// 隐藏弹窗
-function hidePopup() {
-  emit('hide')
-}
-// 填充表达式
-function submitFill() {
-  emit('fill', crontabValueString.value)
-  hidePopup()
-}
-function clearCron() {
-  // 还原选择项
-  crontabValueObj.value = {
-    second: '*',
-    min: '*',
-    hour: '*',
-    day: '*',
-    month: '*',
-    week: '?',
-    year: ''
-  }
-}
-onMounted(() => {
-  expression.value = props.expression
-  hideComponent.value = props.hideComponent
-})
-</script>
-
-<style lang="scss" scoped>
-.pop_btn {
-  text-align: right;
-  margin-top: 20px;
-}
-.popup-main {
-  position: relative;
-  margin: 10px auto;
-  background: #fff;
-  border-radius: 5px;
-  font-size: 12px;
-  overflow: hidden;
-}
-.popup-title {
-  overflow: hidden;
-  line-height: 34px;
-  padding-top: 6px;
-  background: #f2f2f2;
-}
-.popup-result {
-  box-sizing: border-box;
-  line-height: 24px;
-  margin: 25px auto;
-  padding: 15px 10px 10px;
-  border: 1px solid #ccc;
-  position: relative;
-}
-.popup-result .title {
-  position: absolute;
-  top: -28px;
-  left: 50%;
-  width: 140px;
-  font-size: 14px;
-  margin-left: -70px;
-  text-align: center;
-  line-height: 30px;
-  background: #fff;
-}
-.popup-result table {
-  text-align: center;
-  width: 100%;
-  margin: 0 auto;
-}
-.popup-result table td:not(.result) {
-  width: 3.5rem;
-  min-width: 3.5rem;
-  max-width: 3.5rem;
-}
-.popup-result table span {
-  display: block;
-  width: 100%;
-  font-family: arial;
-  line-height: 30px;
-  height: 30px;
-  white-space: nowrap;
-  overflow: hidden;
-  border: 1px solid #e8e8e8;
-}
-.popup-result-scroll {
-  font-size: 12px;
-  line-height: 24px;
-  height: 10em;
-  overflow-y: auto;
-}
-</style>

+ 0 - 131
Web/src/views/system/job/component/cronTab/min.vue

@@ -1,131 +0,0 @@
-<template>
-  <el-form size="small">
-    <el-form-item>
-      <el-radio v-model="radioValue" :label="1"> 分钟,允许的通配符[, - * /] </el-radio>
-    </el-form-item>
-
-    <el-form-item>
-      <el-radio v-model="radioValue" :label="2">
-        周期从
-        <el-input-number v-model="cycle01" :min="0" :max="58" /> - <el-input-number v-model="cycle02" :min="cycle01 + 1" :max="59" /> 分钟
-      </el-radio>
-    </el-form-item>
-
-    <el-form-item>
-      <el-radio v-model="radioValue" :label="3">
-        从
-        <el-input-number v-model="average01" :min="0" :max="58" /> 分钟开始, 每
-        <el-input-number v-model="average02" :min="1" :max="59 - average01" /> 分钟执行一次
-      </el-radio>
-    </el-form-item>
-
-    <el-form-item>
-      <el-radio v-model="radioValue" :label="4">
-        指定
-        <el-select clearable v-model="checkboxList" placeholder="可多选" multiple :multiple-limit="10">
-          <el-option v-for="item in 60" :key="item" :label="item - 1" :value="item - 1" />
-        </el-select>
-      </el-radio>
-    </el-form-item>
-  </el-form>
-</template>
-<script setup lang="ts">
-import { computed, ref, watch } from 'vue';
-
-const emit = defineEmits(['update'])
-const props = defineProps({
-  cron: {
-    type: Object,
-    default: {
-      second: '*',
-      min: '*',
-      hour: '*',
-      day: '*',
-      month: '*',
-      week: '?',
-      year: ''
-    }
-  },
-  check: {
-    type: Function,
-    default: () => {}
-  }
-})
-const radioValue = ref(1)
-const cycle01 = ref(0)
-const cycle02 = ref(1)
-const average01 = ref(0)
-const average02 = ref(1)
-const checkboxList = ref([])
-const checkCopy = ref([0])
-const cycleTotal = computed(() => {
-  cycle01.value = props.check(cycle01.value, 0, 58)
-  cycle02.value = props.check(cycle02.value, cycle01.value + 1, 59)
-  return cycle01.value + '-' + cycle02.value
-})
-const averageTotal = computed(() => {
-  average01.value = props.check(average01.value, 0, 58)
-  average02.value = props.check(average02.value, 1, 59 - average01.value)
-  return average01.value + '/' + average02.value
-})
-const checkboxString = computed(() => {
-  return checkboxList.value.join(',')
-})
-watch(
-  () => props.cron.min,
-  (value) => changeRadioValue(value)
-)
-watch([radioValue, cycleTotal, averageTotal, checkboxString], () => onRadioChange())
-function changeRadioValue(value) {
-  if (value === '*') {
-    radioValue.value = 1
-  } else if (value.indexOf('-') > -1) {
-    const indexArr = value.split('-')
-    cycle01.value = Number(indexArr[0])
-    cycle02.value = Number(indexArr[1])
-    radioValue.value = 2
-  } else if (value.indexOf('/') > -1) {
-    const indexArr = value.split('/')
-    average01.value = Number(indexArr[0])
-    average02.value = Number(indexArr[1])
-    radioValue.value = 3
-  } else {
-    checkboxList.value = [...new Set(value.split(',').map((item) => Number(item)))]
-    radioValue.value = 4
-  }
-}
-function onRadioChange() {
-  switch (radioValue.value) {
-    case 1:
-      emit('update', 'min', '*', 'min')
-      break
-    case 2:
-      emit('update', 'min', cycleTotal.value, 'min')
-      break
-    case 3:
-      emit('update', 'min', averageTotal.value, 'min')
-      break
-    case 4:
-      if (checkboxList.value.length === 0) {
-        checkboxList.value.push(checkCopy.value[0])
-      } else {
-        checkCopy.value = checkboxList.value
-      }
-      emit('update', 'min', checkboxString.value, 'min')
-      break
-  }
-}
-</script>
-
-<style lang="scss" scoped>
-.el-input-number--small,
-.el-input-number--small,
-.el-select,
-.el-select--small {
-  margin: 0 0.2rem;
-}
-.el-select,
-.el-select--small {
-  width: 19.8rem;
-}
-</style>

+ 0 - 146
Web/src/views/system/job/component/cronTab/month.vue

@@ -1,146 +0,0 @@
-<template>
-  <el-form size="small">
-    <el-form-item>
-      <el-radio v-model="radioValue" :label="1"> 月,允许的通配符[, - * /] </el-radio>
-    </el-form-item>
-
-    <el-form-item>
-      <el-radio v-model="radioValue" :label="2">
-        周期从
-        <el-input-number v-model="cycle01" :min="1" :max="11" /> - <el-input-number v-model="cycle02" :min="cycle01 + 1" :max="12" /> 月
-      </el-radio>
-    </el-form-item>
-
-    <el-form-item>
-      <el-radio v-model="radioValue" :label="3">
-        从
-        <el-input-number v-model="average01" :min="1" :max="11" /> 月开始,每
-        <el-input-number v-model="average02" :min="1" :max="12 - average01" /> 月月执行一次
-      </el-radio>
-    </el-form-item>
-
-    <el-form-item>
-      <el-radio v-model="radioValue" :label="4">
-        指定
-        <el-select clearable v-model="checkboxList" placeholder="可多选" multiple :multiple-limit="8">
-          <el-option v-for="item in monthList" :key="item.key" :label="item.value" :value="item.key" />
-        </el-select>
-      </el-radio>
-    </el-form-item>
-  </el-form>
-</template>
-
-<script setup lang="ts">
-import { computed, ref, watch } from 'vue';
-
-const emit = defineEmits(['update'])
-const props = defineProps({
-  cron: {
-    type: Object,
-    default: {
-      second: '*',
-      min: '*',
-      hour: '*',
-      day: '*',
-      month: '*',
-      week: '?',
-      year: ''
-    }
-  },
-  check: {
-    type: Function,
-    default: () => {}
-  }
-})
-const radioValue = ref(1)
-const cycle01 = ref(1)
-const cycle02 = ref(2)
-const average01 = ref(1)
-const average02 = ref(1)
-const checkboxList = ref([])
-const checkCopy = ref([1])
-const monthList = ref([
-  { key: 1, value: '一月' },
-  { key: 2, value: '二月' },
-  { key: 3, value: '三月' },
-  { key: 4, value: '四月' },
-  { key: 5, value: '五月' },
-  { key: 6, value: '六月' },
-  { key: 7, value: '七月' },
-  { key: 8, value: '八月' },
-  { key: 9, value: '九月' },
-  { key: 10, value: '十月' },
-  { key: 11, value: '十一月' },
-  { key: 12, value: '十二月' }
-])
-const cycleTotal = computed(() => {
-  cycle01.value = props.check(cycle01.value, 1, 11)
-  cycle02.value = props.check(cycle02.value, cycle01.value + 1, 12)
-  return cycle01.value + '-' + cycle02.value
-})
-const averageTotal = computed(() => {
-  average01.value = props.check(average01.value, 1, 11)
-  average02.value = props.check(average02.value, 1, 12 - average01.value)
-  return average01.value + '/' + average02.value
-})
-const checkboxString = computed(() => {
-  return checkboxList.value.join(',')
-})
-watch(
-  () => props.cron.month,
-  (value) => changeRadioValue(value)
-)
-watch([radioValue, cycleTotal, averageTotal, checkboxString], () => onRadioChange())
-function changeRadioValue(value) {
-  if (value === '*') {
-    radioValue.value = 1
-  } else if (value.indexOf('-') > -1) {
-    const indexArr = value.split('-')
-    cycle01.value = Number(indexArr[0])
-    cycle02.value = Number(indexArr[1])
-    radioValue.value = 2
-  } else if (value.indexOf('/') > -1) {
-    const indexArr = value.split('/')
-    average01.value = Number(indexArr[0])
-    average02.value = Number(indexArr[1])
-    radioValue.value = 3
-  } else {
-    checkboxList.value = [...new Set(value.split(',').map((item) => Number(item)))]
-    radioValue.value = 4
-  }
-}
-function onRadioChange() {
-  switch (radioValue.value) {
-    case 1:
-      emit('update', 'month', '*', 'month')
-      break
-    case 2:
-      emit('update', 'month', cycleTotal.value, 'month')
-      break
-    case 3:
-      emit('update', 'month', averageTotal.value, 'month')
-      break
-    case 4:
-      if (checkboxList.value.length === 0) {
-        checkboxList.value.push(checkCopy.value[0])
-      } else {
-        checkCopy.value = checkboxList.value
-      }
-      emit('update', 'month', checkboxString.value, 'month')
-      break
-  }
-}
-</script>
-
-<style lang="scss" scoped>
-.el-input-number--small,
-.el-input-number--small,
-.el-select,
-.el-select--small {
-  margin: 0 0.2rem;
-}
-.el-select,
-.el-select--small {
-  width: 18.8rem;
-}
-</style>

+ 0 - 562
Web/src/views/system/job/component/cronTab/result.vue

@@ -1,562 +0,0 @@
-<template>
-  <div class="popup-result" style="padding-left: 25px;">
-    <p class="title">最近5次运行时间</p>
-    <ul class="popup-result-scroll">
-      <template v-if="isShow">
-        <li v-for="item in resultList" :key="item">{{ item }}</li>
-      </template>
-      <li v-else>计算结果中...</li>
-    </ul>
-  </div>
-</template>
-
-<script setup lang="ts">
-import { onMounted, ref, watch } from 'vue';
-
-const props = defineProps({
-  ex: {
-    type: String,
-    default: ''
-  }
-})
-const dayRule = ref('')
-const dayRuleSup = ref('')
-const dateArr = ref([])
-const resultList = ref([])
-const isShow = ref(false)
-watch(
-  () => props.ex,
-  () => expressionChange()
-)
-// 表达式值变化时,开始去计算结果
-function expressionChange() {
-  // 计算开始-隐藏结果
-  isShow.value = false
-  // 获取规则数组[0秒、1分、2时、3日、4月、5星期、6年]
-  let ruleArr = props.ex.split(' ')
-  // 用于记录进入循环的次数
-  let nums = 0
-  // 用于暂时存符号时间规则结果的数组
-  let resultArr = []
-  // 获取当前时间精确至[年、月、日、时、分、秒]
-  let nTime = new Date()
-  let nYear = nTime.getFullYear()
-  let nMonth = nTime.getMonth() + 1
-  let nDay = nTime.getDate()
-  let nHour = nTime.getHours()
-  let nMin = nTime.getMinutes()
-  let nSecond = nTime.getSeconds()
-  // 根据规则获取到近100年可能年数组、月数组等等
-  getSecondArr(ruleArr[0])
-  getMinArr(ruleArr[1])
-  getHourArr(ruleArr[2])
-  getDayArr(ruleArr[3])
-  getMonthArr(ruleArr[4])
-  getWeekArr(ruleArr[5])
-  getYearArr(ruleArr[6], nYear)
-  // 将获取到的数组赋值-方便使用
-  let sDate = dateArr.value[0]
-  let mDate = dateArr.value[1]
-  let hDate = dateArr.value[2]
-  let DDate = dateArr.value[3]
-  let MDate = dateArr.value[4]
-  let YDate = dateArr.value[5]
-  // 获取当前时间在数组中的索引
-  let sIdx = getIndex(sDate, nSecond)
-  let mIdx = getIndex(mDate, nMin)
-  let hIdx = getIndex(hDate, nHour)
-  let DIdx = getIndex(DDate, nDay)
-  let MIdx = getIndex(MDate, nMonth)
-  let YIdx = getIndex(YDate, nYear)
-  // 重置月日时分秒的函数(后面用的比较多)
-  const resetSecond = function () {
-    sIdx = 0
-    nSecond = sDate[sIdx]
-  }
-  const resetMin = function () {
-    mIdx = 0
-    nMin = mDate[mIdx]
-    resetSecond()
-  }
-  const resetHour = function () {
-    hIdx = 0
-    nHour = hDate[hIdx]
-    resetMin()
-  }
-  const resetDay = function () {
-    DIdx = 0
-    nDay = DDate[DIdx]
-    resetHour()
-  }
-  const resetMonth = function () {
-    MIdx = 0
-    nMonth = MDate[MIdx]
-    resetDay()
-  }
-  // 如果当前年份不为数组中当前值
-  if (nYear !== YDate[YIdx]) {
-    resetMonth()
-  }
-  // 如果当前月份不为数组中当前值
-  if (nMonth !== MDate[MIdx]) {
-    resetDay()
-  }
-  // 如果当前“日”不为数组中当前值
-  if (nDay !== DDate[DIdx]) {
-    resetHour()
-  }
-  // 如果当前“时”不为数组中当前值
-  if (nHour !== hDate[hIdx]) {
-    resetMin()
-  }
-  // 如果当前“分”不为数组中当前值
-  if (nMin !== mDate[mIdx]) {
-    resetSecond()
-  }
-  // 循环年份数组
-  goYear: for (let Yi = YIdx; Yi < YDate.length; Yi++) {
-    let YY = YDate[Yi]
-    // 如果到达最大值时
-    if (nMonth > MDate[MDate.length - 1]) {
-      resetMonth()
-      continue
-    }
-    // 循环月份数组
-    goMonth: for (let Mi = MIdx; Mi < MDate.length; Mi++) {
-      // 赋值、方便后面运算
-      let MM = MDate[Mi]
-      MM = MM < 10 ? '0' + MM : MM
-      // 如果到达最大值时
-      if (nDay > DDate[DDate.length - 1]) {
-        resetDay()
-        if (Mi === MDate.length - 1) {
-          resetMonth()
-          continue goYear
-        }
-        continue
-      }
-      // 循环日期数组
-      goDay: for (let Di = DIdx; Di < DDate.length; Di++) {
-        // 赋值、方便后面运算
-        let DD = DDate[Di]
-        let thisDD = DD < 10 ? '0' + DD : DD
-        // 如果到达最大值时
-        if (nHour > hDate[hDate.length - 1]) {
-          resetHour()
-          if (Di === DDate.length - 1) {
-            resetDay()
-            if (Mi === MDate.length - 1) {
-              resetMonth()
-              continue goYear
-            }
-            continue goMonth
-          }
-          continue
-        }
-        // 判断日期的合法性,不合法的话也是跳出当前循环
-        if (
-          checkDate(YY + '-' + MM + '-' + thisDD + ' 00:00:00') !== true &&
-          dayRule.value !== 'workDay' &&
-          dayRule.value !== 'lastWeek' &&
-          dayRule.value !== 'lastDay'
-        ) {
-          resetDay()
-          continue goMonth
-        }
-        // 如果日期规则中有值时
-        if (dayRule.value === 'lastDay') {
-          // 如果不是合法日期则需要将前将日期调到合法日期即月末最后一天
-          if (checkDate(YY + '-' + MM + '-' + thisDD + ' 00:00:00') !== true) {
-            while (DD > 0 && checkDate(YY + '-' + MM + '-' + thisDD + ' 00:00:00') !== true) {
-              DD--
-              thisDD = DD < 10 ? '0' + DD : DD
-            }
-          }
-        } else if (dayRule.value === 'workDay') {
-          // 校验并调整如果是2月30号这种日期传进来时需调整至正常月底
-          if (checkDate(YY + '-' + MM + '-' + thisDD + ' 00:00:00') !== true) {
-            while (DD > 0 && checkDate(YY + '-' + MM + '-' + thisDD + ' 00:00:00') !== true) {
-              DD--
-              thisDD = DD < 10 ? '0' + DD : DD
-            }
-          }
-          // 获取达到条件的日期是星期X
-          let thisWeek = formatDate(new Date(YY + '-' + MM + '-' + thisDD + ' 00:00:00'), 'week')
-          // 当星期日时
-          if (thisWeek === 1) {
-            // 先找下一个日,并判断是否为月底
-            DD++
-            thisDD = DD < 10 ? '0' + DD : DD
-            // 判断下一日已经不是合法日期
-            if (checkDate(YY + '-' + MM + '-' + thisDD + ' 00:00:00') !== true) {
-              DD -= 3
-            }
-          } else if (thisWeek === 7) {
-            // 当星期6时只需判断不是1号就可进行操作
-            if (dayRuleSup.value !== 1) {
-              DD--
-            } else {
-              DD += 2
-            }
-          }
-        } else if (dayRule.value === 'weekDay') {
-          // 如果指定了是星期几
-          // 获取当前日期是属于星期几
-          let thisWeek = formatDate(new Date(YY + '-' + MM + '-' + DD + ' 00:00:00'), 'week')
-          // 校验当前星期是否在星期池(dayRuleSup)中
-          if (dayRuleSup.value.indexOf(thisWeek) < 0) {
-            // 如果到达最大值时
-            if (Di === DDate.length - 1) {
-              resetDay()
-              if (Mi === MDate.length - 1) {
-                resetMonth()
-                continue goYear
-              }
-              continue goMonth
-            }
-            continue
-          }
-        } else if (dayRule.value === 'assWeek') {
-          // 如果指定了是第几周的星期几
-          // 获取每月1号是属于星期几
-          let thisWeek = formatDate(new Date(YY + '-' + MM + '-' + DD + ' 00:00:00'), 'week')
-          if (dayRuleSup.value[1] >= thisWeek) {
-            DD = (dayRuleSup.value[0] - 1) * 7 + dayRuleSup.value[1] - thisWeek + 1
-          } else {
-            DD = dayRuleSup.value[0] * 7 + dayRuleSup.value[1] - thisWeek + 1
-          }
-        } else if (dayRule.value === 'lastWeek') {
-          // 如果指定了每月最后一个星期几
-          // 校验并调整如果是2月30号这种日期传进来时需调整至正常月底
-          if (checkDate(YY + '-' + MM + '-' + thisDD + ' 00:00:00') !== true) {
-            while (DD > 0 && checkDate(YY + '-' + MM + '-' + thisDD + ' 00:00:00') !== true) {
-              DD--
-              thisDD = DD < 10 ? '0' + DD : DD
-            }
-          }
-          // 获取月末最后一天是星期几
-          let thisWeek = formatDate(new Date(YY + '-' + MM + '-' + thisDD + ' 00:00:00'), 'week')
-          // 找到要求中最近的那个星期几
-          if (dayRuleSup.value < thisWeek) {
-            DD -= thisWeek - dayRuleSup.value
-          } else if (dayRuleSup.value > thisWeek) {
-            DD -= 7 - (dayRuleSup.value - thisWeek)
-          }
-        }
-        // 判断时间值是否小于10置换成“05”这种格式
-        DD = DD < 10 ? '0' + DD : DD
-        // 循环“时”数组
-        goHour: for (let hi = hIdx; hi < hDate.length; hi++) {
-          let hh = hDate[hi] < 10 ? '0' + hDate[hi] : hDate[hi]
-          // 如果到达最大值时
-          if (nMin > mDate[mDate.length - 1]) {
-            resetMin()
-            if (hi === hDate.length - 1) {
-              resetHour()
-              if (Di === DDate.length - 1) {
-                resetDay()
-                if (Mi === MDate.length - 1) {
-                  resetMonth()
-                  continue goYear
-                }
-                continue goMonth
-              }
-              continue goDay
-            }
-            continue
-          }
-          // 循环"分"数组
-          goMin: for (let mi = mIdx; mi < mDate.length; mi++) {
-            let mm = mDate[mi] < 10 ? '0' + mDate[mi] : mDate[mi]
-            // 如果到达最大值时
-            if (nSecond > sDate[sDate.length - 1]) {
-              resetSecond()
-              if (mi === mDate.length - 1) {
-                resetMin()
-                if (hi === hDate.length - 1) {
-                  resetHour()
-                  if (Di === DDate.length - 1) {
-                    resetDay()
-                    if (Mi === MDate.length - 1) {
-                      resetMonth()
-                      continue goYear
-                    }
-                    continue goMonth
-                  }
-                  continue goDay
-                }
-                continue goHour
-              }
-              continue
-            }
-            // 循环"秒"数组
-            goSecond: for (let si = sIdx; si <= sDate.length - 1; si++) {
-              let ss = sDate[si] < 10 ? '0' + sDate[si] : sDate[si]
-              // 添加当前时间(时间合法性在日期循环时已经判断)
-              if (MM !== '00' && DD !== '00') {
-                resultArr.push(YY + '-' + MM + '-' + DD + ' ' + hh + ':' + mm + ':' + ss)
-                nums++
-              }
-              // 如果条数满了就退出循环
-              if (nums === 5) break goYear
-              // 如果到达最大值时
-              if (si === sDate.length - 1) {
-                resetSecond()
-                if (mi === mDate.length - 1) {
-                  resetMin()
-                  if (hi === hDate.length - 1) {
-                    resetHour()
-                    if (Di === DDate.length - 1) {
-                      resetDay()
-                      if (Mi === MDate.length - 1) {
-                        resetMonth()
-                        continue goYear
-                      }
-                      continue goMonth
-                    }
-                    continue goDay
-                  }
-                  continue goHour
-                }
-                continue goMin
-              }
-            } //goSecond
-          } //goMin
-        } //goHour
-      } //goDay
-    } //goMonth
-  }
-  // 判断100年内的结果条数
-  if (resultArr.length === 0) {
-    resultList.value = ['没有达到条件的结果!']
-  } else {
-    resultList.value = resultArr
-    if (resultArr.length !== 5) {
-      resultList.value.push('最近100年内只有上面' + resultArr.length + '条结果!')
-    }
-  }
-  // 计算完成-显示结果
-  isShow.value = true
-}
-// 用于计算某位数字在数组中的索引
-function getIndex(arr, value) {
-  if (value <= arr[0] || value > arr[arr.length - 1]) {
-    return 0
-  } else {
-    for (let i = 0; i < arr.length - 1; i++) {
-      if (value > arr[i] && value <= arr[i + 1]) {
-        return i + 1
-      }
-    }
-  }
-}
-// 获取"年"数组
-function getYearArr(rule, year) {
-  dateArr.value[5] = getOrderArr(year, year + 100)
-  if (rule !== undefined) {
-    if (rule.indexOf('-') >= 0) {
-      dateArr.value[5] = getCycleArr(rule, year + 100, false)
-    } else if (rule.indexOf('/') >= 0) {
-      dateArr.value[5] = getAverageArr(rule, year + 100)
-    } else if (rule !== '*') {
-      dateArr.value[5] = getAssignArr(rule)
-    }
-  }
-}
-// 获取"月"数组
-function getMonthArr(rule) {
-  dateArr.value[4] = getOrderArr(1, 12)
-  if (rule.indexOf('-') >= 0) {
-    dateArr.value[4] = getCycleArr(rule, 12, false)
-  } else if (rule.indexOf('/') >= 0) {
-    dateArr.value[4] = getAverageArr(rule, 12)
-  } else if (rule !== '*') {
-    dateArr.value[4] = getAssignArr(rule)
-  }
-}
-// 获取"日"数组-主要为日期规则
-function getWeekArr(rule) {
-  // 只有当日期规则的两个值均为“”时则表达日期是有选项的
-  if (dayRule.value === '' && dayRuleSup.value === '') {
-    if (rule.indexOf('-') >= 0) {
-      dayRule.value = 'weekDay'
-      dayRuleSup.value = getCycleArr(rule, 7, false)
-    } else if (rule.indexOf('#') >= 0) {
-      dayRule.value = 'assWeek'
-      let matchRule = rule.match(/[0-9]{1}/g)
-      dayRuleSup.value = [Number(matchRule[1]), Number(matchRule[0])]
-      dateArr.value[3] = [1]
-      if (dayRuleSup.value[1] === 7) {
-        dayRuleSup.value[1] = 0
-      }
-    } else if (rule.indexOf('L') >= 0) {
-      dayRule.value = 'lastWeek'
-      dayRuleSup.value = Number(rule.match(/[0-9]{1,2}/g)[0])
-      dateArr.value[3] = [31]
-      if (dayRuleSup.value === 7) {
-        dayRuleSup.value = 0
-      }
-    } else if (rule !== '*' && rule !== '?') {
-      dayRule.value = 'weekDay'
-      dayRuleSup.value = getAssignArr(rule)
-    }
-  }
-}
-// 获取"日"数组-少量为日期规则
-function getDayArr(rule) {
-  dateArr.value[3] = getOrderArr(1, 31)
-  dayRule.value = ''
-  dayRuleSup.value = ''
-  if (rule.indexOf('-') >= 0) {
-    dateArr.value[3] = getCycleArr(rule, 31, false)
-    dayRuleSup.value = 'null'
-  } else if (rule.indexOf('/') >= 0) {
-    dateArr.value[3] = getAverageArr(rule, 31)
-    dayRuleSup.value = 'null'
-  } else if (rule.indexOf('W') >= 0) {
-    dayRule.value = 'workDay'
-    dayRuleSup.value = Number(rule.match(/[0-9]{1,2}/g)[0])
-    dateArr.value[3] = [dayRuleSup.value]
-  } else if (rule.indexOf('L') >= 0) {
-    dayRule.value = 'lastDay'
-    dayRuleSup.value = 'null'
-    dateArr.value[3] = [31]
-  } else if (rule !== '*' && rule !== '?') {
-    dateArr.value[3] = getAssignArr(rule)
-    dayRuleSup.value = 'null'
-  } else if (rule === '*') {
-    dayRuleSup.value = 'null'
-  }
-}
-// 获取"时"数组
-function getHourArr(rule) {
-  dateArr.value[2] = getOrderArr(0, 23)
-  if (rule.indexOf('-') >= 0) {
-    dateArr.value[2] = getCycleArr(rule, 24, true)
-  } else if (rule.indexOf('/') >= 0) {
-    dateArr.value[2] = getAverageArr(rule, 23)
-  } else if (rule !== '*') {
-    dateArr.value[2] = getAssignArr(rule)
-  }
-}
-// 获取"分"数组
-function getMinArr(rule) {
-  dateArr.value[1] = getOrderArr(0, 59)
-  if (rule.indexOf('-') >= 0) {
-    dateArr.value[1] = getCycleArr(rule, 60, true)
-  } else if (rule.indexOf('/') >= 0) {
-    dateArr.value[1] = getAverageArr(rule, 59)
-  } else if (rule !== '*') {
-    dateArr.value[1] = getAssignArr(rule)
-  }
-}
-// 获取"秒"数组
-function getSecondArr(rule) {
-  dateArr.value[0] = getOrderArr(0, 59)
-  if (rule.indexOf('-') >= 0) {
-    dateArr.value[0] = getCycleArr(rule, 60, true)
-  } else if (rule.indexOf('/') >= 0) {
-    dateArr.value[0] = getAverageArr(rule, 59)
-  } else if (rule !== '*') {
-    dateArr.value[0] = getAssignArr(rule)
-  }
-}
-// 根据传进来的min-max返回一个顺序的数组
-function getOrderArr(min, max) {
-  let arr = []
-  for (let i = min; i <= max; i++) {
-    arr.push(i)
-  }
-  return arr
-}
-// 根据规则中指定的零散值返回一个数组
-function getAssignArr(rule) {
-  let arr = []
-  let assiginArr = rule.split(',')
-  for (let i = 0; i < assiginArr.length; i++) {
-    arr[i] = Number(assiginArr[i])
-  }
-  arr.sort(compare)
-  return arr
-}
-// 根据一定算术规则计算返回一个数组
-function getAverageArr(rule, limit) {
-  let arr = []
-  let agArr = rule.split('/')
-  let min = Number(agArr[0])
-  let step = Number(agArr[1])
-  while (min <= limit) {
-    arr.push(min)
-    min += step
-  }
-  return arr
-}
-// 根据规则返回一个具有周期性的数组
-function getCycleArr(rule, limit, status) {
-  // status--表示是否从0开始(则从1开始)
-  let arr = []
-  let cycleArr = rule.split('-')
-  let min = Number(cycleArr[0])
-  let max = Number(cycleArr[1])
-  if (min > max) {
-    max += limit
-  }
-  for (let i = min; i <= max; i++) {
-    let add = 0
-    if (status === false && i % limit === 0) {
-      add = limit
-    }
-    arr.push(Math.round((i % limit) + add))
-  }
-  arr.sort(compare)
-  return arr
-}
-// 比较数字大小(用于Array.sort)
-function compare(value1, value2) {
-  if (value2 - value1 > 0) {
-    return -1
-  } else {
-    return 1
-  }
-}
-// 格式化日期格式如:2017-9-19 18:04:33
-function formatDate(value, type) {
-  // 计算日期相关值
-  let time = typeof value == 'number' ? new Date(value) : value
-  let Y = time.getFullYear()
-  let M = time.getMonth() + 1
-  let D = time.getDate()
-  let h = time.getHours()
-  let m = time.getMinutes()
-  let s = time.getSeconds()
-  let week = time.getDay()
-  // 如果传递了type的话
-  if (type === undefined) {
-    return (
-      Y +
-      '-' +
-      (M < 10 ? '0' + M : M) +
-      '-' +
-      (D < 10 ? '0' + D : D) +
-      ' ' +
-      (h < 10 ? '0' + h : h) +
-      ':' +
-      (m < 10 ? '0' + m : m) +
-      ':' +
-      (s < 10 ? '0' + s : s)
-    )
-  } else if (type === 'week') {
-    // 在quartz中 1为星期日
-    return week + 1
-  }
-}
-// 检查日期是否存在
-function checkDate(value) {
-  let time = new Date(value)
-  let format = formatDate(time)
-  return value === format
-}
-onMounted(() => {
-  expressionChange()
-})
-</script>

+ 0 - 133
Web/src/views/system/job/component/cronTab/second.vue

@@ -1,133 +0,0 @@
-<template>
-  <el-form size="small">
-    <el-form-item>
-      <el-radio v-model="radioValue" :label="1"> 秒,允许的通配符[, - * /] </el-radio>
-    </el-form-item>
-
-    <el-form-item>
-      <el-radio v-model="radioValue" :label="2">
-        周期从
-        <el-input-number v-model="cycle01" :min="0" :max="58" /> - <el-input-number v-model="cycle02" :min="cycle01 + 1" :max="59" /> 秒
-      </el-radio>
-    </el-form-item>
-
-    <el-form-item>
-      <el-radio v-model="radioValue" :label="3">
-        从
-        <el-input-number v-model="average01" :min="0" :max="58" /> 秒开始,每
-        <el-input-number v-model="average02" :min="1" :max="59 - average01" /> 秒执行一次
-      </el-radio>
-    </el-form-item>
-
-    <el-form-item>
-      <el-radio v-model="radioValue" :label="4">
-        指定
-        <el-select clearable v-model="checkboxList" placeholder="可多选" multiple :multiple-limit="10">
-          <el-option v-for="item in 60" :key="item" :label="item - 1" :value="item - 1" />
-        </el-select>
-      </el-radio>
-    </el-form-item>
-  </el-form>
-</template>
-
-<script setup lang="ts">
-import { computed, ref, watch } from 'vue';
-
-const emit = defineEmits(['update'])
-const props = defineProps({
-  cron: {
-    type: Object,
-    default: {
-      second: '*',
-      min: '*',
-      hour: '*',
-      day: '*',
-      month: '*',
-      week: '?',
-      year: ''
-    }
-  },
-  check: {
-    type: Function,
-    default: () => {}
-  }
-})
-const radioValue = ref(1)
-const cycle01 = ref(0)
-const cycle02 = ref(1)
-const average01 = ref(0)
-const average02 = ref(1)
-const checkboxList = ref([])
-const checkCopy = ref([0])
-const cycleTotal = computed(() => {
-  cycle01.value = props.check(cycle01.value, 0, 58)
-  cycle02.value = props.check(cycle02.value, cycle01.value + 1, 59)
-  return cycle01.value + '-' + cycle02.value
-})
-const averageTotal = computed(() => {
-  average01.value = props.check(average01.value, 0, 58)
-  average02.value = props.check(average02.value, 1, 59 - average01.value)
-  return average01.value + '/' + average02.value
-})
-const checkboxString = computed(() => {
-  return checkboxList.value.join(',')
-})
-watch(
-  () => props.cron.second,
-  (value) => changeRadioValue(value)
-)
-watch([radioValue, cycleTotal, averageTotal, checkboxString], () => onRadioChange())
-function changeRadioValue(value) {
-  if (value === '*') {
-    radioValue.value = 1
-  } else if (value.indexOf('-') > -1) {
-    const indexArr = value.split('-')
-    cycle01.value = Number(indexArr[0])
-    cycle02.value = Number(indexArr[1])
-    radioValue.value = 2
-  } else if (value.indexOf('/') > -1) {
-    const indexArr = value.split('/')
-    average01.value = Number(indexArr[0])
-    average02.value = Number(indexArr[1])
-    radioValue.value = 3
-  } else {
-    checkboxList.value = [...new Set(value.split(',').map((item) => Number(item)))]
-    radioValue.value = 4
-  }
-}
-// 单选按钮值变化时
-function onRadioChange() {
-  switch (radioValue.value) {
-    case 1:
-      emit('update', 'second', '*', 'second')
-      break
-    case 2:
-      emit('update', 'second', cycleTotal.value, 'second')
-      break
-    case 3:
-      emit('update', 'second', averageTotal.value, 'second')
-      break
-    case 4:
-      if (checkboxList.value.length === 0) {
-        checkboxList.value.push(checkCopy.value[0])
-      } else {
-        checkCopy.value = checkboxList.value
-      }
-      emit('update', 'second', checkboxString.value, 'second')
-      break
-  }
-}
-</script>
-
-<style lang="scss" scoped>
-.el-input-number--small,
-.el-input-number--small,
-.el-select,
-.el-select--small {
-  margin: 0 0.2rem;
-}
-.el-select,
-.el-select--small {
-  width: 18.8rem;
-}
-</style>

+ 0 - 193
Web/src/views/system/job/component/cronTab/week.vue

@@ -1,193 +0,0 @@
-<template>
-  <el-form size="small">
-    <el-form-item>
-      <el-radio v-model="radioValue" :label="1"> 周,允许的通配符[, - * ? / L #] </el-radio>
-    </el-form-item>
-
-    <el-form-item>
-      <el-radio v-model="radioValue" :label="2"> 不指定 </el-radio>
-    </el-form-item>
-
-    <el-form-item>
-      <el-radio v-model="radioValue" :label="3">
-        周期从
-        <el-select clearable v-model="cycle01">
-          <el-option v-for="(item, index) of weekList" :key="index" :label="item.value" :value="item.key" :disabled="item.key === 7">{{
-            item.value
-          }}</el-option>
-        </el-select>
-        -
-        <el-select clearable v-model="cycle02">
-          <el-option v-for="(item, index) of weekList" :key="index" :label="item.value" :value="item.key" :disabled="item.key <= cycle01">{{
-            item.value
-          }}</el-option>
-        </el-select>
-      </el-radio>
-    </el-form-item>
-
-    <el-form-item>
-      <el-radio v-model="radioValue" :label="4">
-        第
-        <el-input-number v-model="average01" :min="1" :max="4" /> 周的
-        <el-select clearable v-model="average02">
-          <el-option v-for="item in weekList" :key="item.key" :label="item.value" :value="item.key" />
-        </el-select>
-      </el-radio>
-    </el-form-item>
-
-    <el-form-item>
-      <el-radio v-model="radioValue" :label="5">
-        本月最后一个
-        <el-select clearable v-model="weekday">
-          <el-option v-for="item in weekList" :key="item.key" :label="item.value" :value="item.key" />
-        </el-select>
-      </el-radio>
-    </el-form-item>
-
-    <el-form-item>
-      <el-radio v-model="radioValue" :label="6">
-        指定
-        <el-select class="multiselect" clearable v-model="checkboxList" placeholder="可多选" multiple :multiple-limit="6">
-          <el-option v-for="item in weekList" :key="item.key" :label="item.value" :value="item.key" />
-        </el-select>
-      </el-radio>
-    </el-form-item>
-  </el-form>
-</template>
-
-<script setup lang="ts">
-import { computed, ref, watch } from 'vue';
-
-const emit = defineEmits(['update'])
-const props = defineProps({
-  cron: {
-    type: Object,
-    default: {
-      second: '*',
-      min: '*',
-      hour: '*',
-      day: '*',
-      month: '*',
-      week: '?',
-      year: ''
-    }
-  },
-  check: {
-    type: Function,
-    default: () => {}
-  }
-})
-const radioValue = ref(2)
-const cycle01 = ref(2)
-const cycle02 = ref(3)
-const average01 = ref(1)
-const average02 = ref(2)
-const weekday = ref(2)
-const checkboxList = ref([])
-const checkCopy = ref([2])
-const weekList = ref([
-  { key: 1, value: '星期日' },
-  { key: 2, value: '星期一' },
-  { key: 3, value: '星期二' },
-  { key: 4, value: '星期三' },
-  { key: 5, value: '星期四' },
-  { key: 6, value: '星期五' },
-  { key: 7, value: '星期六' }
-])
-const cycleTotal = computed(() => {
-  cycle01.value = props.check(cycle01.value, 1, 6)
-  cycle02.value = props.check(cycle02.value, cycle01.value + 1, 7)
-  return cycle01.value + '-' + cycle02.value
-})
-const averageTotal = computed(() => {
-  average01.value = props.check(average01.value, 1, 4)
-  average02.value = props.check(average02.value, 1, 7)
-  return average02.value + '#' + average01.value
-})
-const weekdayTotal = computed(() => {
-  weekday.value = props.check(weekday.value, 1, 7)
-  return weekday.value + 'L'
-})
-const checkboxString = computed(() => {
-  return checkboxList.value.join(',')
-})
-watch(
-  () => props.cron.week,
-  (value) => changeRadioValue(value)
-)
-watch([radioValue, cycleTotal, averageTotal, weekdayTotal, checkboxString], () => onRadioChange())
-function changeRadioValue(value) {
-  if (value === '*') {
-    radioValue.value = 1
-  } else if (value === '?') {
-    radioValue.value = 2
-  } else if (value.indexOf('-') > -1) {
-    const indexArr = value.split('-')
-    cycle01.value = Number(indexArr[0])
-    cycle02.value = Number(indexArr[1])
-    radioValue.value = 3
-  } else if (value.indexOf('#') > -1) {
-    const indexArr = value.split('#')
-    average01.value = Number(indexArr[1])
-    average02.value = Number(indexArr[0])
-    radioValue.value = 4
-  } else if (value.indexOf('L') > -1) {
-    const indexArr = value.split('L')
-    weekday.value = Number(indexArr[0])
-    radioValue.value = 5
-  } else {
-    checkboxList.value = [...new Set(value.split(',').map((item) => Number(item)))]
-    radioValue.value = 6
-  }
-}
-function onRadioChange() {
-  if (radioValue.value === 2 && props.cron.day === '?') {
-    emit('update', 'day', '*', 'week')
-  }
-  if (radioValue.value !== 2 && props.cron.day !== '?') {
-    emit('update', 'day', '?', 'week')
-  }
-  switch (radioValue.value) {
-    case 1:
-      emit('update', 'week', '*', 'week')
-      break
-    case 2:
-      emit('update', 'week', '?', 'week')
-      break
-    case 3:
-      emit('update', 'week', cycleTotal.value, 'week')
-      break
-    case 4:
-      emit('update', 'week', averageTotal.value, 'week')
-      break
-    case 5:
-      emit('update', 'week', weekdayTotal.value, 'week')
-      break
-    case 6:
-      if (checkboxList.value.length === 0) {
-        checkboxList.value.push(checkCopy.value[0])
-      } else {
-        checkCopy.value = checkboxList.value
-      }
-      emit('update', 'week', checkboxString.value, 'week')
-      break
-  }
-}
-</script>
-
-<style lang="scss" scoped>
-.el-input-number--small,
-.el-input-number--small,
-.el-select,
-.el-select--small {
-  margin: 0 0.5rem;
-}
-.el-select,
-.el-select--small {
-  width: 8rem;
-}
-.el-select.multiselect,
-.el-select--small.multiselect {
-  width: 17.8rem;
-}
-</style>

+ 0 - 152
Web/src/views/system/job/component/cronTab/year.vue

@@ -1,152 +0,0 @@
-<template>
-  <el-form size="small">
-    <el-form-item>
-      <el-radio :label="1" v-model="radioValue"> 不填,允许的通配符[, - * /] </el-radio>
-    </el-form-item>
-
-    <el-form-item>
-      <el-radio :label="2" v-model="radioValue"> 每年 </el-radio>
-    </el-form-item>
-
-    <el-form-item>
-      <el-radio :label="3" v-model="radioValue">
-        周期从
-        <el-input-number v-model="cycle01" :min="fullYear" :max="maxFullYear - 1" /> -
-        <el-input-number v-model="cycle02" :min="cycle01 + 1" :max="maxFullYear" />
-      </el-radio>
-    </el-form-item>
-
-    <el-form-item>
-      <el-radio :label="4" v-model="radioValue">
-        从
-        <el-input-number v-model="average01" :min="fullYear" :max="maxFullYear - 1" /> 年开始,每
-        <el-input-number v-model="average02" :min="1" :max="10" /> 年执行一次
-      </el-radio>
-    </el-form-item>
-
-    <el-form-item>
-      <el-radio :label="5" v-model="radioValue">
-        指定
-        <el-select clearable v-model="checkboxList" placeholder="可多选" multiple :multiple-limit="8">
-          <el-option v-for="item in 9" :key="item" :value="item - 1 + fullYear" :label="item - 1 + fullYear" />
-        </el-select>
-      </el-radio>
-    </el-form-item>
-  </el-form>
-</template>
-
-<script setup lang="ts">
-import { computed, onMounted, ref, watch } from 'vue';
-
-const emit = defineEmits(['update'])
-const props = defineProps({
-  cron: {
-    type: Object,
-    default: {
-      second: '*',
-      min: '*',
-      hour: '*',
-      day: '*',
-      month: '*',
-      week: '?',
-      year: ''
-    }
-  },
-  check: {
-    type: Function,
-    default: () => {}
-  }
-})
-const fullYear = ref(0)
-const maxFullYear = ref(0)
-const radioValue = ref(1)
-const cycle01 = ref(0)
-const cycle02 = ref(0)
-const average01 = ref(0)
-const average02 = ref(1)
-const checkboxList = ref([])
-const checkCopy = ref([])
-const cycleTotal = computed(() => {
-  cycle01.value = props.check(cycle01.value, fullYear.value, maxFullYear.value - 1)
-  cycle02.value = props.check(cycle02.value, cycle01.value + 1, maxFullYear.value)
-  return cycle01.value + '-' + cycle02.value
-})
-const averageTotal = computed(() => {
-  average01.value = props.check(average01.value, fullYear.value, maxFullYear.value - 1)
-  average02.value = props.check(average02.value, 1, 10)
-  return average01.value + '/' + average02.value
-})
-const checkboxString = computed(() => {
-  return checkboxList.value.join(',')
-})
-watch(
-  () => props.cron.year,
-  (value) => changeRadioValue(value)
-)
-watch([radioValue, cycleTotal, averageTotal, checkboxString], () => onRadioChange())
-function changeRadioValue(value) {
-  if (value === '') {
-    radioValue.value = 1
-  } else if (value === '*') {
-    radioValue.value = 2
-  } else if (value.indexOf('-') > -1) {
-    const indexArr = value.split('-')
-    cycle01.value = Number(indexArr[0])
-    cycle02.value = Number(indexArr[1])
-    radioValue.value = 3
-  } else if (value.indexOf('/') > -1) {
-    const indexArr = value.split('#')
-    average01.value = Number(indexArr[1])
-    average02.value = Number(indexArr[0])
-    radioValue.value = 4
-  } else {
-    checkboxList.value = [...new Set(value.split(',').map((item) => Number(item)))]
-    radioValue.value = 5
-  }
-}
-function onRadioChange() {
-  switch (radioValue.value) {
-    case 1:
-      emit('update', 'year', '', 'year')
-      break
-    case 2:
-      emit('update', 'year', '*', 'year')
-      break
-    case 3:
-      emit('update', 'year', cycleTotal.value, 'year')
-      break
-    case 4:
-      emit('update', 'year', averageTotal.value, 'year')
-      break
-    case 5:
-      if (checkboxList.value.length === 0) {
-        checkboxList.value.push(checkCopy.value[0])
-      } else {
-        checkCopy.value = checkboxList.value
-      }
-      emit('update', 'year', checkboxString.value, 'year')
-      break
-  }
-}
-onMounted(() => {
-  fullYear.value = Number(new Date().getFullYear())
-  maxFullYear.value = fullYear.value + 10
-  cycle01.value = fullYear.value
-  cycle02.value = cycle01.value + 1
-  average01.value = fullYear.value
-  checkCopy.value = [fullYear.value]
-})
-</script>
-
-<style lang="scss" scoped>
-.el-input-number--small,
-.el-input-number--small,
-.el-select,
-.el-select--small {
-  margin: 0 0.2rem;
-}
-.el-select,
-.el-select--small {
-  width: 18.8rem;
-}
-</style>

+ 3 - 7
Web/src/views/system/job/component/editJobTrigger.vue

@@ -133,7 +133,7 @@
 					<span> Cron表达式生成器 </span>
 				</div>
 			</template>
-			<cronTab @hide="state.showCronDialog = false" @fill="crontabFill" :expression="cronValue"></cronTab>
+			<vcrontab @hide="state.showCronDialog = false" @fill="crontabFill" :expression="cronValue"></vcrontab>
 		</el-dialog>
 	</div>
 </template>
@@ -143,7 +143,8 @@ import { reactive, ref, computed } from 'vue';
 import type { WritableComputedRef } from 'vue';
 import { ElMessage } from 'element-plus';
 
-import cronTab from './cronTab/index.vue';
+import vcrontab from 'vcrontab-3';
+
 import { getAPI } from '/@/utils/axios-utils';
 import { SysJobApi } from '/@/api-services/api';
 import { UpdateJobTriggerInput } from '/@/api-services/models';
@@ -201,29 +202,24 @@ const cronValue: WritableComputedRef<string> = computed({
 		// 触发器周期不是周期,返回默认值
 		if (state.ruleForm.triggerType != 'Furion.Schedule.CronTrigger') return defaultValue;
 		if (!state.ruleForm.args) return defaultValue;
-
 		// Furion 的 cron 表达式有2个入参
 		const value = String(state.ruleForm.args);
 		const parameters = value.split(',');
 		if (parameters.length != 2) return defaultValue;
-
 		const cron = parameters[0].replace(new RegExp('"', 'gm'), '').trim();
 		return cron;
 	},
 	set(value: string) {
 		if (state.ruleForm.args == value) return;
-
 		const newValue = value.trim();
 		// 第二个参数值参阅 https://furion.baiqian.ltd/docs/cron#2624-cronstringformat-%E6%A0%BC%E5%BC%8F%E5%8C%96
 		let cronStringFormatValue = -1;
-
 		// 如果是 Macro 标识符,使用默认格式
 		if (newValue.startsWith('@')) cronStringFormatValue = 0; // 默认格式,书写顺序:分 时 天 月 周
 		else {
 			if (newValue.split(' ').length == 6) cronStringFormatValue = 2; // 带秒格式,书写顺序:秒 分 时 天 月 周
 			else cronStringFormatValue = 3; // 带秒和年格式,书写顺序:秒 分 时 天 月 周 年
 		}
-
 		state.ruleForm.args = `"${newValue}",${cronStringFormatValue}`;
 	},
 });

+ 2 - 2
Web/src/views/system/job/index.vue

@@ -51,7 +51,7 @@
 							<!-- <el-table-column prop="assemblyName" label="程序集" show-overflow-tooltip /> -->
 							<el-table-column prop="args" label="参数" header-align="center" show-overflow-tooltip />
 							<el-table-column prop="description" label="描述" width="120" header-align="center" show-overflow-tooltip />
-							<el-table-column prop="status" label="状态" width="80" align="center" show-overflow-tooltip>
+							<el-table-column prop="status" label="状态" width="120" align="center" show-overflow-tooltip>
 								<template #default="scope">
 									<el-tag type="warning" effect="plain" v-if="(scope.row as SysJobTrigger).status == 0"> 积压 </el-tag>
 									<el-tag type="" effect="plain" v-if="(scope.row as SysJobTrigger).status == 1"> 就绪 </el-tag>
@@ -148,6 +148,7 @@
 						<el-tag v-else> 否 </el-tag>
 					</template>
 				</el-table-column> -->
+				<el-table-column prop="jobDetail.updatedTime" label="更新时间" width="130" align="center" show-overflow-tooltip />
 				<el-table-column prop="jobDetail.properties" label="额外数据" header-align="center" show-overflow-tooltip>
 					<template #default="scope">
 						<span v-if="(scope.row as JobOutput).jobDetail?.createType != JobCreateTypeEnum.NUMBER_2"> {{ (scope.row as JobOutput).jobDetail?.properties }} </span>
@@ -171,7 +172,6 @@
 						</div>
 					</template>
 				</el-table-column>
-				<el-table-column prop="jobDetail.updatedTime" label="更新时间" width="130" align="center" show-overflow-tooltip />
 				<el-table-column label="操作" width="200" fixed="right" align="center" show-overflow-tooltip>
 					<template #default="scope">
 						<el-tooltip content="增加触发器">