背景:
近期,公司的產品經常會遇到日期排班類似的功能;
需求的排班日期長短不一:有些是兩周,有些是四周;要求選中的時候有一個active的狀態區分,另外要提供鈎子獲取選中日期的形如:【2018-04-11】這種格式的數據。
實現:
/* * 獲取當天及之后的排班時間 * @param dayCount:相對於今天的天數,形如:0,1,2....... */ function getDateData(dayCount) { var d = new Date(); d.setDate(d.getDate() + dayCount); var y = d.getFullYear(); var m = (d.getMonth() + 1) > 9 ? d.getMonth() + 1 : '0' + (d.getMonth() + 1); var d = d.getDate() > 9 ? d.getDate() : '0' + d.getDate(); return y + "-" + m + "-" + d; } /* * 獲取日期對應的星期名稱 * @param date:待轉換日期,形如:'2018-04-11' 或 '2018-4-11' */ function dateToDay(date) { var dayNo = new Date(date).getDay(); switch (dayNo) { case 0: return '星期日'; break; case 1: return '星期一'; break; case 2: return '星期二'; break; case 3: return '星期三'; break; case 4: return '星期四'; break; case 5: return '星期五'; break; case 6: return '星期六'; break; default: break; } } /* * 通過參數動態獲取排班日期 * @param weekCount:排班周數,int型 * @param domId: 輸出DomId */ function initWeekData(weekCount, domId) { var weekDateTempl = '', tableTempl = '', tableTh = '', tableTd = '', tableTdArr = [], weekData = [], weekDataFinal = [], weekDateEle; for (var i = 0; i < weekCount * 7; i++) { weekData[i] = getDateData(i); } for (var i = 0; i < weekData.length; i = i + 7) { weekDataFinal.push(weekData.slice(i, i + 7)); } weekDataFinal.forEach(function(item, index) { if (index === 0) { for (var i = 0; i < item.length; i++) { tableTh += '<th>' + dateToDay(item[i]) + '</th>' } tableTh = '<tr>' + tableTh + '</tr>'; //firstWeek for (var j = 0; j < item.length; j++) { if (j === 0) { tableTd += '<td attr-date=' + item[j] + ' class="active">今天</td>'; } else { tableTd += '<td attr-date=' + item[j] + '>' + new Date(item[j]).getDate() + '</td>'; } } tableTd = '<tr>' + tableTd + '</tr>'; tableTdArr[index] = tableTd; tableTd = ''; } else { for (var k = 0; k < item.length; k++) { tableTd += '<td attr-date=' + item[k] + '>' + new Date(item[k]).getDate() + '</td>'; } tableTd = '<tr>' + tableTd + '</tr>'; tableTdArr[index] = tableTd; tableTd = ''; } }); tableTempl = tableTh + tableTdArr.join(''); weekDateEle = document.querySelector('#' + domId); weekDateEle.innerHTML = tableTempl; weekDateEle.querySelectorAll('tr>td').forEach(function(item, index) { item.addEventListener("click", function() { weekDateEle.querySelectorAll('tr>td').forEach(function(item, index) { item.classList.remove('active'); }); this.classList.add('active'); alert(this.getAttribute('attr-date')) }); }); }
調用實例:
//調用實例 initWeekData(2, 'twoWeekDate'); initWeekData(4, 'fourWeekDate');
實現效果:
線上DEMO:
https://codepen.io/kevinInsight/pen/mxoOaz
-------------------------------- 間隔線 --------------------------------
后來過了一段時間,需要一個如下圖所示的排班:
要求:星期title固定;指定月份第一天如果不是周一,則前面置空;最后一天如果不是周日,則后面置空;已經排版的日期,加一個激活態(active),點擊可以查看具體時間(如:2019-2-14)
實現:
/* * 獲取當天及之后的排班時間 * @param month:指定的月份 * @param dayCount:相對於今天的天數,形如:0,1,2....... */ function getDateData(month, dayCount) { let yy, mm, dd; let d = new Date(); let initDay = d.getFullYear() + '-' + month + '-01'; d = new Date(initDay); d.setDate(d.getDate() + dayCount); yy = d.getFullYear(); mm = (d.getMonth() + 1) > 9 ? d.getMonth() + 1 : '0' + (d.getMonth() + 1); dd = d.getDate() > 9 ? d.getDate() : '0' + d.getDate(); return yy + "-" + mm + "-" + dd; } /* * 根據月份查詢排班結果 * @param month: 指定月份,整型數字1-12 */ function schedueByMonth(month) { let dates = [], weekData = [], weekDataFinal = [], d, m, w, weekNum, lastWeek, lastWeekDiff = []; let formatMonth = month > 9 ? month : '0' + month; for (let i = 0; i <= 31; i++) { d = getDateData(formatMonth, i); m = new Date(d).getMonth() + 1; if (m === month) { dates.push(d) } } w = new Date(dates[0]).getDay(); if (w > 0) { for (let j = 0; j < w - 1; j++) { dates.unshift('') } } else if (w === 0) { for (let j = 0; j < 6; j++) { dates.unshift('') } } //dates分組:每組7天 for (let i = 0; i < dates.length; i = i + 7) { weekDataFinal.push(dates.slice(i, i + 7)); } //最后一行不夠7個,則補齊 lastWeek = weekDataFinal[weekDataFinal.length - 1]; if (lastWeek.length < 7) { for (let k = 0; k < (7 - lastWeek.length); k++) { lastWeekDiff.push('') } lastWeek = lastWeek.concat(lastWeekDiff) weekDataFinal[weekDataFinal.length - 1] = lastWeek; } pendingWeekData(dates, weekDataFinal) } function pendingWeekData(dates, weekDataFinal) { let weekTitles = '<tr><td>星期一</td><td>星期二</td><td>星期三</td><td>星期四</td><td>星期五</td><td>星期六</td><td>星期日</td></tr>'; let scheduDom = '', weeksDom = '', weekDom = ''; weekDataFinal.forEach(function(item) { item.forEach(function(subItem) { weekDom += '<td attr-date="' + subItem + '">' + delWithDay(subItem) + '</td>'; }) weeksDom += '<tr>' + weekDom + '</tr>'; weekDom = ''; }) scheduDom = weekTitles + weeksDom; $('#schedue').html(scheduDom); //加入業務數據 let date = ['2019-12-07', '2019-12-12', '2019-12-31']; //date為接口返回的排班時間,形如:['2019-12-07', '2019-12-12', '2019-12-28'] delWithSchedue(dates, date) } function delWithSchedue(dates, date) { let pesoDates = date; //date為接口返回的排班時間 let index; if (pesoDates.length > 0) { pesoDates.forEach(function(item, index) { index = dates.indexOf(item) $('#schedue').find('td').eq(index + 7).addClass('active').click(function() { alert($(this).attr('attr-date')) }) }) } } function delWithDay(day) { if (day) { return new Date(day).getDate() } else { return '' } } //調用實例 schedueByMonth(12)
線上DEMO:
https://codepen.io/kevinInsight/pen/omPeMM