目录
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