FullCalendar日历组件集成实战(20)
创始人
2025-01-10 05:34:15
0

背景

有一些应用系统或应用功能,如日程管理、任务管理需要使用到日历组件。虽然Element Plus也提供了日历组件,但功能比较简单,用来做数据展现勉强可用。但如果需要进行复杂的数据展示,以及互动操作如通过点击添加事件,则需要做大量的二次开发。
FullCalendar是一款备受欢迎的开源日历组件,以其强大的功能而著称。其基础功能不仅免费且开源,为开发者提供了极大的便利,仅有少量高级功能需要收费。然而,尽管该组件功能卓越,其文档却相对简洁,导致在集成过程中需要开发者自行摸索与探索,这无疑增加了不少学习和验证的时间成本。
为此,本专栏通过日程管理系统的真实案例,手把手带你了解该组件的属性和功能,通过需求导向的方式,详细阐述FullCalendar组件的集成思路和实用解决方案。
在介绍过程中,我们将重点关注集成要点和注意事项,力求帮助开发者在集成过程中少走弯路,提供有效的避坑指南,从而提升开发效率,更好地利用这款优秀的日历组件。

官网:https://fullcalendar.io/
image.png
环境Vue3+Element Plus+FullCalendar 6.1.11。

使用

重构任务处理为无刷新模式

前面我们在日历视图上进行任务(事件)的增删改,后端持久化后,前端都调用了refresh刷新方法,重新从后端调用数据,从用户体验上,有一个肉眼可见的页面刷新和数据加载过程。
接下来,我们通过调用FullCalendar的api,来实现任务的无刷新模式。

新增任务

在日历视图中点击或选择一个时间范围后,自动弹出创建任务对话框,如下图所示:
image.png
点击保存按钮后,使用emit触发父页面,也就是FullCalendar所在页面的refresh方法,如下所示:

  // 刷新 refresh() {   const fullCalendar = this.$refs.fullCalendar.calendar    let query = this.$route.query   query = Object.assign(query, {     viewType: fullCalendar.view.type,     showAllFlag: this.showAllFlag,     start: this.$dateFormatter.formatUTCDate(fullCalendar.view.activeStart),     end: this.$dateFormatter.formatUTCDate(fullCalendar.view.activeEnd)   })   refreshSelectedTagWithQuery(query) } 

对于新增任务,FullCalendar提供了addEvent方法,重构如下:

  // 新增任务 addTask(task) {   // 获取日历对象   const fullCalendar = this.$refs.fullCalendar.calendar   // 将任务数据转换为日历事件   const event = this.convertTaskToEvent(task)   // 调用api添加任务   fullCalendar.addEvent(event) }  // 任务数据转换为事件对象 convertTaskToEvent(task) {   // 计算全天事件属性值   const allDay = this.calculateAllDay(task.startTime, task.endTime)   // 数据转换   return {     id: task.id,     title: task.name,     start: task.startTime,     end: task.endTime,     allDay: allDay,     extendedProps: {       status: task.status,       plannedDuration: task.plannedDuration     }   } },  // 计算全天事件属性值 calculateAllDay(startTime, endTime) {        let allDay = false    // 若起止时间不为空且均为00:00:00,则设置为allDay属性为true   if (     startTime &&     endTime &&     startTime.substr(11, 8) === '00:00:00' &&     endTime.substr(11, 8) === '00:00:00'   ) {     allDay = true   }   return allDay }   

任务数据转换为事件对象的方法,以及计算全天事件属性值的方法,因为多处使用,都是从原已实现的方法中通过重构提取出来的。

通过以上重构处理,实现了任务无刷新添加。

删除任务

在日历视图中右键一个现有任务后,弹出菜单中可以选择“删除”,如下所示:
image.png
原处理逻辑如下:

// 事件右键菜单命令 eventContextMenuSelect(command) {   const id = this.contextMenuEventId   if (command === 'copy') {     this.$api.personaltask.task.addSingleByCopy(id).then((res) => {       this.$refs.modifyPage.init(res.data.id)     })   } else if (command === 'remove') {     this.$confirm('此操作将移除任务, 是否继续?', '确认', {       type: 'warning'     })       .then(() => {         this.$api.personaltask.task.remove(id).then(() => {           this.refresh()         })       })       .catch(() => {         this.$message.info('已取消')       })   } else if (command === 'addLog') {     this.addLog(id)   } else if (command === 'setCompleted') {     this.setCompleted(id)   } else if (command === 'setPending') {     this.setPending(id)   }   // 隐藏右键菜单   this.eventContextMenu.visible = false } 

若实现无刷新,则需要在调用后端删除操作完成后,将调用refresh刷新操作,更换为调用FullCalendar的删除事件api,removeEvent,我们封装一个删除任务的方法如下:

