lx-calendar.vue 16 KB

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