time.tsx 8.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297
  1. /*
  2. * Licensed to the Apache Software Foundation (ASF) under one or more
  3. * contributor license agreements. See the NOTICE file distributed with
  4. * this work for additional information regarding copyright ownership.
  5. * The ASF licenses this file to You under the Apache License, Version 2.0
  6. * (the "License"); you may not use this file except in compliance with
  7. * the License. You may obtain a copy of the License at
  8. *
  9. * http://www.apache.org/licenses/LICENSE-2.0
  10. *
  11. * Unless required by applicable law or agreed to in writing, software
  12. * distributed under the License is distributed on an "AS IS" BASIS,
  13. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  14. * See the License for the specific language governing permissions and
  15. * limitations under the License.
  16. */
  17. import _ from 'lodash'
  18. import { defineComponent, onMounted, PropType, ref, toRefs, watch } from 'vue'
  19. import { NInputNumber, NRadio, NRadioGroup, NSelect } from 'naive-ui'
  20. import { useI18n } from 'vue-i18n'
  21. import { ICrontabI18n } from '../types'
  22. import { isStr } from '../common'
  23. import styles from '../index.module.scss'
  24. const props = {
  25. timeValue: {
  26. type: String as PropType<string>,
  27. default: '*'
  28. },
  29. timeI18n: {
  30. type: Object as PropType<ICrontabI18n>,
  31. require: true
  32. }
  33. }
  34. export default defineComponent({
  35. name: 'CrontabTime',
  36. props,
  37. emits: ['update:timeValue'],
  38. setup(props, ctx) {
  39. const options = Array.from({ length: 60 }, (x, i) => ({
  40. label: i.toString(),
  41. value: i
  42. }))
  43. const timeRef = ref()
  44. const radioRef = ref()
  45. const intervalStartRef = ref(0)
  46. const intervalPerformRef = ref(0)
  47. const specificTimesRef = ref<Array<number>>([])
  48. const cycleStartRef = ref(0)
  49. const cycleEndRef = ref(0)
  50. /**
  51. * Parse parameter value
  52. */
  53. const analyticalValue = () => {
  54. const $timeVal = props.timeValue
  55. // Interval time
  56. const $interval = isStr($timeVal, '/')
  57. // Specific time
  58. const $specific = isStr($timeVal, ',')
  59. // Cycle time
  60. const $cycle = isStr($timeVal, '-')
  61. // Every time
  62. if ($timeVal === '*') {
  63. radioRef.value = 'everyTime'
  64. timeRef.value = '*'
  65. return
  66. }
  67. // Positive integer (times)
  68. if (
  69. ($timeVal.length === 1 && _.isInteger(parseInt($timeVal))) ||
  70. ($timeVal.length === 2 && _.isInteger(parseInt($timeVal)))
  71. ) {
  72. radioRef.value = 'specificTime'
  73. specificTimesRef.value = [parseInt($timeVal)]
  74. return
  75. }
  76. // Interval times
  77. if ($interval) {
  78. radioRef.value = 'intervalTime'
  79. intervalStartRef.value = parseInt($interval[0])
  80. intervalPerformRef.value = parseInt($interval[1])
  81. timeRef.value = `${intervalStartRef.value}/${intervalPerformRef.value}`
  82. return
  83. }
  84. // Specific times
  85. if ($specific) {
  86. radioRef.value = 'specificTime'
  87. specificTimesRef.value = $specific.map((item) => parseInt(item))
  88. return
  89. }
  90. // Cycle time
  91. if ($cycle) {
  92. radioRef.value = 'cycleTime'
  93. cycleStartRef.value = parseInt($cycle[0])
  94. cycleEndRef.value = parseInt($cycle[1])
  95. timeRef.value = `${cycleStartRef.value}-${cycleEndRef.value}`
  96. return
  97. }
  98. }
  99. // Interval start time(1)
  100. const onIntervalStart = (value: number | null) => {
  101. intervalStartRef.value = value || 0
  102. if (radioRef.value === 'intervalTime') {
  103. timeRef.value = `${intervalStartRef.value}/${intervalPerformRef.value}`
  104. }
  105. }
  106. // Interval execution time(2)
  107. const onIntervalPerform = (value: number | null) => {
  108. intervalPerformRef.value = value || 0
  109. if (radioRef.value === 'intervalTime') {
  110. timeRef.value = `${intervalStartRef.value}/${intervalPerformRef.value}`
  111. }
  112. }
  113. // Specific time
  114. const onSpecificTimes = (arr: Array<number>) => {
  115. specificTimesRef.value = arr
  116. if (radioRef.value === 'specificTime') {
  117. specificReset()
  118. }
  119. }
  120. // Cycle start value
  121. const onCycleStart = (value: number | null) => {
  122. cycleStartRef.value = value || 0
  123. if (radioRef.value === 'cycleTime') {
  124. timeRef.value = `${cycleStartRef.value}-${cycleEndRef.value}`
  125. }
  126. }
  127. // Cycle end value
  128. const onCycleEnd = (value: number | null) => {
  129. cycleEndRef.value = value || 0
  130. if (radioRef.value === 'cycleTime') {
  131. timeRef.value = `${cycleStartRef.value}-${cycleEndRef.value}`
  132. }
  133. }
  134. // Reset every time
  135. const everyReset = () => {
  136. timeRef.value = '*'
  137. }
  138. // Reset interval time
  139. const intervalReset = () => {
  140. timeRef.value = `${intervalStartRef.value}/${intervalPerformRef.value}`
  141. }
  142. // Reset specific time
  143. const specificReset = () => {
  144. let timeValue = '*'
  145. if (specificTimesRef.value.length) {
  146. timeValue = specificTimesRef.value.join(',')
  147. }
  148. timeRef.value = timeValue
  149. }
  150. // Reset cycle time
  151. const cycleReset = () => {
  152. timeRef.value = `${cycleStartRef.value}-${cycleEndRef.value}`
  153. }
  154. const updateRadioTime = (value: string) => {
  155. switch (value) {
  156. case 'everyTime':
  157. everyReset()
  158. break
  159. case 'intervalTime':
  160. intervalReset()
  161. break
  162. case 'specificTime':
  163. specificReset()
  164. break
  165. case 'cycleTime':
  166. cycleReset()
  167. break
  168. }
  169. }
  170. watch(
  171. () => timeRef.value,
  172. () => ctx.emit('update:timeValue', timeRef.value.toString())
  173. )
  174. onMounted(() => analyticalValue())
  175. return {
  176. options,
  177. radioRef,
  178. intervalStartRef,
  179. intervalPerformRef,
  180. specificTimesRef,
  181. cycleStartRef,
  182. cycleEndRef,
  183. updateRadioTime,
  184. onIntervalStart,
  185. onIntervalPerform,
  186. onSpecificTimes,
  187. onCycleStart,
  188. onCycleEnd,
  189. ...toRefs(props)
  190. }
  191. },
  192. render() {
  193. const { t } = useI18n()
  194. return (
  195. <NRadioGroup
  196. v-model:value={this.radioRef}
  197. onUpdateValue={this.updateRadioTime}
  198. >
  199. <NRadio class={styles['crontab-list']} value={'everyTime'}>
  200. <div class={styles['crontab-list-item']}>
  201. <div>{t(this.timeI18n!.everyTime)}</div>
  202. </div>
  203. </NRadio>
  204. <NRadio class={styles['crontab-list']} value={'intervalTime'}>
  205. <div class={styles['crontab-list-item']}>
  206. <div class={styles['item-text']}>{t(this.timeI18n!.every)}</div>
  207. <div class={styles['number-input']}>
  208. <NInputNumber
  209. defaultValue={0}
  210. min={0}
  211. max={59}
  212. v-model:value={this.intervalStartRef}
  213. onUpdateValue={this.onIntervalStart}
  214. />
  215. </div>
  216. <div class={styles['item-text']}>
  217. {t(this.timeI18n!.timeCarriedOut)}
  218. </div>
  219. <div class={styles['number-input']}>
  220. <NInputNumber
  221. defaultValue={0}
  222. min={0}
  223. max={59}
  224. v-model:value={this.intervalPerformRef}
  225. onUpdateValue={this.onIntervalPerform}
  226. />
  227. </div>
  228. <div class={styles['item-text']}>{t(this.timeI18n!.timeStart)}</div>
  229. </div>
  230. </NRadio>
  231. <NRadio class={styles['crontab-list']} value={'specificTime'}>
  232. <div class={styles['crontab-list-item']}>
  233. <div>{t(this.timeI18n!.specificTime)}</div>
  234. <div class={styles['select-input']}>
  235. <NSelect
  236. multiple
  237. options={this.options}
  238. placeholder={t(this.timeI18n!.specificTimeTip)}
  239. v-model:value={this.specificTimesRef}
  240. onUpdateValue={this.onSpecificTimes}
  241. />
  242. </div>
  243. </div>
  244. </NRadio>
  245. <NRadio class={styles['crontab-list']} value={'cycleTime'}>
  246. <div class={styles['crontab-list-item']}>
  247. <div>{t(this.timeI18n!.cycleFrom)}</div>
  248. <div class={styles['number-input']}>
  249. <NInputNumber
  250. defaultValue={0}
  251. min={0}
  252. max={59}
  253. v-model:value={this.cycleStartRef}
  254. onUpdateValue={this.onCycleStart}
  255. />
  256. </div>
  257. <div>{t(this.timeI18n!.to)}</div>
  258. <div class={styles['number-input']}>
  259. <NInputNumber
  260. defaultValue={0}
  261. min={0}
  262. max={59}
  263. v-model:value={this.cycleEndRef}
  264. onUpdateValue={this.onCycleEnd}
  265. />
  266. </div>
  267. <div>{t(this.timeI18n!.time)}</div>
  268. </div>
  269. </NRadio>
  270. </NRadioGroup>
  271. )
  272. }
  273. })