这是人力统计的一个表格的表头,根据月份,划分周,每周从周一开始到周日(国内习惯性)。而跨月份的周算在前一个月还是后一个月,我们的需求是算在后一个月。根据情况而定。
在表格中我们可以通过动态生成列,维护一个二维的数组,这个二维数组应该长得像这样
外层的属性 nameLabel
是显示在最上面的年月,weekData
对应的是一个数组显示的是下面的周起止日期和周序号 W1 - W5
我们再来看,如何得到一个这样的二维数组?
首先声明一个名为 generateWeeklyArray
的函数,参数为起止年月,格式为年月组成的数字类型好了,如 202108
generateWeeklyArray (startTime, endTime){}
这里为了方便日期转化,和计算,引入了
momnet
日期库
下面是具体的实现,我们对着代码具体讲解下
generateWeeklyArray (startTime, endTime) {
startTime = moment(startTime).format('YYYY-MM-DD')
endTime = moment(endTime).endOf('month').format('YYYY-MM-DD')
let firstDay = new Date(startTime)
let lastDay = new Date(endTime)
let day = firstDay
let weeklyData = []
if (firstDay.getDay !== 1) {
let realFirst = moment(day).add(-6, 'days').format('YYYY-MM-DD')
day = new Date(realFirst)
}
while (day.getTime() < lastDay.getTime() || day.getTime() === lastDay.getTime()) {
if (day.getDay() === 1) {
let yearMonth = moment(day).format('YYYYMM')
if (moment(day).format('M') < moment(day).add(6, 'days').format('M') || moment(day).format('YYYY') < moment(day).add(6, 'days').format('YYYY')) {
yearMonth = moment(day).add(6, 'days').format('YYYYMM')
}
if (moment(day).format('YYYYMM') === moment(lastDay).format('YYYYMM') && moment(lastDay).format('YYYYMM') !== moment(day).add(6, 'days').format('YYYYMM')) {
// console.log('下个月显示')
} else {
let weekRange = moment(day).format('M/D') + '-' + moment(day).add(6, 'days').format('M/D')
weeklyData.push({
nameProp: 'col' + yearMonth + weekRange.replace(/\/|-/g, ''),
weekRange: weekRange,
yearMonth: yearMonth
})
}
day.setDate(day.getDate() + 7)
} else {
day.setDate(day.getDate() + 1)
}
}
let weeklyColumnHeaders = []
weeklyData.forEach(col => {
let colName = 'col' + col.yearMonth
let colItem = weeklyColumnHeaders.find(item => item.nameProp === colName)
if (colItem) {
weeklyColumnHeaders.map(item => {
if (item.nameProp === colName) {
item.weekData.push({
weekRange: col.weekRange,
nameProp: col.nameProp,
weekNo: 'W' + (item.weekData.length + 1)
})
}
})
} else {
weeklyColumnHeaders.push({
nameProp: colName,
nameLabel: col.yearMonth,
weekData: [{weekRange: col.weekRange, nameProp: col.nameProp, weekNo: 'W' + 1}]
})
}
})
return weeklyColumnHeaders
}
这里主要的逻辑是在 while
循环中,以起止时间为条件,循环遍历找出周一的日期,通过向后推算六天,得到周的日期范围,组成数据添加到当前月份的 weekData
的数组中,当前数组的长度即为周的序号。
一般循环需要兼顾下两头的特殊情况,首先看开始的情况:当 startTime
月份的1号不是周一,就需要往前推几天,直到周一作为开始日期。
let day = firstDay
let weeklyData = []
if (firstDay.getDay !== 1) {
let realFirst = moment(day).add(-6, 'days').format('YYYY-MM-DD')
day = new Date(realFirst)
}
再来看结束时间的情况:如果 endTime
所在的月份的最后一周跨了月份,根据我们的规则,我们要把它算在下一个月里,这里要排除掉它
if (moment(day).format('YYYYMM') === moment(lastDay).format('YYYYMM') && moment(lastDay).format('YYYYMM') !== moment(day).add(6, 'days').format('YYYYMM')) {
// console.log('下个月显示')
} else {
let weekRange = moment(day).format('M/D') + '-' + moment(day).add(6, 'days').format('M/D')
weeklyData.push({
nameProp: 'col' + yearMonth + weekRange.replace(/\/|-/g, ''),
weekRange: weekRange,
yearMonth: yearMonth
})
}
好了,这里的需要注意的地方就这些,其它的逻辑简单可以自己看代码。
题外话:这是一篇周六加班后写的文章,身在室内心思早在外面了,写的比较急切,因为想早点出去玩啊!
网友评论