使用Fullcalendar管理日程事件(增刪改查拖放)


原文:https://www.helloweba.net/javascript/622.html

新版Fullcalendar(v4)擁有豐富的選項方法事件配置以及插件應用,對開發者非常友好,開發者可以輕松的利用Fullcalendar定制一個完美的日程安排應用,本文將講解最實際的日程事件管理前后端交互實例,包括事件的增刪改查以及拖放應用的實現。

准備

本實例將要實現的功能:打開日程安排月視圖,默認加載當前月視圖的所有事件;點擊視圖中的任意日期,會彈出新增事件表單,輸入事件相關信息后,保存即可;點擊視圖中的事件,會彈出修改事件表單,可對事件進行修改,也刪除事件;我們也可以對視圖中的事件進行拖放,拖放完畢也就改變了事件的時間。

注意本文提到的“事件”是指Fullcalendar日程安排事件內容。

本文涉及到的web技術有:

Vue + FullCalendar + Axios + Element-ui + PHP。

本文篇幅較長,建議最好邊閱讀邊實際操作。

我們使用Axios作為Ajax請求模塊,具體使用教程可以參考:《Vue項目中使用Axios封裝http請求》,我們還用了Element-ui的Dialog、表單、日期時間拾取器等組件。

我們在上一節文章《在Vue框架下使用Fullcalendar》的基礎上,新建Event.vue文件:

