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. if (this.hideComponent && this.hideComponent.includes(key)) return false;
  137. return true;
  138. },
  139. resolveExp() {
  140. // 反解析 表达式
  141. if (this.expression) {
  142. let arr = this.expression.split(" ");
  143. if (arr.length >= 6) {
  144. //6 位以上是合法表达式
  145. let obj = {
  146. second: arr[0],
  147. min: arr[1],
  148. hour: arr[2],
  149. day: arr[3],
  150. month: arr[4],
  151. week: arr[5],
  152. year: arr[6] ? arr[6] : "",
  153. };
  154. this.crontabValueObj = {
  155. ...obj,
  156. };
  157. for (let i in obj) {
  158. if (obj[i]) this.changeRadio(i, obj[i]);
  159. }
  160. }
  161. } else {
  162. // 没有传入的表达式 则还原
  163. this.clearCron();
  164. }
  165. },
  166. // tab切换值
  167. tabCheck(index) {
  168. this.tabActive = index;
  169. },
  170. // 由子组件触发,更改表达式组成的字段值
  171. updateCrontabValue(name, value, from) {
  172. "updateCrontabValue", name, value, from;
  173. this.crontabValueObj[name] = value;
  174. if (from && from !== name) {
  175. console.log(`来自组件 ${from} 改变了 ${name} ${value}`);
  176. this.changeRadio(name, value);
  177. }
  178. },
  179. // 赋值到组件
  180. changeRadio(name, value) {
  181. let arr = ["second", "min", "hour", "month"],
  182. refName = "cron" + name,
  183. insValue;
  184. if (!this.$refs[refName]) return;
  185. if (arr.includes(name)) {
  186. if (value === "*") {
  187. insValue = 1;
  188. } else if (value.indexOf("-") > -1) {
  189. let indexArr = value.split("-");
  190. isNaN(indexArr[0])
  191. ? (this.$refs[refName].cycle01 = 0)
  192. : (this.$refs[refName].cycle01 = indexArr[0]);
  193. this.$refs[refName].cycle02 = indexArr[1];
  194. insValue = 2;
  195. } else if (value.indexOf("/") > -1) {
  196. let indexArr = value.split("/");
  197. isNaN(indexArr[0])
  198. ? (this.$refs[refName].average01 = 0)
  199. : (this.$refs[refName].average01 = indexArr[0]);
  200. this.$refs[refName].average02 = indexArr[1];
  201. insValue = 3;
  202. } else {
  203. insValue = 4;
  204. this.$refs[refName].checkboxList = value.split(",");
  205. }
  206. } else if (name == "day") {
  207. if (value === "*") {
  208. insValue = 1;
  209. } else if (value == "?") {
  210. insValue = 2;
  211. } else if (value.indexOf("-") > -1) {
  212. let indexArr = value.split("-");
  213. isNaN(indexArr[0])
  214. ? (this.$refs[refName].cycle01 = 0)
  215. : (this.$refs[refName].cycle01 = indexArr[0]);
  216. this.$refs[refName].cycle02 = indexArr[1];
  217. insValue = 3;
  218. } else if (value.indexOf("/") > -1) {
  219. let indexArr = value.split("/");
  220. isNaN(indexArr[0])
  221. ? (this.$refs[refName].average01 = 0)
  222. : (this.$refs[refName].average01 = indexArr[0]);
  223. this.$refs[refName].average02 = indexArr[1];
  224. insValue = 4;
  225. } else if (value.indexOf("W") > -1) {
  226. let indexArr = value.split("W");
  227. isNaN(indexArr[0])
  228. ? (this.$refs[refName].workday = 0)
  229. : (this.$refs[refName].workday = indexArr[0]);
  230. insValue = 5;
  231. } else if (value === "L") {
  232. insValue = 6;
  233. } else {
  234. this.$refs[refName].checkboxList = value.split(",");
  235. insValue = 7;
  236. }
  237. } else if (name == "week") {
  238. if (value === "*") {
  239. insValue = 1;
  240. } else if (value == "?") {
  241. insValue = 2;
  242. } else if (value.indexOf("-") > -1) {
  243. let indexArr = value.split("-");
  244. isNaN(indexArr[0])
  245. ? (this.$refs[refName].cycle01 = 0)
  246. : (this.$refs[refName].cycle01 = indexArr[0]);
  247. this.$refs[refName].cycle02 = indexArr[1];
  248. insValue = 3;
  249. } else if (value.indexOf("#") > -1) {
  250. let indexArr = value.split("#");
  251. isNaN(indexArr[0])
  252. ? (this.$refs[refName].average01 = 1)
  253. : (this.$refs[refName].average01 = indexArr[0]);
  254. this.$refs[refName].average02 = indexArr[1];
  255. insValue = 4;
  256. } else if (value.indexOf("L") > -1) {
  257. let indexArr = value.split("L");
  258. isNaN(indexArr[0])
  259. ? (this.$refs[refName].weekday = 1)
  260. : (this.$refs[refName].weekday = indexArr[0]);
  261. insValue = 5;
  262. } else {
  263. this.$refs[refName].checkboxList = value.split(",");
  264. insValue = 7;
  265. }
  266. } else if (name == "year") {
  267. if (value == "") {
  268. insValue = 1;
  269. } else if (value == "*") {
  270. insValue = 2;
  271. } else if (value.indexOf("-") > -1) {
  272. insValue = 3;
  273. } else if (value.indexOf("/") > -1) {
  274. insValue = 4;
  275. } else {
  276. this.$refs[refName].checkboxList = value.split(",");
  277. insValue = 5;
  278. }
  279. }
  280. this.$refs[refName].radioValue = insValue;
  281. },
  282. // 表单选项的子组件校验数字格式(通过-props传递)
  283. checkNumber(value, minLimit, maxLimit) {
  284. // 检查必须为整数
  285. value = Math.floor(value);
  286. if (value < minLimit) {
  287. value = minLimit;
  288. } else if (value > maxLimit) {
  289. value = maxLimit;
  290. }
  291. return value;
  292. },
  293. // 隐藏弹窗
  294. hidePopup() {
  295. this.$emit("hide");
  296. },
  297. // 填充表达式
  298. submitFill() {
  299. this.$emit("fill", this.crontabValueString);
  300. this.hidePopup();
  301. },
  302. clearCron() {
  303. // 还原选择项
  304. ("准备还原");
  305. this.crontabValueObj = {
  306. second: "*",
  307. min: "*",
  308. hour: "*",
  309. day: "*",
  310. month: "*",
  311. week: "?",
  312. year: "",
  313. };
  314. for (let j in this.crontabValueObj) {
  315. this.changeRadio(j, this.crontabValueObj[j]);
  316. }
  317. },
  318. },
  319. computed: {
  320. crontabValueString: function() {
  321. let obj = this.crontabValueObj;
  322. let str =
  323. obj.second +
  324. " " +
  325. obj.min +
  326. " " +
  327. obj.hour +
  328. " " +
  329. obj.day +
  330. " " +
  331. obj.month +
  332. " " +
  333. obj.week +
  334. (obj.year == "" ? "" : " " + obj.year);
  335. return str;
  336. },
  337. },
  338. components: {
  339. CrontabSecond,
  340. CrontabMin,
  341. CrontabHour,
  342. CrontabDay,
  343. CrontabMonth,
  344. CrontabWeek,
  345. CrontabYear,
  346. CrontabResult,
  347. },
  348. watch: {
  349. expression: "resolveExp",
  350. hideComponent(value) {
  351. // 隐藏部分组件
  352. },
  353. },
  354. mounted: function() {
  355. this.resolveExp();
  356. },
  357. };
  358. </script>
  359. <style scoped>
  360. .pop_btn {
  361. text-align: center;
  362. margin-top: 20px;
  363. }
  364. .popup-main {
  365. position: relative;
  366. margin: 10px auto;
  367. background: #fff;
  368. border-radius: 5px;
  369. font-size: 12px;
  370. overflow: hidden;
  371. }
  372. .popup-title {
  373. overflow: hidden;
  374. line-height: 34px;
  375. padding-top: 6px;
  376. background: #f2f2f2;
  377. }
  378. .popup-result {
  379. box-sizing: border-box;
  380. line-height: 24px;
  381. margin: 25px auto;
  382. padding: 15px 10px 10px;
  383. border: 1px solid #ccc;
  384. position: relative;
  385. }
  386. .popup-result .title {
  387. position: absolute;
  388. top: -28px;
  389. left: 50%;
  390. width: 140px;
  391. font-size: 14px;
  392. margin-left: -70px;
  393. text-align: center;
  394. line-height: 30px;
  395. background: #fff;
  396. }
  397. .popup-result table {
  398. text-align: center;
  399. width: 100%;
  400. margin: 0 auto;
  401. }
  402. .popup-result table span {
  403. display: block;
  404. width: 100%;
  405. font-family: arial;
  406. line-height: 30px;
  407. height: 30px;
  408. white-space: nowrap;
  409. overflow: hidden;
  410. border: 1px solid #e8e8e8;
  411. }
  412. .popup-result-scroll {
  413. font-size: 12px;
  414. line-height: 24px;
  415. height: 10em;
  416. overflow-y: auto;
  417. }
  418. </style>