基于LayUI使用FullCalendar实现日程管理


原文:https://blog.csdn.net/chyanwu68/article/details/90372215

引言

  最新工作中需要实现日程管理功能,由于技术选型(基于layui)限制,从网上对比查询最终选定使用FullCalendar插件来实现日程管理。
其中对比的日程还有XgCalendar、Google Calendar

实现效果
1、打开界面后,月视图

2、切换到周视图

3、切换到日视图

4、在月视图,添加会议室预订


5、在月视图,修改会议室预订


6、在月视图,鼠标移到event,显示详情

对应实现
1、依赖的js
下载路径:https://fullcalendar.io/docs/getting-started

2、对应的index

<!DOCTYPE html>
<html lang='en'>
<head>
<meta charset='utf-8' />
<meta name="renderer" content="webkit">
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
<meta name="apple-mobile-web-app-status-bar-style" content="black">
<meta name="apple-mobile-web-app-capable" content="yes">
<meta name="format-detection" content="telephone=no">

<link rel="stylesheet" href='/fullcalendar/core/main.css' rel='stylesheet' />
<link rel="stylesheet" href='/fullcalendar/daygrid/main.css' rel='stylesheet' />
<link rel="stylesheet" href='/fullcalendar/timegrid/main.css' rel='stylesheet' />
<link rel="stylesheet" href="/assets/libs/layui/css/layui.css" media="all">
<link rel="stylesheet" href="/assets/common.css" media="all">

<style>
#calendar {
max-width: 1200px;
margin: 0 auto;
}

#external-events {
float: left;
width: 150px;
padding: 0 10px;
border: 1px solid #ccc;
background: #eee;
text-align: left;
}

#external-events h4 span {
font-size: 16px;
margin-top: 0;
padding-top: 1em;
}

.external-event { /* try to mimick the look of a real event */
margin: 10px 0;
padding: 2px 4px;
background: #3366CC;
color: #fff;
font-size: .85em;
cursor: pointer;
}

/*日期控件*/
.layui-laydate-content>.layui-laydate-list {
padding-bottom: 0px;
overflow: hidden;
}
.layui-laydate-content>.layui-laydate-list>li{
width:50%
}

/* pop */
.popper,
.tooltip {
position: absolute;
z-index: 9999;
background: #FFC107;
color: black;
width: 150px;
border-radius: 3px;
box-shadow: 0 0 2px rgba(0,0,0,0.5);
padding: 10px;
text-align: center;
}
.style5 .tooltip {
background: #1E252B;
color: #FFFFFF;
max-width: 200px;
width: auto;
font-size: .8rem;
padding: .5em 1em;
}
.popper .popper__arrow,
.tooltip .tooltip-arrow {
width: 0;
height: 0;
border-style: solid;
position: absolute;
margin: 5px;
}

.tooltip .tooltip-arrow,
.popper .popper__arrow {
border-color: #FFC107;
}
.style5 .tooltip .tooltip-arrow {
border-color: #1E252B;
}
.popper[x-placement^="top"],
.tooltip[x-placement^="top"] {
margin-bottom: 5px;
}
.popper[x-placement^="top"] .popper__arrow,
.tooltip[x-placement^="top"] .tooltip-arrow {
border-width: 5px 5px 0 5px;
border-left-color: transparent;
border-right-color: transparent;
border-bottom-color: transparent;
bottom: -5px;
left: calc(50% - 5px);
margin-top: 0;
margin-bottom: 0;
}
.popper[x-placement^="bottom"],
.tooltip[x-placement^="bottom"] {
margin-top: 5px;
}
.tooltip[x-placement^="bottom"] .tooltip-arrow,
.popper[x-placement^="bottom"] .popper__arrow {
border-width: 0 5px 5px 5px;
border-left-color: transparent;
border-right-color: transparent;
border-top-color: transparent;
top: -5px;
left: calc(50% - 5px);
margin-top: 0;
margin-bottom: 0;
}
.tooltip[x-placement^="right"],
.popper[x-placement^="right"] {
margin-left: 5px;
}
.popper[x-placement^="right"] .popper__arrow,
.tooltip[x-placement^="right"] .tooltip-arrow {
border-width: 5px 5px 5px 0;
border-left-color: transparent;
border-top-color: transparent;
border-bottom-color: transparent;
left: -5px;
top: calc(50% - 5px);
margin-left: 0;
margin-right: 0;
}
.popper[x-placement^="left"],
.tooltip[x-placement^="left"] {
margin-right: 5px;
}
.popper[x-placement^="left"] .popper__arrow,
.tooltip[x-placement^="left"] .tooltip-arrow {
border-width: 5px 0 5px 5px;
border-top-color: transparent;
border-right-color: transparent;
border-bottom-color: transparent;
right: -5px;
top: calc(50% - 5px);
margin-left: 0;
margin-right: 0;
}
</style>
</head>
<body>

