FullCalendar日历组件集成实战(18)

news2024/9/23 17:18:06

背景

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

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

使用

拖放日历组件外元素至日志组件内(二)

解决方案

回过头细看官方说明,原来导入的是FullCalendar自身的Draggable组件,但是写法看上去又很奇怪,是JQuery模式的操作,如下:

document.addEventListener('DOMContentLoaded', function() {
  var Calendar = FullCalendar.Calendar;
  var Draggable = FullCalendar.Draggable;

  var containerEl = document.getElementById('external-events');
  var calendarEl = document.getElementById('calendar');
  var checkbox = document.getElementById('drop-remove');

  // initialize the external events
  // -----------------------------------------------------------------

  new Draggable(containerEl, {
    itemSelector: '.fc-event'
  });

  // initialize the calendar
  // -----------------------------------------------------------------

  var calendar = new Calendar(calendarEl, {
    headerToolbar: {
      left: 'prev,next today',
      center: 'title',
      right: 'dayGridMonth,timeGridWeek,timeGridDay'
    },
    editable: true,
    droppable: true, // this allows things to be dropped onto the calendar
    drop: function(info) {
      console.log(info)
      // is the "remove after drop" checkbox checked?
      if (checkbox.checked) {
        // if so, remove the element from the "Draggable Events" list
        info.draggedEl.parentNode.removeChild(info.draggedEl);
      }
    }
  });

  calendar.render();
});

尝试将其转化为vue的写法。
引入draggable组件:

import { Draggable } from '@fullcalendar/interaction'

在任务菜单外,使用div包裹,指定id为external-events,任务列表通过el-row附加v-for,指定class为dragElement,如下:

 <div id="external-events">
          <el-row
            v-for="element in taskList"
            :key="element.id"
            class="dragElement"           
          >
            <el-tag
              closable
              @close="remove(element.id)"
              @click="modify(element.id)"
              :title="element.name"
            >
              {{ element.name }}</el-tag
            >
          </el-row>
        </div>
      </el-card>

初始化加载数据的操作里,调用Draggable,这时候,需要通过 document.getElementById(‘external-events’)获取外层的div元素,并且通过itemSelector: '.dragElement’来获取可拖拽的元素,如下:

 // 初始化
    init() {
      this.loadData()
    },
    loadData() {
      this.$api.personaltask.task.listWithStatus('PENDING').then((res) => {
        if (res.data) {
          this.taskList = res.data

          let containerEl = document.getElementById('external-events')
          new Draggable(containerEl, {
            itemSelector: '.dragElement',
            eventData: function (eventEl) {             
              return {
                title: eventEl.innerText,
                duration: '00:30'
              }
            }
          })
        }
      })
    }

完成上述操作后,可以实现任务从外部拖放到日历组件内部了,当然,仅限于前端。

接下来,就是调用后端服务,将被拖动的任务,根据放到日历组件中的位置,设置其起止时间,并变更其状态为“未开始”。

drop回调事件中,能拿到几个重要属性如下:
allDay:是否全天事件;
date:拖放结束放置的位置所在的时间
draggedEl:被拖放的html元素
我们可以通过date获取开始时间,然后结合allDay来计算结束时间,如果是全天,开始时间+1天为结束时间;如果是非全天,开始时间+半小时(我们自行设置的默认持续时长)。
还有最关键的一点,是如何获取到被拖拽的任务的标识id,通过打印输出的方式,发现draggedEl元素里仅传递了任务标题,并没有传递id。
尝试了很多方式,最终是使用date-id这种定义属性,来放入任务标识:

 <div id="external-events">
  <el-row
    v-for="element in taskList"
    :key="element.id"
    class="dragElement"
    :data-id="element.id"
  >
    <el-tag
      closable
      @close="remove(element.id)"
      @click="modify(element.id)"
      :title="element.name"
    >
      {{ element.name }}</el-tag
    >
  </el-row>
</div>

然后在drop的回调方法中,通过arg.draggedEl.dataset.id的方式取出来,整个回调方法如下:

 drop(arg) {
  // 获取是否全天
  const allDay = arg.allDay
  // 获取开始时间
  const start = arg.date
  // 获取任务标识
  const id = arg.draggedEl.dataset.id
  let endTime = new Date(start)
  if (allDay) {
    //若为全天,结束时间为开始时间加1天
    endTime = this.$dateFormatter.formatUTCTime(new Date(start.getTime() + 24 * 60 * 60 * 1000))
  } else {
    // 非全天,结束时间在开始时间基础上加半小时
    endTime = this.$dateFormatter.formatUTCTime(new Date(start.getTime() + 30 * 60 * 1000))
  }
  const startTime = this.$dateFormatter.formatUTCTime(new Date(start.getTime()))
  // 调用安排工作接口
  this.$api.personaltask.task.assign(id, startTime, endTime).then(() => {
    this.refresh()
  })
}

