lx-calendar.vue 16 KB

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