<div class="layui-fluid">
<div class="layui-card" style="padding-top: 5px; margin-bottom: 8px;">
<div class="layui-row layui-col-space15">
<div class="layui-col-xs12 layui-col-md2">
<div id='external-events'>
<h4>会议室</h4>
<#list roomList as room>
<div class="external-event" id="room${room.id}" roomId="${room.id}" onclick="changeRoom(this.id)">${room.name}</div>
</#list>
<#--<div id="1" roomId="1" onclick="changeRoom(this.id)">会议室1</div>-->
<#--<div id="2" roomId="2" onclick="changeRoom(this.id)">会议室2</div>-->
<#--<div id="3" roomId="3" onclick="changeRoom(this.id)">会议室3</div>-->
<#--<div id="4" roomId="4" onclick="changeRoom(this.id)">会议室4</div>-->
</div>
</div>
<div class="layui-col-xs12 layui-col-md10">
<div id='calendar'></div>
</div>
</div>
</div>
</div>


<!-- 表单弹框 -->
<script type="text/html" id="calendarForm">
<form lay-filter="calendarForm" class="layui-form model-form">
<input name="id" id="id" type="hidden"/>
<div class="layui-form-item">
<label class="layui-form-label">预约主题</label>
<div class="layui-input-block">
<input name="appointTheme" placeholder="请输入会议主题" type="text" class="layui-input" maxlength="50" lay-verify="required" required/>
</div>
</div>
<div class="layui-form-item">
<label class="layui-form-label">预约开始时间</label>
<div class="layui-input-inline">
<input type="text" class="layui-input" id="stime" name="stime" placeholder="HH:mm" lay-verify="required" required>
</div>
</div>
<div class="layui-form-item">
<label class="layui-form-label">预约结束时间</label>
<div class="layui-input-inline">
<input type="text" class="layui-input" id="etime" name="etime" placeholder="HH:mm" lay-verify="required" required>
</div>
</div>
<div class="layui-form-item">
<label class="layui-form-label">预约人</label>
<div class="layui-input-block">

<input name="appointPerson" value="<#if currentUser.name!=''>${currentUser.name}<#else>${currentUser.loginName}</#if>" type="text" class="layui-input" maxlength="50" readonly />
</div>
</div>
<div class="layui-form-item">
<label class="layui-form-label">联系方式</label>
<div class="layui-input-block">
<input name="tel" value="<#if currentUser.phone??>${currentUser.phone}</#if>" type="text" class="layui-input" maxlength="20" readonly />
</div>
</div>
<div class="layui-form-item text-right">
<button class="layui-btn layui-btn-primary" type="button" ew-event="closeDialog">取消</button>
<button class="layui-btn" lay-filter="formSubmit" lay-submit>保存</button>
<button class="layui-btn" type="button" id="delEdit" onclick="del()">删除</button>
</div>
</form>
</script>

<!-- js部分 -->
<script src='/fullcalendar/core/main.js'></script>
<script src='/fullcalendar/core/locales-all.js'></script>
<script src='/fullcalendar/daygrid/main.js'></script>
<script src='/fullcalendar/interaction/main.js'></script>
<script src='/fullcalendar/timegrid/main.js'></script>
<script src='/fullcalendar/core/locales/zh-cn.js'></script>
<script src="/assets/libs/jquery/jquery-3.2.1.min.js"></script>
<script src='/fullcalendar/popper.min.js'></script>
<script src='/fullcalendar/tooltip.min.js'></script>
<script type="text/javascript" src="/assets/libs/layui/layui.all.js"></script>
<script type="text/javascript" src="/assets/js/calendar/index.js"></script>
</body>
</html>
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
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
3、对应的js