最终,实现了将外部元素拖放到日历组件内部的功能。

应用系统

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

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1906435.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

两年经验前端带你重学前端框架必会的ajax+node.js+webpack+git等技术 Day2

前端框架必会的&#xff08;ajaxnode.jswebpackgit&#xff09;个人学习心得作业及bug记录 Day2 你好,我是Qiuner. 为帮助别人少走弯路和记录自己编程学习过程而写博客 这是我的 github https://github.com/Qiuner ⭐️ ​ gitee https://gitee.com/Qiuner &#x1f339; 如果本…

LDR6282-显示器:从技术革新到视觉盛宴

显示器&#xff0c;作为我们日常工作和娱乐生活中不可或缺的一部分&#xff0c;承载着将虚拟世界呈现为现实图像的重要使命。它不仅是我们与电子设备交互的桥梁&#xff0c;更是我们感知信息、享受视觉盛宴的重要窗口。显示器在各个领域的应用也越来越广泛。在办公领域&#xf…

物料主数据BAPI 无法写入扩展(增强)字段问题

在使用BAPI_MATERIAL_SAVEDATA 去创建物料时&#xff0c;因为有增强字段。这时候需要通过extensionin 字段 进行赋值。 https://community.sap.com/t5/application-development-discussions/bapi-material-savedata-extensionin-dec-type-dump/m-p/11760099 但是赋值后仍然没…

不用SMTP实现联系表单提交后发信到指定邮箱

不使用SMTP&#xff0c;如何确保联系表单能安全发送至指定邮箱&#xff1f; 尽管SMTP是实现电子邮件发送的常用方法&#xff0c;但有时我们可能希望绕过SMTP&#xff0c;直接通过其他方式发送邮件到指定邮箱。AokSend将探讨如何在不用SMTP的情况下&#xff0c;实现联系表单提交…

基于mmap的读写工具封装案例

文章目录 注意事项C封装示例添加构造函数重载以支持追加模式支持文件大小动态变化异常安全性和资源泄漏预防提供更高级的数据访问接口示例代码改进 在很多高性能应用中&#xff0c;直接使用内存映射文件&#xff08;mmap&#xff09;进行文件的读写操作可以显著提高效率&#x…

【C++】stack和queue的模拟实现 双端队列deque的介绍

&#x1f525;个人主页&#xff1a; Forcible Bug Maker &#x1f525;专栏&#xff1a; STL || C 目录 &#x1f308;前言&#x1f525;stack的模拟实现&#x1f525;queue的模拟实现&#x1f525;deque&#xff08;双端队列&#xff09;deque的缺陷 &#x1f308;为什么选择…

从无计划到项目管理高手,只需避开这两大误区!

在项目管理的过程中&#xff0c;制定计划是不可或缺的一环。然而&#xff0c;在实践中&#xff0c;我们往往会遇到两种常见的误区&#xff0c;这些误区不仅阻碍了计划的有效实施&#xff0c;还可能让我们在追求目标的道路上迷失方向。 误区一&#xff1a;认为没有什么可计划的…

充电桩开源平台,开发流程有图有工具

慧哥充电桩开源平台产品研发流程是确保产品从概念阶段到市场推广阶段的有序进行的关键。以下是对您给出的步骤的详细解释和建议&#xff1a; 设计业务流程: 在这一步&#xff0c;团队需要确定产品的核心功能、目标用户以及如何满足用户需求。进行市场调研&#xff0c;了解竞争…

无线网卡怎么连接台式电脑?让上网更便捷!

随着无线网络的普及&#xff0c;越来越多的台式电脑用户希望通过无线网卡连接到互联网。无线网卡为台式电脑提供了无线连接的便利性&#xff0c;避免了有线网络的束缚。本文将详细介绍无线网卡怎么连接台式电脑的四种方法&#xff0c;包括使用USB无线网卡、内置无线网卡以及使用…

探索企业信用巅峰:3A企业认证的魅力与价值

