lunc-calendar.vue 32 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979
  1. <template>
  2. <view class="lunc-calendar">
  3. <!-- 头部上下月按钮及月份 -->
  4. <view class="header">
  5. <!-- <text class="day_tit" >选择日期</text> -->
  6. <!-- <text class="head-icon head-pre-month nocheck" v-if="showChangeBtn&&!isshowPrev"></text> -->
  7. <!-- <text class="head-icon head-pre-month" v-if="showChangeBtn&&isshowPrev" @click="changeMonthOrWeek('prev')"></text> -->
  8. <text class="head-icon head-pre-month" v-if="showChangeBtn" @click="changeMonthOrWeek('prev')"></text>
  9. <text class="head-month">{{selDate.year+'年'+(selDate.month<10?'0'+selDate.month:selDate.month)+'月'}}</text>
  10. <text class="head-icon head-next-month" v-if="showChangeBtn" @click="changeMonthOrWeek('next')"></text>
  11. <!-- <text class="go-to-today" v-if="showToday" @click="goToday">今天</text> -->
  12. </view>
  13. <!-- 星期 -->
  14. <view class="week-area" :class="firstDayOfWeek=='sunday'?'week-tit':''">
  15. <text class="week-font" v-for="(item, index) in weekArr" :key="index ">{{ getWeekType + '' + item }}</text>
  16. </view>
  17. <!-- 日历 -->
  18. <swiper class="calendar-data" :current="shrinkType?tranCurrent:tranIndex" circular :duration="tranDuration"
  19. @change="swiperChange" @animationfinish="swiperEndChange" :style="{height:shrinkType?'112rpx':'682rpx'}">
  20. <swiper-item class="swiper-item swiper-prev-item" v-for="(a, i) in getAllData" :key="i">
  21. <text class="month-bg" v-if="showMonthBg">{{ getMontBg }}</text>
  22. <view class="month-days" :class="[shrinkType?'item-week':'']">
  23. <view class="week-days" v-for="(b, j) in a" :key="j">
  24. <view class="day" v-for="(c, k) in b" :key="k" @click="clickDay(c)">
  25. <!-- 之前日期不可约 c.isBefore?'day-infoa':''-->
  26. <view class="day-info" :class="[c.dayClass, getIsSelDay(c)&&'is-sel', c.dayType!='normal'&&'un-month',
  27. ]">
  28. <template v-if="c.sign&&c.sign.length">
  29. <template v-if="c.sign[0].holidaytype">
  30. <text class="day-solar" :class="c.sign[0].holidaytype=='YES'?'co16':'coa'">{{ c.day }}</text>
  31. </template>
  32. <text class="day-solar" v-else>{{ c.day }}</text>
  33. <view class="cirs" v-if="(c.isBefore||c.isToday)&&(c.sign[0].holidaytype!='NO'||!c.sign[0].holidaytype)">
  34. <block v-if="c.week!=0&&c.week!=6||c.sign[0].holidaytype=='YES'">
  35. <view class="cir bga" v-if="c.sign[0].amex=='5'&&c.sign[0].pmex=='5'"></view>
  36. <view class="cir" v-else-if="c.sign[0].amex=='1'&&c.sign[0].pmex=='1'"></view>
  37. <view class="cir bgb" v-else></view>
  38. </block>
  39. <!-- <block v-else>
  40. <view class="cir" :class="c.sign[0].amex=='2'?'bgb':''"></view>
  41. <view class="cir" :class="c.sign[0].pmex=='2'?'bgb':''"></view>
  42. </block> -->
  43. </view>
  44. </template>
  45. <text class="day-solar" v-else>{{ c.day }}</text>
  46. </view>
  47. </view>
  48. </view>
  49. </view>
  50. </swiper-item>
  51. </swiper>
  52. <!-- 收缩按钮 -->
  53. <view class="shrink" v-if="showShrink" @click="changeShrink">
  54. <image :src="upimg" class="shrink-img" :class="[shrinkType?'shrink-open':'shrink-close']"></image>
  55. <!-- <text class="shrink-btn" ></text> -->
  56. </view>
  57. </view>
  58. </template>
  59. <script>
  60. let { calendar } = require("./calendar.js");
  61. /**
  62. * @property {Boolean} showLunar = [true|false] 是否显示农历,默认false
  63. * @property {Boolean} showMonthBg = [true|false] 是否显示月份背景,默认true
  64. * @property {Boolean} showChangeBtn = [true|false] 是否显示上月下月箭头按钮,默认true
  65. * @property {String} firstDayOfWeek = [monday|sunday] 周几为每周的第一天,默认monday
  66. * @value monday 每周从周一开始(默认)
  67. * @value sunday 每周从周日开始
  68. * @property {String} weekType = [''|周|星期] 星期的前缀;如周一周二或星期一星期二,为空则只显示一、二等;不用预设值时可自定义前缀,填的值即为星期前缀;默认周
  69. * @value '' 星期显示:只显示一、二等
  70. * @value 周 星期显示:周一、周二等(默认)
  71. * @value 星期 星期显示:星期一、星期二等
  72. * @property {Boolean} weekend = [true|false] 周末标红(周六周日日期用红色字体),默认true
  73. * @property {Boolean} showShrink = [true|false] 是否显示收缩按钮,可显示一周的日期,默认false
  74. * @property {String} shrinkState = [week|month] 收缩状态,默认month
  75. * @value week 默认打开显示周数据(收起状态)
  76. * @value month 默认打开显示月数据(展开状态)
  77. * @property {Array} signList 标记数组,若当前有多个标记,则显示最后一个,期待格式[{date: '2021-09-10', title: '生日', info: '八月初四张三生日'}]
  78. * @event {Function()} dayChange 点击日期触发事件,返回参数e={year,month,day,week,date,lunar,daySign},详情参数见文档
  79. * @event {Function()} monthChange 切换月份触发事件,返回参数e={year,month,type},详情参数见文档
  80. * @event {Function()} shrinkClick 收缩和展开时触发事件,返回参数e=week|month
  81. */
  82. export default {
  83. name: 'LuncCalendar',
  84. props: {
  85. //是否显示农历
  86. showLunar: {
  87. type: Boolean,
  88. default: false
  89. },
  90. //是否显示月份背景
  91. showMonthBg: {
  92. type: Boolean,
  93. default: true
  94. },
  95. //是否显示上月下月按钮
  96. showChangeBtn: {
  97. type: Boolean,
  98. default: true
  99. },
  100. //每周的周几为第一天
  101. firstDayOfWeek: {
  102. type: String,
  103. default: 'monday'
  104. },
  105. //每周的周几为第一天
  106. weekType: {
  107. type: String,
  108. default: '周'
  109. },
  110. //周末标红
  111. weekend: {
  112. type: Boolean,
  113. default: true
  114. },
  115. //是否可收缩,收起来后以周显示
  116. showShrink: {
  117. type: Boolean,
  118. default: false
  119. },
  120. // 默认打开状态(收起或展开)
  121. shrinkState:{
  122. type: String,
  123. default: 'month'
  124. },
  125. //标记
  126. signList: {
  127. type: Array,
  128. default () {
  129. return []
  130. }
  131. },
  132. // 周几不可约
  133. configWeek:{
  134. type: Array,
  135. default () {
  136. return []
  137. }
  138. },
  139. // 节假日预约
  140. configHoliday:{
  141. type: String,
  142. default () {
  143. return 'Y'
  144. }
  145. },
  146. // 选中的日期
  147. recordDate:{
  148. type: String,
  149. default () {
  150. return ''
  151. }
  152. }
  153. },
  154. data() {
  155. return {
  156. upimg:require("@/static/images/order/comes/up.png"),
  157. weekArr: ['一', '二', '三', '四', '五', '六', '日'], //星期数组
  158. today: {}, //今天日期 -> year, month, day
  159. selDate: {}, //选中日期信息 -> year, month, day
  160. allMonthList: [], // 月份数据 -> [[[周],[周]],[月],[月]]
  161. tranIndex: 1, // 月份轮播所在位置
  162. allWeekList: [], // 周月份数据 -> [[[周]],[月],[月]]
  163. tranCurrent: 1, // 周轮播所在位置
  164. tranDuration: 300, //轮播时间(单位毫秒)
  165. signArr: this.signList, // 标记列表
  166. showToday: false, //显示回到今天(非当月才显示)
  167. isshowPrev:false,//切换当月的上一个月
  168. shrinkType: false, // 收缩状态,true:收起(显示周),false展开(显示月)
  169. deterChange: true, // 防止切换月份过快
  170. redtoday:{}
  171. }
  172. },
  173. created() {
  174. let nd = new Date();
  175. this.today = {
  176. year: nd.getFullYear(),
  177. month: nd.getMonth() + 1,
  178. day: nd.getDate()
  179. }
  180. if(this.recordDate){
  181. let rednd = new Date(this.recordDate);
  182. this.redtoday = {
  183. year: rednd.getFullYear(),
  184. month: rednd.getMonth() + 1,
  185. day: rednd.getDate()
  186. }
  187. }
  188. if (this.firstDayOfWeek == "sunday") this.weekArr = ['日', '一', '二', '三', '四', '五', '六'];
  189. this.initDate();
  190. },
  191. watch: {
  192. signList(nList, oList){
  193. this.signArr = nList;
  194. this.setSignList();
  195. }
  196. },
  197. computed: {
  198. getAllData() { // 切换周或月时,展示的数据不同
  199. return this.shrinkType ? this.allWeekList : this.allMonthList;
  200. },
  201. getMontBg() { // 获取当前月背景
  202. let monthBg = this.selDate.month;
  203. return !this.shrinkType ? (monthBg < 10 ? '0' + monthBg : monthBg) : '';
  204. },
  205. getIsSelDay(c) { // 判断是否是选中日期
  206. return (d) => {
  207. let { year, month, day } = this.selDate;
  208. if(year == d.year && month == d.month && day == d.day){
  209. this.$emit('getIsSelDayFn',d)
  210. }
  211. return year == d.year && month == d.month && day == d.day
  212. }
  213. },
  214. getWeekType(){
  215. let weekType = this.weekType;
  216. if(weekType && weekType != "true" && weekType != "''" && weekType != '""'){
  217. return weekType
  218. }else{
  219. return ''
  220. }
  221. }
  222. },
  223. methods: {
  224. initDate() { // 初始化日期
  225. if(this.recordDate){
  226. this.selDate = JSON.parse(JSON.stringify(this.redtoday));
  227. }else{
  228. this.selDate = JSON.parse(JSON.stringify(this.today));
  229. }
  230. let monthList = this.getMonthData(this.selDate); // 获取当月数据
  231. let prevMonthList = this.getMonthData(this.getMonthDate(this.selDate, -1)); // 上月数据
  232. let nextMonthList = this.getMonthData(this.getMonthDate(this.selDate)); // 下月数据
  233. this.allMonthList = [prevMonthList, monthList, nextMonthList]
  234. this.tranIndex = 1;
  235. if(this.shrinkState == "week" && !this.shrinkType) this.changeShrink();
  236. },
  237. /**
  238. * 根据指定日期获取当月的数据
  239. * @param {Object} date = { year, month, day } 指定的日期
  240. */
  241. getMonthData(date) {
  242. const { year, month, day } = date; //指定的日期
  243. let maxDay = new Date(year, month, 0).getDate(); //当前月最大日期
  244. let firstWeek = new Date(year + "/" + month + "/1").getDay(); //月份1号的星期数
  245. if (this.firstDayOfWeek == "monday") firstWeek = firstWeek - 1 < 0 ? 6 : firstWeek - 1;
  246. let list = [];
  247. //每月显示42天,6周,每周7天
  248. for (var i = 0; i < 42; i++) {
  249. let dayInfo = {}; // 每天的详细信息
  250. if (i < firstWeek) { //指定月份上月的最后几天
  251. let { year, month } = this.getMonthDate(date, -1);
  252. let preMaxDay = new Date(year, month, 0).getDate(); //上月最大日期
  253. let day = preMaxDay - firstWeek + i + 1;
  254. dayInfo = this.getDayInfo({ year, month, day }, 'prev');
  255. } else if (i > maxDay + firstWeek - 1) { //指定月份下月的前几天
  256. let { year, month } = this.getMonthDate(date);
  257. let day = i - maxDay - firstWeek + 1;
  258. dayInfo = this.getDayInfo({ year, month, day }, 'next');
  259. } else {
  260. let day = i - firstWeek + 1;
  261. dayInfo = this.getDayInfo({ year, month, day }, 'normal');
  262. }
  263. if (i % 7 == 0) list.push(new Array());
  264. list[list.length - 1].push(dayInfo);
  265. }
  266. return list;
  267. },
  268. /**
  269. * 获取指定日期的详细信息,包括农历节假日等
  270. * @param {Object} date = { year, month, day } 指定的日期
  271. * @param {String} dayType = [prev|next|normal] 日期类型,上月|下月|当前月
  272. */
  273. getDayInfo(date, dayType) {
  274. const { year, month, day } = date;
  275. let isToday = false; //是否今天
  276. let isBefore=false;//是否今天之前
  277. if (year == this.today.year && month == this.today.month && day == this.today.day) isToday = true;
  278. if(year==this.today.year&&month == this.today.month && day < this.today.day){
  279. isBefore=true;
  280. }else if(year==this.today.year&&month < this.today.month){
  281. isBefore=true;
  282. }else if(year<this.today.year){
  283. isBefore=true;
  284. }
  285. let week = new Date(year + "/" + month + "/" + day).getDay(); //星期数
  286. let lunar = calendar.solar2lunar(year, month, day); //农历
  287. let dayLunar = lunar.IDayCn == '初一' ? lunar.IMonthCn + lunar.IDayCn : lunar.IDayCn;
  288. if (lunar.festival) dayLunar = lunar.festival; // 阳历节日
  289. else if (lunar.lunarFestival) dayLunar = lunar.lunarFestival; // 农历节日
  290. else if (lunar.Term) dayLunar = lunar.Term; // 节气
  291. let holidayArr = ["元旦", "春节", "清明节", "劳动节", "端午节", "中秋节", "国庆节"];
  292. let isHoliday = false;
  293. if (holidayArr.indexOf(dayLunar) != -1) isHoliday = true;
  294. let dayInfo = {
  295. date: year + "-" + month + "-" + day,
  296. year, month, day, week,
  297. lunar, // 农历
  298. dayLunar, // 显示的农历
  299. isToday, // 是否是今日
  300. isBefore,//是否今天之前
  301. isHoliday, // 是否是节假日
  302. dayType, // 日期类型,上月、下月或当前月
  303. sign: this.getSignByDate(date)
  304. }
  305. let dayClass = this.getDayClass(dayInfo);
  306. dayInfo["dayClass"] = dayClass;
  307. return dayInfo;
  308. },
  309. /**
  310. * 根据日期详细信息添加对应的class
  311. * @param {Object} dayInfo 日期详情
  312. */
  313. getDayClass(dayInfo) {
  314. let dClass = "";
  315. if (dayInfo.isToday) dClass += ' is-today'; // 今天日期
  316. if (dayInfo.isHoliday) dClass += ' is-holiday'; // 法定假日
  317. if (this.weekend && (dayInfo.week == 0 || dayInfo.week == 6)) dClass += ' week-end'; // 周末标红
  318. return dClass;
  319. },
  320. /**
  321. * 根据日期获取日期对应的事件
  322. * @param {Object} date = { year, month, day } 指定的日期
  323. */
  324. getSignByDate(date) {
  325. const { year, month, day } = date;
  326. let dayDateS = new Date(year + "/" + month + "/" + day + " 00:00:00").getTime();
  327. let dayDateE = new Date(year + "/" + month + "/" + day + " 23:59:59").getTime();
  328. let daySign = [];
  329. this.signArr.map(sign => {
  330. let signDate = sign.date.replace(/-/g, '/');
  331. let signTimes = new Date(sign.date).getTime();
  332. if (signTimes >= dayDateS && signTimes <= dayDateE) daySign.push(sign)
  333. })
  334. return daySign;
  335. },
  336. /**
  337. * 获取月份数据
  338. * @param {String} type=[pre|next]
  339. */
  340. getOtherData(type) {
  341. let nowMont = this.getMonthDate(this.selDate, type == 'prev' ? -1 : 1); // 获取当前月份
  342. this.selDate = nowMont; // 切换月份后设置选中的日期
  343. let monthData = this.getMonthData(this.getMonthDate(nowMont, type == 'prev' ? -1 : 1));
  344. // 获取上月或下月轮播所在位置
  345. let current = this.getTranIndex().prevNum;
  346. if (type == "next") current = this.getTranIndex().nextNum;
  347. this.allMonthList.splice(current, 1, monthData);
  348. this.judgeShowToday();
  349. this.returnMonthChange(type);
  350. },
  351. /**
  352. * 获取周数据
  353. * @param {String} type=[pre|next]
  354. */
  355. getOtherWeekData(type) {
  356. let oldSel = this.selDate; // 原选中的日期
  357. let newSel = this.getDateByDateAndDay(oldSel, type == 'prev' ? -7 : 7); // 获取7天前或后的日期
  358. if (oldSel.month != newSel.month) { // 跨月,先设置跨月后的月历
  359. // 设置月轮播位置
  360. let current = this.getTranIndex("month").prevNum;
  361. if (type == "next") current = this.getTranIndex("month").nextNum;
  362. this.tranIndex = current;
  363. this.getOtherData(type);
  364. }
  365. this.selDate = newSel;
  366. this.getWeekData(type);
  367. this.judgeShowToday();
  368. },
  369. // 从月历中获取周数据,切换周后获取上周或下周数据
  370. getWeekData(type) {
  371. const { prevNum: prevIndex, nowNum: nowIndex, nextNum: nextIndex } = this.getTranIndex("month");
  372. const { prevNum: prevCurrent, nowNum: nowCurrent, nextNum: nextCurrent } = this.getTranIndex("week");
  373. const { year: selYear, month: selMonth, day: selDay } = this.selDate;
  374. let sDate = selYear + "-" + selMonth + "-" + selDay
  375. let prevMonthList = this.allMonthList[prevIndex];
  376. let nowMonthList = this.allMonthList[nowIndex];
  377. let nextMonthList = this.allMonthList[nextIndex];
  378. for (let i = 0; i < nowMonthList.length; i++) {
  379. for (let j = 0; j < nowMonthList[i].length; j++) {
  380. if (sDate == nowMonthList[i][j].date) {
  381. this.returnDayChange(nowMonthList[i][j]); // 返回选中的日期
  382. if (type == "next") {
  383. this.allWeekList.splice(nextCurrent, 1, [nowMonthList[i + 1]]);
  384. if (i == 5) this.allWeekList.splice(nextCurrent, 1, [nextMonthList[1]]);
  385. } else {
  386. this.allWeekList.splice(prevCurrent, 1, [nowMonthList[i - 1]]);
  387. if (i == 0) {
  388. for (let k = prevMonthList.length - 1; k >= 0; k--) {
  389. if (prevMonthList[k][6].dayType == "normal") {
  390. this.allWeekList.splice(prevCurrent, 1, [prevMonthList[k]]);
  391. break;
  392. }
  393. }
  394. }
  395. }
  396. break;
  397. }
  398. }
  399. }
  400. },
  401. // 根据月份数据获取周数据,相当初始化周数据
  402. getAllWeekData() {
  403. const { prevNum, nowNum, nextNum } = this.getTranIndex("month");
  404. const { year: selYear, month: selMonth, day: selDay } = this.selDate;
  405. let sDate = selYear + "-" + selMonth + "-" + selDay; // 选中的日期
  406. let allWeekList = [[],[],[]];
  407. let prevMonthList = this.allMonthList[prevNum];
  408. let nowMonthList = this.allMonthList[nowNum];
  409. let nextMonthList = this.allMonthList[nextNum];
  410. for (let i = 0; i < nowMonthList.length; i++) {
  411. for (let j = 0; j < nowMonthList[i].length; j++) {
  412. if (sDate == nowMonthList[i][j].date) {
  413. allWeekList[0][0] = nowMonthList[i - 1];
  414. allWeekList[1][0] = nowMonthList[i];
  415. allWeekList[2][0] = nowMonthList[i + 1];
  416. if (i == 5) {
  417. allWeekList[2][0] = nextMonthList[1];
  418. } else if (i == 0) {
  419. for (let k = prevMonthList.length - 1; k >= 0; k--) {
  420. if (prevMonthList[k][6].dayType == "normal") {
  421. allWeekList[0][0] = prevMonthList[k];
  422. break;
  423. }
  424. }
  425. }
  426. break;
  427. }
  428. }
  429. }
  430. this.allWeekList = allWeekList;
  431. },
  432. // 滑动切换结束
  433. swiperEndChange() {
  434. this.tranDuration = 300;
  435. },
  436. // 滑动切换月份或周
  437. swiperChange(e) {
  438. let current = e.detail.current;
  439. let oldIndex = this.shrinkType ? this.tranCurrent : this.tranIndex;
  440. let type = (oldIndex - current == -1 || oldIndex - current == 2) ? 'next' : 'prev';
  441. if (this.shrinkType) {
  442. this.tranCurrent = current;
  443. if (current != oldIndex) this.getOtherWeekData(type);
  444. } else {
  445. this.tranIndex = current;
  446. if (current != oldIndex) this.getOtherData(type);
  447. }
  448. },
  449. // 点击切换月份或周(上月下月切换或上周下周切换)type = [prev|next] 切换类型
  450. changeMonthOrWeek(type) {
  451. if (!this.deterChange) return;
  452. this.deterChange = false;
  453. setTimeout(_ => {
  454. this.deterChange = true;
  455. }, 400); // 防止点击过快
  456. this.tranDuration = 300;
  457. let tranType = this.shrinkType ? 'week' : 'month';
  458. let current = this.getTranIndex(tranType).prevNum;
  459. if (type == "next") current = this.getTranIndex(tranType).nextNum;
  460. if (tranType == "week") {
  461. this.tranCurrent = current;
  462. this.getOtherWeekData(type);
  463. } else {
  464. this.tranIndex = current;
  465. this.getOtherData(type);
  466. }
  467. },
  468. // 点击收缩按钮,切换显示月份或显示周
  469. changeShrink() {
  470. this.shrinkType = !this.shrinkType;
  471. if (this.tranDuration != 0) this.tranDuration = 0;
  472. if (this.shrinkType) {
  473. this.tranCurrent = 1;
  474. this.getAllWeekData();
  475. }
  476. this.returnShrinkChange();
  477. this.judgeShowToday();
  478. },
  479. // 点击回到今天
  480. goToday() {
  481. if (this.tranDuration != 0) this.tranDuration = 0;
  482. let oldDate = JSON.parse(JSON.stringify(this.selDate));
  483. this.initDate();
  484. if (this.shrinkType) {
  485. this.tranCurrent = 1;
  486. this.getAllWeekData();
  487. let today = this.today;
  488. // 判断是否需要触发改变月份事件
  489. if(oldDate.year != today.year || oldDate.month != today.month){
  490. this.returnMonthChange("today");
  491. }else{
  492. this.returnDayChange(this.today);
  493. }
  494. } else {
  495. this.returnMonthChange("today"); // 事件
  496. }
  497. this.judgeShowToday();
  498. },
  499. // 点击日期
  500. clickDay(dayInfo) {
  501. // var isweek=this.configWeek.indexOf(dayInfo.week)
  502. // if(dayInfo.sign && dayInfo.sign.length > 0&&dayInfo.sign[0].title!='可预约'||dayInfo.sign.length==0||isweek!=-1||dayInfo.isHoliday&&this.configHoliday=='N'){
  503. // return
  504. // }
  505. // if(dayInfo.isBefore){
  506. // return
  507. // }
  508. let { year, month, day } = this.selDate;
  509. if (day == dayInfo.day && month == dayInfo.month && year == dayInfo.year) return;
  510. let oldSel = JSON.parse(JSON.stringify(this.selDate));
  511. this.selDate.day = dayInfo.day;
  512. if (oldSel.month != dayInfo.month) {
  513. if (!this.shrinkType) {
  514. this.changeMonthOrWeek(dayInfo.dayType);
  515. return;
  516. } else {
  517. this.selDate.year = dayInfo.year;
  518. this.selDate.month = dayInfo.month;
  519. let nowSel = JSON.parse(JSON.stringify(this.selDate));
  520. let type = "nowNum"
  521. if (nowSel.year > oldSel.year || (nowSel.year === oldSel.year && nowSel.month > oldSel.month)){
  522. type = "nextNum"
  523. } else if (nowSel.year < oldSel.year || (nowSel.year === oldSel.year && nowSel.month < oldSel.month)){
  524. type = "prevNum"
  525. }
  526. this.tranIndex = this.getTranIndex("month")[type];
  527. let monthData = this.getMonthData(this.getMonthDate(this.selDate, type == 'prevNum' ? -1 : 1));
  528. let current = this.getTranIndex("month")[type];
  529. this.allMonthList.splice(current, 1, monthData); // 设置上月或下月数据
  530. }
  531. this.returnMonthChange(dayInfo.dayType);
  532. } else {
  533. this.returnDayChange(dayInfo);
  534. }
  535. },
  536. // 判断是否需要显示回到今天(非本月或本周时显示)
  537. judgeShowToday() {
  538. const { year, month, day } = this.today;
  539. const { year: selYeat, month: selMonth, day: selDay } = this.selDate;
  540. if (this.shrinkType) { // 显示的周
  541. let selTimes = new Date(selYeat, selMonth - 1, selDay).getTime(); // 选中日期的时间戳
  542. let week = new Date(year, month - 1, day).getDay(); // 今天星期
  543. let firstWD = this.getDateByDateAndDay(this.today, -week + (this.firstDayOfWeek == "monday" ? 1 : 0));
  544. let lastWD = this.getDateByDateAndDay(this.today, 6 - week + (this.firstDayOfWeek == "monday" ? 1 : 0));
  545. let firstTimes = new Date(firstWD.year, firstWD.month - 1, firstWD.day).getTime();
  546. let lastTimes = new Date(lastWD.year, lastWD.month - 1, lastWD.day).getTime();
  547. if (selTimes > lastTimes || selTimes < firstTimes) this.showToday = true;
  548. else this.showToday = false;
  549. if(selTimes > lastTimes) this.isshowPrev=true;
  550. else this.isshowPrev=false;
  551. } else {
  552. if (year != selYeat || month != selMonth) this.showToday = true;
  553. else this.showToday = false;
  554. // 判断是并不是当前月上一个月
  555. if(Number(selYeat)>Number(year)||Number(selMonth)>Number(month)) this.isshowPrev=true;
  556. else this.isshowPrev=false;
  557. }
  558. },
  559. // 重新设置标记
  560. setSignList() {
  561. this.allMonthList.map(month => {
  562. month.map(week => {
  563. week.map(day => {
  564. day.sign = this.getSignByDate({ year: day.year, month: day.month, day: day.day })
  565. })
  566. })
  567. })
  568. },
  569. /**
  570. * 添加标记
  571. * @param {Array} list 需要添加的标记
  572. */
  573. addSignList(list) {
  574. let signArr = this.signArr.concat(list);
  575. this.signArr = signArr;
  576. this.setSignList();
  577. },
  578. /**
  579. * 删除标记
  580. * 根据date和title共同判断是否删除
  581. * @param {Array} list 需要删除的标记
  582. */
  583. deleteSignList(list) {
  584. let signArr = this.signArr;
  585. signArr = signArr.filter(s => {
  586. if (list.find(l => l.date == s.date && l.title == s.title)) return false
  587. else return true;
  588. })
  589. this.signArr = signArr;
  590. this.setSignList();
  591. },
  592. /**
  593. * 事件 - 设置返回日期
  594. * @param {Object} dayInfo 日期详情
  595. */
  596. returnDayChange(dayInfo) {
  597. let { year, month, day } = dayInfo;
  598. let dayDate = year + "-" + (month < 10 ? '0' + month : month) + "-" + (day < 10 ? '0' + day : day)
  599. let returnData = {
  600. date: dayDate,
  601. year: year,
  602. month: month,
  603. day: day,
  604. week: dayInfo.week,
  605. daySign: dayInfo.sign
  606. }
  607. if (this.showLunar) returnData["lunar"] = dayInfo.lunar;
  608. this.$emit("dayChange", returnData);
  609. },
  610. /**
  611. * 事件 - 设置返回月份
  612. * @param {String} type 类型
  613. */
  614. returnMonthChange(type) {
  615. let selDate = this.selDate.year + "-" + this.selDate.month + "-" + this.selDate.day;
  616. let monthList = this.allMonthList.flat().flat(); // 二维转一维
  617. let dayInfo = monthList.find(day => day.date == selDate);
  618. this.returnDayChange(dayInfo)
  619. this.$emit("monthChange", {
  620. year: dayInfo.year,
  621. month: dayInfo.month,
  622. type: type
  623. });
  624. },
  625. /**
  626. * 事件 - 返回收缩状态
  627. */
  628. returnShrinkChange() {
  629. let type = this.shrinkType ? 'week' : 'month'
  630. this.$emit("shrinkClick", type);
  631. },
  632. /**
  633. * 获取上一个或下一个轮播位置
  634. * @param {String} type = [month|week] 轮播类型,月轮播(tranIndex),周轮播(tranCurrent)
  635. * @returns {Object} {prevNum, nowNum, nextNum}
  636. */
  637. getTranIndex(type = 'month') {
  638. let current = this.tranIndex;
  639. if (type == "week") current = this.tranCurrent;
  640. let prevNum = current - 1 < 0 ? 2 : current - 1;
  641. let nowNum = current;
  642. let nextNum = current + 1 > 2 ? 0 : current + 1;
  643. return { prevNum, nowNum, nextNum }
  644. },
  645. /**
  646. * 根据日期获取几天后的日期
  647. * @param {Object} date = {year, month, day} 当前日期
  648. * @param {Number} day 当前日期的几天前或几天后(负数)
  649. * @returns {Object} {year, month, day}
  650. */
  651. getDateByDateAndDay(date, num) {
  652. let dTime = new Date(date.year + "/" + date.month + "/" + date.day).getTime() + num * 24 * 60 * 60 * 1000;
  653. let nd = new Date(dTime);
  654. return {
  655. year: nd.getFullYear(),
  656. month: nd.getMonth() + 1,
  657. day: nd.getDate()
  658. }
  659. },
  660. /**
  661. * 获取几个月前或后的日期
  662. * @param {Object} date = {year, month, day} 当前日期
  663. * @param {Number} num 当前日期的num月前或后,默认1月后(下月)
  664. * @returns {Object} {year, month, day}
  665. */
  666. getMonthDate(date, num = 1) {
  667. let nextMonth = date.month + num;
  668. let diffYear = parseInt(Math.abs(nextMonth) / 12);
  669. let year = date.year;
  670. let month = nextMonth;
  671. if (nextMonth > 12) {
  672. year = date.year + diffYear;
  673. month = nextMonth % 12;
  674. } else if (nextMonth < 1) {
  675. year = date.year - (diffYear + 1);
  676. month = nextMonth + 12 * (diffYear + 1);
  677. }
  678. let monthMaxDay = new Date(year, month, 0).getDate(); // 月份最大日期
  679. let day = date.day > monthMaxDay ? monthMaxDay : date.day;
  680. return { year, month, day }
  681. },
  682. }
  683. }
  684. </script>
  685. <style lang="scss">
  686. .cirs{
  687. display: flex;align-items: center;margin-top: 12rpx;
  688. .cir{width: 8rpx;height: 8rpx;background: #0391FD;border-radius: 50%;margin: 0 3rpx;
  689. &.bga{background-color: #DADADA;}
  690. &.bgb{background-color: #F87C29;}
  691. }
  692. }
  693. .lunc-calendar {
  694. background-color: #FFF;
  695. // 头部
  696. .header {
  697. display: flex;
  698. flex-direction: row;
  699. justify-content: center;
  700. align-items: center;
  701. position: relative;
  702. height: 88rpx;
  703. line-height: 88rpx;
  704. border-bottom: 2rpx solid $com-cd3;
  705. .head-month {
  706. font-size: 30rpx;
  707. padding: 0 40rpx;
  708. font-weight: bold;
  709. }
  710. .day_tit{
  711. position: absolute;
  712. left: 0rpx;
  713. top: 26rpx;
  714. font-size: 30rpx;
  715. line-height: 36rpx;
  716. color: #161616;
  717. text-align: center;
  718. font-weight: bold;
  719. }
  720. .go-to-today {
  721. position: absolute;
  722. right: 16rpx;
  723. top: 26rpx;
  724. font-size: 24rpx;
  725. line-height: 36rpx;
  726. color: $com-cd3;
  727. text-align: center;
  728. width: 80rpx;
  729. height: 36rpx;
  730. border: 2rpx solid $com-cd3;
  731. border-radius: 18rpx;
  732. box-sizing: border-box;
  733. }
  734. .head-icon {
  735. content: '';
  736. display: flex;
  737. width: 22rpx;
  738. height: 22rpx;
  739. border-top: 2rpx solid $com-cd3;
  740. border-left: 2rpx solid $com-cd3;
  741. }
  742. .head-icon.head-pre-month {
  743. transform: rotate(-45deg);
  744. }
  745. .head-icon.head-next-month {
  746. transform: rotate(135deg);
  747. }
  748. .head-icon.nocheck {
  749. border-top: 2rpx solid #aaaaaa;
  750. border-left: 2rpx solid #aaaaaa;
  751. }
  752. }
  753. // 星期
  754. .week-area {
  755. display: flex;
  756. flex-direction: row;
  757. align-items: center;
  758. // border-bottom: 1px solid #EEE;
  759. padding: 16rpx 0;
  760. // margin: 0 10rpx;
  761. .week-font {
  762. flex: 1;
  763. text-align: center;
  764. color: #161616;
  765. font-size: 30rpx;
  766. font-weight: bold;
  767. }
  768. &.week-tit{
  769. .week-font:first-child{color: #aaaaaa;}
  770. .week-font:last-child{color: #aaaaaa;}
  771. }
  772. }
  773. // 日历
  774. .calendar-data {
  775. // transition: all 300ms;
  776. .swiper-item {
  777. position: relative;
  778. display: flex;
  779. justify-content: center;
  780. align-items: center;
  781. flex-direction: row;
  782. .month-bg {
  783. position: absolute;
  784. font-size: 460rpx;
  785. color: #EEE;
  786. font-weight: bold;
  787. opacity: 0.4;
  788. z-index: -1;
  789. }
  790. .month-days {
  791. flex: 1;
  792. // margin-top: 10rpx;
  793. position: relative;
  794. .week-days {
  795. display: flex;
  796. flex-direction: row;
  797. padding-top: 10rpx;
  798. margin-bottom: 20rpx;
  799. .day {
  800. flex: 1;
  801. width: 14.28%;
  802. text-align: center;
  803. // height: 84rpx;
  804. height: 76rpx;
  805. color: #000;
  806. /* #ifndef APP-NVUE */
  807. padding: 0 6rpx;
  808. /* #endif */
  809. // box-sizing: border-box;
  810. display: flex;
  811. .day-info {
  812. flex: 1;
  813. display: flex;
  814. flex-direction: column;
  815. justify-content: flex-start;
  816. align-items: center;
  817. position: relative;
  818. .day-solar {
  819. display: flex;
  820. font-size: 30rpx;
  821. line-height: 76rpx;
  822. width: calc(100% - 4rpx);
  823. // height: 50rpx;
  824. // padding-top: 10rpx;
  825. border-radius: 16rpx 16rpx 0 0;
  826. color: #161616;
  827. box-sizing: border-box;
  828. // background:#ffffff;
  829. display: block;
  830. // font-weight: bold;
  831. &.coa{color: #AAAAAA !important;}
  832. &.co16{color: #161616 !important;}
  833. }
  834. .day-lunar,
  835. .day-sign {
  836. color: #161616;
  837. font-size: 24rpx;
  838. line-height: 24rpx;
  839. transform: scale(0.8);
  840. white-space: nowrap;
  841. margin-top: 6rpx;
  842. }
  843. .day-sign {
  844. color: #161616 !important;
  845. }
  846. .day-tag {
  847. content: "";
  848. position: absolute;
  849. top: 8rpx;
  850. right: 8rpx;
  851. width: 10rpx;
  852. height: 10rpx;
  853. border-radius: 6rpx;
  854. background-color: #F75858;
  855. }
  856. }
  857. // 非当月日期
  858. .day-info.un-month {
  859. opacity: 0.25;
  860. transition: opacity 300ms;
  861. }
  862. // 今天日期
  863. .is-today .day-solar,
  864. .is-today .day-sign,
  865. .is-today .day-lunar {
  866. color: $com-cd3;
  867. }
  868. // 周末
  869. .week-end .day-solar {
  870. // color: #FF9595;
  871. color: #AAAAAA;
  872. }
  873. // 法定假日
  874. .is-holiday .day-solar,
  875. .is-holiday .day-sign,
  876. .is-holiday .day-lunar {
  877. color: #161616 !important;
  878. }
  879. //不能预约的日期
  880. .day-infoa,{
  881. .day-solar{color: #AAAAAA !important;}
  882. .day-sign{color: #AAAAAA !important;}
  883. .day-lunar{color: #AAAAAA !important;}
  884. }
  885. // .is-holiday{
  886. // .day-solar{color: #AAAAAA !important;}
  887. // .day-sign{color: #AAAAAA !important;}
  888. // }
  889. // 当前选中的日期
  890. .is-sel {
  891. background-color: $com-cd3;
  892. border-radius: 16rpx;
  893. .day-solar{color: #ffffff !important;
  894. &.coa{color: #ffffff !important;}
  895. &.co16{color: #ffffff !important;}
  896. }
  897. .day-sign{color: #ffffff !important;}
  898. }
  899. }
  900. }
  901. // .week-days.week-hide {
  902. // display: none;
  903. // }
  904. }
  905. .item-week {
  906. .un-month {
  907. opacity: 1 !important;
  908. }
  909. }
  910. }
  911. }
  912. // 收缩按钮
  913. .shrink {
  914. display: flex;
  915. justify-content: center;
  916. align-items: center;
  917. height: 60rpx;
  918. // border-top: 1px solid #DDD;
  919. .shrink-img{width: 32rpx;height: 18rpx;}
  920. /* #ifndef APP-NVUE */
  921. .shrink-btn {
  922. width: 32rpx;
  923. height: 32rpx;
  924. background: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAMhJREFUOE/dky8LAkEQxd9w0WjV72KxWXfggmAyWWzXxHbNYjIJhoOZarvid9FqNB4jCyes3h9OLghu3fceb36zS+h5qKcf/xYgIisAayJKnHMa8lFVZ2YpgB0z7193FQYisgCwAXA3s8QLicgbhwC2zHwMgxshBkFeXzE2Nvh2rW8NsiybRFE0ZuZTXZCIzIuiuMZxfKltICJTAAciegDwIM9eqKozAKmZDQAsmTlvHSGY/1YKR00cWl9iGYRP8p220BXm7//CE8WyQBHBXZb9AAAAAElFTkSuQmCC);
  925. }
  926. .shrink-close {
  927. transform: rotate(180deg);
  928. }
  929. /* #endif */
  930. /* #ifdef APP-NVUE */
  931. .shrink-btn{
  932. content: '';
  933. display: flex;
  934. width: 18rpx;
  935. height: 18rpx;
  936. border-top: 2rpx solid #606266;
  937. border-left: 2rpx solid #606266;
  938. transform: rotate(-135deg);
  939. }
  940. .shrink-close {
  941. transform: rotate(45deg);
  942. }
  943. /* #endif */
  944. }
  945. }
  946. </style>