目录
1.日历页面
2.工作日查询、自然日查询 js
3.修改工作日配置
4.数据库,表结构
5.初始化数据
因系统需要,需要制作一个功能--工作日配置。
需要的业务有:
1.初始化与国家放假情况一致,之后支持手动进行工作日配置;
2.展示12个月的放假/工作日情况;
3.一些特殊的日期,如调休、春节等需要进行展示。
页面展示:
修改页面:
1.日历页面
<!DOCTYPE html> <html xmlns:th="http://www.thymeleaf.org"> <head th:include="include/header_css::header('工作日维护')"></head> <style type="text/css"> .calendar-box * { margin: 0; padding: 0; box-sizing: border-box; } .calendar-box { border: 1px solid #d2d2d2; box-shadow: 0 2px 4px rgba(0,0,0,.12); background-color: #fff; color: #666; position: relative; z-index: 0; display: inline-block; width: 272px; border-radius: 2px; font-size: 14px; } .calendar-content { position: relative; padding: 10px; -moz-user-select: none; -webkit-user-select: none; -ms-user-select: none; } .calendar-content table { border-collapse: collapse; border-spacing: 0; } .calendar-content th, .calendar-content td { border: 1px solid #d3d3d3; width: 36px; height: 30px; padding: 5px; text-align: center; } .calendar-content th { font-weight: 400; color: #333; } .calendar-content td { position: relative; cursor: pointer; transition-duration: .3s; -webkit-transition-duration: .3s; } .calendar-content td:hover { background-color: #eaeaea; color: #333; } .calendar-content .calendar-day-mark-td { height: 33px; } .calendar-day-mark { position: absolute; left: 0; top: 0; width: 100%; height: 100%; line-height: 33px; font-size: 12px; overflow: hidden; } .calendar-content .weekend { color: red; } .calendar-disabled { background: 0 0!important; cursor: not-allowed !important; -moz-user-select: none; -webkit-user-select: none; -ms-user-select: none; } .calendar-workday { color: white; background-color: #080101; } .calendar-workday:hover { background-color: #080101b3; } .calendar-holiday { color: white; background-color: #f08a8a; } .calendar-holiday:hover { background-color: #f08a8aab; } </style> <body> <div id="dpLTE"> <div class="row form-row"> <div class="col-md-2 text-center text-muted"> </div> <div class="col-md-3 text-right text-muted"> 请选择年份: </div> <div class="col-md-3 text-center text-muted"> <select class="form-control" id="yearSelect"> </select> </div> <div class="col-md-4 text-center text-muted"> <a onclick="initDataByYear()" class="btn btn-default"><i class="fa fa-refresh"></i> 初始工作日数据</a> </div> </div> <div class="row"> <div class="col-md-3 text-center text-muted"> 一月 </div> <div class="col-md-3 text-center text-muted"> 二月 </div> <div class="col-md-3 text-center text-muted"> 三月 </div> <div class="col-md-3 text-center text-muted"> 四月 </div> </div> <div class="row"> <div class="col-md-3 text-center text-muted"> <div id="month1"></div> </div> <div class="col-md-3 text-center text-muted"> <div id="month2"></div> </div> <div class="col-md-3 text-center text-muted"> <div id="month3"></div> </div> <div class="col-md-3 text-center text-muted"> <div id="month4"></div> </div> </div> <div class="row"> <div class="col-md-3 text-center text-muted"> 五月 </div> <div class="col-md-3 text-center text-muted"> 六月 </div> <div class="col-md-3 text-center text-muted"> 七月 </div> <div class="col-md-3 text-center text-muted"> 八月 </div> </div> <div class="row"> <div class="col-md-3 text-center text-muted"> <div id="month5"></div> </div> <div class="col-md-3 text-center text-muted"> <div id="month6"></div> </div> <div class="col-md-3 text-center text-muted"> <div id="month7"></div> </div> <div class="col-md-3 text-center text-muted"> <div id="month8"></div> </div> </div> <div class="row"> <div class="col-md-3 text-center text-muted"> 九月 </div> <div class="col-md-3 text-center text-muted"> 十月 </div> <div class="col-md-3 text-center text-muted"> 十一月 </div> <div class="col-md-3 text-center text-muted"> 十二月 </div> </div> <div class="row"> <div class="col-md-3 text-center text-muted"> <div id="month9"></div> </div> <div class="col-md-3 text-center text-muted"> <div id="month10"></div> </div> <div class="col-md-3 text-center text-muted"> <div id="month11"></div> </div> <div class="col-md-3 text-center text-muted"> <div id="month12"></div> </div> </div> <div class="row form-row" style="margin-top: 50px;"> <div class="col-md-12 text-center text-muted"> 工作日查询 </div> </div> <div class="row form-row"> <div class="col-md-2 text-right text-muted"> 请选择日期: </div> <div class="col-md-2 text-center text-muted"> <input class="form-control" id="dateSelect" type="text"/> </div> <div class="col-md-2 text-right text-muted"> 请输入工作日偏移天数: </div> <div class="col-md-2 text-right text-muted"> <input class="form-control" id="days" type="number"/> </div> <div class="col-md-1 text-left text-muted"> <a href="javascript:inputChange();" class="btn btn-primary">查询</a> </div> <div class="col-md-2 text-right text-muted"> <input class="form-control" id="result" type="text" readonly="readonly"/> </div> </div> <div class="row form-row" style="margin-top: 50px;"> <div class="col-md-12 text-center text-muted"> 自然日查询 </div> </div> <div class="row form-row"> <div class="col-md-2 text-right text-muted"> 请选择日期: </div> <div class="col-md-2 text-center text-muted"> <input class="form-control" id="natureDateSelect" type="text"/> </div> <div class="col-md-2 text-right text-muted"> 请输入自然日偏移天数: </div> <div class="col-md-2 text-right text-muted"> <input class="form-control" id="natureDays" type="number"/> </div> <div class="col-md-1 text-left text-muted"> <a href="javascript:natureInputChange();" class="btn btn-primary">查询</a> </div> <div class="col-md-2 text-right text-muted"> <input class="form-control" id="natureResult" type="text" readonly="readonly"/> </div> </div> <div class="row" style="margin-top: 50px;"> </div> </div> <div th:include="include/footer_js::footer"></div> <script type="text/javascript"> $(function() { var year = formatDate(new Date(), 'yyyy'); var data = {}; var nextYear = year * 1 + 1; //下拉框范围:从2024年开始,到当前年份+1 for (var i = 2024; i <= nextYear; i++) { data[i] = i; } // 初始化系统参数,选择年 $('#yearSelect').selectBindEx({ data: data, placeholder: '请选择年份', value: 'stringValue', text: 'name', allowClear: false, selected: [year], change: function (data) { initByYear(data); } }); initByYear(year); laydate.render({ elem: '#dateSelect', trigger: 'click', position: 'fixed', type: 'date', value: new Date(), format: 'yyyy-MM-dd' }); laydate.render({ elem: '#natureDateSelect', trigger: 'click', position: 'fixed', type: 'date', value: new Date(), format: 'yyyy-MM-dd' }); }); function initByYear(year) { var markDayData = []; $.SetForm({ url: '../../system/workDay/listByYear?year=' + year + '&_=' + $.now(), param: {}, async: false, success: function (data) { markDayData = data; } }); // 月份 for(var i = 1; i <= 12; i++) { // 渲染月份html结构 renderMonthHtml(i); // 表格中显示日期 showCalendarData(year, i, markDayData); } } /** * 渲染月份html结构 */ function renderMonthHtml(month) { var calendar = $('#month' + month); calendar.empty(); // 设置表格区的html结构 var _theadHtml = '<thead>' + '<tr>' + '<th class="weekend">日</th>' + '<th>一</th>' + '<th>二</th>' + '<th>三</th>' + '<th>四</th>' + '<th>五</th>' + '<th class="weekend">六</th>' + '</tr>' + '</thead>'; // 一个月最多31天,所以一个月最多占6行表格 var _tbodyHtml = '<tbody>'; for(var i = 0; i < 6; i++) { _tbodyHtml += '<tr>' + '<td></td>' + '<td></td>' + '<td></td>' + '<td></td>' + '<td></td>' + '<td></td>' + '<td></td>' + '</tr>'; } _tbodyHtml += '</tbody>'; // 表格div var _boxHtml = '<div class="calendar-box">' + '<div class="calendar-content">' + '<table>' + _theadHtml + _tbodyHtml + '</table>' + '</div>' + '</div>'; // 添加到节点中 calendar.html(_boxHtml); } /** * 表格中显示数据,并设置类名 */ function showCalendarData(year, month, markDayData) { // 设置表格中的日期数据 var _table = $('#month' + month + ' table'); var _tds = _table.find("td"); var _firstDate = new Date(year, month - 1, 1); // 当前月第一天 for(var i = 0; i < _tds.length; i++) { var _td = $(_tds[i]); var _markHtml = '<span> </span>'; // 日期编号 // < 0,代表是上个月的日期 // > 0,代表是这个月的日期 // > 31,代表是下个月的日期,如1月有31天,超过31号的,是下个月2月 var dayNumber = i + 1 - _firstDate.getDay(); var _thisDate = new Date(year, month - 1, dayNumber); // 当前日期 var _thisDateStr = formatDate(_thisDate, 'yyyy-MM-dd'); // 格式化,年月日 var day = _thisDate.getDate(); // 当前日期,几号 // 不可点击(默认) _td.addClass("calendar-disabled"); _td.html(_markHtml); // 只显示当前月 if (_thisDate.getMonth() == month - 1) { _markHtml = '<span>' + day + '</span>'; _td.html(_markHtml); _td.removeClass("calendar-disabled"); //可点击 _td.attr('id', _thisDateStr); // id,年月日 _td.attr('title', _thisDateStr); _td.attr('year', year); // 年 _td.attr('month', month); // 月 _td.attr('day', day); // 日 _td.attr('onclick', 'editDay(this)'); // 特殊日期 for (var j = 0; j < markDayData.length; j++) { var mItem = markDayData[j]; var mdate = mItem.year + '-' + mItem.month + '-' + mItem.day; // 日期一致 if (_thisDateStr == mdate) { _td.addClass("calendar-day-mark-td"); // 存在特殊日期名称 if (mItem.name) { if (mItem.type == 1) { // 工作日 _markHtml = '<span class="calendar-day-mark calendar-workday">' + mItem.name + '</span>'; _td.html(_markHtml); } else if (mItem.type == 2) { // 节假日 _markHtml = '<span class="calendar-day-mark calendar-holiday">' + mItem.name + '</span>'; _td.html(_markHtml); } } break; } } } } } function editDay(obj) { var id = $(obj).attr('id'); var year = $(obj).attr('year'); dialogOpen({ title: '修改工作日配置', url: 'system/workDay/workDayEdit.html?_' + $.now(), width: '600px', height: '400px', scroll : true, success: function(iframeId){ top.frames[iframeId].vm.workDay.id = id; top.frames[iframeId].vm.setForm(); }, yes : function(iframeId) { // 子页面传值到父页面 var result = top.frames[iframeId].vm.acceptClick(); if (result) { var temp = {}; Object.assign(temp, result); $.ConfirmForm({ url: '../../system/workDay/saveWorkDay?_=' + $.now(), param: temp, close : false, success: function(data) { initByYear(year); dialogCloseById(iframeId); } }); } } }); } function initDataByYear() { var year = $('#yearSelect').val(); $.ConfirmForm({ msg: '您是否要初始'+year+'年工作日数据?', url: '../../system/workDay/initDataByYear?year=' + year + '&_=' + $.now(), param: {}, async: false, success: function (data) { initByYear(year); } }); } function inputChange() { var result = getWorkDayAfterByDate($("#dateSelect").val(), $("#days").val()); $("#result").val(result); } function natureInputChange() { var result = dateAddDays($("#natureDateSelect").val(), $("#natureDays").val()); $("#natureResult").val(result); } </script> </body> </html>
复制
2.工作日查询、自然日查询 js
/** * [dateAddDays 从某个日期增加n天后的日期] * @param {[string]} dateStr [日期字符串] * @param {[int]} dayCount [增加的天数] * @return {[string]}[增加n天后的日期字符串] */ function dateAddDays(dateStr,dayCount) { var tempDate=new Date(dateStr.replace(/-/g,"/"));//把日期字符串转换成日期格式 var resultDate=new Date((tempDate/1000+(86400*dayCount))*1000);//增加n天后的日期 return formatDate(resultDate, "yyyy-MM-dd"); } /** * 查询工作日 * @param date 时间,格式:yyyy-MM-dd,为空将使用当前时间 * @param days 偏移量,整数,为正向后偏移,为负向前偏移 * @returns {*} */ function getWorkDayAfterByDate(date, days) { if (isNullOrEmpty(date)) { date = formatDate(new Date(), 'yyyy-MM-dd'); } if (isNullOrEmpty(days)) { return; } var result; $.SetForm({ url: '../../system/workDay/getWorkDayAfterByDate?date=' + date + '&days=' + days + '&_=' + $.now(), param: {}, async: false, success: function (data) { result = data; } }); return result; }
复制
3.修改工作日配置
<!DOCTYPE html> <html xmlns:th="http://www.thymeleaf.org"> <head th:include="include/header_css::header('编辑-工作日配置')"></head> <body> <div id="dpLTE" class="container-fluid" v-cloak> <table class="form" id="form"> <colgroup> <col width="20%" /> </colgroup> <tr> <td class="formTitle">日期</td> <td class="formValue">{{ workDay.year }}-{{ workDay.month }}-{{ workDay.day }}</td> </tr> <tr> <td class="formTitle">工作日名称</td> <td class="formValue"> <input v-model.trim="workDay.name" type="text" class="form-control" placeholder="请输入工作日名称" errormsg="工作日名称" /> </td> </tr> <tr> <td class="formTitle">备注</td> <td class="formValue"> <input v-model.trim="workDay.descn" type="text" class="form-control" placeholder="请输入备注" errormsg="备注" /> </td> </tr> <tr> <td class="formTitle">工作日类型</td> <td class="formValue"> <label class="radio-inline"> <input type="radio" name="holidayType" value="0" v-model="workDay.holidayType" isvalid="yes" checkexpession="NotNull"/> 工作日 </label> <label class="radio-inline"> <input type="radio" name="holidayType" value="1" v-model="workDay.holidayType" isvalid="yes" checkexpession="NotNull"/> 周末 </label> <label class="radio-inline"> <input type="radio" name="holidayType" value="2" v-model="workDay.holidayType" isvalid="yes" checkexpession="NotNull"/> 节日 </label> <label class="radio-inline"> <input type="radio" name="holidayType" value="3" v-model="workDay.holidayType" isvalid="yes" checkexpession="NotNull"/> 调休 </label> </td> </tr> </table> </div> <div th:include="include/footer_js::footer"></div> <script type="text/javascript"> var vm = new Vue({ el:'#dpLTE', data: { workDay: { id: null, year: null, month: null, day: null, holidayType: 0, } }, methods : { setForm: function() { var param = { id: vm.workDay.id }; $.SetForm({ url: '../../system/workDay/getInfoByDate?_' + $.now(), param: param, success: function(data) { if (data) { vm.workDay = data; } } }); }, acceptClick: function() { if (!$('#form').Validform()) { return false; } return vm.workDay; } } }) </script> </body> </html>
复制
4.数据库,表结构
字段名 | 类型 | 长度 | 主键 | 注释 |
---|---|---|---|---|
id | varchar | 36 | 是 | 主键id 年月日拼接 如:2024-01-01 |
year | varchar | 10 | 否 | 年份 |
month | varchar | 2 | 否 | 月份 |
day | varchar | 2 | 否 | 天 |
name | varchar | 200 | 否 | 名称 |
week | int | 2 | 否 | 星期几(1-7) |
week_mean | varchar | 20 | 否 | 星期几(1-7) 文本,如:星期一 |
type | int | 2 | 否 | 类型 1:工作日 2:非工作日/节假日 默认为工作日 |
holiday_type | int | 2 | 否 | 节假日类型: 0:工作日 1:周末 2:节日 3:调休 |
oper_user_id | varchar | 36 | 否 | 操作用户id |
descn | varchar | 200 | 否 | 备注 |
cdate | datetime | 0 | 否 | 创建时间 |
ldate | datetime | 0 | 否 | 修改时间 |
status | int | 2 | 否 | 状态: 1:有效 0:无效 |
sql脚本:
CREATE TABLE `t_work_day` ( `id` varchar(36) NOT NULL COMMENT '主键id', `year` varchar(10) DEFAULT NULL COMMENT '年份', `month` varchar(2) DEFAULT NULL COMMENT '月份', `day` varchar(2) DEFAULT NULL COMMENT '天', `name` varchar(200) DEFAULT NULL COMMENT '名称', `week` int(2) DEFAULT NULL COMMENT '星期几(1-7)', `week_mean` varchar(20) DEFAULT NULL COMMENT '星期几(1-7)', `type` int(2) DEFAULT NULL COMMENT '类型(1:工作日;2:非工作日/节假日;默认为工作日)', `holiday_type` int(2) DEFAULT NULL COMMENT '节假日类型:0工作日、1周末、2节日、3调休', `oper_user_id` varchar(36) DEFAULT NULL COMMENT '操作用户id', `descn` varchar(200) DEFAULT NULL COMMENT '备注', `cdate` datetime DEFAULT NULL COMMENT '创建时间', `ldate` datetime DEFAULT NULL COMMENT '修改时间', `status` int(2) DEFAULT NULL COMMENT '状态', PRIMARY KEY (`id`) USING BTREE, UNIQUE KEY `year_month_day` (`year`,`month`,`day`) USING BTREE ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='工作日配置表';
复制
数据如下:
5.初始化数据
工作日数据由第三方初始化获取 ,参考:
工作日API文档:http://timor.tech/api/holiday