日历值班表(移动端),网上找了好多三方的控件, 页面样式,功能都不太满足条件! 索性自己写一个! 要求可以查看当月排班记录,可以切换月份,单击某天回调等。。。
效果图如下

可以确认的是一屏日历需要显示6个星期42天,(例如本月30天,上个月2天,下个月10天)。明白页面组成后,要计算出本月总天数,以及本月第一天是星期几,以及上个月最后一天日期!这里有两个地方需要说一下
-
计算总天数采用了一个小技巧 new Date(year, month + 1, 0).getDate();月份加1 ,天传入一个0.就是上个月的最后一天的日期也就是当月的总天数
-
上月的起始日期, 举例; 上个月总天数(31)- 本月第一天星期(3)+ 最后1天(31日)+ 本月第1天(1日) 最后为 passdays = prefays - weekday + 2
var date = new Date();
var year = date.getFullYear(); // 年份
var month = date.getMonth(); //月份
var firstday = new Date(year, month, 1); // 当月第一天
var weekday = firstday.getDay(); // 当月第一天是星期几
var days = new Date(year, month + 1, 0).getDate(); // 当月总天数
if (month == 0) {
var premonth = 12;
var preyear = year - 1;
} else {
var premonth = month - 1;
var preyear = year;
}
var prefays = new Date(preyear, premonth + 1, 0).getDate(); // 上个月总天数
var res = '';
var passdays;
if (weekday == 0) {
weekday = 7;
}
passdays = prefays - weekday + 2 ; // 上个月起始日期
渲染日历
// 上个月部分
for (var i = 0; i < weekday - 1; i++) {
res += '<div><span class="pass">' + passdays + '</span></div>';
passdays++;
}
// 当月部分
for (var j = 1; j <= days; j++) {
if (j == today && year == _year && month == _month) {
res += '<div data-date="' + j + '"><span class="on select">' + j +
'</span></div>';
} else {
res += '<div data-date="' + j + '"><span>' + j + '</span></div>';
}
}
// 下个月部分
var nextdays = 42 - days - weekday + 1;
for (var i = 1; i <= nextdays; i++) {
res += '<div><span class="pass">' + i + '</span></div>';
}
Demo:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<meta name="viewport"
content="width=device-width,initial-scale=1,minimum-scale=1,maximum-scale=1,user-scalable=no" />
<title></title>
<style>
.sign-alert {
background: #fff;
border-radius: 4px;
width: 90%;
margin: 0 auto;
min-height: 200px;
/* margin-top: 40%; */
position: relative;
padding-bottom: 20px;
font-size: 12px;
}
.sign-week {
width: 100%;
background-color: #0071c0;
height: 26px;
display: flex;
justify-content: space-around;
line-height: 26px;
color: #fff;
}
.sign-date {
display: flex;
justify-content: space-around;
flex-wrap: wrap;
}
.sign-date div {
padding: 6px 0;
width: 14.2%;
text-align: center;
}
.sign-date span {
text-align: center;
color: #0071c0;
height: 20px;
width: 20px;
display: inline-block;
line-height: 20px;
}
.sign-date p {
margin: 0 auto;
padding: 0;
font-size: 20px;
transform: scale(0.4);
position: relative;
margin-top: -12px;
width: 20px;
}
.sign-date p::before {
content: "";
width: 10px;
height: 10px;
position: absolute;
background-color: orange;
border-radius: 10px;
top: 24px;
left: 5px;
}
.sign-date span.pass {
color: #999999;
}
.sign-date span.on {
border-radius: 50%;
border: 1px solid #0071c0;
}
.select {
background-color: #0071c0;
color: #fff !important;
border-radius: 50%;
}
</style>
</head>
<body>
<div id="calendar-tem">
</div>
<script>
(function (window, undefined) {
var Calendar = function (params) {
document.getElementById("calendar-tem").innerHTML =
' <button id="preMonth">上个月</button> <button id = "nextMonth"> 下个月 </button> <button id = "today"> 今天 </button> <br> <br>' +
'<div id = "date"> </div> <br> <br> <div id = "sign">' + '<div class = "sign-alert">' +
'<div class = "sign-week"><span> 一 </span> <span> 二 </span> <span> 三 </span> <span> 四 </span> <span > 五 </span> <span > 六 </span> <span > 日 </span> </div> ' +
'<div class = "sign-date"> </div> </div> </div>'
// var Calendar = function (date, initCb, clickCb) {
this.date = params.date ? params.date : new Date();
this.clickCb = params.clickCb || null;
this.initCb = params.initCb || null;
this.preMonthEl = document.getElementById("preMonth");
this.nextMonthEl = document.getElementById("nextMonth");
this.todayEl = document.getElementById("today");
this.today;
this.year;
this.month;
this.init();
}
Calendar.prototype = {
constructor: Calendar,
init: function () {
var date = this.date;
var year = date.getFullYear(); // 当前年
var month = date.getMonth(); // 当前月份 (3 = 4 - 1)
var firstday = new Date(year, month, 1); // 当月第一天
var weekday = firstday.getDay(); // 当月第一天是星期几
var days = new Date(year, month + 1, 0).getDate(); // 当月总天数
var today = new Date().getDate(); // 当前天
var _year = new Date().getFullYear(); // 当前年
var _month = new Date().getMonth(); //当前月
this.year = year;
this.month = month;
this.today = today;
if (month == 0) {
var premonth = 12;
var preyear = year - 1;
} else {
var premonth = month - 1;
var preyear = year;
}
var prefays = new Date(preyear, premonth + 1, 0).getDate(); // 上个月总天数
var res = '';
var passdays;
if (weekday == 0) {
weekday = 7;
}
passdays = prefays - weekday + 2
for (var i = 0; i < weekday - 1; i++) {
res += '<div><span class="pass">' + passdays + '</span></div>';
passdays++;
}
for (var j = 1; j <= days; j++) {
if (j == today && year == _year && month == _month) {
res += '<div data-date="' + j + '"><span class="on select">' + j +
'</span></div>';
} else {
res += '<div data-date="' + j + '"><span>' + j + '</span></div>';
}
}
var nextdays = 42 - days - weekday + 1;
for (var i = 1; i <= nextdays; i++) {
res += '<div><span class="pass">' + i + '</span></div>';
}
document.querySelectorAll(".sign-date")[0].innerHTML = res
document.getElementById("date").innerHTML = year + "-" + Number(month + 1);
this.datesEl = document.querySelectorAll("div[data-date]");
if (this.initCb !== null) {
this.initCb(year + "-" + Number(month + 1))
}
this.bindEvent()
},
toToday: function () {
var date = new Date();
this.date = new Date(date.getFullYear(), date.getMonth(), 1);
this.init()
},
preMonth: function () {
var date = this.date;
this.date = new Date(date.getFullYear(), date.getMonth() - 1, 1);
this.init()
},
nextMonth: function () {
var date = this.date;
this.date = new Date(date.getFullYear(), date.getMonth() + 1, 1);
this.init()
},
bindEvent: function () {
var _this = this;
this.preMonthEl.onclick = function () {
_this.preMonth();
}
this.nextMonthEl.onclick = function () {
_this.nextMonth();
}
this.todayEl.onclick = function () {
_this.toToday();
}
if (_this.clickCb === null) return
for (var i = 0; i < this.datesEl.length; i++) {
(function (i) {
var item = _this.datesEl[i];
item.onclick = function () {
// console.log(item)
var spans = document.getElementsByTagName('span');
for (var j = 0; j < spans.length; j++) {
spans[j].classList.remove('select')
}
item.children[0].classList.add('select')
var obj = {
date: _this.year + "-" + Number(_this.month + 1) + "-" +
item.getAttribute("data-date"),
timePeriod: item.getAttribute("data-time-period")
}
_this.clickCb(obj)
}
})(i)
}
},
bindData: function (arr) {
var _this = this;
var dates = this.datesEl
for (var i = 0; i < arr.length; i++) {
var item = arr[i]
for (var j = 0; j < dates.length; j++) {
var cale = dates[j];
if (item.date == cale.getAttribute("data-date")) {
cale.setAttribute("data-time-period", item.timePeriod)
var p = document.createElement("p");
var txt = document.createTextNode(item.title);
p.appendChild(txt)
cale.appendChild(p);
}
}
}
if (this.clickCb !== null && _this.year == new Date().getFullYear() && _this.month ==
new Date().getMonth()) {
var obj = {
date: _this.year + "-" + Number(_this.month + 1) + "-" + _this.today,
timePeriod: document.querySelector("div[data-date='" + _this.today +
"']")
.getAttribute("data-time-period")
}
this.clickCb(obj)
}
}
};
window.Calendar = window.Calendar || Calendar
}(window));
var _Calendar = new Calendar({
date: new Date(),
clickCb: function (obj) {
console.log("选中日期回调:", obj);
// alert("选中日期回调:" + JSON.stringify)
},
initCb: function (date) {
console.log("初始化回调===>", date);
var data = [{
date: 1,
title: "早",
timePeriod: "00:00-08:00"
},
{
date: 2,
title: "中",
timePeriod: "01:00-09:00"
},
{
date: 10,
title: "晚",
timePeriod: "08:00-16:00"
},
{
date: 4,
title: "早",
timePeriod: "09:00-17:00"
},
{
date: 25,
title: "早",
timePeriod: "00:00-08:00"
},
]
this.bindData(data)
},
})
</script>
</body>
</html>