var addIndex;
var roomId;
var calendar;
var $ = layui.jquery;
var layer = layui.layer;
var form = layui.form;
var laydate = layui.laydate;

roomId = $("#room1").attr("roomId");
$("#room1").css("backgroundColor", "#003399");

document.addEventListener('DOMContentLoaded', function() {
var calendarEl = document.getElementById('calendar');

calendar = new FullCalendar.Calendar(calendarEl, {
plugins: [ 'interaction', 'dayGrid', 'timeGrid' ],
defaultView: 'dayGridMonth',
// defaultDate: '2019-05-07',
selectable: true, // dataClick生效
locale: 'zh-cn', // 设置中文
eventLimit: 4, // 显示更多
displayEventEnd: true, // 显示结束时间
header: {
left: 'prev,next today',
center: 'title',
right: 'dayGridMonth,timeGridWeek,timeGridDay'
},
events: function(info, successCallback, failureCallback) {

$.get("/erpcalendartask/getByParams", {roomId: roomId, sTime: info.start.valueOf(), eTime: info.end.valueOf()}, function (res) {
if(res.code == 200) {
successCallback(res.data);
}else {
failureCallback(res.errStr);
}
});
}
,eventClick: function(info) {
console.log('eventClick ' + info);
openEditLayer(info);
}
,dateClick: function(info) {
console.log('dateClick ' + info.dateStr);
openLayer(info);
}
,eventRender: function(info) {
var tooltip = new Tooltip(info.el, {
title: popContent(info.event.title, info.event.extendedProps.appointPerson, info.event.start, info.event.end, info.event.extendedProps.tel),
placement: 'top',
trigger: 'hover',
container: 'body',
html: true
});
}
});

calendar.render();
});

function popContent(title, appointPerson, stime, etime, tel) {
var sDate =new Date(stime);
var s = sDate.getHours() + '点' + sDate.getMinutes() + '分';
var eDate =new Date(etime);
var e = eDate.getHours() + '点' + eDate.getMinutes() + '分';
var str = '<div style="font-weight: bold;">' + title + '</div>';
str += '<div style="height: 1px;background-color: black;"></div>'
str += '<div style="text-align: left;">预订人:' + appointPerson + '</div>';
str += '<div style="text-align: left;">预订时间:' + s + ' - ' + e + '</div>';
str += '<div style="text-align: left;">预订电话:' + tel + '</div>'
return str;
}

$(document).ready(function () {

});

function initDateCtrl() {
//日期时间选择器
laydate.render({
elem: '#stime' //指定元素
,type: 'time'
,format: 'HH:mm'
,done: function(value, date){
var etime = $("#etime").val();
var ehour = parseInt(etime.split(":")[0]);
var eminute = parseInt(etime.split(":")[1]);
var hour = date.hours;
var minute = date.minutes;
if(ehour < hour) {
$("#finishtime").val(value);
} else {
if(eminute < minute) {
$("#etime").val(value);
}
}
}
});

//日期时间选择器
laydate.render({
elem: '#etime' //指定元素
,type: 'time'
,format: 'HH:mm'
,done: function(value, date){
var stime = $("#stime").val();
var shour = parseInt(stime.split(":")[0]);
var sminute = parseInt(stime.split(":")[1]);
var hour = date.hours;
var minute = date.minutes;
if(shour > hour) {
$("#stime").val(value);
} else {
if(sminute > minute) {
$("#stime").val(value);
}
}
}
});
}

