Javascript:日期排班功能实现
背景:
近期,公司的产品经常会遇到日期排班类似的功能;
需求的排班日期长短不一:有些是两周,有些是四周;要求选中的时候有一个active的状态区分,另外要提供钩子获取选中日期的形如:【2018-04-11】这种格式的数据。
实现:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 | /* * 获取当天及之后的排班时间 * @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' )) }); }); } |
调用实例:
1 2 3 4 | //调用实例 initWeekData(2, 'twoWeekDate' ); initWeekData(4, 'fourWeekDate' ); |
实现效果:
线上DEMO:
https://codepen.io/kevinInsight/pen/mxoOaz
-------------------------------- 间隔线 --------------------------------
后来过了一段时间,需要一个如下图所示的排班:
要求:星期title固定;指定月份第一天如果不是周一,则前面置空;最后一天如果不是周日,则后面置空;已经排版的日期,加一个激活态(active),点击可以查看具体时间(如:2019-2-14)
实现:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 | /* * 获取当天及之后的排班时间 * @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
【推荐】还在用 ECharts 开发大屏?试试这款永久免费的开源 BI 工具!
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 一次Java后端服务间歇性响应慢的问题排查记录
· dotnet 源代码生成器分析器入门
· ASP.NET Core 模型验证消息的本地化新姿势
· 对象命名为何需要避免'-er'和'-or'后缀
· SQL Server如何跟踪自动统计信息更新?
· “你见过凌晨四点的洛杉矶吗?”--《我们为什么要睡觉》
· C# 从零开始使用Layui.Wpf库开发WPF客户端
· 提示词工程师自白:我如何用一个技巧解放自己的生产力
· C#/.NET/.NET Core技术前沿周刊 | 第 31 期(2025年3.17-3.23)
· 编程神器Trae:当我用上后,才知道自己的创造力被低估了多少