index.vue 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430
  1. <template>
  2. <div>
  3. <el-tabs type="border-card">
  4. <el-tab-pane label="秒" v-if="shouldHide('second')">
  5. <CrontabSecond
  6. @update="updateCrontabValue"
  7. :check="checkNumber"
  8. :cron="crontabValueObj"
  9. ref="cronsecond"
  10. />
  11. </el-tab-pane>
  12. <el-tab-pane label="分钟" v-if="shouldHide('min')">
  13. <CrontabMin
  14. @update="updateCrontabValue"
  15. :check="checkNumber"
  16. :cron="crontabValueObj"
  17. ref="cronmin"
  18. />
  19. </el-tab-pane>
  20. <el-tab-pane label="小时" v-if="shouldHide('hour')">
  21. <CrontabHour
  22. @update="updateCrontabValue"
  23. :check="checkNumber"
  24. :cron="crontabValueObj"
  25. ref="cronhour"
  26. />
  27. </el-tab-pane>
  28. <el-tab-pane label="日" v-if="shouldHide('day')">
  29. <CrontabDay
  30. @update="updateCrontabValue"
  31. :check="checkNumber"
  32. :cron="crontabValueObj"
  33. ref="cronday"
  34. />
  35. </el-tab-pane>
  36. <el-tab-pane label="月" v-if="shouldHide('month')">
  37. <CrontabMonth
  38. @update="updateCrontabValue"
  39. :check="checkNumber"
  40. :cron="crontabValueObj"
  41. ref="cronmonth"
  42. />
  43. </el-tab-pane>
  44. <el-tab-pane label="周" v-if="shouldHide('week')">
  45. <CrontabWeek
  46. @update="updateCrontabValue"
  47. :check="checkNumber"
  48. :cron="crontabValueObj"
  49. ref="cronweek"
  50. />
  51. </el-tab-pane>
  52. <el-tab-pane label="年" v-if="shouldHide('year')">
  53. <CrontabYear
  54. @update="updateCrontabValue"
  55. :check="checkNumber"
  56. :cron="crontabValueObj"
  57. ref="cronyear"
  58. />
  59. </el-tab-pane>
  60. </el-tabs>
  61. <div class="popup-main">
  62. <div class="popup-result">
  63. <p class="title">时间表达式</p>
  64. <table>
  65. <thead>
  66. <th v-for="item of tabTitles" width="40" :key="item">{{item}}</th>
  67. <th>Cron 表达式</th>
  68. </thead>
  69. <tbody>
  70. <td>
  71. <span>{{crontabValueObj.second}}</span>
  72. </td>
  73. <td>
  74. <span>{{crontabValueObj.min}}</span>
  75. </td>
  76. <td>
  77. <span>{{crontabValueObj.hour}}</span>
  78. </td>
  79. <td>
  80. <span>{{crontabValueObj.day}}</span>
  81. </td>
  82. <td>
  83. <span>{{crontabValueObj.month}}</span>
  84. </td>
  85. <td>
  86. <span>{{crontabValueObj.week}}</span>
  87. </td>
  88. <td>
  89. <span>{{crontabValueObj.year}}</span>
  90. </td>
  91. <td>
  92. <span>{{crontabValueString}}</span>
  93. </td>
  94. </tbody>
  95. </table>
  96. </div>
  97. <CrontabResult :ex="crontabValueString"></CrontabResult>
  98. <div class="pop_btn">
  99. <el-button size="small" type="primary" @click="submitFill">确定</el-button>
  100. <el-button size="small" type="warning" @click="clearCron">重置</el-button>
  101. <el-button size="small" @click="hidePopup">取消</el-button>
  102. </div>
  103. </div>
  104. </div>
  105. </template>
  106. <script>
  107. import CrontabSecond from "./second.vue";
  108. import CrontabMin from "./min.vue";
  109. import CrontabHour from "./hour.vue";
  110. import CrontabDay from "./day.vue";
  111. import CrontabMonth from "./month.vue";
  112. import CrontabWeek from "./week.vue";
  113. import CrontabYear from "./year.vue";
  114. import CrontabResult from "./result.vue";
  115. export default {
  116. data() {
  117. return {
  118. tabTitles: ["秒", "分钟", "小时", "日", "月", "周", "年"],
  119. tabActive: 0,
  120. myindex: 0,
  121. crontabValueObj: {
  122. second: "*",
  123. min: "*",
  124. hour: "*",
  125. day: "*",
  126. month: "*",
  127. week: "?",
  128. year: "",
  129. },
  130. };
  131. },
  132. name: "vcrontab",
  133. props: ["expression", "hideComponent"],
  134. methods: {
  135. shouldHide(key) {
  136. return !(this.hideComponent && this.hideComponent.includes(key));
  137. },
  138. resolveExp() {
  139. // 反解析 表达式
  140. if (this.expression) {
  141. let arr = this.expression.split(" ");
  142. if (arr.length >= 6) {
  143. //6 位以上是合法表达式
  144. let obj = {
  145. second: arr[0],
  146. min: arr[1],
  147. hour: arr[2],
  148. day: arr[3],
  149. month: arr[4],
  150. week: arr[5],
  151. year: arr[6] ? arr[6] : "",
  152. };
  153. this.crontabValueObj = {
  154. ...obj,
  155. };
  156. for (let i in obj) {
  157. if (obj[i]) this.changeRadio(i, obj[i]);
  158. }
  159. }
  160. } else {
  161. // 没有传入的表达式 则还原
  162. this.clearCron();
  163. }
  164. },
  165. // tab切换值
  166. tabCheck(index) {
  167. this.tabActive = index;
  168. },
  169. // 由子组件触发,更改表达式组成的字段值
  170. updateCrontabValue(name, value, from) {
  171. "updateCrontabValue", name, value, from;
  172. this.crontabValueObj[name] = value;
  173. if (from && from !== name) {
  174. console.log(`来自组件 ${from} 改变了 ${name} ${value}`);
  175. this.changeRadio(name, value);
  176. }
  177. },
  178. // 赋值到组件
  179. changeRadio(name, value) {
  180. let arr = ["second", "min", "hour", "month"],
  181. refName = "cron" + name,
  182. insValue;
  183. if (!this.$refs[refName]) return;
  184. if (arr.includes(name)) {
  185. if (value === "*") {
  186. insValue = 1;
  187. } else if (value.indexOf("-") > -1) {
  188. let indexArr = value.split("-");
  189. isNaN(indexArr[0])
  190. ? (this.$refs[refName].cycle01 = 0)
  191. : (this.$refs[refName].cycle01 = indexArr[0]);
  192. this.$refs[refName].cycle02 = indexArr[1];
  193. insValue = 2;
  194. } else if (value.indexOf("/") > -1) {
  195. let indexArr = value.split("/");
  196. isNaN(indexArr[0])
  197. ? (this.$refs[refName].average01 = 0)
  198. : (this.$refs[refName].average01 = indexArr[0]);
  199. this.$refs[refName].average02 = indexArr[1];
  200. insValue = 3;
  201. } else {
  202. insValue = 4;
  203. this.$refs[refName].checkboxList = value.split(",");
  204. }
  205. } else if (name === "day") {
  206. if (value === "*") {
  207. insValue = 1;
  208. } else if (value === "?") {
  209. insValue = 2;
  210. } else if (value.indexOf("-") > -1) {
  211. let indexArr = value.split("-");
  212. isNaN(indexArr[0])
  213. ? (this.$refs[refName].cycle01 = 0)
  214. : (this.$refs[refName].cycle01 = indexArr[0]);
  215. this.$refs[refName].cycle02 = indexArr[1];
  216. insValue = 3;
  217. } else if (value.indexOf("/") > -1) {
  218. let indexArr = value.split("/");
  219. isNaN(indexArr[0])
  220. ? (this.$refs[refName].average01 = 0)
  221. : (this.$refs[refName].average01 = indexArr[0]);
  222. this.$refs[refName].average02 = indexArr[1];
  223. insValue = 4;
  224. } else if (value.indexOf("W") > -1) {
  225. let indexArr = value.split("W");
  226. isNaN(indexArr[0])
  227. ? (this.$refs[refName].workday = 0)
  228. : (this.$refs[refName].workday = indexArr[0]);
  229. insValue = 5;
  230. } else if (value === "L") {
  231. insValue = 6;
  232. } else {
  233. this.$refs[refName].checkboxList = value.split(",");
  234. insValue = 7;
  235. }
  236. } else if (name === "week") {
  237. if (value === "*") {
  238. insValue = 1;
  239. } else if (value === "?") {
  240. insValue = 2;
  241. } else if (value.indexOf("-") > -1) {
  242. let indexArr = value.split("-");
  243. isNaN(indexArr[0])
  244. ? (this.$refs[refName].cycle01 = 0)
  245. : (this.$refs[refName].cycle01 = indexArr[0]);
  246. this.$refs[refName].cycle02 = indexArr[1];
  247. insValue = 3;
  248. } else if (value.indexOf("#") > -1) {
  249. let indexArr = value.split("#");
  250. isNaN(indexArr[0])
  251. ? (this.$refs[refName].average01 = 1)
  252. : (this.$refs[refName].average01 = indexArr[0]);
  253. this.$refs[refName].average02 = indexArr[1];
  254. insValue = 4;
  255. } else if (value.indexOf("L") > -1) {
  256. let indexArr = value.split("L");
  257. isNaN(indexArr[0])
  258. ? (this.$refs[refName].weekday = 1)
  259. : (this.$refs[refName].weekday = indexArr[0]);
  260. insValue = 5;
  261. } else {
  262. this.$refs[refName].checkboxList = value.split(",");
  263. insValue = 6;
  264. }
  265. } else if (name === "year") {
  266. if (value === "") {
  267. insValue = 1;
  268. } else if (value === "*") {
  269. insValue = 2;
  270. } else if (value.indexOf("-") > -1) {
  271. insValue = 3;
  272. } else if (value.indexOf("/") > -1) {
  273. insValue = 4;
  274. } else {
  275. this.$refs[refName].checkboxList = value.split(",");
  276. insValue = 5;
  277. }
  278. }
  279. this.$refs[refName].radioValue = insValue;
  280. },
  281. // 表单选项的子组件校验数字格式(通过-props传递)
  282. checkNumber(value, minLimit, maxLimit) {
  283. // 检查必须为整数
  284. value = Math.floor(value);
  285. if (value < minLimit) {
  286. value = minLimit;
  287. } else if (value > maxLimit) {
  288. value = maxLimit;
  289. }
  290. return value;
  291. },
  292. // 隐藏弹窗
  293. hidePopup() {
  294. this.$emit("hide");
  295. },
  296. // 填充表达式
  297. submitFill() {
  298. this.$emit("fill", this.crontabValueString);
  299. this.hidePopup();
  300. },
  301. clearCron() {
  302. // 还原选择项
  303. ("准备还原");
  304. this.crontabValueObj = {
  305. second: "*",
  306. min: "*",
  307. hour: "*",
  308. day: "*",
  309. month: "*",
  310. week: "?",
  311. year: "",
  312. };
  313. for (let j in this.crontabValueObj) {
  314. this.changeRadio(j, this.crontabValueObj[j]);
  315. }
  316. },
  317. },
  318. computed: {
  319. crontabValueString: function() {
  320. let obj = this.crontabValueObj;
  321. let str =
  322. obj.second +
  323. " " +
  324. obj.min +
  325. " " +
  326. obj.hour +
  327. " " +
  328. obj.day +
  329. " " +
  330. obj.month +
  331. " " +
  332. obj.week +
  333. (obj.year === "" ? "" : " " + obj.year);
  334. return str;
  335. },
  336. },
  337. components: {
  338. CrontabSecond,
  339. CrontabMin,
  340. CrontabHour,
  341. CrontabDay,
  342. CrontabMonth,
  343. CrontabWeek,
  344. CrontabYear,
  345. CrontabResult,
  346. },
  347. watch: {
  348. expression: "resolveExp",
  349. hideComponent(value) {
  350. // 隐藏部分组件
  351. },
  352. },
  353. mounted: function() {
  354. this.resolveExp();
  355. },
  356. };
  357. </script>
  358. <style scoped>
  359. .pop_btn {
  360. text-align: center;
  361. margin-top: 20px;
  362. }
  363. .popup-main {
  364. position: relative;
  365. margin: 10px auto;
  366. background: #fff;
  367. border-radius: 5px;
  368. font-size: 12px;
  369. overflow: hidden;
  370. }
  371. .popup-title {
  372. overflow: hidden;
  373. line-height: 34px;
  374. padding-top: 6px;
  375. background: #f2f2f2;
  376. }
  377. .popup-result {
  378. box-sizing: border-box;
  379. line-height: 24px;
  380. margin: 25px auto;
  381. padding: 15px 10px 10px;
  382. border: 1px solid #ccc;
  383. position: relative;
  384. }
  385. .popup-result .title {
  386. position: absolute;
  387. top: -28px;
  388. left: 50%;
  389. width: 140px;
  390. font-size: 14px;
  391. margin-left: -70px;
  392. text-align: center;
  393. line-height: 30px;
  394. background: #fff;
  395. }
  396. .popup-result table {
  397. text-align: center;
  398. width: 100%;
  399. margin: 0 auto;
  400. }
  401. .popup-result table span {
  402. display: block;
  403. width: 100%;
  404. font-family: arial;
  405. line-height: 30px;
  406. height: 30px;
  407. white-space: nowrap;
  408. overflow: hidden;
  409. border: 1px solid #e8e8e8;
  410. }
  411. .popup-result-scroll {
  412. font-size: 12px;
  413. line-height: 24px;
  414. height: 10em;
  415. overflow-y: auto;
  416. }
  417. </style>