如何使用DHTMLX Scheduler的拖放功能,在 JS 日程安排日历中创建一组相同的事件
DHTMLX Scheduler 是一个全面的调度解决方案,涵盖了与规划事件相关的广泛需求。假设您在我们的 Scheduler 文档中找不到任何功能,并且希望在我们的 Scheduler 文档中看到您的项目。在这种情况下,很可能可以使用自定义解决方案来实现此类功能。今年,我们将继续探索JavaScript 调度组件的自定义功能。
今天,您将学习如何通过拖放功能在日历的“周”视图中轻松添加一系列类似的事件。
DHTMLX Scheduler 最新版下载
通过用户界面安排一组活动的新方法
DHTMLX Scheduler 在 JavaScript 日历中创建新事件时非常灵活。最终用户可以计划各种类型的事件,从基本的一次性约会到基于各种设置的重复活动。但是,如果您需要介于两者之间的活动怎么办?例如,如果最终用户在一周内有一系列类似格式的会议(或其他活动),该怎么办?可以使用重复事件表单,但它似乎很复杂且耗时,尤其是在不需要额外条件的情况下。幸运的是,我们的 JavaScript 调度组件的广泛 API 允许实现自定义解决方案,如下面的示例所示,我们将更详细地讨论。

查看示例 >
如您所见,此解决方案使创建一组相同的事件变得更容易、更快捷。更具体地说,只需一次拖动操作即可在所需时间段内为每一天创建事件副本。此定制不仅包括创建一周多天具有相同时间范围的新事件(约会)的功能,还包括一些视觉元素,例如为事件副本呈现标记的时间跨度。
从编码角度来看,此解决方案需要使用 Scheduler API(插件、方法和事件)以及一些自定义函数(compareTime、getDatesBetween、getWeekdayNumbers和timeFixer)。这些函数用于将可用数据转换为所需的格式。
现在我们可以继续描述将此功能添加到您的项目所需的具体步骤。
准备步骤
您应该从准备步骤开始,其结果稍后会用到。这包括启用视觉部分所需的插件(限制)、设置可选配置以及创建变量。
scheduler.plugins({limit: true,
});scheduler.config.time_step = 10;
scheduler.config.first_hour = 6;
scheduler.config.last_hour = 22;let marked = null;
let start, end;
let backward;
let dates = [];
let daysToCreate = [];
在继续之前,还应注意,此自定义是专门为“周”视图设计的,而其他视图则以常规模式工作。此限制在以下条件下启用:
if(scheduler.getState().mode == "week"){
步骤 1
现在,您应该使用onEventDrag事件。当在日历的 Week 视图中通过拖动创建新事件时,将调用该事件。该事件在拖动操作结束前一直有效。此事件有助于在事件拖动操作期间收集日期,并将它们添加到上一步中声明的变量中:
scheduler.attachEvent("onEventDrag", function (id, mode, e){...start = scheduler.getEvent(id).start_date;end = scheduler.getActionData(e).date;
这样,您将获得创建初始事件副本的日期。
第 2 步
您使用自定义getDatesBetween函数创建事件的副本,该函数获取两个日期之间的天数序列,并使用getWeekdayNumbers函数返回这些天的数字。
这些功能可以合并为一个,但我们的方法似乎更清晰:
daysToCreate = getWeekdayNumbers(getDatesBetween(start, end)); daysToCreate = daysToCreate.filter(el => el != start.getDay())
步骤3
此外,您还需要使用自定义compareTime函数通过比较小时和分钟来检查事件创建的方向(时间上向前或向后):
backward = compareTime(start, end);
您将需要它来正确呈现事件副本的占位符。
这是本次定制功能部分的基础。整个代码块如下:
scheduler.attachEvent("onEventDrag", function (id, mode, e){start = scheduler.getEvent(id).start_date;end = scheduler.getActionData(e).date;backward = compareTime(start, end);daysToCreate = getWeekdayNumbers(getDatesBetween(start, end));daysToCreate = daysToCreate.filter(el => el != start.getDay())}};
步骤4
在拖动操作结束时,使用onDragEvent事件确定向前和向后创建事件的开始和结束日期:
scheduler.attachEvent("onDragEnd", function(id, mode, e){if(scheduler.getState().mode == "week"){// store dates for event copiesif(backward != -1){start = scheduler.getActionData(e).date;end = scheduler.getEvent(id).end_date;} else {start = scheduler.getEvent(id).start_date;end = scheduler.getActionData(e).date;}}});
步骤5
拖拽操作完成后,可以通过灯箱添加新事件及其副本的参数。保存包含数据的灯箱时,将触发onEventSave事件。
scheduler.attachEvent("onEventSave",function(id,ev,is_new){
onDragEnd事件中更新的getDatesBetween函数的参数(start,end)用于填充用于创建事件副本的日期数组。
如果最终用户通过灯箱更改事件日期,您可以在onEventSave事件中存储新的开始和结束参数:
start = ev.start_date; end = ev.end_date;
如果日期数组包含多个日期,则可以使用addEvent()方法为每天创建事件的副本。
使用自定义的timeFixer函数,您可以单独控制事件副本的日期(分钟/小时),以便它们与初始事件相匹配。
if(datesToCreate.length > 1){datesToCreate.forEach(el => {scheduler.addEvent({start_date: timeFixer(el).fixedStart,end_date: timeFixer(el).fixedEnd,text: ev.text})
})
之后,清除日期数组(datesToCreate):
datesToCreate = [];
应阻止创建事件的默认方式(它也将被副本替换)并且手动隐藏灯箱。
// block default event creationscheduler.hideLightbox();return false;}return true; })
现在,它按预期运行,但事件副本将显示在哪里尚不完全清楚。

查看示例 >
可以通过添加事件副本的占位符渲染来解决此问题。
第 6 步
由于事件副本需要在拖动过程中动态渲染,因此它们是从onEventDrag事件中获取的。
占位符使用markedTimespan()方法呈现。您还需要几个变量(zonesStartTime、zonesEndTime)。这些变量将为markedTimespan()方法存储格式化的时间。
要获取格式化的时间,您必须采用通用格式(小时/分钟)获取事件时间,然后使用自定义convertMinutesToPercentage()方法将分钟转换为小时的百分比。
if(backward != -1){start = scheduler.getEvent(id).end_date;zonesEndTime = `${scheduler.getEvent(id).end_date.getHours()}.${convertMinutesToPercentage(scheduler.getEvent(id).end_date.getMinutes())}`;zonesStartTime = `${end.getHours()}.${convertMinutesToPercentage(end.getMinutes())}`;
} else {zonesStartTime = `${start.getHours()}.${convertMinutesToPercentage(start.getMinutes())}`;zonesEndTime = `${end.getHours()}.${convertMinutesToPercentage(end.getMinutes())}`;
}
现在,您已经有了呈现占位符(daysToCreate)的天数以及所需格式(zoneStartTime和zoneEndTime)的时间。
以下是在事件创建期间动态呈现占位符的方法:
if(mode == "new-size"){
// Each time delete old placeholdersscheduler.unmarkTimespan(marked);
// And render new placeholders for creating eventsif(+start < +end){marked = scheduler.markTimespan({html: `<div class="marked_placeholder">${scheduler.templates.event_date(start)+" - "+scheduler.templates.event_date(end)}</br> New Event<div>`,days: daysToCreate,zones:[zonesStartTime*60,zonesEndTime*60],css: "highlighted_timespan"});}if(+start > +end){marked = scheduler.markTimespan({html: `<div class="marked_placeholder">${scheduler.templates.event_date(end)+" - "+scheduler.templates.event_date(start)}</br> New Event<div>`,days: daysToCreate,zones:[zonesStartTime*60,zonesEndTime*60],css: "highlighted_timespan"});}}
});
最后要提的是,事件及其副本结束后,所有 markTimespan 都应被删除。该操作在 lightbox 关闭后立即完成。
scheduler.attachEvent("onAfterLightbox", function (){// remove marked timespan after closing the lightboxscheduler.unmarkTimespan(marked);
});
按照上述说明,您可以像我们的示例一样,通过拖放操作在“周”视图中添加一种方便的创建事件组的方法。
总结
在这篇博文中,我们回顾了一个有用的自定义功能,它有助于更方便地管理事件并增强 Web 项目中 JavaScript 调度解决方案的可用性。我们回顾了实现此类自定义功能的一个示例,该功能可以进一步修改并用于特定的用例场景。DHTMLX Scheduler 丰富且文档齐全的 API 无疑有助于满足您的大部分调度需求,同时我们将继续在 DHTMLX 教程中与您分享解决方案,以满足更具体的需求。
相关文章:
如何使用DHTMLX Scheduler的拖放功能,在 JS 日程安排日历中创建一组相同的事件
DHTMLX Scheduler 是一个全面的调度解决方案,涵盖了与规划事件相关的广泛需求。假设您在我们的 Scheduler 文档中找不到任何功能,并且希望在我们的 Scheduler 文档中看到您的项目。在这种情况下,很可能可以使用自定义解决方案来实现此类功能。…...
QxOrm生成json
下载Qxorm-1.5版本 使用vs打开项目,直接生成即可: lib目录中会生成dll和lib文件 新建Qt项目使用Qxorm: 将QxOrm中上面三个目录拷贝到新建的Qt项目中 pro文件添加使用QxOrm第三方库 INCLUDEPATH $$PWD/include/ LIBS -L"$$PWD/lib" LIBS…...
XS9922B(CHIPUP) 模拟高清 寄存器手册 XS9922B 四通道 多合一模拟高清解码芯片
XS9922B 是一款 4 通道模拟复合视频解码芯片,支持 HDCCTV 高清协议和 CVBS 标 清协议,视频制式支持 720P/1080P 高清制式和 960H/D1 标清制式。芯片将接收到的高清 模拟复合视频信号经过模数转化,视频解码以及 2D 图像处理之后…...
Django创建超管用户
在 Django 中创建超级用户(superuser)可以通过命令行工具 createsuperuser 完成。以下是具体步骤: 1. 确保已进行数据库迁移 在创建超级用户前,确保已执行数据库迁移: python manage.py migrate 2. 创建超级用户 …...
基于Kotlin中Flow扩展重试方法
最近项目中统一采用Kotlin的Flow来重构了网络请求相关代码。 目前的场景是,接口在请求的时候需要一个accessToken值,因为此值会过期或者不存在,需要刷新,因此最终方案是在使用Flow请求的时候先获取accessToken值然后再进行接口请求…...
好好说话:深度学习扫盲
大创项目是和目标检测算法YOLO相关的,浅浅了解了一些有关深度学习的知识。在这里根据本人的理解做一些梳理。 深度学习是什么? 之前经常听到AI,机器学习,深度学习这三个概念,但是对于三者的区别一直很模糊。 AI&…...
【状态空间方程】对于状态空间方程矩阵D≠0时的状态反馈与滑模控制
又到新的一年啦,2025新年快乐~。前几个月都没更新,主要还是因为不能把项目上的私密工作写进去,所以暂时没啥可写的。最近在山里实习,突然想起年前遗留了个问题一直没解决,没想到这两天在deepseek的加持下很快解决了&am…...
腾讯大数据基于 StarRocks 的向量检索探索
作者:赵裕隆,腾讯大数据研发工程师 本文整理自腾讯大数据工程师在 StarRocks 年度峰会上的分享,深入探讨了向量检索技术的原理与应用。此功能已应用到腾讯内部多个场景,引入 StarRocks 后,业务不仅不需要维护多套数据库…...
Linux系统调用
文章目录 系统调用和POSIX标准系统调用表程序直接访问系统调用新增系统调用 在linux中,内核空间和用户空间之间增加了一个中间层——系统调用层,如下图: 系统内调用层主要作用: 为用户空间程序提供一层硬件抽象接口。保证系统稳定…...
如何在Servlet容器中使用HttpServletResponse?
HttpServletResponse 是 Java Servlet API 中的一个接口,它代表了服务器对客户端的响应。通过 HttpServletResponse 对象,可以设置响应的状态码、发送数据到客户端(如 HTML 页面、文件等)、添加响应头信息等。下面是如何在 Servle…...
SpringCloud - Seata 分布式事务
前言 该博客为Sentinel学习笔记,主要目的是为了帮助后期快速复习使用 学习视频:7小快速通关SpringCloud 辅助文档:SpringCloud快速通关 源码地址:cloud-demo 一、简介 官网:https://seata.apache.org/zh-cn/ Seata …...
Ansible批量配置服务器免密登录步骤详解
一、准备工作 192.168.85.138 安装ansible,计划配置到139的免密 192.168.85.139 待配置免密 1. 生成SSH密钥对 在Ansible控制节点生成密钥对,用于后续免密认证: ssh-keygen -t rsa -b 4096 -f ~/.ssh/id_rsa 全部回车默认,无…...
互联网大厂中面试的高频计算机网络问题及详解
前言 哈喽各位小伙伴们,本期小梁给大家带来了互联网大厂中计算机网络部分的高频面试题,本文会以通俗易懂的语言以及图解形式描述,希望能给大家的面试带来一点帮助,祝大家offer拿到手软!!! 话不多说,我们立刻进入本期正题! 一、计算机网络基础部分 1 …...
人工智能时代下ai智能语音机器人如何以假乱真?
智能语音机器人若要达到以假乱真的效果,需要在以下几个关键方面不断提升: 一、语音合成技术 音色模拟 多维度采样 对大量真人语音样本进行多维度采样,包括不同年龄、性别、地域的人的语音。例如,采集不同年龄段男性从低沉到清亮…...
【橘子ES】Aggregations 聚合准备
一、聚合的概念 聚合文档 聚合区别于检索,检索是使用一系列条件把文档从es中搜索回来。但是聚合则是在搜索回来的文档的基础上进一步进行处理。 简单来说聚合就是将数据汇总为指标、统计数据或其他分析。聚合可以解决以下几类问题: 我的网站的平均加载…...
vue3读取webrtc-stream 视频流
一.首先下载webrtc-stream,方便自己本地搭建视频流服务 https://download.csdn.net/download/cyw8998/90373521 解压后,启动命令 webrtc-streamer.exe -H 127.0.0.1:8020 二.vue3代码如下 <template><h1>video</h1><video id&…...
springcloud集成gateway
本篇文章只介绍gateway模块的搭建步骤,并无gateway详细介绍 gateway详解请查看:SpringCloudGateway官方文档详解 前置处理 父模块中已指定版本 不知道如何选择版本看这篇: 手把手教你梳理springcloud与springboot与springcloudalibaba的版本…...
2025常用的SEO工具有哪些?
在互联网时代,如何让自己的网站或内容脱颖而出,成为许多企业和个人站长们最关注的问题。而在这个过程中,SEO(搜索引擎优化)作为一种有效的提升网站曝光度和吸引流量的手段,已经成为了网站运营的核心之一。对…...
C++类和对象进阶:运算符重载深度详解
C类和对象进阶:运算符重载 前言引入运算符重载定义语法注意事项重载为全局函数重载为成员函数运算符重载的本质 默认赋值运算符重载(默认成员函数)编译器自己生成的赋值运算符重载函数需要自己实现的场景总结默认赋值运算符重载 拷贝构造函数和赋值重载的区分验证 总…...
Mybatisplus——Mybatisplus3.5.2版本使用Page分页插件查询,records有数据但是total显示0
目录 一、问题背景 debug 执行Mybatisplus使用Page分页插件查询时,发现 Page 里面的records有数据但是total显示0。 二、问题产生的原因 未配置MybatisPlus的分页插件拦截器导致的或者因mybatis-plus版本3.4或3.5版本导致原先的分页插件paginationInterceptor无法…...
【JavaEE】-- HTTP
1. HTTP是什么? HTTP(全称为"超文本传输协议")是一种应用非常广泛的应用层协议,HTTP是基于TCP协议的一种应用层协议。 应用层协议:是计算机网络协议栈中最高层的协议,它定义了运行在不同主机上…...
从深圳崛起的“机器之眼”:赴港乐动机器人的万亿赛道赶考路
进入2025年以来,尽管围绕人形机器人、具身智能等机器人赛道的质疑声不断,但全球市场热度依然高涨,入局者持续增加。 以国内市场为例,天眼查专业版数据显示,截至5月底,我国现存在业、存续状态的机器人相关企…...
Linux云原生安全:零信任架构与机密计算
Linux云原生安全:零信任架构与机密计算 构建坚不可摧的云原生防御体系 引言:云原生安全的范式革命 随着云原生技术的普及,安全边界正在从传统的网络边界向工作负载内部转移。Gartner预测,到2025年,零信任架构将成为超…...
SpringTask-03.入门案例
一.入门案例 启动类: package com.sky;import lombok.extern.slf4j.Slf4j; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.cache.annotation.EnableCach…...
Web中间件--tomcat学习
Web中间件–tomcat Java虚拟机详解 什么是JAVA虚拟机 Java虚拟机是一个抽象的计算机,它可以执行Java字节码。Java虚拟机是Java平台的一部分,Java平台由Java语言、Java API和Java虚拟机组成。Java虚拟机的主要作用是将Java字节码转换为机器代码&#x…...
jdbc查询mysql数据库时,出现id顺序错误的情况
我在repository中的查询语句如下所示,即传入一个List<intager>的数据,返回这些id的问题列表。但是由于数据库查询时ID列表的顺序与预期不一致,会导致返回的id是从小到大排列的,但我不希望这样。 Query("SELECT NEW com…...
AxureRP-Pro-Beta-Setup_114413.exe (6.0.0.2887)
Name:3ddown Serial:FiCGEezgdGoYILo8U/2MFyCWj0jZoJc/sziRRj2/ENvtEq7w1RH97k5MWctqVHA 注册用户名:Axure 序列号:8t3Yk/zu4cX601/seX6wBZgYRVj/lkC2PICCdO4sFKCCLx8mcCnccoylVb40lP...
【HarmonyOS 5】鸿蒙中Stage模型与FA模型详解
一、前言 在HarmonyOS 5的应用开发模型中,featureAbility是旧版FA模型(Feature Ability)的用法,Stage模型已采用全新的应用架构,推荐使用组件化的上下文获取方式,而非依赖featureAbility。 FA大概是API7之…...
STM32标准库-ADC数模转换器
文章目录 一、ADC1.1简介1. 2逐次逼近型ADC1.3ADC框图1.4ADC基本结构1.4.1 信号 “上车点”:输入模块(GPIO、温度、V_REFINT)1.4.2 信号 “调度站”:多路开关1.4.3 信号 “加工厂”:ADC 转换器(规则组 注入…...
VUE3 ref 和 useTemplateRef
使用ref来绑定和获取 页面 <headerNav ref"headerNavRef"></headerNav><div click"showRef" ref"buttonRef">refbutton</div>使用ref方法const后面的命名需要跟页面的ref值一样 const buttonRef ref(buttonRef) cons…...
