fullcalendar 日历插件的使用
【需求】:使用 fullcalendar日历插件,完成如下功能:可以进行拖动,点击空白处添加,双击后修改和删除等功能。API 链接
一、html 文件中引入相关依赖,主要包括引入的 css和 js;
1 <!DOCTYPE html>
2 <html lang="zh_CN" xmlns:th="http://www.thymeleaf.org"
3 xmlns:shiro="http://www.pollix.at/thymeleaf/shiro">
4 <meta charset="utf-8">
5 <head th:include="include :: header"></head>
6 <body class="gray-bg">
7 <div class="wrapper wrapper-content ">
8 <div class="col-sm-12">
9 <div class="ibox">
10 <div class="ibox-body">
11 <div class="fixed-table-toolbar">
12 <div class="columns pull-left col-md-2 nopadding">
13 <input id="orgCode2" name="orgCode2" th:value="${orgCode2}" type="hidden">
14 <select id="filter_orgCode" name="filter_orgCode" class="form-control" type="text" required="true">
15 <option> </option>
16 </select>
17 <div class="error-msg"></div>
18 </div>
19
20 <div class="columns pull-left">
21 <button class="btn btn-success" type="button" class="btn btn-primary" onclick="reloadCalendar()" id="btnSearch">
22 <i aria-hidden="true"></i>查询
23 </button>
24 <button shiro:hasPermission="centerInfo:personSchedul:add" type="button" class="btn btn-primary" onclick="add()">
25 <i class="fa fa-plus" aria-hidden="true"></i>添加排班
26 </button>
27 <!--<button shiro:hasPermission="centerInfo:personSchedul:batchRemove" type="button" class="btn btn-danger"
28 onclick="batchRemove()">
29 <i class="fa fa-trash" aria-hidden="true"></i>批量删除
30 </button>-->
31 </div>
32 <div class="columns pull-left">
33 <span style="font-size: 9px;">说明:点击单元格空白处,可添加排班;双击单条排班可编辑和删除</span>
34 </div>
35 </div>
36 <div id="senscloud-container" class="form-group table-contain senscloud-container"
37 style="border-top: solid 1px #EDEEF2;">
38 <div style="padding: 10px 0;">
39 <div id='calendar' class="col-xs-12"></div>
40 </div>
41 </div>
42 </div>
43 </div>
44 </div>
45 </div>
46 <!--shiro控制bootstraptable行内按钮看见性 来自bootdo的创新方案 -->
47 <div>
48 <script type="text/javascript">
49 var s_edit_h = 'hidden';
50 var s_remove_h = 'hidden';
51 var s_resetPwd_h = 'hidden';
52 </script>
53 </div>
54 <div shiro:hasPermission="centerInfo:personSchedul:edit">
55 <script type="text/javascript">
56 s_edit_h = '';
57 </script>
58 </div>
59 <div shiro:hasPermission="centerInfo:personSchedul:remove">
60 <script type="text/javascript">
61 var s_remove_h = '';
62 </script>
63 </div>
64 <div shiro:hasPermission="centerInfo:personSchedul:resetPwd">
65 <script type="text/javascript">
66 var s_resetPwd_h = '';
67 </script>
68 </div>
69 </div>
70 <div th:include="include :: footer"></div>
71 <link th:href="@{/css/plugins/fullcalendar/fullcalendar.css}" rel='stylesheet'/>
72 <link th:href="@{/css/plugins/fullcalendar/fullcalendar.print.css}" rel='stylesheet' media='print'/>
73 <link th:href="@{/css/bootstrap.min.css}" rel='stylesheet' type="text/css"/>
74 <script type="text/javascript" th:src="@{/js/plugins/jquery-ui/jquery-ui.min.js}"></script>
75
76 <script type="text/javascript" th:src="@{/js/plugins/fullcalendar/moment.min.js}"></script>
77 <script type="text/javascript" th:src="@{/js/plugins/fullcalendar/fullcalendar.min.js}"></script>
78
79 <link th:href="@{/css/plugins/bootstrap-timepicker/bootstrap-timepicker.min.css}" rel='stylesheet'/>
80 <script type="text/javascript" th:src="@{/js/plugins/bootstrap-timepicker/bootstrap-timepicker.min.js}"></script>
81 <script type="text/javascript" th:src="@{/js/plugins/datapicker/bootstrap-datepicker.js}"></script>
82 <script type="text/javascript" th:src="@{/js/appjs/centerInfo/perSchedul/personSchedul.js}"></script>
83 </body>
84 </html>
二、js 中使用 fullCalendar 插件完成该功能
1 var prefix = "/dms/centerInfo/personSchedul"
2 /**
3 * 在页面加载此js文件
4 * 使用例:new Date().format("yyyy-MM-dd hh:mm:ss")
5 */
6 Date.prototype.format = function (fmt) {
7 var o = {
8 "M+": this.getMonth() + 1, //月份
9 "d+": this.getDate(), //日
10 "h+": this.getHours(), //小时
11 "m+": this.getMinutes(), //分
12 "s+": this.getSeconds(), //秒
13 "q+": Math.floor((this.getMonth() + 3) / 3), //季度
14 "S": this.getMilliseconds() //毫秒
15 };
16 if (/(y+)/.test(fmt)) {
17 fmt = fmt.replace(RegExp.$1, (this.getFullYear() + "").substr(4 - RegExp.$1.length));
18 }
19 for (var k in o) {
20 if (new RegExp("(" + k + ")").test(fmt)) {
21 fmt = fmt.replace(RegExp.$1, (RegExp.$1.length == 1) ? (o[k]) : (("00" + o[k]).substr(("" + o[k]).length)));
22 }
23 }
24 return fmt;
25 }
26
27 var myCalendar;
28 var nextWeek = new Date();
29 var tomorrow = new Date();
30 nextWeek.setDate(nextWeek.getDate() + 7);
31 tomorrow.setDate(tomorrow.getDate() + 1);
32
33 var tomorrowWord = tomorrow.format('yyyy-MM-dd');
34 var nextWeekWord = nextWeek.format('yyyy-MM-dd');
35 $(function() {
36
37 //下拉框 orgcode 赋值
38 $("#filter_orgCode").select2({
39 data:getOrgCode(),
40 placeholder:"请选择",
41 allowClear:true,
42 language:"zh-CN"
43 }).val($("#orgCode2").val()).trigger("change");
44
45 //如果分拨编码为空,说明是超级管理员,可以进行下拉选择,否则不允许修改
46 if($("#filter_orgCode").val() != null && $("#filter_orgCode").val() != ""){
47 $("#filter_orgCode").attr("disabled",true);
48 }
49
50 //查询条件进行复制
51 $('.timepicker').timepicker({
52 defaultTime: '9:00',
53 showMeridian: false,
54 minuteStep: 1
55 });
56 myCalendar = $("#calendar").fullCalendar({
57 header: {
58 left: '',
59 center: 'title',
60 right: 'today prev,next'
61 },
62 height: window.parent.document.body.clientHeight - 180,
63 windowResize: function (view) {
64 $('#calendar').fullCalendar('option', 'height', window.parent.document.body.clientHeight - 180);
65 },
66 fixedWeekCount: false,
67 locale: getNowLanguage(1).toLowerCase(),
68 //设置是否可被单击或者拖动选择
69 selectable: true,
70 //点击或者拖动选择时,是否显示时间范围的提示信息,该属性只在agenda视图里可用
71 selectHelper: true,
72 //点击或者拖动选中之后,点击日历外的空白区域是否取消选中状态 true为取消 false为不取消,只有重新选择时才会取消
73 unselectAuto: true,
74 events: function (start, end, callback) {
75 var submitGroup = $("#filter_orgCode").val().toString();
76 if (myCalendar != null && myCalendar != undefined) {
77 serachCalendarWorkSchedule(submitGroup, start, end, callback);
78 }
79 },
80 eventClick: function (event) {
81 //当点击日历中的某一日程(事件)时,触发此操作,编辑人员排版
82 //edit(event.id)
83 },
84 dayClick: function (date, allDay, jsEvent, view) {
85 //当单击日历中的某一天时,触发callback,添加人员排版
86 add(date);
87 },
88 //Event是否可被拖动或者拖拽
89 editable: true,
90 //Event被拖动时的不透明度
91 dragOpacity: 0.6,
92 eventDrop: function (event, dayDelta, minuteDelta, allDay, revertFunc) {//当拖拽完成并且时间改变时触发
93 var color = event.backgroundColor;
94 if(color=='#E0FFFF'){
95 layer.alert("已过期排班不能拖动!", {skin:'layui-layer-red',closeBtn:0,icon:2});
96 revertFunc(); //恢复原状
97 return;
98 }
99 $.ajax({
100 type : 'POST',
101 url: prefix+"/dropView",
102 data: {
103 "dayDelta": dayDelta,
104 "id": event.id
105 },
106 dataType: "json",
107 success: function (data) {
108 reloadCalendar();
109 }
110 });
111 },
112 eventRender: function (event, element) {
113 //alert("eventRender")
114 },
115 eventAfterRender: function (event, element, view) {
116 $(element).on("dblclick", function () {
117 //双击触发该事件
118 edit(event.id);
119 });
120 },
121 eventResize: function (event, dayDelta, revertFunc) {
122 //alert("eventResize")
123 },
124 });
125
126 $("#beginDay").datepicker({
127 format: 'yyyy-mm-dd',//显示格式
128 todayHighlight: 1,//今天高亮
129 autoclose: 1,//选择后自动关闭
130 minView: 1,
131 language: getNowLanguage(1)
132 });
133 $("#endDay").datepicker({
134 format: 'yyyy-mm-dd',//显示格式
135 todayHighlight: 1,//今天高亮
136 autoclose: 1,//选择后自动关闭
137 minView: 1,
138 language: getNowLanguage(1)
139 });
140
141 $("#beginDay").val(tomorrowWord);
142 $("#endDay").val(nextWeekWord);
143
144 $(document).keyup(function (event) {//回车查询
145 if (event.keyCode == 13) {
146 $("#btnSearch").trigger("click");
147 }
148 });
149 });
150
151 //重新加载日历中的信息
152 reloadCalendar = function () {
153 myCalendar.fullCalendar('refetchEvents');
154 }
155
156 //添加员工排班
157 function add(date) {
158 layer.open({
159 type : 2,
160 title : '添加排班',
161 maxmin : true,
162 shadeClose : false, // 点击遮罩关闭层
163 area : [ '800px', '520px' ],
164 content : prefix + '/add' +"?date=" + date // iframe的url
165 });
166 }
167
168 //批量删除
169 function batchRemove() {
170 var rows = $('#exampleTable').bootstrapTable('getSelections'); // 返回所有选择的行,当没有选择的记录时,返回一个空数组
171 if (rows.length == 0) {
172 layer.msg("请选择要删除的数据");
173 return;
174 }
175 layer.confirm("确认要删除选中的'" + rows.length + "'条数据吗?", {
176 btn : [ '确定', '取消' ]
177 // 按钮
178 }, function() {
179 var ids = new Array();
180 // 遍历所有选择的行数据,取每条数据对应的ID
181 $.each(rows, function(i, row) {
182 ids[i] = row['id'];
183 });
184 $.ajax({
185 type : 'POST',
186 data : {
187 "ids" : ids
188 },
189 url : prefix + '/batchRemove',
190 success : function(r) {
191 if (r.code == 0) {
192 layer.msg(r.msg);
193 reLoad();
194 } else {
195 layer.msg(r.msg);
196 }
197 }
198 });
199 }, function() {
200
201 });
202 }
203
204 //将数据库的时间戳转成 *年*月*日 字符串
205 function getDate(DBTime){
206 var date = new Date(DBTime);
207 var year = date.getFullYear();
208 var month = date.getMonth()+1;
209 var day = date.getDate();
210 var dateStr;
211 if(month<10&&day<10){
212 dateStr = year+"-0"+month+"-0"+day;
213 }else if(month<10&&day>=10){
214 dateStr = year+"-0"+month+"-"+day;
215 }else if(month>=10&&day<10){
216 dateStr = year+"-"+month+"-0"+day;
217 }else if(month>=10&&day>=10){
218 dateStr = year+"-"+month+"-"+day;
219 }
220 return dateStr;
221 }
222
223 //将数据库的时间戳转成 *时*分 字符串
224 function getTime(DBTime){
225 var time = DBTime.substring(0,2)+"-"+DBTime.substring(3,5);
226 return time;
227 }
228
229 /**
230 * 获取当前语言类型
231 * @return {*}
232 */
233 function getNowLanguage(type) {
234 try {
235 var rk = $.cookie('resource_key');
236 if (!rk) {
237 rk = "zh_CN";
238 }
239 if (type) {
240 // 日期控件
241 if ("1" == type) {
242 if ("en_US" == rk) {
243 return "en";
244 }
245 if ("zh_CN" == rk) {
246 return "zh-CN";
247 }
248 // 评分控件
249 } else if ("2" == type) {
250 if ("en_US" == rk) {
251 return "en";
252 }
253 if ("zh_CN" == rk) {
254 return "zh";
255 }
256 }
257 }
258 return rk;
259 } catch (e) {
260 return "en_US";
261 }
262 }
263
264 //查询,按用户组织查询排班
265 serachCalendarWorkSchedule = function (addGroup, start, end, callback) {
266 var groupIds = "";
267 if (addGroup != null && addGroup != '' && addGroup != 'undefined') {
268 groupIds = addGroup;
269 } else {
270 groupIds = $("#filter_orgCode").val().toString();
271
272 }
273 myCalendar.fullCalendar('removeEvents');
274 var startDate = start;
275 if (undefined == startDate || null == startDate || "" == startDate) {
276 startDate = myCalendar.fullCalendar('getView').start.valueOf();
277 }
278 var endDate = end;
279 if (undefined == endDate || null == endDate || "" == endDate) {
280 endDate = myCalendar.fullCalendar('getView').end.valueOf();
281 }
282
283 if (groupIds == null || groupIds == undefined || groupIds == "" || groupIds == "null") {
284 return;
285 }
286
287 $.ajax({
288 type: "POST",
289 url: prefix + "/list",
290 data: {
291 "start": TimeStampConvertDate(startDate),
292 "end": TimeStampConvertDate(endDate),
293 "orgCode": groupIds
294 },
295 async: false,
296 dataType: "json",
297 success: function (data) {
298 var dataList = [];
299 var jsonData = data;
300 for (var i = 0; i < jsonData.length; i++) {
301 var begin_time = DataTimeConvertDate(jsonData[i].startTime);
302 var ccDate = begin_time.replace(/\-/g,"");
303 var nowDate = new Date().format("yyyyMMdd");
304 if( ccDate > nowDate ){
305 data = {
306 id: jsonData[i].id,
307 title: timestampToHourMinute(jsonData[i].startTime) + "-" + timestampToHourMinute(jsonData[i].endTime) + ":【" + jsonData[i].staffName + "】" + "分拨:"+ jsonData[i].orgCode,
308 start: begin_time,
309 allday: true,
310 backgroundColor: '#FFFFE0',//大于今天的设置
311 borderColor:'black'
312 };
313 }else if (ccDate == nowDate){
314 data = {
315 id: jsonData[i].id,
316 title: timestampToHourMinute(jsonData[i].startTime) + "-" + timestampToHourMinute(jsonData[i].endTime) + ":【" + jsonData[i].staffName + "】" + "分拨:"+ jsonData[i].orgCode,
317 start: begin_time,
318 allday: true,
319 backgroundColor: '#98FB98',//当天的设置
320 borderColor:'black',
321 };
322 }else{
323 data = {
324 id: jsonData[i].id,
325 title: timestampToHourMinute(jsonData[i].startTime) + "-" + timestampToHourMinute(jsonData[i].endTime) + ":【" + jsonData[i].staffName + "】" + "分拨:"+ jsonData[i].orgCode,
326 start: begin_time,
327 allday: true,
328 backgroundColor: '#E0FFFF',//过期的设置
329 borderColor:'black'
330 };
331 }
332 dataList.push(data);
333 }
334 //反馈,重新赋值event的值,进行绑定
335 callback(dataList);
336 }
337 });
338 }
339
340 //日期截取
341 function DataTimeConvertDate(timeStamp) {
342 var newDate = new Date(timeStamp);
343 return newDate.format('yyyy-MM-dd');
344 }
345
346 //时间戳转成时间格式(带跨时区差值处理)
347 function TimeStampConvertDate(timeStamp) {
348 var timestamp3;
349 if(typeof(timeStamp) == "number")
350 timestamp3 = convertTimestampCompensate(timeStamp);
351 else
352 timestamp3 = timeStamp;
353
354 var newDate = new Date();
355 newDate.setTime(timestamp3);
356 return newDate.format('yyyy-MM-dd');
357 }
358
359 //找到小时和分钟
360 function timestampToHourMinute(timestamp) {
361 var date = new Date(timestamp);//时间戳为10位需*1000,时间戳为13位的话不需乘1000
362 h = date.getHours() + ':';
363 m = date.getMinutes();
364 if (m < 10) {
365 m = "0" + m;
366 }
367 return h + m;
368 }
369
370 /**
371 * timestamp型转date型前的时区补差
372 * @param dateTime
373 * @returns {string|*}
374 */
375 function convertTimestampCompensate(timestamp) {
376 if (!timestamp)
377 return null;
378
379 const serverTimeZone = getServerTimeZone();
380 if(!serverTimeZone)
381 return timestamp;
382
383 // 当前时区与中时区时差,以min为维度
384 const _dif = new Date().getTimezoneOffset();
385 // 计算当前时区时间: 当前时区时间 = 服务器时区时间 + 服务器时区 - 当前时区
386 const localDateTime = timestamp + serverTimeZone * 60 * 60 * 1000 - (-_dif * 60 * 1000);
387 return localDateTime;
388 }
389
390 function edit(id) {
391 layer.open({
392 type : 2,
393 title : '编辑排班',
394 maxmin : true,
395 shadeClose : false, // 点击遮罩关闭层
396 area : [ '800px', '520px' ],
397 content : prefix + '/edit/' + id // iframe的url
398 });
399 }
400
401 /** 获取 orgCode 下拉列表
402 * @Description
403 * @Author zhengzhaoxiang
404 * @Date 2020/8/24 8:58
405 * @Param
406 * @Return
407 */
408 function getOrgCode() {
409 var orgCode = "";
410 $.ajax({
411 type: "POST",
412 async: false,
413 url: "/dms/common/baseInfo/selectCenter",
414 data: "",
415 dataType: "json",
416 contentType: "application/json",
417 success: function (data) {
418 if (data) {
419 orgCode = data;
420 }
421 }
422 })
423 return orgCode;
424 }
三、controller 层实现代码展示
1 import cn.hutool.core.util.StrUtil;
2 import org.apache.commons.beanutils.BeanMap;
3 import org.apache.shiro.authz.annotation.RequiresPermissions;
4 import org.springframework.beans.factory.annotation.Autowired;
5 import org.springframework.stereotype.Controller;
6 import org.springframework.ui.Model;
7 import org.springframework.web.bind.annotation.*;
8
9 import javax.servlet.http.HttpServletRequest;
10 import java.sql.Timestamp;
11 import java.util.*;
12
13 /**
14 * 人员排班
15 * @author zzx
16 * @email zhengzhaojava@163.com
17 * @date 2020-08-18 13:32:22
18 */
19
20 @Controller
21 @RequestMapping("/centerInfo/personSchedul")
22 public class PersonSchedulController extends BaseController {
23 @Autowired
24 private PersonSchedulService personSchedulService;
25 /**
26 * @Description 页面初始化功能
27 * @Author zhengzhaoxiang
28 * @Date 2020/8/24 15:03
29 * @Param [model]
30 * @Return java.lang.String
31 */
32 @GetMapping()
33 @RequiresPermissions("centerInfo:personSchedul:personSchedul")
34 String PersonSchedul(Model model){
35 model.addAttribute("orgCode2",getOrgCode());
36 return "centerInfo/perSchedul/personSchedul";
37 }
38
39 @ResponseBody
40 @PostMapping("/list")
41 public List list(@RequestParam Map<String, Object> params){
42 //查询列表数据
43 List<PersonSchedulDO> personSchedulList = personSchedulService.list(params);
44 return personSchedulList;
45 }
46
47 /**
48 * @Description 添加页面
49 * @Author zhengzhaoxiang
50 * @Date 2020/8/24 15:00
51 * @Param [model]
52 * @Return java.lang.String
53 */
54 @GetMapping("/add")
55 String add(HttpServletRequest request,Model model){
56 String currDate = request.getParameter("date");
57 //当前日期
58 model.addAttribute("currDate",currDate);
59 model.addAttribute("orgCode",getOrgCode());
60 return "centerInfo/perSchedul/add";
61 }
62
63 /**
64 * @Description 修改页面,同时返回 回显信息。
65 * @Author zhengzhaoxiang
66 * @Date 2020/8/24 15:01
67 * @Param [id, model]
68 * @Return java.lang.String
69 */
70 @GetMapping("/edit/{id}")
71 String edit(@PathVariable("id") Integer id,Model model){
72 PersonSchedulDO personSchedul = personSchedulService.get(id);
73 Map<String, Object> personSchedulMap = new HashMap<>();
74 Map map = new BeanMap(personSchedul);
75 personSchedulMap.putAll(map);
76 Date startTime = personSchedul.getStartTime();
77 String times = DateUtils.formatDate(startTime, DateUtils.DATE_TIME_PATTERN);
78 //修改页面的日期和时间是分开存储的
79 if(StrUtil.isNotBlank(times)){
80 String[] time = times.split(" ");
81 personSchedulMap.put("beginDay",time[0]);
82 personSchedulMap.put("beginTime",time[1].substring(0,5));
83 }
84 Date endTime = personSchedul.getEndTime();
85 String endTimes = DateUtils.formatDate(endTime, DateUtils.DATE_TIME_PATTERN);
86 if(StrUtil.isNotBlank(endTimes)){
87 String[] time = endTimes.split(" ");
88 personSchedulMap.put("endDay",time[0]);
89 personSchedulMap.put("endTime",time[1].substring(0,5));
90 }
91 model.addAttribute("personSchedul", personSchedulMap);
92 return "centerInfo/perSchedul/edit";
93 }
94
95 /**
96 * @Description 保存, 需求修改:为了方便后期单个任务的修改,这里将 开始时间 与 结束时间 区间进行拆分,每一个时间存储一个单独的任务,方便后期其他处理
97 * @Author zhengzhaoxiang
98 * @Date 2020/8/24 15:00
99 * @Param
100 * @Return
101 */
102 @ResponseBody
103 @PostMapping("/save")
104 @RequiresPermissions("centerInfo:personSchedul:add")
105 public R save(HttpServletRequest request){
106 //获取所属分拨中心
107 String orgCode = request.getParameter("orgCode");
108 //获取员工姓名
109 String staffName = request.getParameter("staffName");
110 //开始日期
111 String beginDay = request.getParameter("beginDay");
112 //结束日期
113 String endDay = request.getParameter("endDay");
114 //工作时间
115 String beginTime = request.getParameter("beginTime");
116 //工作时间
117 String endTime = request.getParameter("endTime");
118 //数据校验
119 R x = checkSaveAndUpdate(staffName, beginDay, endDay, beginTime, endTime,orgCode);
120 if (x != null) return x;
121 //备注
122 String remark = request.getParameter("remark");
123 //组装数据
124 PersonSchedulDO personSchedulDO = getPersonSchedulDO(orgCode, staffName, beginDay, beginDay, beginTime, endTime, remark);
125 /**
126 * 组装保存的对象:根据 startDay 与 endDay 进行循环插入多条
127 */
128 int start = Integer.valueOf(beginDay.replace("-", ""));
129 int end = Integer.valueOf(endDay.replace("-", ""));
130 //开始时间
131 String startTimeString = personSchedulDO.getStartTime().toString();
132 //结束时间
133 String endTimeString = personSchedulDO.getEndTime().toString();
134 for(int i=start; i<= end; i++){
135 //开始时间
136 String dateAfterDays = DateUtils.getDateAfterNDays(startTimeString, i-start);
137 //结束时间
138 String dateEndDays = DateUtils.getDateAfterNDays(endTimeString, i-start);
139 //修改组装数据的 startTime 和 endTime
140 personSchedulDO.setStartTime(DateUtils.getDateFromString(dateAfterDays,DateUtils.DATE_FORMAT_DATETIME));
141 personSchedulDO.setEndTime(DateUtils.getDateFromString(dateEndDays,DateUtils.DATE_FORMAT_DATETIME));
142 //入库
143 personSchedulService.save(personSchedulDO);
144 }
145 return R.ok();
146 }
147
148 /**
149 * @Description 增加修改时,数据封装
150 * @Author zhengzhaoxiang
151 * @Date 2020/8/24 15:05
152 * @Param [orgCode, staffName, beginDay, endDay, beginTime, endTime, remark]
153 * @Return com.yunda.base.centerInfo.domain.PersonSchedulDO
154 */
155 private PersonSchedulDO getPersonSchedulDO(String orgCode, String staffName, String beginDay, String endDay, String beginTime, String endTime, String remark) {
156 //创建需要进行存库的对象
157 PersonSchedulDO personSchedulDO = new PersonSchedulDO();
158 personSchedulDO.setOrgCode(orgCode);
159 personSchedulDO.setStaffName(staffName);
160 personSchedulDO.setRemark(remark);
161 //组装时间
162 String newBegintime = beginDay + " " + beginTime + ":00";
163 String newEndtime = endDay + " " + endTime + ":00";
164
165 personSchedulDO.setStartTime(Timestamp.valueOf(newBegintime));
166 personSchedulDO.setEndTime(Timestamp.valueOf(newEndtime));
167 return personSchedulDO;
168 }
169
170 /**
171 * @Description 修改
172 * @Author zhengzhaoxiang
173 * @Date 2020/8/24 15:02
174 * @Param
175 * @Return
176 */
177 @ResponseBody
178 @RequestMapping("/update")
179 @RequiresPermissions("centerInfo:personSchedul:edit")
180 public R update( HttpServletRequest request){
181 //获取用户ID
182 String id = request.getParameter("id");
183 if(StrUtil.isBlank(id)){
184 return R.error("id不能为空");
185 }
186 //获取所属分拨中心
187 String orgCode = request.getParameter("orgCode");
188 //获取员工姓名
189 String staffName = request.getParameter("staffName");
190 //工作日期
191 String beginDay = request.getParameter("beginDay");
192 //工作时间
193 String beginTime = request.getParameter("beginTime");
194 //工作时间
195 String endTime = request.getParameter("endTime");
196 //数据校验
197 R x = checkSaveAndUpdate(staffName, beginDay, beginDay, beginTime, endTime,orgCode);
198 if (x != null) return x;
199 //备注
200 String remark = request.getParameter("remark");
201 //组装保存的对象
202 PersonSchedulDO personSchedulDO = getPersonSchedulDO(orgCode, staffName, beginDay, beginDay, beginTime, endTime, remark);
203 personSchedulDO.setId(Integer.valueOf(id));
204 personSchedulService.update(personSchedulDO);
205 return R.ok();
206 }
207
208 /**
209 * @Description 删除
210 * @Author zhengzhaoxiang
211 * @Date 2020/8/24 15:02
212 * @Param
213 * @Return
214 */
215 @PostMapping( "/remove")
216 @ResponseBody
217 public R remove( String id){
218 if(StrUtil.isNotBlank(id) && personSchedulService.remove(Integer.valueOf(id))>0){
219 return R.ok();
220 }
221 return R.error();
222 }
223
224 /**
225 * @Description 批量删除
226 * @Author zhengzhaoxiang
227 * @Date 2020/8/24 15:03
228 * @Param
229 * @Return
230 */
231 @PostMapping( "/batchRemove")
232 @ResponseBody
233 @RequiresPermissions("centerInfo:personSchedul:batchRemove")
234 public R remove(@RequestParam("ids[]") Integer[] ids){
235 personSchedulService.batchRemove(ids);
236 return R.ok();
237 }
238
239
240 /**
241 * @Description 拖动任务时,进行时间上的处理
242 * @Author zhengzhaoxiang
243 * @Date 2020/8/24 15:04
244 * @Param [request]
245 * @Return com.yunda.base.common.utils.R
246 */
247 @PostMapping("/dropView")
248 @ResponseBody
249 public R dropView(HttpServletRequest request){
250 String id = request.getParameter("id");
251 if(StrUtil.isBlank(id)){
252 return R.error("id 不能为空");
253 }
254 String dayDelta = request.getParameter("dayDelta");
255 if(StrUtil.isBlank(dayDelta)){
256 return R.error("dayDelta");
257 }
258 //拖动日期进行计算
259 PersonSchedulDO personSchedulDO = personSchedulService.get(Integer.valueOf(id));
260 Date startTime = personSchedulDO.getStartTime();
261 String dateTime = DateUtils.formatDate(startTime, DateUtils.DATE_TIME_PATTERN);
262 String dateAfterNDays = DateUtils.getDateAfterNDays(dateTime, Integer.valueOf(dayDelta));
263 //日期
264 Date dateFromString = DateUtils.getDateFromString(dateAfterNDays, DateUtils.DATE_TIME_PATTERN);
265 personSchedulDO.setStartTime(dateFromString);
266 //根据ID进行更新
267 personSchedulService.update(personSchedulDO);
268 return R.ok();
269 }
270 }
四、表结构展示
1 SET NAMES utf8mb4;
2 SET FOREIGN_KEY_CHECKS = 0;
3
4 -- ----------------------------
5 -- Table structure for person_schedul
6 -- ----------------------------
7 DROP TABLE IF EXISTS `person_schedul`;
8 CREATE TABLE `person_schedul` (
9 `id` int(11) NOT NULL AUTO_INCREMENT COMMENT '主键',
10 `org_code` varchar(10) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin NULL DEFAULT NULL COMMENT '所属分拨中心',
11 `staff_name` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin NULL DEFAULT NULL COMMENT '员工姓名',
12 `start_time` datetime(0) NULL DEFAULT NULL COMMENT '开始日期',
13 `end_time` datetime(0) NULL DEFAULT NULL COMMENT '结束日期',
14 `remark` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin NULL DEFAULT NULL COMMENT '备注',
15 PRIMARY KEY (`id`) USING BTREE
16 ) ENGINE = InnoDB AUTO_INCREMENT = 150 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_bin COMMENT = '人员排班' ROW_FORMAT = Compact;
17
18 SET FOREIGN_KEY_CHECKS = 1;
五、add 页面展示,edit 与之类似,需要添加 th:value="${personSchedul.endTime}" 等进行回显。
1 <!DOCTYPE html>
2 <html lang="zh_CN" xmlns:th="http://www.thymeleaf.org">
3 <meta charset="utf-8">
4 <head th:include="include :: header"></head>
5 <body class="gray-bg">
6 <div class="wrapper wrapper-content ">
7 <div class="row">
8 <div class="col-sm-12">
9 <div class="ibox float-e-margins">
10 <div class="ibox-content">
11 <form class="form-horizontal m-t" id="signupForm">
12 <input id="currDate" name="currDate" th:value="${currDate}" type="hidden">
13 <div class="form-group">
14 <label class="col-sm-3 control-label">所属分拨中心:</label>
15 <div class="col-sm-8">
16 <input id="orgCode" name="orgCode" class="form-control" th:value="${orgCode}" type="text" readonly="true" required="true">
17 </div>
18 </div>
19 <div class="form-group">
20 <label class="col-sm-3 control-label">员工姓名:</label>
21 <div class="col-sm-8">
22 <select id="staffName" name="staffName" class="form-control" type="text" required="true">
23 <option> </option>
24 </select>
25 <div class="error-msg"></div>
26 </div>
27 </div>
28 <div class="form-group">
29 <label class="col-sm-3 control-label">开始日期:</label>
30 <div class="col-sm-8">
31 <input id="beginDay" name="beginDay" class="form-control" type="date">
32 </div>
33 </div>
34 <div class="form-group">
35 <label class="col-sm-3 control-label">结束日期:</label>
36 <div class="col-sm-8">
37 <input id="endDay" name="endDay" class="form-control" type="date">
38 </div>
39 </div>
40 <div class="form-group">
41 <label class="col-sm-3 control-label">工作时间:</label>
42 <div class="col-sm-2" style="position: relative; float: left; padding-left: 19px;"
43 align="left">
44 <div class="input-group monday">
45 <input type="time" id="beginTime" name="beginTime"
46 class="form-control timepicker timepicker-default startTime" autocomplete="off">
47 </div>
48 </div>
49 <div style="width: 3px; position: relative; float: left;" align="center">
50 <p>-</p>
51 </div>
52 <div class="col-sm-2" style="position: relative; float: left;" align="left">
53 <div class="input-group monday">
54 <input type="time" id="endTime" name="endTime"
55 class="form-control timepicker timepicker-default endTime" autocomplete="off">
56 </div>
57 </div>
58 </div>
59 <div class="form-group">
60 <label class="col-sm-3 control-label">备注:</label>
61 <div class="col-sm-8">
62 <input id="remark" name="remark" class="form-control" type="text" maxlength="100">
63 </div>
64 </div>
65 <div class="form-group">
66 <div class="col-sm-8 col-sm-offset-3">
67 <button type="submit" class="btn btn-primary">提交</button>
68 </div>
69 </div>
70 </form>
71 </div>
72 </div>
73 </div>
74 </div>
75 </div>
76 <div th:include="include::footer"></div>
77 <script type="text/javascript" th:src="@{/js/appjs/centerInfo/perSchedul/add.js}">
78 </script>
79 </body>
80 </html>
六、add.js 代码展示
1 $().ready(function() {
2 validateRule();
3 $("#staffName").select2({
4 data:getStaffName(),
5 placeholder:"请选择",
6 allowClear:true,
7 language:"zh-CN"
8 }).val(null).trigger("change");
9 });
10
11 $.validator.setDefaults({
12 submitHandler : function() {
13 save();
14 }
15 });
16 function save() {
17 $.ajax({
18 cache : true,
19 type : "POST",
20 url : "/dms/centerInfo/personSchedul/save",
21 data : $('#signupForm').serialize(),// 你的formid
22 async : false,
23 error : function(request) {
24 parent.layer.alert("Connection error");
25 },
26 success : function(data) {
27 if (data.code == 0) {
28 parent.layer.msg("操作成功");
29 parent.reloadCalendar();
30 var index = parent.layer.getFrameIndex(window.name); // 获取窗口索引
31 parent.layer.close(index);
32
33 } else {
34 parent.layer.alert(data.msg)
35 }
36
37 }
38 });
39
40 }
41
42 /**
43 * 在页面加载此js文件
44 * 使用例:new Date().format("yyyy-MM-dd hh:mm:ss")
45 */
46 Date.prototype.format = function (fmt) {
47 var o = {
48 "M+": this.getMonth() + 1, //月份
49 "d+": this.getDate(), //日
50 "h+": this.getHours(), //小时
51 "m+": this.getMinutes(), //分
52 "s+": this.getSeconds(), //秒
53 "q+": Math.floor((this.getMonth() + 3) / 3), //季度
54 "S": this.getMilliseconds() //毫秒
55 };
56 if (/(y+)/.test(fmt)) {
57 fmt = fmt.replace(RegExp.$1, (this.getFullYear() + "").substr(4 - RegExp.$1.length));
58 }
59 for (var k in o) {
60 if (new RegExp("(" + k + ")").test(fmt)) {
61 fmt = fmt.replace(RegExp.$1, (RegExp.$1.length == 1) ? (o[k]) : (("00" + o[k]).substr(("" + o[k]).length)));
62 }
63 }
64 return fmt;
65 }
66
67 function validateRule() {
68 var icon = "<i class='fa fa-times-circle'></i> ";
69 $("#signupForm").validate({
70 rules : {
71 name : {
72 required : true
73 }
74 },
75 messages : {
76 name : {
77 required : icon + "请输入姓名"
78 }
79 }
80 })
81 //如果点击页面时,就根据页面点击的日期为准
82 var weekTime
83 if($('#currDate').val() != null && $('#currDate').val() != "" && $('#currDate').val() !="undefined"){
84 weekTime = new Date($('#currDate').val());
85 $("#beginDay").val(new Date($('#currDate').val()).format('yyyy-MM-dd'));
86 }else{
87 $("#beginDay").val(new Date().format('yyyy-MM-dd'));
88 weekTime = new Date();
89 }
90 weekTime.setDate(weekTime.getDate() + 7);
91 $("#endDay").val(weekTime.format('yyyy-MM-dd'));
92 $('#beginTime').val("09:00");
93 $('#endTime').val("17:00");
94 }
95
96 function getStaffName() {
97 $.ajax({
98 type: "POST",
99 url: "/dms/centerInfo/personSchedul/getUserInfo",
100 data: '',
101 async: false,
102 dataType: "json",
103 // contentType : "application/json",
104 success: function (data) {
105 if (data) {
106 types = data;
107 }
108 }
109 })
110 return types;
111 }
七、edit.js 代码展示:删除功能也在该页面完成
1 var prefix = "/dms/centerInfo/personSchedul"
2
3 $().ready(function() {
4 validateRule();
5 $("#staffName").select2({
6 data:getStaffName(),
7 placeholder:"请选择",
8 allowClear:true,
9 language:"zh-CN"
10 }).val($("#staffName2").val()).trigger("change");
11 });
12
13 $.validator.setDefaults({
14 submitHandler : function() {
15 update();
16 }
17 });
18 function update() {
19 $.ajax({
20 cache : true,
21 type : "POST",
22 url : "/dms/centerInfo/personSchedul/update",
23 data : $('#signupForm').serialize(),// 你的formid
24 async : false,
25 error : function(request) {
26 parent.layer.alert("Connection error");
27 },
28 success : function(data) {
29 if (data.code == 0) {
30 parent.layer.msg("操作成功");
31 parent.reloadCalendar();
32 var index = parent.layer.getFrameIndex(window.name); // 获取窗口索引
33 parent.layer.close(index);
34
35 } else {
36 parent.layer.alert(data.msg)
37 }
38
39 }
40 });
41
42 }
43 function validateRule() {
44 var icon = "<i class='fa fa-times-circle'></i> ";
45 $("#signupForm").validate({
46 rules : {
47 name : {
48 required : true
49 }
50 },
51 messages : {
52 name : {
53 required : icon + "请输入名字"
54 }
55 }
56 })
57 }
58
59 function getStaffName() {
60 $.ajax({
61 type: "POST",
62 url: "/dms/centerInfo/personSchedul/getUserInfo",
63 data: '',
64 async: false,
65 dataType: "json",
66 // contentType : "application/json",
67 success: function (data) {
68 if (data) {
69 types = data;
70 }
71 }
72 })
73 return types;
74 }
75
76 function remove() {
77 layer.confirm('确定要删除选中的记录?', {
78 btn : [ '确定', '取消' ]
79 }, function() {
80 $.ajax({
81 url : prefix+"/remove",
82 type : "post",
83 data : {
84 'id' : $("#id").val()
85 },
86 success : function(r) {
87 if (r.code==0) {
88 layer.msg(r.msg);
89 parent.reloadCalendar();
90 var index = parent.layer.getFrameIndex(window.name); // 获取窗口索引
91 parent.layer.close(index);
92 }else{
93 parent.layer.msg(r.msg);
94 }
95 }
96 });
97 })
98 }
fullcalendar 日历插件的使用的更多相关文章
- fullcalendar日历插件的使用并动态增删改查
我上个项目是做了一个关于教育方面的web端页面,其中的课程表就要用到fullcalendar日历插件,刚开始也是不会用,因为以前也没用过,后面也是看官方文档,问同事,最后完成了这个课程表,个人感觉fu ...
- php使用fullcalendar日历插件
最近做课程表的项目,找了好多个插件感觉都不好用,无意间看到了fullcalendar,还挺简单的,很方便,先贴一张项目页面 <!DOCTYPE html> <html> < ...
- FullCalendar日历插件说明文档
FullCalendar提供了丰富的属性设置和方法调用,开发者可以根据FullCalendar提供的API快速完成一个日历日程的开发,本文将FullCalendar的常用属性和方法.回调函数等整理成中 ...
- FullCalendar 日历插件中文说明文档
FullCalendar提供了丰富的属性设置和方法调用,开发者可以根据FullCalendar提供的API快速完成一个日历日程的开发,本文将FullCalendar的常用属性和方法.回调函数等整理成中 ...
- FullCalendar日历插件(中文API)
FullCalendar提供了丰富的属性设置和方法调用,开发者可以根据FullCalendar提供的API快速完成一个日历日程的开发,本文将FullCalendar的常用属性和方法.回调函数等整理成中 ...
- FullCalendar日历插件说明文档(看到这篇手册,解决了困扰我3天的js问题)
FullCalendar提供了丰富的属性设置和方法调用,开发者可以根据FullCalendar提供的API快速完成一个日历日程的开发,本文将FullCalendar的常用属性和方法.回调函数等整理成中 ...
- fullcalendar 日历插件3.9.0 -- 基本插件使用
以下主要结构,直接执行即可以使用 ,仅用参考: html: <!DOCTYPE html> <html> <head> <title>test</ ...
- fullcalendar日历插件
https://www.helloweba.net/javascript/231.html
- 日历插件FullCalendar应用:(二)数据增删改
接上一篇 日历插件FullCalendar应用:(一)数据展现. 这一篇主要讲使用fullcalendar插件如何做数据的增删改,用到了art.dialog web对话框组件,上一篇用到的webFor ...
- jQuery插件实战之fullcalendar(日历插件)Demo
jQuery的插件许多,应用的场景也很丰富,今天我这里给大家介绍一款很有用的日历页面开发插件 - fullcalendar,眼下最新版本号是1.5.1,使用这款插件可以高速帮助你高速编程实现基于web ...
随机推荐
- sourceTree工具使用方法
https://www.cnblogs.com/tian-xie/p/6264104.html
- SaaS、PaaS、IaaS的区别
我们从SaaS.PaaS.IaaS的定义.工业应用以及具体案例几方面来介绍他们之间的区别 一.定义层面的区别 SaaS.PaaS.IaaS简单的说都属于云计算服务,也就是云计算+服务. 我们对于云计算 ...
- mysql 8/oracle 登录失败处理,应配置并启用结束会话、限制非法登录次数和当登录连接超时自动退出等相关措施
1 mysql 8 先安装密码插件 install plugin CONNECTION_CONTROL soname 'connection_control.so';install plugin CO ...
- 【Operating System】——An interesting question on Process Creation
In the book Operating System Concepts- 9th Edition - Chapter 3 - Page 117 - Page 120 it says: How do ...
- Flink状态后端的对比及机制
1. Flink状态后端的类型: MemoryStateBackend FsStateBackend RocksDBStateBackend 2. 各状态后端对比: 2.1 MemoryStateBa ...
- Elasticsearch 查询小笔记
2.x 版本,组合多查询https://www.elastic.co/guide/cn/elasticsearch/guide/current/combining-queries-together.h ...
- node邮件发送html,简单2步附代码
node 发送 html 邮件 安装 npm install nodemailer 新建 html 文件 ① 新建 views 目录下面新增 index.html(当然也可以使用其它目录结构,下面的代 ...
- CSS 常用样式-文本属性
文本类样式我们已经学习过颜色 color 属性,严格来说行高 line-height 也是文本类属性,由于其可以合写在 font 属性中个,暂时先归类到字体中学习,接下来还有几个常用的文本属性. 水平 ...
- 区分 PaaS、IaaS 、SaaS
- axis2 WebService 请求参数xml格式
方法定义 public class GetBillInfoService { public String getBillList(String xmlData, String temp ){} 传入接 ...