<template> <FullCalendar defaultView="dayGridMonth" locale="zh-cn" timeZone="UTC" firstDay="1" weekNumberCalculation="ISO" editable="true" droppable="true" displayEventEnd="true" :eventTimeFormat="evnetTime" :header="header" :plugins="calendarPlugins" :events="calendarEvents" @dateClick="handleDateClick" @eventClick="handleEventClick" @eventDrop="calendarEventDrop" @datesRender="handleDatesRender" /> </template> <script> import FullCalendar from '@fullcalendar/vue' import dayGridPlugin from '@fullcalendar/daygrid' import timeGridPlugin from '@fullcalendar/timegrid' import interactionPlugin, { Draggable } from '@fullcalendar/interaction'; import '@fullcalendar/core/main.css'; import '@fullcalendar/daygrid/main.css'; import '@fullcalendar/timegrid/main.css'; export default { components: { FullCalendar }, data() { return { calendarPlugins: [ dayGridPlugin, timeGridPlugin, interactionPlugin ], header: { left: 'prev,next today', center: 'title', right: 'dayGridMonth,timeGridWeek,timeGridDay' }, evnetTime: { hour: 'numeric', minute: '2-digit', hour12: false }, calendarEvents: [], calendarEventDrop: info => { this.dropEvent(info); }, handleDatesRender: arg => { this.getEventsList(arg.view) }, dialogFormVisible: false, form: { title: null, start: null, end: null }, optTitle: '添加事件', } }, created() { // }, methods: { 獲取事件列表 getEventsList(info) { }, handleDateClick(arg) { this.dialogFormVisible = true; this.optTitle = '新增事件'; this.form.title = '', this.form.id = '', this.form.start = arg.date; this.form.end = arg.date; }, handleEventClick(info) { info.el.style.borderColor = 'red'; this.dialogFormVisible = true; this.optTitle = '修改事件'; this.form = { id: info.event.id, title: info.event.title, start: info.event.start, end: info.event.end, }; }, //保存事件 saveEvent() { }, //刪除事件 delEvent() { }, //拖動事件 dropEvent(info) { } } } </script> 

讀取事件

我們希望每次載入Fullcalendar,以及切換日期的時候,會讀取視圖中的日期范圍內的事件列表。Fullcalendar提供了事件源屬性events,支持json,數組,回調函數等方式獲取日程數據,但是如果要對數據進行修改會新增的時候處理起來比較麻煩了。而我們采用Fullcalendar的另一個方法函數datesRender,它的意思是當視圖中的日期渲染時,回調函數。

我們在data中,回調getEventsList()

handleDatesRender: arg => { this.getEventsList(arg.view) }, 

methods中的getEventsList()代碼如下:

getEventsList(info) {
            let params = { start: info.activeStart, end: info.activeEnd }; this.$get('events.php', params) .then((res) => { this.calendarEvents = res; }); }, 

大家一看就明白,我們使用了Axios發送get請求,參數就是當前視圖中的開始事件和結束時間,獲取events.php返回的數據,並將數據賦給events

新增事件

當我們單擊視圖中的某一天時,觸發日期點擊事件:@dateClick="handleDateClick",我們在handleDateClick()中,彈出表單框,定義表單元素默認值。注意參數arg是一個內置對象,可以獲取當前點擊的日期等數據。

handleDateClick(arg) {
            this.dialogFormVisible = true; this.optTitle = '新增事件'; this.form.title = '', this.form.id = '', this.form.start = arg.date; this.form.end = arg.date; }, 

在彈出的dialog表單中,有日程事件的名稱,起始和結束時間。當新增和編輯的時候我們共用這一個表單,在編輯表單時會顯示刪除按鈕。

<el-dialog :title="optTitle" :visible.sync="dialogFormVisible"> <el-form :model="form"> <el-form-item label="事件名稱" label-width="80px"> <el-input v-model="form.title" auto-complete="off" placeholder="請輸入事件名稱"></el-input> </el-form-item> <el-form-item label="開始時間" label-width="80px"> <el-date-picker v-model="form.start" type="datetime" placeholder="選擇日期時間"> </el-date-picker> </el-form-item> <el-form-item label="結束時間" label-width="80px"> <el-date-picker v-model="form.end" type="datetime" placeholder="選擇日期時間"> </el-date-picker> </el-form-item> </el-form> <div slot="footer" class="dialog-footer"> <el-button type="warning" @click="delEvent" v-if="form.id" style="float: left;">刪 除</el-button> <el-button @click="dialogFormVisible = false">取 消</el-button> <el-button type="primary" @click="saveEvent">確 定</el-button> </div> </el-dialog> 

當點擊表單中的“確定”按鈕時,調用saveEvent

saveEvent() {
            this.$post('events.php?action=save', this.form) .then((res) => { if (res.code === 0) { if (this.form.id === undefined || this.form.id == '') { //新增 this.form.id = res.id; this.calendarEvents.push(this.form); this.$message({ message: '新增成功!', type: 'success' }); } else { //修改 this.calendarEvents.forEach((item, index, arr) => { if (item.id == this.form.id) { arr[index].title = this.form.title arr[index].start = this.form.start arr[index].end = this.form.end } }); this.$message({ message: '修改成功!', type: 'success' }); } this.dialogFormVisible = false; } else { this.$message({ message: res.message, type: 'error' }); } }); }, 

使用Axios發送了一個post請求,根據返回數據和本地form對象中是否有id參數,如果沒有則是新增事件,直接this.calendarEvents.push(this.form);,就是往事件數組追加當前表單的數據,然后關閉Dialog,這時對應的日期內就會顯示剛剛添加的事件。

修改事件

當點擊視圖中的某一個日程事件,會彈出Dialog,這時會觸發@eventClick="handleEventClick"

handleEventClick(info) {
            info.el.style.borderColor = 'red'; this.dialogFormVisible = true; this.optTitle = '修改事件'; this.form = { id: info.event.id, title: info.event.title, start: info.event.start, end: info.event.end, }; }, 

handleEventClick自帶info參數,可以根據該參數獲取當前要修改事件的標題名稱、起始和結束日期等數據。將這些數據賦值給form,並彈出Dialog。和新增事件一樣,保存表單的時候也執行了saveEvent。因為修改事件時已知了事件的id,這個時候修改好的事件怎么替換原有的事件呢?我們使用forEach方法遍歷事件數組,比對如果事件id與當前表單id相當時則修改事件名稱和日期時間等,詳情請看上面修改事件部分。

刪除事件

點擊修改事件彈出框Dialog時,左下角會出現“刪除”按鈕,點擊該按鈕,調用delEvent()

delEvent() {
            this.$post('events.php?action=del', {id: this.form.id}) .then((res) => { if (res.code === 0) { this.calendarEvents.forEach((item, index, arr) => { if(item.id == this.form.id) { arr.splice(index, 1); } }); this.dialogFormVisible = false; this.$message({ message: '刪除成功!', type: 'success' }); } else { this.$message({ message: res.message, type: 'error' }); } }); }, 

刪除當前事件后,同樣的我們用forEach遍歷事件數組,使用splice將當前刪除的事件從事件數組中剔除。

拖放事件

當按住視圖中的某一個日程事件,拖動至另一個日期中,觸發@eventDrop="calendarEventDrop"

calendarEventDrop: info => { this.dropEvent(info); }, 

eventDrop傳遞info參數給this.dropEvent(info)

dropEvent(info) {
            this.form = { id: info.event.id, title: info.event.title, start: info.event.start, end: info.event.end }; this.saveEvent(); } 

在拖動后,我們將data中的form對象的值改變,並調用saveEvent()保存拖動后的數據。

后端PHP

后端提供了與前端交互的API接口,PHP接收請求,並作出響應,Mysql提供數據存儲查詢功能。首先創建數據表:

CREATE TABLE `fullcalendar` ( `id` int(11) NOT NULL AUTO_INCREMENT, `title` varchar(128) NOT NULL, `start_time` int(10) NOT NULL DEFAULT '0', `end_time` int(10) NOT NULL DEFAULT '0', `created_at` datetime NOT NULL, `updated_at` datetime DEFAULT NULL, PRIMARY KEY (`id`) ) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8mb4; 

events.php接收獲取事件列表、新增、修改、刪除事件的接口,具體代碼如下:

require_once('conn.php'); $action = isset($_GET['action']) ? $_GET['action'] : ''; if ($action == 'save') { //添加|修改 $res['code'] = -1; $data = file_get_contents('php://input'); $post = json_decode($data, true); $title = htmlentities($post['title']); $start = htmlentities($post['start']); $end = htmlentities($post['end']); if (empty($end)) { $end = $start; } if (empty($title)) { $res['message'] = '名稱不能為空!'; echo json_encode($res); exit; } $id = isset($post['id']) ? (int)$post['id'] : '0'; if ($id == 0) { //添加 $sql = "INSERT INTO `fullcalendar` (title,start_time,end_time,created_at) VALUES (:title,:start_time,:end_time,:created_at)"; $stmt = $db->prepare($sql); $stmt->execute([ ':title' => $title, ':start_time' => strtotime($start), ':end_time' => strtotime($end), ':created_at' => date('Y-m-d H:i:s') ]); $lastid = $db->lastInsertId(); if ($lastid > 0) { $res['id'] = $lastid; $res['code'] = 0; } } else { //修改 $sql = "UPDATE `fullcalendar` SET title=:title,start_time=:start_time,end_time=:end_time,updated_at=:updated_at WHERE id=:id"; $stmt = $db->prepare($sql); $stmt->execute([ ':title' => $title, ':start_time' => strtotime($start), ':end_time' => strtotime($end), ':updated_at' => date('Y-m-d H:i:s'), ':id' => $id ]); $res['code'] = 0; } echo json_encode($res); } elseif ($action == 'del') { //刪除 $res['code'] = -1; $data = file_get_contents('php://input'); $post = json_decode($data, true); $id = isset($post['id']) ? (int)$post['id'] : '0'; if ($id == 0) { $res['message'] = '非法參數'; echo json_encode($res); exit; } $sql = "DELETE FROM `fullcalendar` WHERE id=:id"; $stmt = $db->prepare($sql); $rs = $stmt->execute([ ':id' => $id ]); if ($rs) { $res['code'] = 0; } else { $res['message'] = '刪除失敗'; } echo json_encode($res); } else { $start = isset($_GET['start']) ? (int)$_GET['start']/1000 : 0; $end = isset($_GET['end']) ? (int)$_GET['end']/1000 : 0; $start = isset($_GET['start']) ? strtotime($_GET['start']) : 0; $end = isset($_GET['end']) ? strtotime($_GET['end']) : 0; $sql = "SELECT id,title,start_time,end_time FROM `fullcalendar` WHERE start_time>=:startTime AND end_time<:endTime ORDER BY id desc"; $stmt = $db->prepare($sql); $stmt->execute([ ':startTime' => $start, ':endTime' => $end ]); $list = $stmt->fetchAll(PDO::FETCH_ASSOC); foreach ($list as $key => &$val) { $val['start'] = date('Y-m-d H:i:s', $val['start_time']); $val['end'] = date('Y-m-d H:i:s', $val['end_time']); $val['description'] = 'aaa'; } echo json_encode($list); } 

完整的實例代碼請下載源碼查看。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM