index.vue 9.4KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194
  1. <template>
  2. <uni-shadow-root class="vant-dist-calendar-components-month-index"><view class="van-calendar__month" :style="computed.getMonthStyle(visible, date, rowHeight)">
  3. <view v-if="showMonthTitle" class="van-calendar__month-title">
  4. {{ computed.formatMonthTitle(date) }}
  5. </view>
  6. <view v-if="visible" class="van-calendar__days">
  7. <view v-if="showMark" class="van-calendar__month-mark">
  8. {{ computed.getMark(date) }}
  9. </view>
  10. <view v-for="(item,index) in (days)" :key="item.index" :style="computed.getDayStyle(item.type, index, date, rowHeight, color, firstDayOfWeek)" :class="(utils.bem('calendar__day', [item.type]))+' '+(item.className)" :data-index="index" @click="onClick">
  11. <view v-if="item.type === 'selected'" class="van-calendar__selected-day" :style="'background: '+(color)">
  12. <view v-if="item.topInfo" class="van-calendar__top-info">{{ item.topInfo }}</view>
  13. {{ item.text }}
  14. <view v-if="item.bottomInfo" class="van-calendar__bottom-info">
  15. {{ item.bottomInfo }}
  16. </view>
  17. </view>
  18. <view v-else>
  19. <view v-if="item.topInfo" class="van-calendar__top-info">{{ item.topInfo }}</view>
  20. {{ item.text }}
  21. <view v-if="item.bottomInfo" class="van-calendar__bottom-info">
  22. {{ item.bottomInfo }}
  23. </view>
  24. </view>
  25. </view>
  26. </view>
  27. </view></uni-shadow-root>
  28. </template>
  29. <wxs src="./index.wxs" module="computed"></wxs><wxs src="../../../wxs/utils.wxs" module="utils"></wxs>
  30. <script>
  31. global['__wxRoute'] = 'vant/dist/calendar/components/month/index'
  32. import { VantComponent } from '../../../common/component';
  33. import { getMonthEndDay, compareDay, getPrevDay, getNextDay, } from '../../utils';
  34. VantComponent({
  35. props: {
  36. date: {
  37. type: null,
  38. observer: 'setDays',
  39. },
  40. type: {
  41. type: String,
  42. observer: 'setDays',
  43. },
  44. color: String,
  45. minDate: {
  46. type: null,
  47. observer: 'setDays',
  48. },
  49. maxDate: {
  50. type: null,
  51. observer: 'setDays',
  52. },
  53. showMark: Boolean,
  54. rowHeight: null,
  55. formatter: {
  56. type: null,
  57. observer: 'setDays',
  58. },
  59. currentDate: {
  60. type: null,
  61. observer: 'setDays',
  62. },
  63. firstDayOfWeek: {
  64. type: Number,
  65. observer: 'setDays',
  66. },
  67. allowSameDay: Boolean,
  68. showSubtitle: Boolean,
  69. showMonthTitle: Boolean,
  70. },
  71. data: {
  72. visible: true,
  73. days: [],
  74. },
  75. methods: {
  76. onClick(event) {
  77. const { index } = event.currentTarget.dataset;
  78. const item = this.data.days[index];
  79. if (item.type !== 'disabled') {
  80. this.$emit('click', item);
  81. }
  82. },
  83. setDays() {
  84. const days = [];
  85. const startDate = new Date(this.data.date);
  86. const year = startDate.getFullYear();
  87. const month = startDate.getMonth();
  88. const totalDay = getMonthEndDay(startDate.getFullYear(), startDate.getMonth() + 1);
  89. for (let day = 1; day <= totalDay; day++) {
  90. const date = new Date(year, month, day);
  91. const type = this.getDayType(date);
  92. let config = {
  93. date,
  94. type,
  95. text: day,
  96. bottomInfo: this.getBottomInfo(type),
  97. };
  98. if (this.data.formatter) {
  99. config = this.data.formatter(config);
  100. }
  101. days.push(config);
  102. }
  103. this.setData({ days });
  104. },
  105. getMultipleDayType(day) {
  106. const { currentDate } = this.data;
  107. if (!Array.isArray(currentDate)) {
  108. return '';
  109. }
  110. const isSelected = (date) => currentDate.some((item) => compareDay(item, date) === 0);
  111. if (isSelected(day)) {
  112. const prevDay = getPrevDay(day);
  113. const nextDay = getNextDay(day);
  114. const prevSelected = isSelected(prevDay);
  115. const nextSelected = isSelected(nextDay);
  116. if (prevSelected && nextSelected) {
  117. return 'multiple-middle';
  118. }
  119. if (prevSelected) {
  120. return 'end';
  121. }
  122. return nextSelected ? 'start' : 'multiple-selected';
  123. }
  124. return '';
  125. },
  126. getRangeDayType(day) {
  127. const { currentDate, allowSameDay } = this.data;
  128. if (!Array.isArray(currentDate)) {
  129. return '';
  130. }
  131. const [startDay, endDay] = currentDate;
  132. if (!startDay) {
  133. return '';
  134. }
  135. const compareToStart = compareDay(day, startDay);
  136. if (!endDay) {
  137. return compareToStart === 0 ? 'start' : '';
  138. }
  139. const compareToEnd = compareDay(day, endDay);
  140. if (compareToStart === 0 && compareToEnd === 0 && allowSameDay) {
  141. return 'start-end';
  142. }
  143. if (compareToStart === 0) {
  144. return 'start';
  145. }
  146. if (compareToEnd === 0) {
  147. return 'end';
  148. }
  149. if (compareToStart > 0 && compareToEnd < 0) {
  150. return 'middle';
  151. }
  152. return '';
  153. },
  154. getDayType(day) {
  155. const { type, minDate, maxDate, currentDate } = this.data;
  156. if (compareDay(day, minDate) < 0 || compareDay(day, maxDate) > 0) {
  157. return 'disabled';
  158. }
  159. if (type === 'single') {
  160. return compareDay(day, currentDate) === 0 ? 'selected' : '';
  161. }
  162. if (type === 'multiple') {
  163. return this.getMultipleDayType(day);
  164. }
  165. /* istanbul ignore else */
  166. if (type === 'range') {
  167. return this.getRangeDayType(day);
  168. }
  169. return '';
  170. },
  171. getBottomInfo(type) {
  172. if (this.data.type === 'range') {
  173. if (type === 'start') {
  174. return '开始';
  175. }
  176. if (type === 'end') {
  177. return '结束';
  178. }
  179. if (type === 'start-end') {
  180. return '开始/结束';
  181. }
  182. }
  183. },
  184. },
  185. });
  186. export default global['__wxComponents']['vant/dist/calendar/components/month/index']
  187. </script>
  188. <style platform="mp-weixin">
  189. @import '../../../common/index.css';.van-calendar{display:flex;flex-direction:column;height:100%;background-color:#fff;background-color:var(--calendar-background-color,#fff)}.van-calendar__month-title{text-align:center;height:44px;height:var(--calendar-header-title-height,44px);font-weight:500;font-weight:var(--font-weight-bold,500);font-size:14px;font-size:var(--calendar-month-title-font-size,14px);line-height:44px;line-height:var(--calendar-header-title-height,44px)}.van-calendar__days{position:relative;display:flex;flex-wrap:wrap;-webkit-user-select:none;user-select:none}.van-calendar__month-mark{position:absolute;top:50%;left:50%;z-index:0;transform:translate(-50%,-50%);pointer-events:none;color:rgba(242,243,245,.8);color:var(--calendar-month-mark-color,rgba(242,243,245,.8));font-size:160px;font-size:var(--calendar-month-mark-font-size,160px)}.van-calendar__day,.van-calendar__selected-day{display:flex;align-items:center;justify-content:center;text-align:center}.van-calendar__day{position:relative;width:14.285%;height:64px;height:var(--calendar-day-height,64px);font-size:16px;font-size:var(--calendar-day-font-size,16px)}.van-calendar__day--end,.van-calendar__day--multiple-middle,.van-calendar__day--multiple-selected,.van-calendar__day--start,.van-calendar__day--start-end{color:#fff;color:var(--calendar-range-edge-color,#fff);background-color:#ee0a24;background-color:var(--calendar-range-edge-background-color,#ee0a24)}.van-calendar__day--start{border-radius:4px 0 0 4px;border-radius:var(--border-radius-md,4px) 0 0 var(--border-radius-md,4px)}.van-calendar__day--end{border-radius:0 4px 4px 0;border-radius:0 var(--border-radius-md,4px) var(--border-radius-md,4px) 0}.van-calendar__day--multiple-selected,.van-calendar__day--start-end{border-radius:4px;border-radius:var(--border-radius-md,4px)}.van-calendar__day--middle{color:#ee0a24;color:var(--calendar-range-middle-color,#ee0a24)}.van-calendar__day--middle:after{position:absolute;top:0;right:0;bottom:0;left:0;background-color:currentColor;content:"";opacity:.1;opacity:var(--calendar-range-middle-background-opacity,.1)}.van-calendar__day--disabled{cursor:default;color:#c8c9cc;color:var(--calendar-day-disabled-color,#c8c9cc)}.van-calendar__bottom-info,.van-calendar__top-info{position:absolute;right:0;left:0;font-size:10px;font-size:var(--calendar-info-font-size,10px);line-height:14px;line-height:var(--calendar-info-line-height,14px)}@media (max-width:350px){.van-calendar__bottom-info,.van-calendar__top-info{font-size:9px}}.van-calendar__top-info{top:6px}.van-calendar__bottom-info{bottom:6px}.van-calendar__selected-day{width:54px;width:var(--calendar-selected-day-size,54px);height:54px;height:var(--calendar-selected-day-size,54px);color:#fff;color:var(--calendar-selected-day-color,#fff);background-color:#ee0a24;background-color:var(--calendar-selected-day-background-color,#ee0a24);border-radius:4px;border-radius:var(--border-radius-md,4px)}
  190. </style>