123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432 |
- /**
- * @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)
- }
- }
- }
- }
- }
|