背景
有一些应用系统或应用功能,如日程管理、任务管理需要使用到日历组件。虽然Element Plus也提供了日历组件,但功能比较简单,用来做数据展现勉强可用。但如果需要进行复杂的数据展示,以及互动操作如通过点击添加事件,则需要做大量的二次开发。
FullCalendar是一款备受欢迎的开源日历组件,以其强大的功能而著称。其基础功能不仅免费且开源,为开发者提供了极大的便利,仅有少量高级功能需要收费。然而,尽管该组件功能卓越,其文档却相对简洁,导致在集成过程中需要开发者自行摸索与探索,这无疑增加了不少学习和验证的时间成本。
为此,本专栏通过日程管理系统的真实案例,手把手带你了解该组件的属性和功能,通过需求导向的方式,详细阐述FullCalendar组件的集成思路和实用解决方案。
在介绍过程中,我们将重点关注集成要点和注意事项,力求帮助开发者在集成过程中少走弯路,提供有效的避坑指南,从而提升开发效率,更好地利用这款优秀的日历组件。
官网:https://fullcalendar.io/
环境Vue3+Element Plus+FullCalendar 6.1.11。
使用
按需加载数据(四)
前面实现了功能,不过说的主要的前端的事。
后端取数也比较重要,在这补充说明下。
后端取数逻辑需要考虑周全,涉及到四个时间的比较。
任务开始时间
任务结束时间
查询范围开始时间(FullCalendar组件)
查询范围结束时间(FullCalendar组件)
假设任务的起止时间都有值的情况下,实际需要考虑三种情况:
- 任务开始时间>=区域开始时间且任务开始时间<=区域结束时间
- 任务结束时间>=区域开始时间且任务结束时间<=区域结束时间
- 任务开始时间<=区域开始时间且任务结束时间>=区域结束时间
即任务开始时间落在区域时间范围内,或任务结束时间落在区域时间范围内,或任务起止时间包含在区域时间内部。
服务方法如下:
@Override
public List<Task> listWithScope(LocalDateTime startTime, LocalDateTime endTime) {
QueryWrapper<Task> queryWrapper = new QueryWrapper<>();
queryWrapper.lambda()
// 任务开始时间落在区域范围内,即任务开始时间>=区域开始时间且任务开始时间<=区域结束时间
.and(x -> x.ge(Task::getStartTime, startTime).le(Task::getStartTime, endTime))
// 或者 任务结束时间落在区域范围内,即任务结束时间>=区域开始时间且任务结束时间<=区域结束时间
.or(x -> x.ge(Task::getEndTime, startTime).le(Task::getEndTime, endTime))
// 或者 任务起止时间包含区域范围,即任务开始时间<=区域开始时间且任务结束时间>=区域结束时间
.or(x -> x.le(Task::getStartTime, startTime).ge(Task::getEndTime, endTime))
;
return this.list(queryWrapper);
}
此外,任务的开始时间和结束时间并非必填项,有些业务场景会只设置其中一项:
- 场景1:任务耗时极短,我们只需要标记开始时间即可,无需设置结束时间,相当于起到备忘功能,即开始时间有值,结束时间为空
- 场景2:任务耗时不确定,开始时间可以安排,结束时间无法计划,即开始时间有值,结束时间为空
- 场景3:任务有截止时间,但尚未安排什么时间开始做,即开始时间为空,结束时间有值
以上3个场景对应两类情况,上面的后端处理逻辑仍能获取期望范围内的数据。
但是,FullCalendar组件这边发现存在问题。
对于场景1和2,开始时间有值,结束时间为空,会在视图中显示一条只有开始时间,没有结束时间的事件,正常。
对于场景3,开始时间为空,结束时间有值,该事件不会在视图中显示,就跟不存在一样。
思考了下,对于场景3,不适合由系统自动补全一个开始时间,例如参照结束时间,会跟初衷相违背。此时,由用户注意这点,设置一个相对宽泛的开始时间,比如周五截止的任务,设置周一为开始时间,或者干脆就设置截止时间同一天,但作为日程安排的制定人,对任务的情况是清楚的,也没影响到用户体验。
注:至于起止时间都为空,往往是一项尚未拆解的大任务大目标,或者作为任务的归类,没有显示在日程表上的必要。