lx-calendar.vue 16 KB

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