const DAY_NUM = 42 const WEEK_DAY_NUM = 7 const DATE_CHECK = /^(\d{4})-(\d{2})-(\d{2})$/ Component({ externalClasses: ['calendar-class'], properties: { defaultSelectDate: { type: String, value: '' }, mode: { type: String, value: '' }, showToday: { type: Boolean, value: true } }, data: { pickDate: '', pickDateDisplay: '', tMonthFirstDayWeek: 0, allDays: [], selectedDate: '', today: '', dateRange: [] }, ready() { const now = new Date() if (!DATE_CHECK.test(this.data.defaultSelectDate)) { this.setData({ defaultSelectDate: '' }) } this.setData({ selectedDate: this.data.defaultSelectDate || this.parseTime(now, '{y}-{m}-{d}'), today: this.parseTime(now, '{y}-{m}-{d}') }) this.setCalendar(this.parseTime(now, '{y}-{m}')) }, methods: { setCalendar(dateStr) { const self = this const selectDate = new Date(dateStr) const pickDate = self.parseTime(selectDate, '{y}-{m}') const dateSplit = dateStr.split('-') const thisYear = dateSplit[0] const thisMonth = dateSplit[1] const tempWeek = new Date(`${self.parseTime(selectDate, '{y}-{m}-')}01`).getDay() const tMonthFirstDayWeek = tempWeek === 0 ? WEEK_DAY_NUM : tempWeek const lastMonthOrigin = [...Array(self.getMonthDayNum(selectDate.getFullYear(), selectDate.getMonth())).keys()] const thisMonthOrigin = [...Array(self.getMonthDayNum(selectDate.getFullYear(), selectDate.getMonth() + 1)).keys()] const nextMonthOrigin = [...Array(self.getMonthDayNum(selectDate.getFullYear(), selectDate.getMonth() + 2)).keys()] const lastMonthFinal = [...lastMonthOrigin].splice(lastMonthOrigin.length - (tMonthFirstDayWeek - 1), lastMonthOrigin.length) const nextMonthFinal = [...nextMonthOrigin].splice(0, DAY_NUM - lastMonthFinal.length - thisMonthOrigin.length) self.setData({ pickDate, pickDateDisplay: self.parseTime(selectDate, '{y}年{m}月'), tMonthFirstDayWeek, allDays: [ ...this.mapMonth(lastMonthFinal, thisYear, Number(thisMonth) - 1, pickDate), ...this.mapMonth(thisMonthOrigin, thisYear, Number(thisMonth), pickDate), ...this.mapMonth(nextMonthFinal, thisYear, Number(thisMonth) + 1, pickDate) ] }) }, mapMonth(dayArr, year, month, pickDate = null) { const thisMonthNum = pickDate && Number(pickDate.split('-')[1]) return dayArr.map(item => { const date = `${year}-${month < 10 ? `0${month}` : month}-${(item + 1) < 10 ? `0${item + 1}` : item + 1}` const week = new Date(date).getDay() return { dateNumber: item + 1, date, week: week === 0 ? 7 : week, position: thisMonthNum === month ? '' : month === thisMonthNum - 1 ? 'next-month' : 'pre-month' } }) }, bindPickDateChange(event) { const { value } = event.detail this.setData({ pickDate: value, pickDateDisplay: this.parseTime(value, '{y}年{m}月') }) this.setCalendar(value) this.triggerEvent('onPickDateChange', value) }, // 获取月天数 getMonthDayNum(year, month) { const d = new Date(year, month, 0) return d.getDate() }, control(event) { const { mode } = event.currentTarget.dataset const { pickDate } = this.data let dateArr = pickDate.split('-') let oldMonth = Number(dateArr[1]) let oldYear = Number(dateArr[0]) let newDate = '' switch(mode) { case 'pre': newDate = oldMonth === 1 ? `${oldYear - 1}-12` : `${oldYear}-${oldMonth - 1 < 10 ? `0${oldMonth - 1}` : oldMonth - 1}` break; case 'reset': newDate = this.data.defaultSelectDate || new Date() if (this.data.mode === 'range') { this.setData({ selectedDate: newDate, dateRange: [] }) } else { this.setData({ selectedDate: this.parseTime(newDate, '{y}-{m}-{d}') }) } break; case 'next': newDate = oldMonth === 12 ? `${oldYear + 1}-01` : `${oldYear}-${oldMonth + 1 < 10 ? `0${oldMonth + 1}` : oldMonth + 1}` break; } const timeParse = this.parseTime(new Date(newDate), '{y}-{m}') this.setCalendar(timeParse) if (mode !== 'reset' && this.data.mode === 'range') { this.findRange(this.data.dateRange) } this.triggerEvent('onControl', { mode, newDate: timeParse }) wx.vibrateShort() }, onPickDay(event) { const { day } = event.currentTarget.dataset const { mode } = this.data let dateRange = [...this.data.dateRange] if (mode === 'range') { this.setData({ selectedDate: '' }) if (!dateRange[0]) { dateRange.push(day.date) this.setData({ dateRange }) } else if (!dateRange[1]) { dateRange.push(day.date) dateRange.sort((a, b) => a > b ? 1 : -1) this.setData({ dateRange }) this.findRange(dateRange) this.triggerEvent('onRangePick', dateRange) } else { this.setData({ dateRange: [day.date] }) this.findRange([day.date]) } } else { this.setData({ selectedDate: day.date }) this.triggerEvent('onPickDay', day) } }, // 找出range内的日期 findRange(dateRange) { const minTimeStamp = Date.parse(dateRange[0]) const maxTimeStamp = Date.parse(dateRange[1]) let allDays = [...this.data.allDays] allDays.forEach(item => { const parseDate = Date.parse(item.date) item[`inRange`] = dateRange.length === 1 ? false : parseDate < maxTimeStamp && parseDate > minTimeStamp }) this.setData({ allDays }) }, parseTime(time, cFormat) { if (arguments.length === 0) { return null } const format = cFormat || '{y}-{m}-{d} {h}:{i}:{s}' let date if (typeof time === 'object') { date = time } else { if (('' + time).length === 10) time = parseInt(time) * 1000 date = new Date(time) } const formatObj = { y: date.getFullYear(), m: date.getMonth() + 1, d: date.getDate(), h: date.getHours(), i: date.getMinutes(), s: date.getSeconds(), a: date.getDay() } const timeStr = format.replace(/{(y|m|d|h|i|s|a)+}/g, (result, key) => { let value = formatObj[key] if (key === 'a') return ['一', '二', '三', '四', '五', '六', '日'][value - 1] if (result.length > 0 && value < 10) { value = '0' + value } return value || 0 }) return timeStr } } })