lj-calendar.vue 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443
  1. <template>
  2. <section class="wh_container">
  3. <div class="wh_content_all">
  4. <!--月份选择器-->
  5. <div class="wh_top_changge" v-if="!monthTopHide">
  6. <li @click="PreMonth(myDate,false)">
  7. <div class="wh_jiantou1"></div>
  8. </li>
  9. <li class="wh_content_li">{{dateTop}}</li>
  10. <li @click="NextMonth(myDate,false)">
  11. <div class="wh_jiantou2"></div>
  12. </li>
  13. </div>
  14. <!--标题:星期几-->
  15. <div class="wh_content">
  16. <div class="wh_content_item" v-for="tag in textTop">
  17. <div class="wh_top_tag" :style="{color:(tag === '六' || tag === '日')? '#ff9800':'#757575'}">
  18. {{tag}}
  19. </div>
  20. </div>
  21. </div>
  22. <!--内容-->
  23. <div class="wh_content">
  24. <div class="wh_content_item" v-for="(item,index) in list" @click="clickDay(item,index)">
  25. <div
  26. class="wh_item_date"
  27. v-bind:class="[{ wh_isMark: item.isMark},{wh_other_dayhide:item.otherMonth!=='nowMonth'},{wh_want_dayhide:item.dayHide},{wh_isToday:item.isToday},{wh_chose_day:item.chooseDay},{wh_isNotify:item.isNotify},setClass(item)]"
  28. >{{item.id}}
  29. </div>
  30. </div>
  31. </div>
  32. </div>
  33. </section>
  34. </template>
  35. <script>
  36. import timeUtil from "./lj-time-util";
  37. export default {
  38. name: "lj-calendar",
  39. props: {
  40. markDate: {
  41. type: Array,
  42. default: () => []
  43. },
  44. markDateMore: {
  45. type: Array,
  46. default: () => []
  47. },
  48. textTop: {
  49. type: Array,
  50. default: () => ["一", "二", "三", "四", "五", "六", "日"]
  51. },
  52. sundayStart: {
  53. type: Boolean,
  54. default: () => false
  55. },
  56. agoDayHide: {
  57. type: String,
  58. default: `0`
  59. },
  60. futureDayHide: {
  61. type: String,
  62. default: `2554387200`
  63. },
  64. monthTopHide: {//隐藏顶部月份选择
  65. type: Boolean,
  66. default: false
  67. },
  68. range: {
  69. // 时间范围,包括开始时间与结束时间。开始时间必须是周一,结束时间必须是周日
  70. type: Array
  71. },
  72. value: {}
  73. },
  74. data() {
  75. return {
  76. myDate: [],
  77. list: [],
  78. historyChose: [],
  79. dateTop: "",
  80. currentValue: undefined
  81. };
  82. },
  83. created() {
  84. this.intStart();
  85. if (this.value) {
  86. this.myDate = new Date(this.value);
  87. } else {
  88. this.myDate = new Date();
  89. }
  90. },
  91. mounted() {
  92. this.getList(this.myDate, timeUtil.dateFormat(this.myDate));
  93. },
  94. methods: {
  95. intStart() {
  96. timeUtil.sundayStart = this.sundayStart;
  97. },
  98. setClass(data) {
  99. let obj = {};
  100. obj[data.markClassName] = data.markClassName;
  101. return obj;
  102. },
  103. clickDay: function (item, index) {
  104. if (item.otherMonth === "nowMonth" && !item.dayHide) {
  105. this.getList(this.myDate, item.date);
  106. }
  107. if (item.otherMonth !== "nowMonth") {
  108. item.otherMonth === "preMonth"
  109. ? this.PreMonth(item.date)
  110. : this.NextMonth(item.date);
  111. }
  112. },
  113. ChoseMonth: function (date, isChosedDay = true) {
  114. date = timeUtil.dateFormat(date);
  115. this.myDate = new Date(date);
  116. this.$emit("changeMonth", timeUtil.dateFormat(this.myDate));
  117. if (isChosedDay) {
  118. this.getList(this.myDate, date, isChosedDay);
  119. } else {
  120. this.getList(this.myDate);
  121. }
  122. },
  123. PreMonth: function (date, isChosedDay = true) {
  124. date = timeUtil.dateFormat(date);
  125. this.myDate = timeUtil.getOtherMonth(this.myDate, "preMonth");
  126. this.$emit("changeMonth", timeUtil.dateFormat(this.myDate));
  127. if (isChosedDay) {
  128. this.getList(this.myDate, date, isChosedDay);
  129. } else {
  130. this.getList(this.myDate);
  131. }
  132. },
  133. NextMonth: function (date, isChosedDay = true) {
  134. date = timeUtil.dateFormat(date);
  135. this.myDate = timeUtil.getOtherMonth(this.myDate, "nextMonth");
  136. this.$emit("changeMonth", timeUtil.dateFormat(this.myDate));
  137. if (isChosedDay) {
  138. this.getList(this.myDate, date, isChosedDay);
  139. } else {
  140. this.getList(this.myDate);
  141. }
  142. },
  143. forMatArgs: function () {
  144. let markDate = this.markDate;
  145. let markDateMore = this.markDateMore;
  146. markDate = markDate.map(k => {
  147. return timeUtil.dateFormat(k);
  148. });
  149. markDateMore = markDateMore.map(k => {
  150. k.date = timeUtil.dateFormat(k.date);
  151. return k;
  152. });
  153. return [markDate, markDateMore];
  154. },
  155. getList: function (date, chooseDay, isChosedDay = true) {
  156. if (chooseDay) {
  157. this.handleChooseDayChanged(chooseDay);
  158. }
  159. console.log(this.currentValue);
  160. const [markDate, markDateMore] = this.forMatArgs();
  161. this.dateTop = `${date.getFullYear()}年${date.getMonth() + 1}月`;
  162. let arr = timeUtil.getMonthList(this.myDate);
  163. let filtedArr = [];
  164. let startDay = this.range && this.range[0] ? new Date(timeUtil.dateFormat(this.range[0])) : undefined;
  165. let endDay = this.range && this.range[1] ? new Date(timeUtil.dateFormat(this.range[1])) : undefined;
  166. if (this.sundayStart) {
  167. if (startDay && startDay.getDay() !== 0) {
  168. console.error("lj-calendar:开始日期必须为星期天");
  169. return;
  170. }
  171. if (endDay && endDay.getDay() !== 6) {
  172. console.error("lj-calendar:结束日期必须为星期六");
  173. return;
  174. }
  175. } else {
  176. if (startDay && startDay.getDay() !== 1) {
  177. console.error("lj-calendar:开始日期必须为星期一");
  178. return;
  179. }
  180. if (endDay && endDay.getDay() !== 0) {
  181. console.error("lj-calendar:结束日期必须为星期天");
  182. return;
  183. }
  184. }
  185. for (let i = 0; i < arr.length; i++) {
  186. let markClassName = "";
  187. let k = arr[i];
  188. k.chooseDay = false;
  189. const nowTime = k.date;
  190. let dateObject = new Date(nowTime);
  191. if (startDay && dateObject < startDay) {
  192. continue;
  193. }
  194. if (endDay && endDay < dateObject) {
  195. continue;
  196. }
  197. const t = new Date(nowTime).getTime() / 1000;
  198. //看每一天的class
  199. for (const c of markDateMore) {
  200. if (c.date === nowTime) {
  201. markClassName = c.className || "";
  202. }
  203. }
  204. //标记选中某些天 设置class
  205. k.markClassName = markClassName;
  206. k.isMark = markDate.indexOf(nowTime) > -1;
  207. //无法选中某天
  208. k.dayHide = t < this.agoDayHide || t > this.futureDayHide;
  209. if (k.isToday) {
  210. this.$emit("isToday", nowTime);
  211. }
  212. let flag = !k.dayHide && k.otherMonth === "nowMonth";
  213. if (chooseDay && chooseDay === nowTime && flag) {
  214. this.$emit("choseDay", nowTime);
  215. this.historyChose.push(nowTime);
  216. k.chooseDay = true;
  217. } else if (
  218. this.historyChose[this.historyChose.length - 1] === nowTime &&
  219. !chooseDay &&
  220. flag
  221. ) {
  222. k.chooseDay = true;
  223. }
  224. filtedArr.push(k)
  225. }
  226. this.list = filtedArr;
  227. this.$emit("display-range-changed", {
  228. startDay: this.list[0].date,
  229. endDay: this.list[this.list.length - 1].date,
  230. list: this.list // 获得日对象,可设置isNotify
  231. });
  232. },
  233. handleChooseDayChanged(chooseDay) {
  234. let newValue = new Date(chooseDay);
  235. if (!this.currentValue || this.currentValue.toString() !== newValue.toString()) {
  236. this.currentValue = newValue;
  237. this.$emit('input', this.currentValue);
  238. this.$emit('change', this.currentValue);
  239. }
  240. }
  241. },
  242. watch: {
  243. value: {
  244. handler(val, oldVal) {
  245. if (val !== oldVal && val !== this.currentValue) {
  246. this.currentValue = val;
  247. this.getList(this.myDate, timeUtil.dateFormat(this.currentValue));
  248. }
  249. },
  250. deep: true
  251. },
  252. range: {
  253. handler(val, oldVal) {
  254. console.log("range changed");
  255. this.getList(this.myDate, timeUtil.dateFormat(this.currentValue));
  256. },
  257. deep: true
  258. },
  259. markDate: {
  260. handler(val, oldVal) {
  261. this.getList(this.myDate);
  262. },
  263. deep: true
  264. },
  265. markDateMore: {
  266. handler(val, oldVal) {
  267. this.getList(this.myDate);
  268. },
  269. deep: true
  270. },
  271. agoDayHide: {
  272. handler(val, oldVal) {
  273. this.getList(this.myDate);
  274. },
  275. deep: true
  276. },
  277. futureDayHide: {
  278. handler(val, oldVal) {
  279. this.getList(this.myDate);
  280. },
  281. deep: true
  282. },
  283. sundayStart: {
  284. handler(val, oldVal) {
  285. this.intStart();
  286. this.getList(this.myDate);
  287. },
  288. deep: true
  289. }
  290. }
  291. };
  292. </script>
  293. <style scoped>
  294. @media screen and (min-width: 460px) {
  295. .wh_item_date:hover {
  296. background: #71c7a5;
  297. cursor: pointer;
  298. }
  299. }
  300. * {
  301. margin: 0;
  302. padding: 0;
  303. }
  304. .wh_container {
  305. max-width: 410px;
  306. margin: auto;
  307. }
  308. li {
  309. list-style-type: none;
  310. }
  311. .wh_top_changge {
  312. display: flex;
  313. }
  314. .wh_top_changge li {
  315. cursor: pointer;
  316. display: flex;
  317. color: #000;
  318. font-size: 18px;
  319. flex: 1;
  320. justify-content: center;
  321. align-items: center;
  322. height: 47px;
  323. }
  324. .wh_top_changge .wh_content_li {
  325. cursor: auto;
  326. flex: 2.5;
  327. }
  328. .wh_content_all {
  329. font-family: -apple-system, BlinkMacSystemFont, "PingFang SC",
  330. "Helvetica Neue", STHeiti, "Microsoft Yahei", Tahoma, Simsun, sans-serif;
  331. background-color: #ffffff;
  332. width: 100%;
  333. overflow: hidden;
  334. padding-bottom: 8px;
  335. }
  336. .wh_content {
  337. display: flex;
  338. flex-wrap: wrap;
  339. padding: 0 3% 0 3%;
  340. width: 100%;
  341. justify-content: center;
  342. align-items: center;
  343. }
  344. .wh_content:first-child .wh_content_item_tag,
  345. .wh_content:first-child .wh_content_item {
  346. color: #ddd;
  347. font-size: 16px;
  348. }
  349. .wh_content_item, wh_content_item_tag {
  350. font-size: 15px;
  351. width: 13.4%;
  352. text-align: center;
  353. color: #000000;
  354. position: relative;
  355. }
  356. .wh_content_item {
  357. height: 40px;
  358. }
  359. .wh_top_tag {
  360. width: 40px;
  361. height: 40px;
  362. line-height: 40px;
  363. margin: auto;
  364. display: flex;
  365. justify-content: center;
  366. align-items: center;
  367. }
  368. .wh_item_date {
  369. width: 40px;
  370. height: 40px;
  371. line-height: 40px;
  372. margin: auto;
  373. display: flex;
  374. justify-content: center;
  375. align-items: center;
  376. }
  377. .wh_jiantou1 {
  378. width: 12px;
  379. height: 12px;
  380. border-top: 2px solid #000000;
  381. border-left: 2px solid #000000;
  382. transform: rotate(-45deg);
  383. }
  384. .wh_jiantou1:active,
  385. .wh_jiantou2:active {
  386. border-color: #ddd;
  387. }
  388. .wh_jiantou2 {
  389. width: 12px;
  390. height: 12px;
  391. border-top: 2px solid #000000;
  392. border-right: 2px solid #000000;
  393. transform: rotate(45deg);
  394. }
  395. .wh_content_item > .wh_isMark {
  396. margin: auto;
  397. border-radius: 100px;
  398. background: #42a5f5;
  399. z-index: 2;
  400. }
  401. .wh_content_item .wh_other_dayhide {
  402. color: #bfbfbf;
  403. }
  404. .wh_content_item .wh_want_dayhide {
  405. color: #bfbfbf;
  406. }
  407. .wh_content_item .wh_isToday {
  408. color: #26a69a;
  409. /*background: #fff176;*/
  410. border-radius: 100px;
  411. }
  412. .wh_content_item .wh_chose_day {
  413. background: #42a5f5;
  414. border-radius: 100px;
  415. color: #ffffff !important;
  416. }
  417. .wh_content_item .wh_isNotify {
  418. text-decoration: underline;
  419. }
  420. </style>