index.tsx 6.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207
  1. import { Button, Calendar, Dialog, Icon, Image, Popup, showToast, Tag, Toast } from 'vant'
  2. import { defineComponent } from 'vue'
  3. import dayjs from 'dayjs'
  4. import styles from './index.module.less'
  5. import IconArrow from '../../images/icon_arrow.png'
  6. import IconArrowDefault from '../../images/icon_arrow_default.png'
  7. import isToday from 'dayjs/plugin/isToday'
  8. import isSameOrBefore from 'dayjs/plugin/isSameOrBefore'
  9. import OHeader from '@/components/o-header'
  10. dayjs.extend(isToday)
  11. dayjs.extend(isSameOrBefore)
  12. export default defineComponent({
  13. name: 'calendar',
  14. props: {
  15. /**
  16. * @description 选中的日期
  17. */
  18. calendarDate: {
  19. type: String,
  20. default: ''
  21. },
  22. // 接口数据
  23. list: {
  24. type: Array,
  25. default: () => []
  26. },
  27. /**
  28. * 点击并选中任意日期时触发
  29. */
  30. onSelect: {
  31. type: Function,
  32. default: (date: Date) => {}
  33. },
  34. /**
  35. * 上一月,不能小于当月
  36. */
  37. prevMonth: {
  38. type: Function,
  39. default: (date: Date) => {}
  40. },
  41. /**
  42. * 下一月,暂无限制
  43. */
  44. nextMonth: {
  45. type: Function,
  46. default: (date: Date) => {}
  47. },
  48. /**
  49. * 日期选择结束时触发
  50. */
  51. selectDay: {
  52. type: Function,
  53. default: (obj: any) => {}
  54. },
  55. /**
  56. * 销毁时
  57. * */
  58. onDestory: {
  59. type: Function,
  60. default: () => {}
  61. }
  62. },
  63. data() {
  64. return {
  65. minDate: new Date(),
  66. maxDate: new Date(),
  67. currentDate: dayjs().toDate(), // 当前日历日期
  68. subtitle: '',
  69. dayList: [],
  70. selectDays: [] as any
  71. }
  72. },
  73. computed: {
  74. arrowStatus() {
  75. // 上月箭头状态
  76. return !dayjs().isBefore(dayjs(this.currentDate), 'month')
  77. },
  78. selectDayTitle() {
  79. // 选中日期标题
  80. return dayjs(this.currentDate).format('YYYY-MM-DD')
  81. }
  82. },
  83. watch: {
  84. calendarDate() {
  85. // 初始化标题和最大显示日期
  86. this.subtitle = dayjs(this.calendarDate || new Date()).format('YYYY年MM月')
  87. this.maxDate = dayjs(this.calendarDate || new Date())
  88. .endOf('month')
  89. .toDate()
  90. this.minDate = dayjs(this.calendarDate || new Date()).toDate()
  91. this.currentDate = dayjs(this.calendarDate || new Date()).toDate()
  92. }
  93. },
  94. mounted() {
  95. // 初始化标题和最大显示日期
  96. this.subtitle = dayjs(this.calendarDate || new Date()).format('YYYY年MM月')
  97. this.maxDate = dayjs(this.calendarDate || new Date())
  98. .endOf('month')
  99. .toDate()
  100. this.minDate = dayjs(this.calendarDate || new Date()).toDate()
  101. this.currentDate = dayjs(this.calendarDate || new Date()).toDate()
  102. console.log(this.list, 'this.list')
  103. console.log(this.calendarDate, 'calendarDate')
  104. },
  105. methods: {
  106. formatter(date: any) {
  107. const dateStr = dayjs(date.date).format('YYYY-MM-DD')
  108. let isActive = false // 是否可选
  109. this.list.forEach((item: any) => {
  110. // console.log(dateStr, item.calendarDate)
  111. if (item.calendarDate === dateStr) {
  112. isActive = true
  113. }
  114. })
  115. // 判断是否有课程 并且 时间在当前时间之后
  116. // console.log(dayjs().isSameOrBefore(dayjs(date.date)), date.date)
  117. if (isActive && dayjs(dayjs().format('YYYY-MM-DD')).isSameOrBefore(dayjs(date.date))) {
  118. date.bottomInfo = '可选'
  119. if (dayjs(dateStr).isSame(this.calendarDate)) {
  120. date.type = 'selected'
  121. } else {
  122. date.type = ''
  123. }
  124. } else {
  125. date.type = 'disabled'
  126. }
  127. return date
  128. },
  129. onPrevMonth() {
  130. // 上一月
  131. if (this.arrowStatus) return
  132. const tempDate = dayjs(this.currentDate).subtract(1, 'month')
  133. this._monthChange(tempDate)
  134. // this._dayChange(this.minDate)
  135. this.prevMonth && this.prevMonth(this.minDate)
  136. },
  137. onNextMonth() {
  138. // 下一月
  139. const tempDate = dayjs(this.currentDate).add(1, 'month')
  140. this._monthChange(tempDate)
  141. // this._dayChange(this.minDate)
  142. this.nextMonth && this.nextMonth(this.minDate)
  143. },
  144. _monthChange(date: any) {
  145. // 月份改变
  146. // 需要判断是否是当月,需要单独处理最小时间
  147. const currentMinDate = dayjs().add(1, 'day').toDate()
  148. const monthMinDate = date.startOf('month').toDate()
  149. this.minDate = dayjs(currentMinDate).isAfter(monthMinDate) ? currentMinDate : monthMinDate
  150. this.maxDate = date.endOf('month').toDate()
  151. this.currentDate = date.toDate()
  152. this.subtitle = date.format('YYYY年MM月')
  153. },
  154. onDateSelect(date: any) {
  155. // 选择日历上某一个日期
  156. this._dayChange(date)
  157. this.onSelect && this.onSelect(date)
  158. },
  159. _dayChange(date: Date) {
  160. this.currentDate = date // 更新当前日期
  161. this.$emit('update:calendarDate', dayjs(date).format('YYYY-MM-DD'))
  162. }
  163. },
  164. unmounted() {
  165. this.onDestory()
  166. },
  167. render() {
  168. return (
  169. <div class={styles.calendarContainer}>
  170. <OHeader title="训练日期" border={false} background="transparent" desotry={false} />
  171. <Calendar
  172. class={styles.calendar}
  173. showTitle={false}
  174. poppable={false}
  175. showConfirm={false}
  176. showMark={false}
  177. firstDayOfWeek={1}
  178. rowHeight={62}
  179. minDate={this.minDate}
  180. maxDate={this.maxDate}
  181. defaultDate={dayjs(this.calendarDate || '').toDate()}
  182. color="var(--van-primary)"
  183. formatter={this.formatter}
  184. onSelect={this.onDateSelect}
  185. v-slots={{
  186. subtitle: () => (
  187. <div class={styles.subtitle}>
  188. <span>{this.subtitle}</span>
  189. <div>
  190. <Icon
  191. name={this.arrowStatus ? IconArrowDefault : IconArrow}
  192. size={22}
  193. class={[styles.right]}
  194. onClick={this.onPrevMonth}
  195. />
  196. <Icon name={IconArrow} size={22} onClick={this.onNextMonth} />
  197. </div>
  198. </div>
  199. )
  200. }}
  201. />
  202. </div>
  203. )
  204. }
  205. })