• FullCalendar日历组件:进行任务增删改,参考gitee例子修改


    效果

    参考路径

    zxj/FullCalendar开发示例 - 码云 - 开源中国 (gitee.com)

    代码

    主页面:index.php

    1. ob_start();
    2. include('includes/session.inc');
    3. ?>
    4. html>
    5. <html>
    6. <head>
    7. <title>日程管理title>
    8. <meta charset="UTF-8">
    9. <style>
    10. #calendar {
    11. max-width: 1100px;
    12. height: auto;
    13. margin: 0 auto;
    14. }
    15. .qtip-default {
    16. border: 1px solid #ffffff !important;
    17. background-color: #ffffff !important;
    18. color: #555;
    19. }
    20. .qtip-event-detail .qtip-content {
    21. width: 255px;
    22. background-color: #ffffff;
    23. border: 1px solid #e0e0e0;
    24. border-radius: 2px;
    25. border-top: 3px solid #2878f0;
    26. padding: 2px;
    27. box-shadow: 0 0 8px rgba(0, 0, 0, .2);
    28. }
    29. .event-detail-wrap {
    30. padding: 10px;
    31. font-size: 14px;
    32. line-height: 26px;
    33. color: #666
    34. }
    35. .detail-info-list {
    36. color: #999;
    37. }
    38. .event-detail-wrap .action-group {
    39. border-top: 1px solid #e0e0e0;
    40. padding-top: 8px;
    41. margin-top: 8px;
    42. text-align: right;
    43. }
    44. .event-detail-wrap .action-group a {
    45. color: #2878f0;
    46. text-decoration: none;
    47. display: inline-block;
    48. margin-left: 6px;
    49. }
    50. style>
    51. <link href="dist/jquery.qtip.min.css" rel="stylesheet" type="text/css" />
    52. <link href="dist/layui/css/layui.css" rel="stylesheet" type="text/css" />
    53. head>
    54. <body>
    55. <div class="layui-three-main">
    56. <div class="layui-card">
    57. <div class="layui-card-body zgui-marginTop10">
    58. <div id="calendar">div>
    59. div>
    60. div>
    61. <div id="add-wrapper" style="display: none;padding: 10px">
    62. <form class="layui-form" id="add-filter" lay-filter="add-filter">
    63. <div class="layui-row">
    64. <div class="layui-form-item">
    65. <label class="layui-form-label">任务标题<text style="color:red">*text>label>
    66. <div class="layui-input-block">
    67. <input autocomplete="off" required="required" class="layui-input" lay-verify="required" name="title" placeholder="请输入" type="text">
    68. div>
    69. div>
    70. div>
    71. <div class="layui-row">
    72. <div class="layui-form-item">
    73. <label class="layui-form-label">任务内容<text style="color:red">*text>label>
    74. <div class="layui-input-block">
    75. <textarea class="layui-textarea" required="required" name="content" placeholder="请输入内容">textarea>
    76. div>
    77. div>
    78. div>
    79. <div class="layui-row">
    80. <div class="layui-form-item">
    81. <label class="layui-form-label">开始时间<text style="color:red">*text>label>
    82. <div class="layui-input-block">
    83. <input autocomplete="off" class="layui-input" id="start" lay-verify="required|date" name="start" placeholder="请选择任务开始时间">
    84. div>
    85. div>
    86. <div class="layui-form-item">
    87. <label class="layui-form-label">结束时间<text style="color:red">*text>label>
    88. <div class="layui-input-block">
    89. <input autocomplete="off" class="layui-input" id="end" lay-verify="required|date" name="end" placeholder="请选择任务结束时间">
    90. div>
    91. div>
    92. div>
    93. <div class="layui-row">
    94. <div class="layui-form-item">
    95. <label class="layui-form-label">整天事件label>
    96. <div class="layui-input-block">
    97. <input lay-skin="switch" name="allDay" title="是|否" type="checkbox" value="1">
    98. div>
    99. div>
    100. div>
    101. form>
    102. div>
    103. <div id="edit-wrapper" style="display: none;padding: 10px">
    104. <form class="layui-form" id="edit-filter" lay-filter="edit-filter">
    105. <div class="layui-row">
    106. <div class="layui-form-item">
    107. <label class="layui-form-label">任务标题<text style="color:red">*text>label>
    108. <div class="layui-input-block">
    109. <input autocomplete="off" required="required" class="layui-input" lay-verify="required" name="title" placeholder="请输入" type="text">
    110. div>
    111. div>
    112. div>
    113. <div class="layui-row">
    114. <div class="layui-form-item">
    115. <label class="layui-form-label">任务内容<text style="color:red">*text>label>
    116. <div class="layui-input-block">
    117. <textarea class="layui-textarea" required="required" name="content" placeholder="请输入内容">textarea>
    118. div>
    119. div>
    120. div>
    121. <div class="layui-row">
    122. <div class="layui-form-item">
    123. <label class="layui-form-label">开始时间<text style="color:red">*text>label>
    124. <div class="layui-input-block">
    125. <input autocomplete="off" class="layui-input" id="start" lay-verify="required|date" name="start" placeholder="请选择任务开始时间">
    126. div>
    127. div>
    128. <div class="layui-form-item">
    129. <label class="layui-form-label">结束时间<text style="color:red">*text>label>
    130. <div class="layui-input-block">
    131. <input autocomplete="off" class="layui-input" id="end" lay-verify="required|date" name="end" placeholder="请选择任务结束时间">
    132. div>
    133. div>
    134. div>
    135. <div class="layui-row">
    136. <div class="layui-form-item">
    137. <label class="layui-form-label">整天事件label>
    138. <div class="layui-input-block">
    139. <input lay-skin="switch" name="allDay" title="是|否" type="checkbox" value="1">
    140. div>
    141. div>
    142. div>
    143. form>
    144. div>
    145. div>
    146. body>
    147. <script src="dist/index.global.min.js">script>
    148. <script src="dist/jquery-3.7.1.min.js">script>
    149. <script src="dist/jquery.qtip.min.js">script>
    150. <script src="dist/zh-cn.global.min.js">script>
    151. <script src="dist/layui/layui.js">script>
    152. <script type="text/javascript">
    153. layui.use(['layer', 'laydate', 'form', 'jquery'], function() {
    154. let layer = layui.layer; //创建各种弹出式窗口。
    155. let $ = layui.jquery; //可以通过 $ 来使用 jQuery 的功能
    156. let laydate = layui.laydate; //引入 layui 框架中的日期选择器模块,用于方便地选择日期和时间。
    157. let form = layui.form;
    158. //这行代码是调用 laydate 模块的 render 方法来渲染一个日期选择器,指定了要渲染的 HTML 元素为 id 为 start 的元素,
    159. //并且设置日期选择器的类型为 datetime,即包括日期和时间
    160. laydate.render({
    161. elem: '#start',
    162. type: 'datetime',
    163. });
    164. //这行代码也是渲染一个日期选择器,但是针对的是 id 为 end 的元素。
    165. laydate.render({
    166. elem: '#end',
    167. type: 'datetime',
    168. });
    169. //这里使用 layui 的 form 模块的 val 方法,通过传入表单的 id 或 class(这里是 'add-filter')和一个对象来设置对应字段的值。
    170. //这是一个对象字面量(Object Literal),表示要设置的字段名和对应的值。在这里,start 和 end 是表单字段的名称,startTime 和 endTime 是传入函数的参数,表示要设置的值。
    171. function setData(startTime, endTime) {
    172. // 格式化日期时间为年月日时分秒格式
    173. var currentDateTimeString = formatDate(new Date(startTime));
    174. var nextDayDateTimeString = formatDate(new Date(endTime));
    175. // 填充到表单字段中
    176. form.val('add-filter', {
    177. "start": currentDateTimeString,
    178. "end": nextDayDateTimeString,
    179. });
    180. }
    181. function formatDate(date) {
    182. var year = date.getFullYear();
    183. var month = (date.getMonth() + 1 < 10 ? '0' : '') + (date.getMonth() + 1);
    184. var day = (date.getDate() < 10 ? '0' : '') + date.getDate();
    185. var hours = (date.getHours() < 10 ? '0' : '') + date.getHours();
    186. var minutes = (date.getMinutes() < 10 ? '0' : '') + date.getMinutes();
    187. var seconds = (date.getSeconds() < 10 ? '0' : '') + date.getSeconds();
    188. return year + '-' + month + '-' + day + ' ' + hours + ':' + minutes + ':' + seconds;
    189. }
    190. //新增任务
    191. function addTask(arg) {
    192. //调用函数 setData() 并传入上述三个参数,用于将事件的开始时间、结束时间填充到表单中。
    193. setData(arg.startStr, arg.endStr, arg.allDay);
    194. let index = layer.open({ //layui 的 layer.open() 方法创建一个弹出层,并将返回的索引值赋给变量 index。该方法接收一个配置对象作为参数,用于指定弹出层的各种属性和行为。
    195. type: 1, //弹出层的类型为普通层,即内容区域为一个固定大小的盒子。
    196. title: "新增任务",
    197. shade: false, //用于设置弹出层不显示遮罩层。
    198. area: ["800px", "600px"], //配置对象中的属性,用于设置弹出层的宽度为 800 像素,高度为 600 像素。
    199. btn: ['保存', '取消'], //配置对象中的属性,用于设置弹出层的底部按钮,第一个按钮显示文本 "保存",第二个按钮显示文本 "取消"。
    200. content: $('#add-wrapper'), // 用于设置弹出层的内容区域为 id 为 "add-wrapper" 的元素。该元素可能是一个表单或者其他需要展示的内容。
    201. //保存
    202. yes: function() {
    203. let data = form.val('add-filter');
    204. // 判断必填项是否已填写
    205. if (data.title && data.content && data.start && data.end) {
    206. // 发送数据到后端进行保存
    207. $.ajax({
    208. type: "POST",
    209. url: "save_calendar.php", // 后端 PHP 文件的路径
    210. data: {
    211. action: 'save_event', // 指定要执行的方法
    212. title: data.title,
    213. content: data.content,
    214. start: data.start,
    215. end: data.end,
    216. allDay: data.allDay ? 1 : ''
    217. },
    218. success: function(response) {
    219. var response = JSON.parse(response);
    220. if (response == 'success') {
    221. calendar.addEvent({
    222. action: 'save_event', // 指定要执行的方法
    223. title: data.title,
    224. content: data.content,
    225. start: data.start,
    226. end: data.end,
    227. allDay: data.allDay ? 1 : ''
    228. });
    229. calendar.unselect();
    230. layer.msg("保存成功", {
    231. time: 1000
    232. }, function() {
    233. // 删除成功后刷新整个页面
    234. location.reload();
    235. });
    236. } else {
    237. layer.msg("保存失败");
    238. }
    239. }
    240. });
    241. } else {
    242. layer.msg("请填写必填项", {
    243. icon: 5
    244. }); // 给出提示
    245. return false; // 阻止提交
    246. }
    247. },
    248. end: function() {
    249. document.getElementById("add-filter").reset(); //来重置表单的字段值,将其恢复到初始状态
    250. }
    251. });
    252. };
    253. //日历组件
    254. let calendarEl = document.getElementById('calendar');
    255. //通过 new 关键字创建一个 FullCalendar 的日历对象。
    256. //第一个参数 calendarEl 是一个表示日历要插入的 DOM 元素的选择器或者元素对象。第二个参数是一个配置对象,用于设置日历的各种属性和行为
    257. let calendar = new FullCalendar.Calendar(calendarEl, {
    258. locale: 'zh-cn', //设置日历的语言为中文,即使用中文的月份和星期名称。
    259. headerToolbar: { //配置日历头部的工具栏,用于显示导航按钮和标题。
    260. left: 'prev,next today', //在左侧显示上一个、下一个和今天的导航按钮
    261. center: 'title', //在中间显示当前日期范围的标题。
    262. // right: 'multiMonthYear,dayGridMonth,timeGridWeek,timeGridDay' //在右侧显示多月份选择器、月视图、周视图和日视图的切换按钮。
    263. right: 'dayGridMonth,timeGridWeek'
    264. },
    265. // initialDate: "2023-09-13",//设置初始日期为 "2023-09-13",即日历加载时所显示的日期。
    266. navLinks: true, //启用导航链接功能,即当用户点击日期时可以跳转到对应的日视图。
    267. selectable: true, //启用选择功能,允许用户通过拖动鼠标选择日期范围。
    268. selectMirror: true, //启用选择镜像效果,即在用户拖动鼠标选择日期范围时,会显示一个半透明的镜像效果来预览选择的范围。
    269. select: function(arg) { //当用户完成选择日期范围时,执行的回调函数。在这段代码中,调用了 addTask(arg) 函数来处理新增任务的逻辑。参数 arg 包含了用户选择的日期范围信息。
    270. //新增任务
    271. addTask(arg);
    272. },
    273. eventClick: function(args) { //当用户点击日历中的事件时,执行的回调函数
    274. },
    275. eventDidMount: function(args) {
    276. // console.log(endFormatted)
    277. // var timeRange = args.event.startStr + ' - ' + args.event.endStr;
    278. if (args.event.allDay == 1) {
    279. var timeRange = args.event.startStr + ' - ' + args.event.endStr;
    280. } else {
    281. var start = new Date(args.event.start);
    282. var end = new Date(args.event.end);
    283. var options = {
    284. year: 'numeric',
    285. month: '2-digit',
    286. day: '2-digit',
    287. hour: '2-digit',
    288. minute: '2-digit',
    289. second: '2-digit'
    290. };
    291. var startFormatted = start.toLocaleString('zh-CN', options); // 格式化开始时间为本地日期时间字符串
    292. var endFormatted = end.toLocaleString('zh-CN', options); // 格式化结束时间为本地日期时间字符串
    293. var timeRange = startFormatted + ' - ' + endFormatted;
    294. }
    295. $(args.el).qtip({ //将 jQuery 对象 $(args.el) 转换为 qTip2 插件对象,并设置相关配置选项。
    296. content: { //设置提示框的内容,包括日期范围、团队名称、科目和教师等信息,以及编辑和删除操作的链接。
    297. text: `
    298. ${timeRange}
    299. ${args.event.title}
  • ` //要提示的内容,就是上面创建的那个浮层
  • },
  • position: { //设置提示框在事件元素下方居中显示。
  • my: 'bottom center',
  • at: 'top center'
  • },
  • show: { //设置提示框只能单独显示,而不会同时出现多个。
  • solo: true //保证每次只显示一个提示框
  • },
  • hide: { //设置提示框隐藏的方式,包括是否可以操作提示框、隐藏延迟时间和触发隐藏的事件
  • fixed: true, //能够操作提示框
  • delay: 100, //多久之后隐藏提示框
  • event: ' mouseleave',
  • },
  • style: { //设置提示框的样式,这里使用了自定义的样式类 qtip-event-detail
  • classes: 'qtip-event-detail' //自定义的弹层样式
  • },
  • events: {
  • visible: function(event, api) {
  • // 在提示框显示完成后给删除按钮绑定点击事件
  • api.elements.content.find('#delete').on('click', function(e) {
  • e.preventDefault();
  • var eventId = args.event.id; // 获取事件的唯一标识符,用于指定要删除的事件
  • // 发送 AJAX 请求删除事件
  • $.ajax({
  • url: 'save_calendar.php', // 后端处理删除事件的接口地址
  • method: 'POST',
  • data: {
  • action: 'del_event',
  • eventId: eventId
  • }, // 传递要删除的事件ID
  • success: function(response) {
  • var response = JSON.parse(response);
  • console.log(response)
  • // 处理删除成功的情况
  • if (response == 'success') {
  • layer.msg("删除成功", {
  • time: 1000
  • }, function() {
  • // 删除成功后刷新整个页面
  • location.reload();
  • });
  • } else {
  • layer.msg("删除失败");
  • }
  • },
  • });
  • });
  • //编辑
  • // 在提示框显示完成后给编辑按钮绑定点击事件
  • api.elements.content.find('#edit').on('click', function(e) {
  • e.preventDefault();
  • var eventId = args.event.id; // 获取事件的唯一标识符,用于指定要编辑的事件
  • $.ajax({
  • url: 'save_calendar.php', // 后端处理获取事件详细信息的接口地址
  • method: 'POST',
  • data: {
  • action: 'details_event',
  • eventId: eventId
  • }, // 传递要获取详细信息的事件ID
  • success: function(response) {
  • var eventDetails = JSON.parse(response);
  • // 将事件详细信息填充到编辑表单中
  • $('#edit-filter input[name="title"]').val(eventDetails.title);
  • $('#edit-filter textarea[name="content"]').val(eventDetails.content);
  • $('#edit-filter input[name="start"]').val(eventDetails.start);
  • $('#edit-filter input[name="end"]').val(eventDetails.end);
  • // 设置整天事件的默认值并更新复选框状态
  • var form = layui.form;
  • $('#edit-filter input[name="allDay"]').prop('checked', eventDetails.allDay === '1');
  • form.render('checkbox'); // 重新渲染复选框,确保样式正确显示
  • // 打开弹窗,显示填充好信息的编辑表单
  • let index = layer.open({
  • type: 1,
  • title: "编辑任务",
  • shade: false,
  • area: ["800px", "600px"],
  • btn: ['保存', '取消'],
  • content: $('#edit-wrapper'),
  • yes: function() {
  • // 获取编辑表单中的数据并保存到后端
  • var editedData = form.val('edit-filter');
  • if (editedData.title && editedData.content && editedData.start && editedData.end) {
  • console.log(editedData)
  • // 发送数据到后端进行保存
  • $.ajax({
  • type: "POST",
  • url: "save_calendar.php",
  • data: {
  • action: 'edit_event',
  • eventId: eventId, // 传递要编辑的事件ID
  • title: editedData.title,
  • content: editedData.content,
  • start: editedData.start,
  • end: editedData.end,
  • allDay: editedData.allDay ? 1 : '',
  • },
  • success: function(response) {
  • var response = JSON.parse(response);
  • if (response == 'success') {
  • layer.msg("修改成功", {
  • time: 1000
  • }, function() {
  • // 删除成功后刷新整个页面
  • location.reload();
  • });
  • } else {
  • layer.msg("修改失败");
  • }
  • }
  • });
  • } else {
  • layer.msg("请填写必填项", {
  • icon: 5
  • }); // 给出提示
  • return false; // 阻止提交
  • }
  • },
  • });
  • }
  • });
  • });
  • }
  • }
  • });
  • },
  • editable: true, //启用可编辑功能,允许用户通过拖拽事件元素来修改事件的时间和日期等信息。
  • dayMaxEvents: true, // 启用“更多”链接功能,当某一天的事件数量过多时,会在日历中显示一个“更多”链接,点击链接可以查看所有事件。
  • //静态数据
  • events: [], // 初始时先为空,后续通过 AJAX 请求获取事件数据
  • });
  • // 发送 AJAX 请求获取数据库中的事件数据
  • $.ajax({
  • type: "POST",
  • url: "save_calendar.php", // 后端 PHP 文件的路径
  • data: {
  • action: 'get_event', // 指定要执行的方法
  • },
  • success: function(response) {
  • if (response) {
  • var eventsData = JSON.parse(response);
  • // console.log(eventsData)
  • // 将获取到的事件数据填充到日历组件中
  • calendar.addEventSource(eventsData);
  • // 重新渲染日历,显示最新的事件数据
  • calendar.render();
  • }
  • }
  • });
  • calendar.render();
  • })
  • script>
  • html>
  • 全后端连接:save_calendar.php

    1. // 数据库连接参数
    2. $servername = "localhost";
    3. $username = "root";
    4. $password = "root";
    5. $dbname = "tianhao";
    6. // 创建连接
    7. $conn = mysqli_connect($servername, $username, $password, $dbname);
    8. //执行保存事件
    9. if ($_POST['action'] === 'save_event') {
    10. $title = $_POST['title'];
    11. $content = $_POST['content'];
    12. $start = strtotime($_POST['start']);
    13. $end = strtotime($_POST['end']);
    14. $allDay = $_POST['allDay'];
    15. $sql = "INSERT INTO calendar_info (title,content, start, end,allDay) VALUES ('$title', '$content', '$start', '$end', '$allDay')";
    16. $sql_result = mysqli_query($conn, $sql);
    17. if ($sql_result) {
    18. // 插入成功
    19. $response = 'success';
    20. } else {
    21. // 插入失败
    22. $response = 'failed';
    23. }
    24. // 返回处理结果给前端
    25. echo json_encode($response);
    26. }
    27. //获取事件
    28. if ($_POST['action'] === 'get_event') {
    29. $sql_get = "select * from calendar_info";
    30. $sqlget_result = mysqli_query($conn, $sql_get);
    31. while ($row = mysqli_fetch_assoc($sqlget_result)) {
    32. $event = array(
    33. 'id' => $row['id'],
    34. 'title' => $row['title'],
    35. 'content' => $row['content'],
    36. 'start' => ($row['start'] ? date('Y-m-d H:i:s', $row['start']) : ''),
    37. 'end' => ($row['end'] ? date('Y-m-d H:i:s', $row['end']) : ''),
    38. 'allDay' => $row['allDay']
    39. );
    40. $events[] = $event; // 将每个事件添加到事件数组中
    41. }
    42. // 如果有数据,输出数组$events;如果没有数据,输出为0
    43. if (!empty($events)) {
    44. echo json_encode($events);
    45. } else {
    46. echo 0;
    47. }
    48. }
    49. //删除事件
    50. if ($_POST['action'] === 'del_event') {
    51. $eventId = $_POST['eventId'];
    52. $sql_del = "DELETE FROM calendar_info WHERE id = $eventId";
    53. if (mysqli_query($conn, $sql_del)) { // 假设你使用的是 MySQL 数据库,$conn 是数据库连接对象
    54. $response = 'success';
    55. } else {
    56. // 插入失败
    57. $response = 'failed';
    58. }
    59. // 返回处理结果给前端
    60. echo json_encode($response);
    61. }
    62. //详细信息事件
    63. if ($_POST['action'] === 'details_event') {
    64. $eventId = $_POST['eventId'];
    65. $sql_details = "SELECT * FROM calendar_info WHERE id = $eventId LIMIT 1";
    66. $sqldetails_result = mysqli_query($conn, $sql_details);
    67. if ($row = mysqli_fetch_assoc($sqldetails_result)) {
    68. $event = array(
    69. 'id' => $row['id'],
    70. 'title' => $row['title'],
    71. 'content' => $row['content'],
    72. 'start' => ($row['start'] ? date('Y-m-d H:i:s', $row['start']) : ''),
    73. 'end' => ($row['end'] ? date('Y-m-d H:i:s', $row['end']) : ''),
    74. 'allDay' => $row['allDay']
    75. );
    76. echo json_encode($event);
    77. } else {
    78. echo 0;
    79. }
    80. }
    81. //编辑事件
    82. if ($_POST['action'] === 'edit_event') {
    83. $eventId = $_POST['eventId'];
    84. $title = $_POST['title'];
    85. $content = $_POST['content'];
    86. $start = strtotime($_POST['start']);
    87. $end = strtotime($_POST['end']);
    88. $allDay = $_POST['allDay'];
    89. // 更新数据库中对应事件ID的记录
    90. $sql_edit = "UPDATE calendar_info SET title = '$title ', content = '$content', start = '$start', end = '$end', allDay = '$allDay' WHERE id = $eventId";
    91. // 执行更新操作
    92. $result_edit = mysqli_query($conn, $sql_edit);
    93. if ($result_edit) {
    94. $response = 'success';
    95. } else {
    96. $response = 'failed';
    97. }
    98. echo json_encode($response);
    99. }

    数据库

  • 相关阅读:
    Linux 信号集 及其 部分函数
    新的iLeakage攻击从Apple Safari窃取电子邮件和密码
    字符串函数用指针定义
    C#实现二分查找算法
    SizeBasedTriggeringPolicy简介说明
    Dubbo 3 易用性升级之 Dubbo 官网大改版
    Android 8.1实战隐藏状态栏图标的实例代码
    【讲座笔记】基于 Apache Calcite 的多引擎指标管理最佳实践|CommunityOverCode Asia 2023 | 字节开源
    使用ros发布自定义的消息
    【适用于电力系统和音频系统】计算信号的总谐波失真 (THD)(Matlab代码实现)
  • 原文地址:https://blog.csdn.net/weixin_46001736/article/details/136292553