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.
305 lines
8.9 KiB
305 lines
8.9 KiB
/** |
|
* @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 |
|
} |
|
) |
|
} |
|
} |
|
} |
|
} |
|
}
|
|
|