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.
433 lines
14 KiB
433 lines
14 KiB
|
10 months ago
|
/**
|
||
|
|
* @Author: drfu*
|
||
|
|
* @Description: 周视图
|
||
|
|
* @Date: 2020-10-08 21:22:09*
|
||
|
|
* @Last Modified by: drfu
|
||
|
|
* @Last Modified time: 2020-10-12 14:39:45
|
||
|
|
* */
|
||
|
|
|
||
|
|
import { renderCalendar } from '../render'
|
||
|
|
import {
|
||
|
|
getCalendarConfig,
|
||
|
|
getCalendarData,
|
||
|
|
logger,
|
||
|
|
dateUtil
|
||
|
|
} from '../utils/index'
|
||
|
|
import { calcJumpData } from '../core'
|
||
|
|
|
||
|
|
/**
|
||
|
|
* 当月第一周所有日期
|
||
|
|
*/
|
||
|
|
function firstWeekInMonth(
|
||
|
|
target = {},
|
||
|
|
calendarDates = [],
|
||
|
|
calendarConfig = {}
|
||
|
|
) {
|
||
|
|
const { firstDayOfWeek } = calendarConfig
|
||
|
|
const firstDayOfWeekIsMon = firstDayOfWeek === 'Mon'
|
||
|
|
const { year, month } = target
|
||
|
|
let firstDay = dateUtil.getDayOfWeek(year, month, 1)
|
||
|
|
if (firstDayOfWeekIsMon && firstDay === 0) {
|
||
|
|
firstDay = 7
|
||
|
|
}
|
||
|
|
const [, end] = [0, 7 - firstDay]
|
||
|
|
return calendarDates.slice(0, firstDayOfWeekIsMon ? end + 1 : end)
|
||
|
|
}
|
||
|
|
|
||
|
|
/**
|
||
|
|
* 当月最后一周所有日期
|
||
|
|
*/
|
||
|
|
function lastWeekInMonth(target = {}, calendarDates = [], calendarConfig = {}) {
|
||
|
|
const { firstDayOfWeek } = calendarConfig
|
||
|
|
const firstDayOfWeekIsMon = firstDayOfWeek === 'Mon'
|
||
|
|
const { year, month } = target
|
||
|
|
const lastDay = dateUtil.getDatesCountOfMonth(year, month)
|
||
|
|
let lastDayWeek = dateUtil.getDayOfWeek(year, month, lastDay)
|
||
|
|
if (firstDayOfWeekIsMon && lastDayWeek === 0) {
|
||
|
|
lastDayWeek = 7
|
||
|
|
}
|
||
|
|
const [start, end] = [lastDay - lastDayWeek, lastDay]
|
||
|
|
return calendarDates.slice(firstDayOfWeekIsMon ? start : start - 1, end)
|
||
|
|
}
|
||
|
|
|
||
|
|
/**
|
||
|
|
* 判断目标日期是否在某些指定日历内
|
||
|
|
*/
|
||
|
|
function dateIsInDatesRange(target, dates) {
|
||
|
|
if (!target || !dates || !dates.length) return false
|
||
|
|
const targetDateStr = dateUtil.toTimeStr(target)
|
||
|
|
let rst = false
|
||
|
|
for (let date of dates) {
|
||
|
|
const dateStr = dateUtil.toTimeStr(date)
|
||
|
|
if (dateStr === targetDateStr) {
|
||
|
|
rst = true
|
||
|
|
return rst
|
||
|
|
}
|
||
|
|
rst = false
|
||
|
|
}
|
||
|
|
return rst
|
||
|
|
}
|
||
|
|
|
||
|
|
function getDatesWhenTargetInFirstWeek(target, firstWeekDates) {
|
||
|
|
const { year, month } = target
|
||
|
|
const prevMonthInfo = dateUtil.getPrevMonthInfo({ year, month })
|
||
|
|
let lastMonthDatesCount = dateUtil.getDatesCountOfMonth(
|
||
|
|
prevMonthInfo.year,
|
||
|
|
prevMonthInfo.month
|
||
|
|
)
|
||
|
|
let dates = firstWeekDates
|
||
|
|
let firstWeekCount = firstWeekDates.length
|
||
|
|
for (let i = 0; i < 7 - firstWeekCount; i++) {
|
||
|
|
const week = dateUtil.getDayOfWeek(+year, +month, lastMonthDatesCount)
|
||
|
|
dates.unshift({
|
||
|
|
year: prevMonthInfo.year,
|
||
|
|
month: prevMonthInfo.month,
|
||
|
|
date: lastMonthDatesCount,
|
||
|
|
week
|
||
|
|
})
|
||
|
|
lastMonthDatesCount -= 1
|
||
|
|
}
|
||
|
|
return dates
|
||
|
|
}
|
||
|
|
|
||
|
|
function getDatesWhenTargetInLastWeek(target, lastWeekDates) {
|
||
|
|
const { year, month } = target
|
||
|
|
const prevMonthInfo = dateUtil.getNextMonthInfo({ year, month })
|
||
|
|
let dates = lastWeekDates
|
||
|
|
let lastWeekCount = lastWeekDates.length
|
||
|
|
for (let i = 0; i < 7 - lastWeekCount; i++) {
|
||
|
|
const week = dateUtil.getDayOfWeek(+year, +month, i + 1)
|
||
|
|
dates.push({
|
||
|
|
year: prevMonthInfo.year,
|
||
|
|
month: prevMonthInfo.month,
|
||
|
|
date: i + 1,
|
||
|
|
week
|
||
|
|
})
|
||
|
|
}
|
||
|
|
return dates
|
||
|
|
}
|
||
|
|
|
||
|
|
function getDates(target, calendarDates = [], calendarConfig = {}) {
|
||
|
|
const { year, month, date } = target
|
||
|
|
const targetDay = dateUtil.getDayOfWeek(year, month, date)
|
||
|
|
const { firstDayOfWeek } = calendarConfig
|
||
|
|
const firstDayOfWeekIsMon = firstDayOfWeek === 'Mon'
|
||
|
|
if (firstDayOfWeekIsMon) {
|
||
|
|
const startIdx = date - (targetDay || 7)
|
||
|
|
return calendarDates.splice(startIdx, 7)
|
||
|
|
} else {
|
||
|
|
const startIdx = date - targetDay - 1
|
||
|
|
return calendarDates.splice(startIdx, 7)
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
function getTargetWeekDates(target, calendarConfig) {
|
||
|
|
if (!target) return
|
||
|
|
const { year, month } = target
|
||
|
|
const calendarDates = dateUtil.calcDates(year, month)
|
||
|
|
const firstWeekDates = firstWeekInMonth(target, calendarDates, calendarConfig)
|
||
|
|
const lastWeekDates = lastWeekInMonth(target, calendarDates, calendarConfig)
|
||
|
|
if (dateIsInDatesRange(target, firstWeekDates)) {
|
||
|
|
return getDatesWhenTargetInFirstWeek(target, firstWeekDates)
|
||
|
|
} else if (dateIsInDatesRange(target, lastWeekDates)) {
|
||
|
|
return getDatesWhenTargetInLastWeek(target, lastWeekDates)
|
||
|
|
} else {
|
||
|
|
return getDates(target, calendarDates, calendarConfig)
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
/**
|
||
|
|
* 计算周视图下当前这一周最后一天
|
||
|
|
*/
|
||
|
|
function calculateLastDateOfCurrentWeek(calendarData = {}) {
|
||
|
|
const { dates = [] } = calendarData
|
||
|
|
return dates[dates.length - 1]
|
||
|
|
}
|
||
|
|
/**
|
||
|
|
* 计算周视图下当前这一周第一天
|
||
|
|
*/
|
||
|
|
function calculateFirstDateOfCurrentWeek(calendarData = {}) {
|
||
|
|
const { dates } = calendarData
|
||
|
|
return dates[0]
|
||
|
|
}
|
||
|
|
|
||
|
|
/**
|
||
|
|
* 计算下一周的日期
|
||
|
|
*/
|
||
|
|
function calculateNextWeekDates(calendarData = {}) {
|
||
|
|
let { curYear, curMonth } = calendarData
|
||
|
|
let calendarDates = []
|
||
|
|
let lastDateInThisWeek = calculateLastDateOfCurrentWeek(calendarData)
|
||
|
|
const { year: LYear, month: LMonth } = lastDateInThisWeek
|
||
|
|
if (curYear !== LYear || curMonth !== LMonth) {
|
||
|
|
calendarDates = dateUtil.calcDates(LYear, LMonth)
|
||
|
|
curYear = LYear
|
||
|
|
curMonth = LMonth
|
||
|
|
} else {
|
||
|
|
calendarDates = dateUtil.calcDates(curYear, curMonth)
|
||
|
|
}
|
||
|
|
const lastDateInThisMonth = dateUtil.getDatesCountOfMonth(curYear, curMonth)
|
||
|
|
const count = lastDateInThisMonth - lastDateInThisWeek.date
|
||
|
|
const lastDateIdx = calendarDates.findIndex(
|
||
|
|
date => dateUtil.toTimeStr(date) === dateUtil.toTimeStr(lastDateInThisWeek)
|
||
|
|
)
|
||
|
|
const startIdx = lastDateIdx + 1
|
||
|
|
if (count >= 7) {
|
||
|
|
return {
|
||
|
|
dates: calendarDates.splice(startIdx, 7),
|
||
|
|
year: curYear,
|
||
|
|
month: curMonth
|
||
|
|
}
|
||
|
|
} else {
|
||
|
|
const nextMonth = dateUtil.getNextMonthInfo({
|
||
|
|
year: curYear,
|
||
|
|
month: curMonth
|
||
|
|
})
|
||
|
|
const { year, month } = nextMonth || {}
|
||
|
|
const calendarDatesOfNextMonth = dateUtil.calcDates(year, month)
|
||
|
|
const remainDatesOfThisMonth = calendarDates.splice(startIdx)
|
||
|
|
const patchDatesOfNextMonth = calendarDatesOfNextMonth.splice(
|
||
|
|
0,
|
||
|
|
7 - remainDatesOfThisMonth.length
|
||
|
|
)
|
||
|
|
return {
|
||
|
|
dates: [...remainDatesOfThisMonth, ...patchDatesOfNextMonth],
|
||
|
|
...nextMonth
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
/**
|
||
|
|
* 计算上一周的日期
|
||
|
|
*/
|
||
|
|
function calculatePrevWeekDates(calendarData = {}) {
|
||
|
|
let { curYear, curMonth } = calendarData
|
||
|
|
let firstDateInThisWeek = calculateFirstDateOfCurrentWeek(calendarData)
|
||
|
|
let calendarDates = []
|
||
|
|
const { year: FYear, month: FMonth } = firstDateInThisWeek
|
||
|
|
if (curYear !== FYear || curMonth !== FMonth) {
|
||
|
|
calendarDates = dateUtil.calcDates(FYear, FMonth)
|
||
|
|
curYear = FYear
|
||
|
|
curMonth = FMonth
|
||
|
|
} else {
|
||
|
|
calendarDates = dateUtil.calcDates(curYear, curMonth)
|
||
|
|
}
|
||
|
|
const firstDateIdx = calendarDates.findIndex(
|
||
|
|
date => dateUtil.toTimeStr(date) === dateUtil.toTimeStr(firstDateInThisWeek)
|
||
|
|
)
|
||
|
|
if (firstDateIdx - 7 >= 0) {
|
||
|
|
const startIdx = firstDateIdx - 7
|
||
|
|
return {
|
||
|
|
dates: calendarDates.splice(startIdx, 7),
|
||
|
|
year: curYear,
|
||
|
|
month: curMonth
|
||
|
|
}
|
||
|
|
} else {
|
||
|
|
const prevMonth = dateUtil.getPrevMonthInfo({
|
||
|
|
year: curYear,
|
||
|
|
month: curMonth
|
||
|
|
})
|
||
|
|
const { year, month } = prevMonth || {}
|
||
|
|
const calendarDatesOfPrevMonth = dateUtil.calcDates(year, month)
|
||
|
|
const remainDatesOfThisMonth = calendarDates.splice(
|
||
|
|
0,
|
||
|
|
firstDateInThisWeek.date - 1
|
||
|
|
)
|
||
|
|
const patchDatesOfPrevMonth = calendarDatesOfPrevMonth.splice(
|
||
|
|
-(7 - remainDatesOfThisMonth.length)
|
||
|
|
)
|
||
|
|
return {
|
||
|
|
dates: [...patchDatesOfPrevMonth, ...remainDatesOfThisMonth],
|
||
|
|
...prevMonth
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
export default () => {
|
||
|
|
return {
|
||
|
|
name: 'week',
|
||
|
|
beforeRender(calendarData = {}, calendarConfig = {}, component) {
|
||
|
|
const { initializedWeekMode, selectedDates } = calendarData
|
||
|
|
if (calendarConfig.weekMode && !initializedWeekMode) {
|
||
|
|
const { defaultDate } = calendarConfig
|
||
|
|
const target =
|
||
|
|
(selectedDates && selectedDates[0]) ||
|
||
|
|
(defaultDate && dateUtil.transformDateRow2Dict(defaultDate)) ||
|
||
|
|
dateUtil.todayFMD()
|
||
|
|
const waitRenderData = this.methods(
|
||
|
|
component
|
||
|
|
).__calcDatesWhenSwitchView('week', target)
|
||
|
|
const { data, config } = waitRenderData || {}
|
||
|
|
const setSelectDates = this.methods(
|
||
|
|
component
|
||
|
|
).__selectTargetDateWhenJump(target, data.dates, config)
|
||
|
|
return {
|
||
|
|
calendarData: {
|
||
|
|
...data,
|
||
|
|
...setSelectDates,
|
||
|
|
weeksCh: dateUtil.getWeekHeader(calendarConfig.firstDayOfWeek),
|
||
|
|
initializedWeekMode: true
|
||
|
|
},
|
||
|
|
calendarConfig
|
||
|
|
}
|
||
|
|
}
|
||
|
|
return {
|
||
|
|
calendarData,
|
||
|
|
calendarConfig
|
||
|
|
}
|
||
|
|
},
|
||
|
|
onSwitchCalendar(target = {}, calendarData = {}, component) {
|
||
|
|
const { direction } = target
|
||
|
|
const { curYear, curMonth } = calendarData
|
||
|
|
const calendarConfig = getCalendarConfig(component)
|
||
|
|
let waitRenderData = {}
|
||
|
|
if (calendarConfig.weekMode) {
|
||
|
|
if (direction === 'left') {
|
||
|
|
waitRenderData = calculateNextWeekDates(calendarData)
|
||
|
|
} else {
|
||
|
|
waitRenderData = calculatePrevWeekDates(calendarData)
|
||
|
|
}
|
||
|
|
const { dates, year, month } = waitRenderData
|
||
|
|
return {
|
||
|
|
...calendarData,
|
||
|
|
dates,
|
||
|
|
curYear: year || curYear,
|
||
|
|
curMonth: month || curMonth
|
||
|
|
}
|
||
|
|
}
|
||
|
|
return calendarData
|
||
|
|
},
|
||
|
|
methods(component) {
|
||
|
|
return {
|
||
|
|
__selectTargetDateWhenJump: (target = {}, dates = [], config = {}) => {
|
||
|
|
let selectedDate = target
|
||
|
|
const weekDates = dates.map((date, idx) => {
|
||
|
|
const tmp = { ...date }
|
||
|
|
tmp.id = idx
|
||
|
|
const isTarget =
|
||
|
|
dateUtil.toTimeStr(target) === dateUtil.toTimeStr(tmp)
|
||
|
|
if (isTarget && !target.choosed && config.autoChoosedWhenJump) {
|
||
|
|
tmp.choosed = true
|
||
|
|
selectedDate = tmp
|
||
|
|
}
|
||
|
|
return tmp
|
||
|
|
})
|
||
|
|
return {
|
||
|
|
dates: weekDates,
|
||
|
|
selectedDates: [selectedDate]
|
||
|
|
}
|
||
|
|
},
|
||
|
|
__calcDatesForWeekMode(target, config = {}, calendarData = {}) {
|
||
|
|
const { year, month } = target || {}
|
||
|
|
const weekDates = getTargetWeekDates(target, config)
|
||
|
|
weekDates.forEach((date, idx) => (date.id = idx))
|
||
|
|
return {
|
||
|
|
data: {
|
||
|
|
...calendarData,
|
||
|
|
prevMonthGrids: null,
|
||
|
|
nextMonthGrids: null,
|
||
|
|
dates: weekDates,
|
||
|
|
curYear: year,
|
||
|
|
curMonth: month
|
||
|
|
},
|
||
|
|
config: {
|
||
|
|
...config,
|
||
|
|
weekMode: true
|
||
|
|
}
|
||
|
|
}
|
||
|
|
},
|
||
|
|
__calcDatesForMonthMode(target, config = {}, calendarData = {}) {
|
||
|
|
const { year, month } = target || {}
|
||
|
|
const waitRenderData = calcJumpData({
|
||
|
|
dateInfo: target,
|
||
|
|
config
|
||
|
|
})
|
||
|
|
return {
|
||
|
|
data: {
|
||
|
|
...calendarData,
|
||
|
|
...waitRenderData,
|
||
|
|
curYear: year,
|
||
|
|
curMonth: month
|
||
|
|
},
|
||
|
|
config: {
|
||
|
|
...config,
|
||
|
|
weekMode: false
|
||
|
|
}
|
||
|
|
}
|
||
|
|
},
|
||
|
|
/**
|
||
|
|
* 周、月视图切换
|
||
|
|
* @param {string} view 视图 [week, month]
|
||
|
|
* @param {object} target
|
||
|
|
*/
|
||
|
|
__calcDatesWhenSwitchView: (view, target) => {
|
||
|
|
const calendarConfig = getCalendarConfig(component)
|
||
|
|
if (calendarConfig.multi)
|
||
|
|
return logger.warn('多选模式不能切换周月视图')
|
||
|
|
const existCalendarData = getCalendarData('calendar', component) || {}
|
||
|
|
const {
|
||
|
|
selectedDates = [],
|
||
|
|
dates = [],
|
||
|
|
curYear,
|
||
|
|
curMonth
|
||
|
|
} = existCalendarData
|
||
|
|
const currentMonthSelected = selectedDates.filter(
|
||
|
|
item => curYear === +item.year || curMonth === +item.month
|
||
|
|
)
|
||
|
|
let jumpTarget = {}
|
||
|
|
if (target) {
|
||
|
|
jumpTarget = target
|
||
|
|
} else {
|
||
|
|
if (currentMonthSelected.length) {
|
||
|
|
jumpTarget = currentMonthSelected.pop()
|
||
|
|
} else {
|
||
|
|
jumpTarget = dates[0]
|
||
|
|
}
|
||
|
|
}
|
||
|
|
if (view === 'week') {
|
||
|
|
return this.methods(component).__calcDatesForWeekMode(
|
||
|
|
jumpTarget,
|
||
|
|
calendarConfig,
|
||
|
|
existCalendarData
|
||
|
|
)
|
||
|
|
} else {
|
||
|
|
return this.methods(component).__calcDatesForMonthMode(
|
||
|
|
jumpTarget,
|
||
|
|
calendarConfig,
|
||
|
|
existCalendarData
|
||
|
|
)
|
||
|
|
}
|
||
|
|
},
|
||
|
|
weekModeJump: dateInfo => {
|
||
|
|
const target = dateInfo || dateUtil.todayFMD()
|
||
|
|
const existCalendarData = getCalendarData('calendar', component) || {}
|
||
|
|
const waitRenderData = this.methods(
|
||
|
|
component
|
||
|
|
).__calcDatesWhenSwitchView('week', target)
|
||
|
|
const { data, config } = waitRenderData || {}
|
||
|
|
const setSelectDates = this.methods(
|
||
|
|
component
|
||
|
|
).__selectTargetDateWhenJump(target, data.dates, config)
|
||
|
|
return renderCalendar.call(
|
||
|
|
component,
|
||
|
|
{
|
||
|
|
...existCalendarData,
|
||
|
|
...data,
|
||
|
|
...setSelectDates
|
||
|
|
},
|
||
|
|
config
|
||
|
|
)
|
||
|
|
},
|
||
|
|
switchView: (view, target) => {
|
||
|
|
const waitRenderData = this.methods(
|
||
|
|
component
|
||
|
|
).__calcDatesWhenSwitchView(view, target)
|
||
|
|
const { data, config } = waitRenderData || {}
|
||
|
|
if (!data) return logger.warn('当前状态不能切换为周视图')
|
||
|
|
return renderCalendar.call(component, data, config)
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|