lx-calendar.vue 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691
  1. <template>
  2. <view class="date">
  3. <view class="head">
  4. <view class="icon" @click="switch_month_week('prev',true)"><text class="iconfont icon-fanhui" :class="[disabled_goto_prev() ? 'month_disabled' : '']" /></view>
  5. <view class="title">{{nowYear+'年'+nowMonth+'月'}}</view>
  6. <view class="icon" @click="switch_month_week('next',true)"><text class="iconfont next icon-fanhui" :class="[disabled_goto_next() ? 'month_disabled' : '']" /></view>
  7. </view>
  8. <view class="date_dl" >
  9. <view class="dd" v-for="(item,index) in week" :key="index">{{item}}</view>
  10. </view>
  11. <swiper :style="{height:(retract ? 2 * 80 : (week_list.length + 1) * 80 ) + 'rpx'}" :current="current" @change="change_date">
  12. <swiper-item>
  13. <view class="date_dl" v-show="!retract || index == to_week_index" v-for="(item,index) in week_list" :key="index">
  14. <view class="dd" @click="item_click(vo,index,key)" v-for="(vo,key) in item" :key="key">
  15. <!-- <view class="num" :class="[vo.today ? 'today' : '',vo.type == 'month' ? 'month' : (retract ? '' : 'disabled')]">{{vo.day}}</view> -->
  16. <view class="num" :class="[vo.today ? 'today' : '', vo.dot ? '' : 'disabled']">{{vo.day}}</view>
  17. <view v-show="vo.dot && (vo.type == 'month' || retract)" class="dot"></view>
  18. </view>
  19. </view>
  20. <view @click="open" class="retract icon" v-show="false"><text class="iconfont next icon-fanhui" :class="[retract ? '' : 'retract_icon']" /></view>
  21. </swiper-item>
  22. </swiper>
  23. </view>
  24. </template>
  25. <script>
  26. export default {
  27. props:{
  28. value:{
  29. type:[String,Number],
  30. default:''
  31. },
  32. dot_lists:{
  33. type:Array,
  34. default:()=>{
  35. return [];
  36. }
  37. }
  38. },
  39. data(){
  40. return {
  41. debug:false,
  42. week:['日','一','二','三','四','五','六'],
  43. week_list:[],
  44. week_list_prev:[],
  45. week_list_prev_week:[],
  46. week_list_next:[],
  47. week_list_next_week:[],
  48. now_date:'',
  49. start_date:'',
  50. end_date:'',
  51. prev_date:'',
  52. next_date:'',
  53. nowYear:'',
  54. nowMonth:'',
  55. currentMonth:'',
  56. nowDay:'',
  57. retract:true,
  58. to_week_index:0,
  59. to_prev_week_index:0,
  60. to_next_week_index:0,
  61. nowTime:0,
  62. dot_list:[],
  63. current:0,
  64. date:'',
  65. }
  66. },
  67. watch:{
  68. value(value){
  69. this.get_date(this.date_parse(value));
  70. },
  71. dot_lists:{
  72. immediate:true,
  73. handler(value){
  74. this.dot_list = value;
  75. this.set_doc_lists_update()
  76. }
  77. }
  78. },
  79. computed:{
  80. week_list_prev_co(){
  81. return this.retract ? this.week_list_prev_week : this.week_list_prev
  82. },
  83. week_list_next_co(){
  84. return this.retract ? this.week_list_next_week : this.week_list_next
  85. }
  86. },
  87. created(){
  88. this.init();
  89. },
  90. methods:{
  91. change(){
  92. let value = {
  93. fulldate:this.date.replace(/-(\d)(?!\d)/g, '-0$1')
  94. };
  95. this.$emit('change',value)
  96. },
  97. init(){
  98. console.log(this.value)
  99. if(this.value){
  100. this.get_date(this.date_parse(this.value));
  101. }else{
  102. this.get_date();
  103. }
  104. let date = new Date();
  105. this.currentMonth = date.getMonth() + 1;
  106. this.doc_list_update();
  107. this.update_month();
  108. this.open();
  109. },
  110. open(){
  111. this.retract = !this.retract;
  112. this.get_date(this.nowTime);
  113. this.set_to_day('week_list_prev')
  114. this.set_to_day('week_list_next')
  115. this.change_week();
  116. if(this.retract){
  117. this.update_swiper_item('week')
  118. }else{
  119. this.update_swiper_item('month')
  120. }
  121. this.set_doc_lists_update();
  122. },
  123. change_week(){
  124. if(this.to_week_index < this.week_list.length - 1){
  125. this.to_next_week_index = this.to_week_index + 1;
  126. this.week_list_next_week = this.week_list;
  127. }else{
  128. this.to_next_week_index = 0;
  129. this.week_list_next_week = this.week_list_next;
  130. }
  131. if(this.to_week_index == 0 ){
  132. this.update_month();
  133. // if(){
  134. let next_day = this.week_list_prev[this.week_list_prev.length - 1][6].day;
  135. // }
  136. this.to_prev_week_index = this.week_list_prev.length - 1 - Math.ceil(next_day / 7);
  137. this.week_list_prev_week = JSON.parse(JSON.stringify(this.week_list_prev));
  138. }else{
  139. this.to_prev_week_index = this.to_week_index - 1;
  140. this.week_list_prev_week = this.week_list;
  141. }
  142. // if(this.current == 1){
  143. // }
  144. // let to_week_index = this.to_week_index;
  145. // if(this.current == 2){
  146. // this.to_next_week_index = this.to_week_index;
  147. // this.to_week_index = this.to_week_index - 1;
  148. // this.to_prev_week_index = this.to_next_week_index + 1;
  149. // }else if(this.current == 0){
  150. // this.to_next_week_index = this.to_week_index;
  151. // this.to_week_index = this.to_week_index - 1;
  152. // this.to_prev_week_index = this.to_next_week_index + 1;
  153. // }
  154. },
  155. change_date_week(type){
  156. let week_list = this.week_list;
  157. let to_week_index = this.to_week_index;
  158. if(type == 'prev'){
  159. this.to_week_index = this.to_prev_week_index;
  160. this.to_prev_week_index = this.to_next_week_index
  161. this.to_next_week_index = to_week_index;
  162. this.week_list = this.week_list_prev_week
  163. this.week_list_prev_week = this.week_list_next_week;
  164. this.week_list_next_week = week_list;
  165. }else if(type == 'next'){
  166. this.to_week_index = this.to_next_week_index;
  167. this.to_next_week_index = this.to_prev_week_index
  168. this.to_prev_week_index = to_week_index;
  169. this.week_list = this.week_list_next_week
  170. this.week_list_next_week = this.week_list_prev_week;
  171. this.week_list_prev_week = week_list;
  172. }
  173. this.set_to_day_all();
  174. },
  175. change_date_month(type){
  176. let week_list = this.week_list;
  177. if(type == 'prev'){
  178. this.week_list = this.week_list_prev
  179. this.week_list_prev = this.week_list_next;
  180. this.week_list_next = week_list;
  181. }else if(type == 'next'){
  182. this.week_list = this.week_list_next
  183. this.week_list_next = this.week_list_prev;
  184. this.week_list_prev = week_list;
  185. }
  186. },
  187. change_date(e){
  188. //return;
  189. let primary_current = this.current
  190. let current = e.detail.current;
  191. this.current = current;
  192. /*
  193. uni.showToast({
  194. title: primary_current + ' ' + current,
  195. icon:'none'
  196. });
  197. */
  198. //return;
  199. this.date = '';
  200. if(primary_current - current == -1){
  201. if(this.retract){
  202. this.switch_month_week('next')
  203. this.change_week()
  204. if(primary_current - current == -1 && current != 1){
  205. this.change_date_week('prev')
  206. }else if(primary_current - current == 2){
  207. this.change_date_week('next')
  208. }
  209. }else{
  210. this.get_date(this.get_month('next'));
  211. this.update_month();
  212. /*
  213. if(primary_current - current == -1 && current != 1){
  214. this.change_date_month('prev')
  215. }else if(primary_current - current == 2){
  216. this.change_date_month('next')
  217. }
  218. */
  219. this.change_date_month('prev');
  220. }
  221. }else{
  222. if(this.retract){
  223. this.switch_month_week('prev')
  224. this.change_week()
  225. if(primary_current - current == 1 && current != 1){
  226. this.change_date_week('next')
  227. }else if(primary_current - current == -2){
  228. this.change_date_week('prev')
  229. }
  230. }else{
  231. this.get_date(this.get_month('prev'));
  232. this.update_month();
  233. /*
  234. if(primary_current - current == 1 && current != 0){
  235. this.change_date_month('next')
  236. }else{
  237. this.change_date_month('prev')
  238. }
  239. */
  240. //this.change_date_month('prev');
  241. }
  242. }
  243. this.set_to_day_all();
  244. this.set_doc_lists_update();
  245. this.change()
  246. },
  247. update_month(){
  248. this.get_date(this.get_month('prev'),'prev');
  249. this.get_date(this.get_month('next'),'next');
  250. },
  251. set_doc_lists_update(){
  252. this.doc_list_update('week_list');
  253. this.doc_list_update('week_list_prev');
  254. this.doc_list_update('week_list_next');
  255. this.doc_list_update('week_list_prev_week')
  256. this.doc_list_update('week_list_next_week')
  257. },
  258. doc_list_update(week_list = 'week_list'){
  259. let list = [];
  260. this[week_list].map((item,index)=>{
  261. list.push(item.map((vo,key)=>{
  262. if (vo.day == ""){
  263. vo.dot = false;
  264. }
  265. else if(this.dot_list.indexOf(vo.date) > -1 || this.dot_list.indexOf(vo.date.replace(/-(\d)(?!\d)/g, '-0$1')) > -1 ){
  266. vo.dot = true;
  267. }else{
  268. vo.dot = false;
  269. }
  270. return {...vo}
  271. }))
  272. })
  273. this[week_list] = list;
  274. },
  275. set_to_day(type){
  276. let list = [];
  277. this[type].map((item,index)=>{
  278. list.push(item.map((vo,key)=>{
  279. if(vo.date == `${this.date}`){
  280. vo.today = true;
  281. }else{
  282. vo.today = false;
  283. }
  284. return {...vo};
  285. }))
  286. })
  287. this[type] = list;
  288. },
  289. item_click(item,item_index = -1){
  290. // if(!this.retract && item.type !== 'month'){
  291. // return false;
  292. // }
  293. if(!item.dot){
  294. return false;
  295. }
  296. console.log(item.date)
  297. this.date = item.date;
  298. if(item.type == 'month'){
  299. this.nowDay = item.day;
  300. if(item_index >= 0) this.to_week_index = item_index;
  301. }else if(this.retract){
  302. this.nowDay = item.day;
  303. }
  304. let now_arr = item.date.split('-')
  305. this.nowYear = now_arr[0];
  306. this.nowMonth = now_arr[1];
  307. this.nowDay = now_arr[2];
  308. this.set_to_day_all(item_index);
  309. this.nowTime = this.date_parse(`${item.date}`);
  310. this.change()
  311. this.set_doc_lists_update();
  312. },
  313. set_to_day_all(item_index){
  314. this.set_to_day('week_list')
  315. this.set_to_day('week_list_prev')
  316. this.set_to_day('week_list_next')
  317. this.set_to_day('week_list_prev_week')
  318. this.set_to_day('week_list_next_week')
  319. },
  320. get_month(type){
  321. let nowMonth = this.nowMonth;
  322. let nowYear = this.nowYear;
  323. let nowDay = this.nowDay;
  324. if(type == 'prev'){
  325. if(nowMonth == 1){
  326. nowMonth = 12;
  327. nowYear = nowYear - 1;
  328. }else{
  329. nowMonth--;
  330. }
  331. }else if(type == 'next'){
  332. if(nowMonth == 12){
  333. nowMonth = 1;
  334. nowYear = parseInt(nowYear) + 1;
  335. }else{
  336. nowMonth++;
  337. }
  338. }
  339. let days = this.get_month_days(nowMonth,nowYear);
  340. if(nowDay > days){
  341. nowDay = days;
  342. }
  343. return this.date_parse(`${nowYear}-${nowMonth}-${nowDay}`);
  344. },
  345. date_parse(str){
  346. return Date.parse(str.replace(/-(\d)(?!\d)/g, '-0$1'));
  347. },
  348. disabled_goto_prev(){
  349. let date = new Date();
  350. let cy = date.getFullYear();
  351. if (cy < this.nowYear){
  352. return false;
  353. }
  354. if (this.currentMonth >= this.nowMonth){
  355. return true;
  356. }
  357. return false;
  358. },
  359. disabled_goto_next(){
  360. let date = new Date();
  361. let cy = date.getFullYear();
  362. if (cy < this.nowYear){
  363. return true;
  364. }
  365. if (this.currentMonth < this.nowMonth){
  366. return true;
  367. }
  368. return false;
  369. },
  370. switch_month_week(type = 'next',update_week = false){
  371. if (type=="prev" && this.disabled_goto_prev()){
  372. return;
  373. }
  374. if (type == "next" && this.disabled_goto_next()){
  375. return;
  376. }
  377. // this.nowDay = '';
  378. this.date = '';
  379. if(this.retract){
  380. if(type == 'prev'){
  381. this.get_date(this.nowTime - 86400 * 7 * 1000);
  382. }else if(type == 'next'){
  383. this.get_date(this.nowTime + 86401 * 7 * 1000);
  384. }
  385. if(update_week){
  386. this.update_swiper_item('week');
  387. this.set_doc_lists_update();
  388. }
  389. }else{
  390. this.get_date(this.get_month(type))
  391. //this.update_swiper_item('month');
  392. }
  393. this.set_doc_lists_update();
  394. this.set_to_day_all();
  395. if(update_week){
  396. this.change()
  397. }
  398. },
  399. update_swiper_item(type = 'month'){
  400. //return ;
  401. if(type == 'month'){
  402. if(this.current == 0){
  403. this.change_date_month('next')
  404. }else if(this.current == 2){
  405. this.change_date_month('prev')
  406. }
  407. }else if(type == 'week'){
  408. if(this.current == 0){
  409. this.change_date_week('next')
  410. }else if(this.current == 2){
  411. this.change_date_week('prev')
  412. }
  413. }
  414. },
  415. next(){
  416. this.get_date(this.next_date)
  417. },
  418. get_date(value = '',type = 'same'){
  419. let date = new Date();
  420. if(value){
  421. date = new Date(value);
  422. }
  423. let nowMonth = date.getMonth() + 1,
  424. nowYear = date.getFullYear(),
  425. nowDay = date.getDate(),
  426. nowTime = date.getTime(),
  427. nowWeek = date.getDay();
  428. let days = this.get_month_days(nowMonth,nowYear);
  429. let start_date = new Date(nowYear,nowMonth - 1, 1);
  430. let end_date = new Date(nowYear,nowMonth - 1, days);
  431. let prev_date = new Date(start_date.getTime() - 1);
  432. let prev_date_days = prev_date.getDate();
  433. let next_date = new Date(end_date.getTime() + 86401 * 1000);
  434. let next_date_days = next_date.getDate();
  435. let start_week = start_date.getDay();
  436. let date_arrs = [];
  437. let week_list = [];
  438. let count_days = 35;
  439. for(let i = prev_date_days - start_week + 1; i <= prev_date_days; i++){
  440. date_arrs.push({
  441. day:"",
  442. type:'prev',
  443. date:`${prev_date.getFullYear()}-${prev_date.getMonth()+1}-${i}`
  444. })
  445. }
  446. for(let i = 1; i <= days; i++){
  447. date_arrs.push({
  448. day:i,
  449. type:'month',
  450. today:i == nowDay ? true : false,
  451. date:`${nowYear}-${nowMonth}-${i}`
  452. })
  453. if(i == nowDay && type == 'same'){
  454. // this.date = `${nowYear}-${nowMonth}-${i}`;
  455. }
  456. }
  457. if(this.debug) console.log(value,date,this.date,`${next_date.getFullYear()}-${next_date.getMonth()+1}-${next_date.getDate()}`)
  458. let date_arrs_length = date_arrs.length;
  459. if(date_arrs_length > 35){
  460. count_days = 42;
  461. }
  462. for(let i = 1; i <= count_days - date_arrs_length; i++){
  463. date_arrs.push({
  464. day:"",
  465. type:'next',
  466. date:`${next_date.getFullYear()}-${next_date.getMonth()+1}-${i}`
  467. })
  468. }
  469. for(let i = 0; i < date_arrs.length / 7; i++){
  470. let arr = [];
  471. for(let j = 0; j < 7; j++){
  472. if(date_arrs[i * 7 + j].today){
  473. if(type == 'same'){
  474. this.to_week_index = i
  475. }
  476. }
  477. arr.push(date_arrs[i * 7 + j]);
  478. }
  479. week_list.push(arr);
  480. }
  481. if(type == 'same'){
  482. this.week_list = week_list;
  483. this.nowYear = nowYear;
  484. this.nowMonth = nowMonth;
  485. this.nowDay = nowDay;
  486. this.nowTime = nowTime;
  487. this.start_date = start_date;
  488. this.end_date = end_date;
  489. this.prev_date = prev_date;
  490. this.next_date = next_date;
  491. }else if(type == 'prev'){
  492. this.week_list_prev = week_list;
  493. }else if(type == 'next'){
  494. this.week_list_next = week_list;
  495. }
  496. },
  497. get_month_days(nowMonth,nowYear){
  498. let month_arr = [1,3,5,7,8,10,12];
  499. let days = 0;
  500. if(nowMonth == 2){
  501. if(nowYear % 4 == 0){
  502. days = 29;
  503. }else{
  504. days = 28;
  505. }
  506. }else if(month_arr.indexOf(nowMonth) >= 0){
  507. days = 31;
  508. }else{
  509. days = 30;
  510. }
  511. return days;
  512. }
  513. }
  514. }
  515. </script>
  516. <style lang="less">
  517. @import (less) '../../static/lx-calendar/fonts/iconfont.css';
  518. @color:#007aff;
  519. @color_disabled:#a1a1a1;
  520. @color_standard:#333;
  521. @color_border:#f5f5f5;
  522. .date{
  523. width: 750rpx;
  524. }
  525. .head{
  526. display: flex; align-items: center; height: 100rpx; justify-content: center;
  527. border-bottom: 1rpx solid @color_border; color:@color_standard;
  528. .title{
  529. width: 200rpx; font-size: 30rpx; text-align: center;
  530. }
  531. .icon{
  532. display: block;
  533. .next{
  534. transform: rotate(180deg); display: block;
  535. }
  536. }
  537. }
  538. .month_disabled{
  539. color: @color_disabled;
  540. }
  541. .retract{
  542. display: flex; justify-content: center; align-items: center; height: 80rpx;;
  543. .iconfont{
  544. transform: rotate(270deg);
  545. &.retract_icon{
  546. transform: rotate(90deg);
  547. }
  548. }
  549. }
  550. .date_dl{
  551. display: flex; width: 100%;
  552. .dd{
  553. flex:1; text-align: center;
  554. height: 80rpx;
  555. font-size: 26rpx;
  556. display: flex;
  557. flex-direction: column;
  558. align-items: center;
  559. justify-content: center;
  560. position: relative;
  561. .num{
  562. width: 60rpx; height: 60rpx; border-radius: 50%; line-height: 60rpx;
  563. &.disabled{
  564. color: @color_disabled;
  565. }
  566. &.month{
  567. color: @color_standard;
  568. }
  569. &.today{
  570. background: @color; color:#fff;
  571. }
  572. }
  573. .dot{
  574. width: 12rpx; height: 12rpx; border-radius: 50%; background: #7bd571;
  575. position: absolute; bottom: 0; left: 50%; transform: translateX(-50%);
  576. }
  577. }
  578. }
  579. </style>