// 删除任务 revmoveTask(taskId) {   const fullCalendar = this.$refs.fullCalendar.calendar   const event = fullCalendar.getEventById(taskId)   event.remove() } 

修改任务

在日历视图中点击一个现有任务后,自动弹出修改任务对话框,如下图所示:
image.png
点击保存按钮后,使用emit触发父页面,也就是FullCalendar所在页面的refresh方法,跟上面新增原实现模式一致。

对于修改事件,FullCalendar并未提供一个像新增事件addEvent类似的事件,而是提供了一组事件。

需要通过日历对象的getEventById方法,通过事件id拿到事件对象。
然后调用事件对象的以下方法:
设置非时间相关的属性,使用event.setProp( name, value ),比如事件的名称
设置时间相关的属性,使用以下方法:
setStart
setEnd
setAllDay
设置扩展属性,使用event.setExtendedProp( name, value ),比如我们自定义的任务状态

对于修改任务,综合运用上述方法,重构如下:

// 修改任务 modifyTask(task) {   const fullCalendar = this.$refs.fullCalendar.calendar   const event = fullCalendar.getEventById(task.id)   event.setProp('title', task.name)   event.setStart(task.startTime)   event.setEnd(task.endTime)   let allDay = this.calculateAllDay(task.startTime, task.endTime)   event.setAllDay(allDay)   event.setExtendedProp('status', task.status)   event.setExtendedProp('plannedDuration', task.plannedDuration) } 

这里测试发现存在小问题,当修改任务时,把起止时间都清空的情况下,应当把该任务视为待安排,从日历视图中移除,放回到收集箱中,而FullCalendar提供的setStart方法,不接受空值,设置空值无效,仍会显示原时间。

针对上述问题,调整如下:

 // 修改任务   modifyTask(task) {     const fullCalendar = this.$refs.fullCalendar.calendar     const event = fullCalendar.getEventById(task.id)     if (task.startTime) {       // 开始时间有值,更新任务信息       event.setProp('title', task.name)       event.setStart(task.startTime)       event.setEnd(task.endTime)       let allDay = this.calculateAllDay(task.startTime, task.endTime)       event.setAllDay(allDay)       event.setExtendedProp('status', task.status)       event.setExtendedProp('plannedDuration', task.plannedDuration)     } else {       // 开始时间无值       // 从日历视图中移除任务       event.remove(task.id)       // 添加到收集箱中 TODO     }   } 

如何添加到收集箱涉及到收集箱功能的无刷新改造,暂放,标记为todo,后面再说。

同时,在保存任务时,检测开始时间是否为空,如为空弹出确认框,说明该任务会自动放入收集箱,避免用户产生明明执行保存操作了,但日历中不显示的疑惑。