function openEditLayer(info){
addIndex=layer.open({
title : '<i class="fa fa-plus"></i>&nbsp;编辑日程',
type : 1,
fix : false,
skin : 'layui-layer-rim',
// 加上边框
area : [ '470px', '450px' ],
// 宽高
content : $('#calendarForm').html(),
success: function (layero, index) {
initDateCtrl();
$("#delEdit").show();

var data = {};
data.id = info.event.id;
var sDate =new Date(info.event.start);
data.stime = sDate.getHours() + ':' + sDate.getMinutes() ;
var eDate =new Date(info.event.end);
data.etime = eDate.getHours() + ':' + eDate.getMinutes() ;
data.appointTheme = info.event.title;
data.appointPerson = info.event.extendedProps.appointPerson;
data.tel = info.event.extendedProps.tel;
form.val('calendarForm', data);

// 表单提交事件
form.on('submit(formSubmit)', function (d) {
var dataStr = sDate.getFullYear() + '-' + (sDate.getMonth() + 1) + '-' + sDate.getDate();
d.field.roomId = roomId;
d.field.stime = dataStr + " " + d.field.stime + ":00";
d.field.etime = dataStr + " " + d.field.etime + ":00";
$.ajax({
type: 'POST',
url: '/erpcalendartask/update',//发送请求
contentType: "application/json; charset=utf-8",
async: true,
data: JSON.stringify(d.field),
dataType: "json",
success: function (res) {
layer.closeAll("loading");
if(res.code == 200){
// layer.msg("添加成功!", {icon: 1});
calendar.refetchEvents();
layer.closeAll('page');
}else{
layer.msg(res.msg, {icon: 2});
}
}
});

return false;
});
}
});
}

function openLayer(info){
addIndex=layer.open({
title : '<i class="fa fa-plus"></i>&nbsp;新增日程',
type : 1,
fix : false,
skin : 'layui-layer-rim',
// 加上边框
area : [ '470px', '450px' ],
// 宽高
content : $('#calendarForm').html(),
success: function (layero, index) {
initDateCtrl();
$("#delEdit").hide();
// 表单提交事件
form.on('submit(formSubmit)', function (d) {
d.field.roomId = roomId;
d.field.stime = info.dateStr + " " + d.field.stime + ":00";
d.field.etime = info.dateStr + " " + d.field.etime + ":00";

$.ajax({
type: 'POST',
url: '/erpcalendartask/create',//发送请求
contentType: "application/json; charset=utf-8",
async: true,
data: JSON.stringify(d.field),
dataType: "json",
success: function (res) {
layer.closeAll("loading");
if(res.code == 200){
// layer.msg("添加成功!", {icon: 1});
calendar.refetchEvents();
layer.closeAll('page');
}else{
layer.msg(res.msg, {icon: 2});
}
}
});


return false;
});
}
});
}

function changeRoom(id){
$(".external-event").each(function(i){
if(this.id==id){
$(this).css("backgroundColor", "#003399");
roomId = $(this).attr("roomId");
}else{
$(this).css("backgroundColor", "#3366CC");
}
});
calendar.refetchEvents();
}

function del(){
var id=$("#id").val();
layer.confirm('确定要删除吗?', {
offset: '65px',
title: '提示'
}, function (i) {
layer.close(i);
layer.load(2);
$.post("/erpcalendartask/deleteByID", {id: id}, function (res){
layer.closeAll('loading');
if(res.code == 200){
// layer.msg("删除成功");
calendar.refetchEvents();
layer.closeAll('page');
}else{
layer.msg(res.message);
}
});
});
}

// 所有ew-event
$('body').on('click', '*[ew-event]', function () {
var event = $(this).attr('ew-event');
if (event == 'closeDialog') {
var id = $(this).parents('.layui-layer').attr('id').substring(11);
layer.close(id);
}
});
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
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
考虑到Java服务端只是CRUD,避免文字的篇幅太长,所以大家如需继续研究,可以在git上下载:
https://github.com/chyanwu/erp-framework

更多精彩,更多技术请关注:码蚁在线(coding_online)
————————————————
版权声明:本文为CSDN博主「伍婷」的原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/chyanwu68/article/details/90372215


免责声明!

本站转载的文章为个人学习借鉴使用,本站对版权不负任何法律责任。如果侵犯了您的隐私权益,请联系本站邮箱yoyou2525@163.com删除。



 
粤ICP备18138465号  © 2018-2025 CODEPRJ.COM