calendar.js 8.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238
  1. const DAY_NUM = 42
  2. const WEEK_DAY_NUM = 7
  3. const DATE_CHECK = /^(\d{4})-(\d{2})-(\d{2})$/
  4. Component({
  5. externalClasses: ['calendar-class'],
  6. properties: {
  7. defaultSelectDate: {
  8. type: String,
  9. value: ''
  10. },
  11. mode: {
  12. type: String,
  13. value: ''
  14. },
  15. showToday: {
  16. type: Boolean,
  17. value: true
  18. }
  19. },
  20. data: {
  21. pickDate: '',
  22. pickDateDisplay: '',
  23. tMonthFirstDayWeek: 0,
  24. allDays: [],
  25. selectedDate: '',
  26. today: '',
  27. dateRange: []
  28. },
  29. ready() {
  30. const now = new Date()
  31. if (!DATE_CHECK.test(this.data.defaultSelectDate)) {
  32. this.setData({
  33. defaultSelectDate: ''
  34. })
  35. }
  36. this.setData({
  37. selectedDate: this.data.defaultSelectDate || this.parseTime(now, '{y}-{m}-{d}'),
  38. today: this.parseTime(now, '{y}-{m}-{d}')
  39. })
  40. this.setCalendar(this.parseTime(now, '{y}-{m}'))
  41. },
  42. methods: {
  43. setCalendar(dateStr) {
  44. const self = this
  45. const selectDate = new Date(dateStr)
  46. const pickDate = self.parseTime(selectDate, '{y}-{m}')
  47. const dateSplit = dateStr.split('-')
  48. const thisYear = dateSplit[0]
  49. const thisMonth = dateSplit[1]
  50. const tempWeek = new Date(`${self.parseTime(selectDate, '{y}-{m}-')}01`).getDay()
  51. const tMonthFirstDayWeek = tempWeek === 0 ? WEEK_DAY_NUM : tempWeek
  52. const lastMonthOrigin = [...Array(self.getMonthDayNum(selectDate.getFullYear(), selectDate.getMonth())).keys()]
  53. const thisMonthOrigin = [...Array(self.getMonthDayNum(selectDate.getFullYear(), selectDate.getMonth() + 1)).keys()]
  54. const nextMonthOrigin = [...Array(self.getMonthDayNum(selectDate.getFullYear(), selectDate.getMonth() + 2)).keys()]
  55. const lastMonthFinal = [...lastMonthOrigin].splice(lastMonthOrigin.length - (tMonthFirstDayWeek - 1), lastMonthOrigin.length)
  56. const nextMonthFinal = [...nextMonthOrigin].splice(0, DAY_NUM - lastMonthFinal.length - thisMonthOrigin.length)
  57. self.setData({
  58. pickDate,
  59. pickDateDisplay: self.parseTime(selectDate, '{y}年{m}月'),
  60. tMonthFirstDayWeek,
  61. allDays: [
  62. ...this.mapMonth(lastMonthFinal, thisYear, Number(thisMonth) - 1, pickDate),
  63. ...this.mapMonth(thisMonthOrigin, thisYear, Number(thisMonth), pickDate),
  64. ...this.mapMonth(nextMonthFinal, thisYear, Number(thisMonth) + 1, pickDate)
  65. ]
  66. })
  67. },
  68. mapMonth(dayArr, year, month, pickDate = null) {
  69. const thisMonthNum = pickDate && Number(pickDate.split('-')[1])
  70. return dayArr.map(item => {
  71. const date = `${year}-${month < 10 ? `0${month}` : month}-${(item + 1) < 10 ? `0${item + 1}` : item + 1}`
  72. const week = new Date(date).getDay()
  73. return {
  74. dateNumber: item + 1,
  75. date,
  76. week: week === 0 ? 7 : week,
  77. position: thisMonthNum === month ? '' : month === thisMonthNum - 1 ? 'next-month' : 'pre-month'
  78. }
  79. })
  80. },
  81. bindPickDateChange(event) {
  82. const {
  83. value
  84. } = event.detail
  85. this.setData({
  86. pickDate: value,
  87. pickDateDisplay: this.parseTime(value, '{y}年{m}月')
  88. })
  89. this.setCalendar(value)
  90. this.triggerEvent('onPickDateChange', value)
  91. },
  92. // 获取月天数
  93. getMonthDayNum(year, month) {
  94. const d = new Date(year, month, 0)
  95. return d.getDate()
  96. },
  97. control(event) {
  98. const {
  99. mode
  100. } = event.currentTarget.dataset
  101. const {
  102. pickDate
  103. } = this.data
  104. let dateArr = pickDate.split('-')
  105. let oldMonth = Number(dateArr[1])
  106. let oldYear = Number(dateArr[0])
  107. let newDate = ''
  108. switch (mode) {
  109. case 'pre':
  110. newDate = oldMonth === 1 ? `${oldYear - 1}-12` : `${oldYear}-${oldMonth - 1 < 10 ? `0${oldMonth - 1}` : oldMonth - 1}`
  111. break;
  112. case 'reset':
  113. newDate = this.data.defaultSelectDate || new Date()
  114. if (this.data.mode === 'range') {
  115. this.setData({
  116. selectedDate: newDate,
  117. dateRange: []
  118. })
  119. } else {
  120. this.setData({
  121. selectedDate: this.parseTime(newDate, '{y}-{m}-{d}')
  122. })
  123. }
  124. break;
  125. case 'next':
  126. newDate = oldMonth === 12 ? `${oldYear + 1}-01` : `${oldYear}-${oldMonth + 1 < 10 ? `0${oldMonth + 1}` : oldMonth + 1}`
  127. break;
  128. }
  129. const timeParse = this.parseTime(new Date(newDate), '{y}-{m}')
  130. this.setCalendar(timeParse)
  131. if (mode !== 'reset' && this.data.mode === 'range') {
  132. this.findRange(this.data.dateRange)
  133. }
  134. this.triggerEvent('onControl', {
  135. mode,
  136. newDate: timeParse
  137. })
  138. wx.vibrateShort()
  139. },
  140. onPickDay(event) {
  141. const {
  142. day
  143. } = event.currentTarget.dataset
  144. const {
  145. mode
  146. } = this.data
  147. let dateRange = [...this.data.dateRange]
  148. if (mode === 'range') {
  149. this.setData({
  150. selectedDate: ''
  151. })
  152. if (!dateRange[0]) {
  153. dateRange.push(day.date)
  154. this.setData({
  155. dateRange
  156. })
  157. } else if (!dateRange[1]) {
  158. dateRange.push(day.date)
  159. dateRange.sort((a, b) => a > b ? 1 : -1)
  160. this.setData({
  161. dateRange
  162. })
  163. this.findRange(dateRange)
  164. this.triggerEvent('onRangePick', dateRange)
  165. } else {
  166. this.setData({
  167. dateRange: [day.date]
  168. })
  169. this.findRange([day.date])
  170. }
  171. } else {
  172. this.setData({
  173. selectedDate: day.date
  174. })
  175. this.triggerEvent('onPickDay', day)
  176. }
  177. },
  178. // 找出range内的日期
  179. findRange(dateRange) {
  180. const minTimeStamp = Date.parse(dateRange[0])
  181. const maxTimeStamp = Date.parse(dateRange[1])
  182. let allDays = [...this.data.allDays]
  183. allDays.forEach(item => {
  184. const parseDate = Date.parse(item.date)
  185. item[`inRange`] = dateRange.length === 1 ? false : parseDate < maxTimeStamp && parseDate > minTimeStamp
  186. })
  187. this.setData({
  188. allDays
  189. })
  190. },
  191. parseTime(time, cFormat) {
  192. if (arguments.length === 0) {
  193. return null
  194. }
  195. const format = cFormat || '{y}-{m}-{d} {h}:{i}:{s}'
  196. let date
  197. if (typeof time === 'object') {
  198. date = time
  199. } else {
  200. if (('' + time).length === 10) time = parseInt(time) * 1000
  201. date = new Date(time)
  202. }
  203. const formatObj = {
  204. y: date.getFullYear(),
  205. m: date.getMonth() + 1,
  206. d: date.getDate(),
  207. h: date.getHours(),
  208. i: date.getMinutes(),
  209. s: date.getSeconds(),
  210. a: date.getDay()
  211. }
  212. const timeStr = format.replace(/{(y|m|d|h|i|s|a)+}/g, (result, key) => {
  213. let value = formatObj[key]
  214. if (key === 'a') return ['一', '二', '三', '四', '五', '六', '日'][value - 1]
  215. if (result.length > 0 && value < 10) {
  216. value = '0' + value
  217. }
  218. return value || 0
  219. })
  220. return timeStr
  221. }
  222. }
  223. })