在现代商业环境中&#xff0c;企业的信用和信誉是其发展的核心要素之一。3A企业认证作为信用评级的最高等级&#xff0c;正在吸引越来越多企业的关注。究竟什么是3A企业认证&#xff1f;它为什么对企业如此重要&#xff1f;本文将深入探讨3A企业认证的独特魅力和巨大价值。 3A企…

使用vue3-treeselect问题

1.当vue3-treeselect是单选时&#xff0c;使用watch监听绑定value&#xff0c;无法监听到值清空 对照后将:value改为v-model&#xff0c;如图 2.使用vue3-treeselect全部清空按钮如何置空select的值&#xff0c;使用watch监听 多选&#xff1a;pageInfo.officeName(val) {// …

mybatis中的标签

在MyBatis中&#xff0c;除了基本的SQL映射功能外&#xff0c;还有许多用于动态SQL构建的标签。这些标签允许我们根据不同的条件和需求构建复杂的SQL语句。主要的动态SQL标签包括<if>, <choose>, <when>, <otherwise>, <trim>, <set>, <…

加密与安全_ 解读非对称密钥解决密钥配送问题的四个方案

文章目录 Pre对称密钥的死穴 - 经典的密钥配送问题什么是非对称密钥非对称密钥解决密钥配送问题的四个方案共享密钥密钥分配中心&#xff08;KDC&#xff09;Diffie-Hellman 密钥交换体系公钥密码体系RSA算法 Pre 对称密钥的死穴 - 经典的密钥配送问题 假设 Alice 和 Bob 两个人…

什么是海外仓管理自动化?策略及落地实施步骤指南

作为海外仓的管理者&#xff0c;你每天都面临提高海外仓运营效率、降低成本和满足客户需求的问题。海外仓自动化管理技术为这些问题提供了不错的解决思路&#xff0c;不过和任何新技术一样&#xff0c;从策略到落地实施&#xff0c;都有一个对基础逻辑的认识过程。 今天我们整…

安装 node.js 完整教程

安装 官方下载地址: https://nodejs.org/en/ 下载LTS版本&#xff08;长期稳定版本&#xff09; 安装可以更改安装路径 其余的都是选择 下一步, 安装 安装完成查看 node -v 查看node的版本 npm -v 查看npm的版本(新版的node安装自带安装npm) 配置环境变量 在nodejs文件夹…

关于SQL NOT IN判断失效的情况记录

1.准备测试数据 CREATE TABLE tmp_1 (val integer);CREATE TABLE tmp_2 (val integer, val2 integer);INSERT INTO tmp_1 (val) VALUES (1); INSERT INTO tmp_1 (val) VALUES (2); INSERT INTO tmp_2 (val) VALUES (1); INSERT INTO tmp_2 (val, val2) VALUES (NULL,0);2.测…

基于Address Sanitizer实现Android NDK的内存错误检测DEMO

1.简介 基于Address Sanitizer实现Android NDK的内存错误检测Demo。 ps:适用于Android 13&#xff08;API 级别 33&#xff09;以下的设备&#xff0c;Android 14&#xff08;API 级别 34&#xff09;或更高版本的 ARM64设备推荐使用HWAddress Sanitizer配置更简单。 GitHub源…

算法题:用JS实现删除链表的倒数第N个节点

学习目标&#xff1a; 删除链表的倒数第N个节点 leetcode原题链接 学习内容&#xff1a; 给你一个链表&#xff0c;删除链表的倒数第 n 个结点&#xff0c;并且返回链表的头结点 示例 1: 输入&#xff1a;head [1,2,3,4,5], n 2 输出&#xff1a;[1,2,3,5] 示例 2: 输入&a…

Python酷库之旅-第三方库Pandas(010)

目录 一、用法精讲 22、pandas.read_hdf函数 22-1、语法 22-2、参数 22-3、功能 22-4、返回值 22-5、说明 22-6、用法 22-6-1、数据准备 22-6-2、代码示例 22-6-3、结果输出 23、pandas.HDFStore.put方法 23-1、语法 23-2、参数 23-3、功能 23-4、返回值 23-5…

【APK】Unity出android包,报错 Gradle build failed.See the Console for details

参考大佬的博客&#xff1a;报错&#xff1a;Gradle build failed.See the Console for details.&#xff08;已解决&#xff09;_starting a gradle daemon, 1 incompatible daemon co-CSDN博客 本地出Android包&#xff0c;Build失败 解决办法&#xff1a; 1.下载一个低版本…