You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
306 lines
8.9 KiB
306 lines
8.9 KiB
|
3 weeks ago
|
/**
|
||
|
|
* @Author: drfu*
|
||
|
|
* @Description: 时间区域选择
|
||
|
|
* @Date: 2020-10-08 21:22:09*
|
||
|
|
* @Last Modified by: drfu
|
||
|
|
* @Last Modified time: 2020-10-11 13:56:32
|
||
|
|
* */
|
||
|
|
|
||
|
|
import { renderCalendar } from '../render'
|
||
|
|
import {
|
||
|
|
logger,
|
||
|
|
dateUtil,
|
||
|
|
getCalendarConfig,
|
||
|
|
getCalendarData
|
||
|
|
} from '../utils/index'
|
||
|
|
|
||
|
|
function pusheNextMonthDateArea(
|
||
|
|
dateInfo = {},
|
||
|
|
startTimestamp,
|
||
|
|
endTimestamp,
|
||
|
|
selectedDates = []
|
||
|
|
) {
|
||
|
|
let tempOfSelectedDate = [...selectedDates]
|
||
|
|
const dates = dateUtil.calcDates(dateInfo.year, dateInfo.month)
|
||
|
|
let datesLen = dates.length
|
||
|
|
for (let i = 0; i < datesLen; i++) {
|
||
|
|
const date = dates[i]
|
||
|
|
const timeStamp = dateUtil.getTimeStamp(date)
|
||
|
|
if (timeStamp <= endTimestamp && timeStamp >= startTimestamp) {
|
||
|
|
tempOfSelectedDate.push({
|
||
|
|
...date,
|
||
|
|
choosed: true
|
||
|
|
})
|
||
|
|
}
|
||
|
|
if (i === datesLen - 1 && timeStamp < endTimestamp) {
|
||
|
|
pusheNextMonthDateArea(
|
||
|
|
dateUtil.getNextMonthInfo(date),
|
||
|
|
startTimestamp,
|
||
|
|
endTimestamp,
|
||
|
|
tempOfSelectedDate
|
||
|
|
)
|
||
|
|
}
|
||
|
|
}
|
||
|
|
return tempOfSelectedDate
|
||
|
|
}
|
||
|
|
function pushPrevMonthDateArea(
|
||
|
|
dateInfo = {},
|
||
|
|
startTimestamp,
|
||
|
|
endTimestamp,
|
||
|
|
selectedDates = []
|
||
|
|
) {
|
||
|
|
let tempOfSelectedDate = [...selectedDates]
|
||
|
|
const dates = dateUtil.sortDatesByTime(
|
||
|
|
dateUtil.calcDates(dateInfo.year, dateInfo.month),
|
||
|
|
'desc'
|
||
|
|
)
|
||
|
|
let datesLen = dates.length
|
||
|
|
let firstDate = dateUtil.getTimeStamp(dates[0])
|
||
|
|
for (let i = 0; i < datesLen; i++) {
|
||
|
|
const date = dates[i]
|
||
|
|
const timeStamp = dateUtil.getTimeStamp(date)
|
||
|
|
if (timeStamp >= startTimestamp && timeStamp <= endTimestamp) {
|
||
|
|
tempOfSelectedDate.push({
|
||
|
|
...date,
|
||
|
|
choosed: true
|
||
|
|
})
|
||
|
|
}
|
||
|
|
if (i === datesLen - 1 && firstDate > startTimestamp) {
|
||
|
|
pushPrevMonthDateArea(
|
||
|
|
dateUtil.getPrevMonthInfo(date),
|
||
|
|
startTimestamp,
|
||
|
|
endTimestamp,
|
||
|
|
tempOfSelectedDate
|
||
|
|
)
|
||
|
|
}
|
||
|
|
}
|
||
|
|
return tempOfSelectedDate
|
||
|
|
}
|
||
|
|
/**
|
||
|
|
* 当设置日期区域非当前时保存其它月份的日期至已选日期数组
|
||
|
|
* @param {object} info
|
||
|
|
*/
|
||
|
|
function calcDateWhenNotInOneMonth(info) {
|
||
|
|
const { firstDate, lastDate, startTimestamp, endTimestamp } = info
|
||
|
|
let { selectedDate } = info
|
||
|
|
if (dateUtil.getTimeStamp(firstDate) > startTimestamp) {
|
||
|
|
selectedDate = pushPrevMonthDateArea(
|
||
|
|
dateUtil.getPrevMonthInfo(firstDate),
|
||
|
|
startTimestamp,
|
||
|
|
endTimestamp,
|
||
|
|
selectedDate
|
||
|
|
)
|
||
|
|
}
|
||
|
|
if (dateUtil.getTimeStamp(lastDate) < endTimestamp) {
|
||
|
|
selectedDate = pusheNextMonthDateArea(
|
||
|
|
dateUtil.getNextMonthInfo(lastDate),
|
||
|
|
startTimestamp,
|
||
|
|
endTimestamp,
|
||
|
|
selectedDate
|
||
|
|
)
|
||
|
|
}
|
||
|
|
return [...selectedDate]
|
||
|
|
}
|
||
|
|
|
||
|
|
/**
|
||
|
|
* 指定日期区域转时间戳
|
||
|
|
* @param {array} timearea 时间区域
|
||
|
|
*/
|
||
|
|
export function convertTimeRangeToTimestamp(timearea = []) {
|
||
|
|
const start = timearea[0].split('-')
|
||
|
|
const end = timearea[1].split('-')
|
||
|
|
if (start.length !== 3 || end.length !== 3) {
|
||
|
|
logger.warn('enableArea() 参数格式为: ["2018-2-1", "2018-3-1"]')
|
||
|
|
return {}
|
||
|
|
}
|
||
|
|
const startTimestamp = dateUtil
|
||
|
|
.newDate(start[0], start[1], start[2])
|
||
|
|
.getTime()
|
||
|
|
const endTimestamp = dateUtil.newDate(end[0], end[1], end[2]).getTime()
|
||
|
|
return {
|
||
|
|
start,
|
||
|
|
end,
|
||
|
|
startTimestamp,
|
||
|
|
endTimestamp
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
/**
|
||
|
|
* 校验时间区域是否合法
|
||
|
|
* @param {array} dateArea 时间区域
|
||
|
|
*/
|
||
|
|
function validateTimeRange(dateArea) {
|
||
|
|
const {
|
||
|
|
start,
|
||
|
|
end,
|
||
|
|
startTimestamp,
|
||
|
|
endTimestamp
|
||
|
|
} = convertTimeRangeToTimestamp(dateArea)
|
||
|
|
if (!start || !end) return
|
||
|
|
const startMonthDays = dateUtil.getDatesCountOfMonth(start[0], start[1])
|
||
|
|
const endMonthDays = dateUtil.getDatesCountOfMonth(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
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
export default () => {
|
||
|
|
return {
|
||
|
|
name: 'timeRange',
|
||
|
|
beforeRender(calendarData = {}, calendarConfig = {}) {
|
||
|
|
const {
|
||
|
|
chooseAreaTimestamp = [],
|
||
|
|
dates = [],
|
||
|
|
selectedDates = []
|
||
|
|
} = calendarData
|
||
|
|
let __dates = dates
|
||
|
|
let __selectedDates = selectedDates
|
||
|
|
const [startDateTimestamp, endDateTimestamp] = chooseAreaTimestamp
|
||
|
|
if (chooseAreaTimestamp.length === 2) {
|
||
|
|
__selectedDates = []
|
||
|
|
__dates = dates.map(d => {
|
||
|
|
const date = { ...d }
|
||
|
|
const dateTimeStamp = dateUtil.getTimeStamp(date)
|
||
|
|
if (
|
||
|
|
dateTimeStamp >= startDateTimestamp &&
|
||
|
|
endDateTimestamp >= dateTimeStamp
|
||
|
|
) {
|
||
|
|
date.choosed = true
|
||
|
|
__selectedDates.push(date)
|
||
|
|
} else {
|
||
|
|
date.choosed = false
|
||
|
|
__selectedDates = __selectedDates.filter(
|
||
|
|
item => dateUtil.getTimeStamp(item) !== dateTimeStamp
|
||
|
|
)
|
||
|
|
}
|
||
|
|
return date
|
||
|
|
})
|
||
|
|
const monthOfStartDate = new Date(startDateTimestamp).getMonth()
|
||
|
|
const monthOfEndDate = new Date(endDateTimestamp).getMonth()
|
||
|
|
if (monthOfStartDate !== monthOfEndDate) {
|
||
|
|
__selectedDates = calcDateWhenNotInOneMonth({
|
||
|
|
firstDate: __dates[0],
|
||
|
|
lastDate: __dates[__dates.length - 1],
|
||
|
|
startTimestamp: startDateTimestamp,
|
||
|
|
endTimestamp: endDateTimestamp,
|
||
|
|
selectedDate: __selectedDates
|
||
|
|
})
|
||
|
|
}
|
||
|
|
}
|
||
|
|
return {
|
||
|
|
calendarData: {
|
||
|
|
...calendarData,
|
||
|
|
dates: __dates,
|
||
|
|
selectedDates: dateUtil.sortDatesByTime(
|
||
|
|
dateUtil.uniqueArrayByDate(__selectedDates)
|
||
|
|
)
|
||
|
|
},
|
||
|
|
calendarConfig
|
||
|
|
}
|
||
|
|
},
|
||
|
|
onTapDate(tapedDate, calendarData = {}, calendarConfig = {}) {
|
||
|
|
if (!calendarConfig.chooseAreaMode) {
|
||
|
|
return {
|
||
|
|
calendarData,
|
||
|
|
calendarConfig
|
||
|
|
}
|
||
|
|
}
|
||
|
|
let {
|
||
|
|
tempChooseAreaTimestamp = [],
|
||
|
|
chooseAreaTimestamp: existChooseAreaTimestamp = [],
|
||
|
|
selectedDates = [],
|
||
|
|
dates = []
|
||
|
|
} = calendarData
|
||
|
|
const timestamp = dateUtil.getTimeStamp(tapedDate)
|
||
|
|
let __dates = [...dates]
|
||
|
|
let __selectedDates = [...selectedDates]
|
||
|
|
if (
|
||
|
|
tempChooseAreaTimestamp.length === 2 ||
|
||
|
|
existChooseAreaTimestamp.length === 2
|
||
|
|
) {
|
||
|
|
tempChooseAreaTimestamp = [tapedDate]
|
||
|
|
__selectedDates = []
|
||
|
|
__dates.forEach(d => (d.choosed = false))
|
||
|
|
} else if (tempChooseAreaTimestamp.length === 1) {
|
||
|
|
const preChoosedDate = tempChooseAreaTimestamp[0]
|
||
|
|
const preTimestamp = dateUtil.getTimeStamp(preChoosedDate)
|
||
|
|
if (preTimestamp <= timestamp) {
|
||
|
|
tempChooseAreaTimestamp.push(tapedDate)
|
||
|
|
} else if (preTimestamp > timestamp) {
|
||
|
|
tempChooseAreaTimestamp.unshift(tapedDate)
|
||
|
|
}
|
||
|
|
} else {
|
||
|
|
tempChooseAreaTimestamp = [tapedDate]
|
||
|
|
}
|
||
|
|
let chooseAreaTimestamp = []
|
||
|
|
if (tempChooseAreaTimestamp.length === 2) {
|
||
|
|
const [startDate, endDate] = tempChooseAreaTimestamp
|
||
|
|
const startDateTimestamp = dateUtil.getTimeStamp(startDate)
|
||
|
|
const endDateTimestamp = dateUtil.getTimeStamp(endDate)
|
||
|
|
chooseAreaTimestamp = [startDateTimestamp, endDateTimestamp]
|
||
|
|
}
|
||
|
|
return {
|
||
|
|
calendarData: {
|
||
|
|
...calendarData,
|
||
|
|
chooseAreaTimestamp,
|
||
|
|
tempChooseAreaTimestamp,
|
||
|
|
dates: __dates,
|
||
|
|
selectedDates: __selectedDates
|
||
|
|
},
|
||
|
|
calendarConfig: {
|
||
|
|
...calendarConfig,
|
||
|
|
multi: true
|
||
|
|
}
|
||
|
|
}
|
||
|
|
},
|
||
|
|
methods(component) {
|
||
|
|
return {
|
||
|
|
/**
|
||
|
|
* 设置连续日期选择区域
|
||
|
|
* @param {array} dateArea 区域开始结束日期数组
|
||
|
|
*/
|
||
|
|
chooseDateArea: (dateArea = []) => {
|
||
|
|
if (dateArea.length === 1) {
|
||
|
|
dateArea = dateArea.concat(dateArea)
|
||
|
|
}
|
||
|
|
if (dateArea.length !== 2) return
|
||
|
|
const isRight = validateTimeRange(dateArea)
|
||
|
|
if (!isRight) return
|
||
|
|
const config = getCalendarConfig(component) || {}
|
||
|
|
const { startTimestamp, endTimestamp } = convertTimeRangeToTimestamp(
|
||
|
|
dateArea
|
||
|
|
)
|
||
|
|
const existCalendarData = getCalendarData('calendar', component)
|
||
|
|
return renderCalendar.call(
|
||
|
|
component,
|
||
|
|
{
|
||
|
|
...existCalendarData,
|
||
|
|
chooseAreaTimestamp: [startTimestamp, endTimestamp]
|
||
|
|
},
|
||
|
|
{
|
||
|
|
...config,
|
||
|
|
multi: true,
|
||
|
|
chooseAreaMode: true
|
||
|
|
}
|
||
|
|
)
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|