123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543 |
- import WxData from './wxData'
- import CalendarConfig from './config'
- import convertSolarLunar from './convertSolarLunar'
- import {
- Logger,
- GetDate,
- getDateTimeStamp,
- uniqueArrayByDate,
- delRepeatedEnableDay,
- convertEnableAreaToTimestamp,
- converEnableDaysToTimestamp
- } from './utils'
- const logger = new Logger()
- const getDate = new GetDate()
- const toString = Object.prototype.toString
- class Day extends WxData {
- constructor(component) {
- super(component)
- this.Component = component
- }
- getCalendarConfig() {
- return this.Component.config
- }
- /**
- *
- * @param {number} year
- * @param {number} month
- */
- buildDate(year, month) {
- const today = getDate.todayDate()
- const thisMonthDays = getDate.thisMonthDays(year, month)
- const dates = []
- for (let i = 1; i <= thisMonthDays; i++) {
- const isToday =
- +today.year === +year && +today.month === +month && i === +today.date
- const config = this.getCalendarConfig()
- const date = {
- year,
- month,
- day: i,
- choosed: false,
- week: getDate.dayOfWeek(year, month, i),
- isToday: isToday && config.highlightToday,
- lunar: convertSolarLunar.solar2lunar(+year, +month, +i)
- }
- dates.push(date)
- }
- return dates
- }
- /**
- * 指定可选日期范围
- * @param {array} area 日期访问数组
- */
- enableArea(dateArea = []) {
- if (dateArea.length === 2) {
- const isRight = this.__judgeParam(dateArea)
- if (isRight) {
- let { days = [], selectedDay = [] } = this.getData('calendar')
- const { startTimestamp, endTimestamp } = convertEnableAreaToTimestamp(
- dateArea
- )
- const dataAfterHandle = this.__handleEnableArea(
- {
- dateArea,
- days,
- startTimestamp,
- endTimestamp
- },
- selectedDay
- )
- this.setData({
- 'calendar.enableArea': dateArea,
- 'calendar.days': dataAfterHandle.dates,
- 'calendar.selectedDay': dataAfterHandle.selectedDay,
- 'calendar.enableAreaTimestamp': [startTimestamp, endTimestamp]
- })
- }
- } else {
- logger.warn(
- 'enableArea()参数需为时间范围数组,形如:["2018-8-4" , "2018-8-24"]'
- )
- }
- }
- /**
- * 指定特定日期可选
- * @param {array} days 指定日期数组
- */
- enableDays(dates = []) {
- const { enableArea = [] } = this.getData('calendar')
- let expectEnableDaysTimestamp = []
- if (enableArea.length) {
- expectEnableDaysTimestamp = delRepeatedEnableDay(dates, enableArea)
- } else {
- expectEnableDaysTimestamp = converEnableDaysToTimestamp(dates)
- }
- let { days = [], selectedDay = [] } = this.getData('calendar')
- const dataAfterHandle = this.__handleEnableDays(
- {
- days,
- expectEnableDaysTimestamp
- },
- selectedDay
- )
- this.setData({
- 'calendar.days': dataAfterHandle.dates,
- 'calendar.selectedDay': dataAfterHandle.selectedDay,
- 'calendar.enableDays': dates,
- 'calendar.enableDaysTimestamp': expectEnableDaysTimestamp
- })
- }
- /**
- * 设置多个日期选中
- * @param {array} selected 需选中日期
- */
- setSelectedDays(selected) {
- const config = CalendarConfig(this.Component).getCalendarConfig()
- if (!config.multi) {
- return logger.warn('单选模式下不能设置多日期选中,请配置 multi')
- }
- let { days } = this.getData('calendar')
- let newSelectedDay = []
- if (!selected) {
- days.map(item => {
- item.choosed = true
- item.showTodoLabel = false
- })
- newSelectedDay = days
- } else if (selected && selected.length) {
- const { dates, selectedDates } = this.__handleSelectedDays(
- days,
- newSelectedDay,
- selected
- )
- days = dates
- newSelectedDay = selectedDates
- }
- CalendarConfig(this.Component).setCalendarConfig('multi', true)
- this.setData({
- 'calendar.days': days,
- 'calendar.selectedDay': newSelectedDay
- })
- }
- /**
- * 禁用指定日期
- * @param {array} dates 禁用
- */
- disableDays(dates) {
- const { disableDays = [], days } = this.getData('calendar')
- if (Object.prototype.toString.call(dates) !== '[object Array]') {
- return logger.warn('disableDays 参数为数组')
- }
- let _disableDays = []
- if (dates.length) {
- _disableDays = uniqueArrayByDate(dates.concat(disableDays))
- const disableDaysCol = _disableDays.map(d => getDate.toTimeStr(d))
- days.forEach(item => {
- const cur = getDate.toTimeStr(item)
- if (disableDaysCol.includes(cur)) item.disable = true
- })
- } else {
- days.forEach(item => {
- item.disable = false
- })
- }
- this.setData({
- 'calendar.days': days,
- 'calendar.disableDays': _disableDays
- })
- }
- /**
- * 设置连续日期选择区域
- * @param {array} dateArea 区域开始结束日期数组
- */
- chooseArea(dateArea = []) {
- return new Promise((resolve, reject) => {
- if (dateArea.length === 1) {
- dateArea = dateArea.concat(dateArea)
- }
- if (dateArea.length === 2) {
- const isRight = this.__judgeParam(dateArea)
- if (isRight) {
- const config = CalendarConfig(this.Component).getCalendarConfig()
- const { startTimestamp, endTimestamp } = convertEnableAreaToTimestamp(
- dateArea
- )
- this.setData(
- {
- calendarConfig: {
- ...config,
- chooseAreaMode: true,
- mulit: true
- },
- 'calendar.chooseAreaTimestamp': [startTimestamp, endTimestamp]
- },
- () => {
- this.__chooseContinuousDates(startTimestamp, endTimestamp)
- .then(resolve)
- .catch(reject)
- }
- )
- }
- }
- })
- }
- __pusheNextMonthDateArea(item, startTimestamp, endTimestamp, selectedDates) {
- const days = this.buildDate(item.year, item.month)
- let daysLen = days.length
- for (let i = 0; i < daysLen; i++) {
- const item = days[i]
- const timeStamp = getDateTimeStamp(item)
- if (timeStamp <= endTimestamp && timeStamp >= startTimestamp) {
- selectedDates.push({
- ...item,
- choosed: true
- })
- }
- if (i === daysLen - 1 && timeStamp < endTimestamp) {
- this.__pusheNextMonthDateArea(
- getDate.nextMonth(item),
- startTimestamp,
- endTimestamp,
- selectedDates
- )
- }
- }
- }
- __pushPrevMonthDateArea(item, startTimestamp, endTimestamp, selectedDates) {
- const days = getDate.sortDates(
- this.buildDate(item.year, item.month),
- 'desc'
- )
- let daysLen = days.length
- let firstDate = getDateTimeStamp(days[0])
- for (let i = 0; i < daysLen; i++) {
- const item = days[i]
- const timeStamp = getDateTimeStamp(item)
- if (timeStamp >= startTimestamp && timeStamp <= endTimestamp) {
- selectedDates.push({
- ...item,
- choosed: true
- })
- }
- if (i === daysLen - 1 && firstDate > startTimestamp) {
- this.__pushPrevMonthDateArea(
- getDate.prevMonth(item),
- startTimestamp,
- endTimestamp,
- selectedDates
- )
- }
- }
- }
- /**
- * 当设置日期区域非当前时保存其他月份的日期至已选日期数组
- * @param {object} info
- */
- __calcDateWhenNotInOneMonth(info) {
- const {
- firstDate,
- lastDate,
- startTimestamp,
- endTimestamp,
- filterSelectedDate
- } = info
- if (getDateTimeStamp(firstDate) > startTimestamp) {
- this.__pushPrevMonthDateArea(
- getDate.prevMonth(firstDate),
- startTimestamp,
- endTimestamp,
- filterSelectedDate
- )
- }
- if (getDateTimeStamp(lastDate) < endTimestamp) {
- this.__pusheNextMonthDateArea(
- getDate.nextMonth(lastDate),
- startTimestamp,
- endTimestamp,
- filterSelectedDate
- )
- }
- const newSelectedDates = [...getDate.sortDates(filterSelectedDate)]
- return newSelectedDates
- }
- /**
- * 设置连续日期段
- * @param {number} startTimestamp 连续日期段开始日期时间戳
- * @param {number} endTimestamp 连续日期段结束日期时间戳
- */
- __chooseContinuousDates(startTimestamp, endTimestamp) {
- return new Promise((resolve, reject) => {
- const { days, selectedDay = [] } = this.getData('calendar')
- const selectedDateStr = []
- let filterSelectedDate = []
- selectedDay.forEach(item => {
- const timeStamp = getDateTimeStamp(item)
- if (timeStamp >= startTimestamp && timeStamp <= endTimestamp) {
- filterSelectedDate.push(item)
- selectedDateStr.push(getDate.toTimeStr(item))
- }
- })
- days.forEach(item => {
- const timeStamp = getDateTimeStamp(item)
- const dateInSelecedArray = selectedDateStr.includes(
- getDate.toTimeStr(item)
- )
- if (timeStamp >= startTimestamp && timeStamp <= endTimestamp) {
- if (dateInSelecedArray) {
- return
- }
- item.choosed = true
- filterSelectedDate.push(item)
- } else {
- item.choosed = false
- if (dateInSelecedArray) {
- const idx = filterSelectedDate.findIndex(
- selectedDate =>
- getDate.toTimeStr(selectedDate) === getDate.toTimeStr(item)
- )
- if (idx > -1) {
- filterSelectedDate.splice(idx, 1)
- }
- }
- }
- })
- const firstDate = days[0]
- const lastDate = days[days.length - 1]
- const newSelectedDates = this.__calcDateWhenNotInOneMonth({
- firstDate,
- lastDate,
- startTimestamp,
- endTimestamp,
- filterSelectedDate
- })
- try {
- this.setData(
- {
- 'calendar.days': [...days],
- 'calendar.selectedDay': newSelectedDates
- },
- () => {
- resolve(newSelectedDates)
- }
- )
- } catch (err) {
- reject(err)
- }
- })
- }
- /**
- * 设置指定日期样式
- * @param {array} dates 待设置特殊样式的日期
- */
- setDateStyle(dates) {
- if (toString.call(dates) !== '[object Array]') return
- const { days, specialStyleDates } = this.getData('calendar')
- if (toString.call(specialStyleDates) === '[object Array]') {
- dates = uniqueArrayByDate([...specialStyleDates, ...dates])
- }
- const _specialStyleDates = dates.map(
- item => `${item.year}_${item.month}_${item.day}`
- )
- const _days = days.map(item => {
- const idx = _specialStyleDates.indexOf(
- `${item.year}_${item.month}_${item.day}`
- )
- if (idx > -1) {
- return {
- ...item,
- class: dates[idx].class
- }
- } else {
- return { ...item }
- }
- })
- this.setData({
- 'calendar.days': _days,
- 'calendar.specialStyleDates': dates
- })
- }
- __judgeParam(dateArea) {
- const {
- start,
- end,
- startTimestamp,
- endTimestamp
- } = convertEnableAreaToTimestamp(dateArea)
- if (!start || !end) return
- const startMonthDays = getDate.thisMonthDays(start[0], start[1])
- const endMonthDays = getDate.thisMonthDays(end[0], end[1])
- if (start[2] > startMonthDays || start[2] < 1) {
- logger.warn('enableArea() 开始日期错误,指定日期不在当前月份天数范围内')
- return false
- } else if (start[1] > 12 || start[1] < 1) {
- logger.warn('enableArea() 开始日期错误,月份超出1-12月份')
- return false
- } else if (end[2] > endMonthDays || end[2] < 1) {
- logger.warn('enableArea() 截止日期错误,指定日期不在当前月份天数范围内')
- return false
- } else if (end[1] > 12 || end[1] < 1) {
- logger.warn('enableArea() 截止日期错误,月份超出1-12月份')
- return false
- } else if (startTimestamp > endTimestamp) {
- logger.warn('enableArea()参数最小日期大于了最大日期')
- return false
- } else {
- return true
- }
- }
- __getDisableDateTimestamp() {
- let disableDateTimestamp
- const { date, type } = this.getCalendarConfig().disableMode || {}
- if (date) {
- const t = date.split('-')
- if (t.length < 3) {
- logger.warn('配置 disableMode.date 格式错误')
- return {}
- }
- disableDateTimestamp = getDateTimeStamp({
- year: +t[0],
- month: +t[1],
- day: +t[2]
- })
- }
- return {
- disableDateTimestamp,
- disableType: type
- }
- }
- __handleEnableArea(data = {}, selectedDay = []) {
- const { area, days, startTimestamp, endTimestamp } = data
- const enableDays = this.getData('calendar.enableDays') || []
- let expectEnableDaysTimestamp = []
- if (enableDays.length) {
- expectEnableDaysTimestamp = delRepeatedEnableDay(enableDays, area)
- }
- const {
- disableDateTimestamp,
- disableType
- } = this.__getDisableDateTimestamp()
- const dates = [...days]
- dates.forEach(item => {
- const timestamp = +getDate
- .newDate(item.year, item.month, item.day)
- .getTime()
- const ifOutofArea =
- (+startTimestamp > timestamp || timestamp > +endTimestamp) &&
- !expectEnableDaysTimestamp.includes(timestamp)
- if (
- ifOutofArea ||
- (disableType === 'before' &&
- disableDateTimestamp &&
- timestamp < disableDateTimestamp) ||
- (disableType === 'after' &&
- disableDateTimestamp &&
- timestamp > disableDateTimestamp)
- ) {
- item.disable = true
- if (item.choosed) {
- item.choosed = false
- selectedDay = selectedDay.filter(
- d => getDate.toTimeStr(item) !== getDate.toTimeStr(d)
- )
- }
- } else if (item.disable) {
- item.disable = false
- }
- })
- return {
- dates,
- selectedDay
- }
- }
- __handleEnableDays(data = {}, selectedDay = []) {
- const { days, expectEnableDaysTimestamp } = data
- const { enableAreaTimestamp = [] } = this.getData('calendar')
- const dates = [...days]
- dates.forEach(item => {
- const timestamp = getDate
- .newDate(item.year, item.month, item.day)
- .getTime()
- let setDisable = false
- if (enableAreaTimestamp.length) {
- if (
- (+enableAreaTimestamp[0] > +timestamp ||
- +timestamp > +enableAreaTimestamp[1]) &&
- !expectEnableDaysTimestamp.includes(+timestamp)
- ) {
- setDisable = true
- }
- } else if (!expectEnableDaysTimestamp.includes(+timestamp)) {
- setDisable = true
- }
- if (setDisable) {
- item.disable = true
- if (item.choosed) {
- item.choosed = false
- selectedDay = selectedDay.filter(
- d => getDate.toTimeStr(item) !== getDate.toTimeStr(d)
- )
- }
- } else {
- item.disable = false
- }
- })
- return {
- dates,
- selectedDay
- }
- }
- __handleSelectedDays(days = [], newSelectedDay = [], selected) {
- const { selectedDay, showLabelAlways } = this.getData('calendar')
- if (selectedDay && selectedDay.length) {
- newSelectedDay = uniqueArrayByDate(selectedDay.concat(selected))
- } else {
- newSelectedDay = selected
- }
- const { year: curYear, month: curMonth } = days[0]
- const currentSelectedDays = []
- newSelectedDay.forEach(item => {
- if (+item.year === +curYear && +item.month === +curMonth) {
- currentSelectedDays.push(getDate.toTimeStr(item))
- }
- })
- ;[...days].map(item => {
- if (currentSelectedDays.includes(getDate.toTimeStr(item))) {
- item.choosed = true
- if (showLabelAlways && item.showTodoLabel) {
- item.showTodoLabel = true
- } else {
- item.showTodoLabel = false
- }
- }
- })
- return {
- dates: days,
- selectedDates: newSelectedDay
- }
- }
- }
- export default component => new Day(component)
|