beforeSaveData() {     if (!this.entityData.startTime) {       // 开始时间为空,需用户确认是否继续       return this.$confirm(         '开始时间为空,该任务将放入收集箱,不会显示在日历中, 是否继续?',         '确认',         {           type: 'warning'         }       )     } else {       // 开始时间不为空,直接返回       return new Promise((resolve) => {         resolve()       })     } } 

复制任务

之前实现的复制任务,是调用后端服务的复制新增功能,将新增后的数据返回回来,调用修改页面,传入新增记录的id来实现的,如下:

 if (command === 'copy') {         this.$api.personaltask.task.addSingleByCopy(id).then((res) => {           this.$refs.modifyPage.init(res.data.id)         }) }  

在上面的修改任务的回调中,我们调用的是FullCalendar的修改事件的一系列api,这里是存在冲突的,即在复制这个场景下,我们应该最终调用的是FullCalendar的addEvent,来实现将通过复制新建的事件添加到日历中显示,因此调整如下:

引入modifyPage,将其组件命名修改为CopyPage,如下:

import CopyPage from '../task/modify.vue' 

然后设定回调方法,如下:

 

回调的依旧是新增任务的方法,跟前面新增页面保存的回调是一致的,如下:

 // 新增任务 addTask(task) {   // 获取日历对象   const fullCalendar = this.$refs.fullCalendar.calendar   // 将任务数据转换为日历事件   const event = this.convertTaskToEvent(task)   // 调用api添加任务   fullCalendar.addEvent(event) } 

退回收集

先前我们实现了通过右键菜单,将某个暂不具备的执行条件的任务退回了收集箱,采用的是整个页面刷新的模式。

// 设置待安排 setPending(id) {   this.$api.personaltask.task.changeStatus(id, 'PENDING').then(() => {     this.refresh()   }) }  // 刷新 refresh() {   const fullCalendar = this.$refs.fullCalendar.calendar   // console.log(fullCalendar.view)   let query = this.$route.query   query = Object.assign(query, {     viewType: fullCalendar.view.type,     showAllFlag: this.showAllFlag,     start: this.$dateFormatter.formatUTCDate(fullCalendar.view.activeStart),     end: this.$dateFormatter.formatUTCDate(fullCalendar.view.activeEnd)   })   refreshSelectedTagWithQuery(query) } 

现改造为无刷新模式,当执行任务退回收集箱操作时,调用FullCalendar的删除任务的api,并调用收集箱的加载数据方法,来实现页面无刷新,如下:

// 设置待安排 setPending(id) {   this.$api.personaltask.task.changeStatus(id, 'PENDING').then(() => {     this.revmoveTask(id)     this.reloadCollectionBox()   }) }  // 删除任务 revmoveTask(taskId) {   const fullCalendar = this.$refs.fullCalendar.calendar   const event = fullCalendar.getEventById(taskId)   event.remove() }  // 刷新收集箱 reloadCollectionBox() {   this.$refs.collectionBox.loadData() } 

应用系统

名称:遇见
地址:https://meet.popsoft.tech
说明:基于一二三应用开发平台和FullCalendar日历组件实现的面向个人的时间管理、任务管理系统,1分钟注册,完整功能,欢迎使用~

相关内容

热门资讯

一秒了解新全游房卡领取码/新猴... 一秒了解新全游房卡领取码/新猴王大厅房卡在哪里购买!游戏中心打开微信,添加客服【113857776】...
全攻略普及,微信链接金花房卡怎... 大圣大厅是一款非常受欢迎的棋牌游戏,咨询房/卡添加微信:44346008许多玩家在游戏中会购买房卡来...
ia攻略/如何购买金花房卡雷霆... 微信游戏中心:雷霆大厅房卡在哪里买打开微信,添加客服微信【88355042】,进入游戏中心或相关小程...
推荐一款!金花房卡怎么购买雷霆... 雷霆大厅是一款非常受欢迎的棋牌游戏,咨询房/卡添加微信:【3329006910】或QQ:332900...
终于发现!微信牛牛房卡如何购买... 微信游戏中心:牛牛房卡,添加微信【71319951】,进入游戏中心或相关小程序,搜索“微信牛牛房卡”...
秒懂百科新西楚房卡多少米/天蝎... 第二也可以在游戏内商城:在游戏界面中找到 “微信金花,斗牛链接房卡”“商城”选项,选择房卡的购买选项...
正版授权!金花房卡专卖店宝马系... 今 日消息,宝马系列/随意玩房卡添加微信33549083 苹果今日发布了 iOS 16.1 正式版更...
玩家推荐,购买斗牛房卡联系方式... 斗牛是一款非常受欢迎的棋牌游戏,咨询房/卡添加微信:15984933许多玩家在游戏中会购买房卡来享受...
IA解析/牛牛房卡官网天蝎大厅... 天蝎大厅房卡更多详情添加微:33549083、 2、在商城页面中选择房卡选项。 3、根...
终于发现!炸金花从哪里买房卡,... 微信游戏中心:炸金花房卡,添加微信【56001354】,进入游戏中心或相关小程序,搜索“微信炸金花房...
一秒了解新云游房卡到哪里买/天... 一秒了解新云游房卡到哪里买/天蝎大厅房卡客服!微信房卡充值 添加房卡批售商:微【113857776】...
正版授权!游戏推荐牛牛房卡出售... 玄灵大厅是一款非常受欢迎的棋牌游戏,咨询房/卡添加微信:【3329006910】或QQ:332900...
玩家必备攻略,微信斗牛房卡怎么... 微信斗牛是一款非常受欢迎的棋牌游戏,咨询房/卡添加微信:160470940许多玩家在游戏中会购买房卡...
终于发现!微信牛牛房卡购买联系... 微信游戏中心:牛牛房卡,添加微信【66336574】,进入游戏中心或相关小程序,搜索“微信牛牛房卡”...
玩家须知新荣耀房卡怎么弄/新猴... 玩家须知新荣耀房卡怎么弄/新猴王大厅房卡在哪里购买! 微信牛牛房卡客服微信号微信游戏中心打开微信,添...
科技实测!牛牛房卡哪里有卖的新... 今 日消息,新神兽/青龙大厅房卡添加微信33549083 苹果今日发布了 iOS 16.1 正式版更...
推荐一款!金花微信链接市场价格... 推荐一款!金花微信链接市场价格表战皇大厅/微信链接房卡价格一览表战皇大厅是一款非常受欢迎的游戏,咨询...
居家必备,牛牛链接房卡那里有卡... 卡贝大厅是一款非常受欢迎的棋牌游戏,咨询房/卡添加微信:15984933许多玩家在游戏中会购买房卡来...
实测分享美人房卡怎么得/王者大... 第二也可以在游戏内商城:在游戏界面中找到 “微信金花,斗牛链接房卡”“商城”选项,选择房卡的购买选项...
终于发现!微信里面炸金花链接房... 微信游戏中心:炸金花房卡,添加微信【71319951】,进入游戏中心或相关小程序,搜索“微信炸金花房...