Newer
Older
KaiFengPC / src / components / Crontab / index.vue
@zhangdeliang zhangdeliang on 23 May 8 KB 初始化项目
  1. <template>
  2. <div>
  3. <el-tabs>
  4. <el-tab-pane label="秒" v-if="shouldHide('second')">
  5. <CrontabSecond @update="updateCrontabValue" :check="checkNumber" :cron="crontabValueObj" ref="cronsecond" />
  6. </el-tab-pane>
  7.  
  8. <el-tab-pane label="分钟" v-if="shouldHide('min')">
  9. <CrontabMin @update="updateCrontabValue" :check="checkNumber" :cron="crontabValueObj" ref="cronmin" />
  10. </el-tab-pane>
  11.  
  12. <el-tab-pane label="小时" v-if="shouldHide('hour')">
  13. <CrontabHour @update="updateCrontabValue" :check="checkNumber" :cron="crontabValueObj" ref="cronhour" />
  14. </el-tab-pane>
  15.  
  16. <el-tab-pane label="日" v-if="shouldHide('day')">
  17. <CrontabDay @update="updateCrontabValue" :check="checkNumber" :cron="crontabValueObj" ref="cronday" />
  18. </el-tab-pane>
  19.  
  20. <el-tab-pane label="月" v-if="shouldHide('month')">
  21. <CrontabMonth @update="updateCrontabValue" :check="checkNumber" :cron="crontabValueObj" ref="cronmonth" />
  22. </el-tab-pane>
  23.  
  24. <el-tab-pane label="周" v-if="shouldHide('week')">
  25. <CrontabWeek @update="updateCrontabValue" :check="checkNumber" :cron="crontabValueObj" ref="cronweek" />
  26. </el-tab-pane>
  27.  
  28. <el-tab-pane label="年" v-if="shouldHide('year')">
  29. <CrontabYear @update="updateCrontabValue" :check="checkNumber" :cron="crontabValueObj" ref="cronyear" />
  30. </el-tab-pane>
  31. </el-tabs>
  32.  
  33. <div class="popup-main">
  34. <div class="popup-result">
  35. <p class="title">时间表达式</p>
  36. <table>
  37. <thead>
  38. <th v-for="item of tabTitles" :key="item">{{ item }}</th>
  39. <th>Cron 表达式</th>
  40. </thead>
  41. <tbody>
  42. <td>
  43. <span v-if="crontabValueObj.second.length < 10">{{ crontabValueObj.second }}</span>
  44. <el-tooltip v-else :content="crontabValueObj.second" placement="top"
  45. ><span>{{ crontabValueObj.second }}</span></el-tooltip
  46. >
  47. </td>
  48. <td>
  49. <span v-if="crontabValueObj.min.length < 10">{{ crontabValueObj.min }}</span>
  50. <el-tooltip v-else :content="crontabValueObj.min" placement="top"
  51. ><span>{{ crontabValueObj.min }}</span></el-tooltip
  52. >
  53. </td>
  54. <td>
  55. <span v-if="crontabValueObj.hour.length < 10">{{ crontabValueObj.hour }}</span>
  56. <el-tooltip v-else :content="crontabValueObj.hour" placement="top"
  57. ><span>{{ crontabValueObj.hour }}</span></el-tooltip
  58. >
  59. </td>
  60. <td>
  61. <span v-if="crontabValueObj.day.length < 10">{{ crontabValueObj.day }}</span>
  62. <el-tooltip v-else :content="crontabValueObj.day" placement="top"
  63. ><span>{{ crontabValueObj.day }}</span></el-tooltip
  64. >
  65. </td>
  66. <td>
  67. <span v-if="crontabValueObj.month.length < 10">{{ crontabValueObj.month }}</span>
  68. <el-tooltip v-else :content="crontabValueObj.month" placement="top"
  69. ><span>{{ crontabValueObj.month }}</span></el-tooltip
  70. >
  71. </td>
  72. <td>
  73. <span v-if="crontabValueObj.week.length < 10">{{ crontabValueObj.week }}</span>
  74. <el-tooltip v-else :content="crontabValueObj.week" placement="top"
  75. ><span>{{ crontabValueObj.week }}</span></el-tooltip
  76. >
  77. </td>
  78. <td>
  79. <span v-if="crontabValueObj.year.length < 10">{{ crontabValueObj.year }}</span>
  80. <el-tooltip v-else :content="crontabValueObj.year" placement="top"
  81. ><span>{{ crontabValueObj.year }}</span></el-tooltip
  82. >
  83. </td>
  84. <td class="result">
  85. <span v-if="crontabValueString.length < 90">{{ crontabValueString }}</span>
  86. <el-tooltip v-else :content="crontabValueString" placement="top"
  87. ><span>{{ crontabValueString }}</span></el-tooltip
  88. >
  89. </td>
  90. </tbody>
  91. </table>
  92. </div>
  93. <CrontabResult :ex="crontabValueString"></CrontabResult>
  94.  
  95. <div class="pop_btn">
  96. <el-button type="primary" @click="submitFill">确定</el-button>
  97. <el-button type="warning" @click="clearCron">重置</el-button>
  98. <el-button @click="hidePopup">取消</el-button>
  99. </div>
  100. </div>
  101. </div>
  102. </template>
  103.  
  104. <script setup>
  105. import CrontabSecond from './second.vue';
  106. import CrontabMin from './min.vue';
  107. import CrontabHour from './hour.vue';
  108. import CrontabDay from './day.vue';
  109. import CrontabMonth from './month.vue';
  110. import CrontabWeek from './week.vue';
  111. import CrontabYear from './year.vue';
  112. import CrontabResult from './result.vue';
  113. const { proxy } = getCurrentInstance();
  114. const emit = defineEmits(['hide', 'fill']);
  115. const props = defineProps({
  116. hideComponent: {
  117. type: Array,
  118. default: () => [],
  119. },
  120. expression: {
  121. type: String,
  122. default: '',
  123. },
  124. });
  125. const tabTitles = ref(['秒', '分钟', '小时', '日', '月', '周', '年']);
  126. const tabActive = ref(0);
  127. const hideComponent = ref([]);
  128. const expression = ref('');
  129. const crontabValueObj = ref({
  130. second: '*',
  131. min: '*',
  132. hour: '*',
  133. day: '*',
  134. month: '*',
  135. week: '?',
  136. year: '',
  137. });
  138. const crontabValueString = computed(() => {
  139. const obj = crontabValueObj.value;
  140. return (
  141. obj.second + ' ' + obj.min + ' ' + obj.hour + ' ' + obj.day + ' ' + obj.month + ' ' + obj.week + (obj.year === '' ? '' : ' ' + obj.year)
  142. );
  143. });
  144. watch(expression, () => resolveExp());
  145. function shouldHide(key) {
  146. return !(hideComponent.value && hideComponent.value.includes(key));
  147. }
  148. function resolveExp() {
  149. // 反解析 表达式
  150. if (expression.value) {
  151. const arr = expression.value.split(/\s+/);
  152. if (arr.length >= 6) {
  153. //6 位以上是合法表达式
  154. let obj = {
  155. second: arr[0],
  156. min: arr[1],
  157. hour: arr[2],
  158. day: arr[3],
  159. month: arr[4],
  160. week: arr[5],
  161. year: arr[6] ? arr[6] : '',
  162. };
  163. crontabValueObj.value = {
  164. ...obj,
  165. };
  166. }
  167. } else {
  168. // 没有传入的表达式 则还原
  169. clearCron();
  170. }
  171. }
  172. // tab切换值
  173. function tabCheck(index) {
  174. tabActive.value = index;
  175. }
  176. // 由子组件触发,更改表达式组成的字段值
  177. function updateCrontabValue(name, value, from) {
  178. crontabValueObj.value[name] = value;
  179. }
  180. // 表单选项的子组件校验数字格式(通过-props传递)
  181. function checkNumber(value, minLimit, maxLimit) {
  182. // 检查必须为整数
  183. value = Math.floor(value);
  184. if (value < minLimit) {
  185. value = minLimit;
  186. } else if (value > maxLimit) {
  187. value = maxLimit;
  188. }
  189. return value;
  190. }
  191. // 隐藏弹窗
  192. function hidePopup() {
  193. emit('hide');
  194. }
  195. // 填充表达式
  196. function submitFill() {
  197. emit('fill', crontabValueString.value);
  198. hidePopup();
  199. }
  200. function clearCron() {
  201. // 还原选择项
  202. crontabValueObj.value = {
  203. second: '*',
  204. min: '*',
  205. hour: '*',
  206. day: '*',
  207. month: '*',
  208. week: '?',
  209. year: '',
  210. };
  211. }
  212. onMounted(() => {
  213. expression.value = props.expression;
  214. hideComponent.value = props.hideComponent;
  215. });
  216. </script>
  217.  
  218. <style lang="scss" scoped>
  219. .pop_btn {
  220. text-align: center;
  221. margin-top: 20px;
  222. }
  223. .popup-main {
  224. position: relative;
  225. margin: 10px auto;
  226. background: #fff;
  227. border-radius: 5px;
  228. font-size: 12px;
  229. overflow: hidden;
  230. }
  231. .popup-title {
  232. overflow: hidden;
  233. line-height: 34px;
  234. padding-top: 6px;
  235. background: #f2f2f2;
  236. }
  237. .popup-result {
  238. box-sizing: border-box;
  239. line-height: 24px;
  240. margin: 25px auto;
  241. padding: 15px 10px 10px;
  242. border: 1px solid #ccc;
  243. position: relative;
  244. }
  245. .popup-result .title {
  246. position: absolute;
  247. top: -28px;
  248. left: 50%;
  249. width: 140px;
  250. font-size: 14px;
  251. margin-left: -70px;
  252. text-align: center;
  253. line-height: 30px;
  254. background: #fff;
  255. }
  256. .popup-result table {
  257. text-align: center;
  258. width: 100%;
  259. margin: 0 auto;
  260. }
  261. .popup-result table td:not(.result) {
  262. width: 3.5rem;
  263. min-width: 3.5rem;
  264. max-width: 3.5rem;
  265. }
  266. .popup-result table span {
  267. display: block;
  268. width: 100%;
  269. font-family: arial;
  270. line-height: 30px;
  271. height: 30px;
  272. white-space: nowrap;
  273. overflow: hidden;
  274. border: 1px solid #e8e8e8;
  275. }
  276. .popup-result-scroll {
  277. font-size: 12px;
  278. line-height: 24px;
  279. height: 10em;
  280. overflow-y: auto;
  281. }
  282. </style>