用于资源计划的JavaScript事件日历

目录

新功能:Next.js日历

新教程:ASP.NET 核心维护计划

第1步:事件日历JavaScript库

第2步:事件日历占位符

第3步:初始化调度程序

第4步:加载数据

第5步:事件移动

第6步:事件编辑

第7步:应用CSS主题

具有实时预览功能的Configurator应用程序

调度程序CSS主题

默认CSS主题

绿色CSS主题

传统CSS主题

透明CSS主题

白色CSS主题

每月活动日历

活动日历本地化

使用日期选取器更改计划程序日期

持续时间栏

事件自定义(HTML、CSS)

月历活动定制

支持Angular、React和Vue

资源日历

图标和上下文菜单

日/周/月日历视图切换

资源标头自定义

另见


在本文中,我们将构建一个简单的 HTML5/JavaScript事件日历 Web应用程序。客户端部分是通用的。我们将使用示例PHPASP.NET Core后端。

特征:

  • 每周HTML5事件日历/调度程序
  • 资源计划程序模式,将资源显示为列
  • 使用日期导航器更改日历(左侧)
  • 拖放事件创建、移动和调整大小
  • 向事件添加图标和图像(状态、分配的资源、上下文菜单提示)
  • 使用CSS主题单击更改外观
  • PHP RES后端
  • ASP.NET Core REST后端(.NET 8、Entity Framework)

我们将使用开源的DayPilot Lite for JavaScript [javascript.daypilot.org]来构建活动日历。DayPilot Lite for JavaScriptApache许可证2.0下可用。

新功能:Next.js日历

2024.1版本开始,DayPilot支持在Next.js应用程序中集成React日历组件。有关简介和示例项目下载,请参阅以下教程:

新教程:ASP.NET 核心维护计划

现在提供了一个新教程,解释了如何使用DayPilotASP.NET Core中创建颜色编码的维护计划:

此维护计划应用程序具有以下功能:

  • 该应用程序使用为每个维护任务定义蓝图的维护类型。
  • 每种维护类型都有指定的颜色,并定义维护期间需要执行的操作清单。
  • 计划任务显示在每月计划日历视图中。
  • 您可以使用拖放来调整计划,并根据需要移动计划任务。
  • 完成所有清单操作后,您可以轻松安排下一次维护的日期。
  • fronted是用HTML5/JavaScript实现的。
  • 后端是使用ASP.NET Core、Entity Framework和SQL Server实现的。

1步:事件日历JavaScript

包括daypilot-all.min.js。基本外观不需要其他依赖项(默认的CSS主题是嵌入的)。

<script src="js/daypilot/daypilot-all.min.js" type="text/javascript"></script> 

2步:事件日历占位符

HTML5页面添加占位符<div>

<div id="dp"></div> 

3步:初始化调度程序

使用Daypilot.Calendar类初始化调度程序:

<script type="text/javascript">
  const dp = new DayPilot.Calendar("dp", {
    viewType: "Week"
  });
  dp.init();
</script>

这些简单的步骤将呈现一个空的调度程序:

4步:加载数据

我们将使用简单的HTTP调用将数据加载到事件日历中:

async function loadEvents() {
  const start = dp.visibleStart();
  const end = dp.visibleEnd();

  // in .NET, use "/api/CalendarEvents?start=${start}&end=${end)"
  const {data} = await DayPilot.Http.get(`backend_events.php?start=${start}&end=${end)`);
  dp.update({
    events: data
  });
}

自从 2018.2.232版本起,您还可以使用内置的快捷方法来加载事件:

function loadEvents() {
  // in .NET, use "api/CalendarEvents"
  dp.events.load("backend_events.php"); 
}

您可以使用visibleStart()visibleEnd()方法检测当前可见的日期范围events.load() 方法自动将开始和结束添加到URL查询字符串。

backend_event.php端点以以下格式返回日历事件数

[
  {
    "id":"1",
    "text":"Calendar Event 1",
    "start":"2023-02-25T10:30:00",
    "end":"2023-02-25T16:30:00"
  },
  {
    "id":"2",
    "text":"Calendar Event 2",
    "start":"2023-02-24T09:00:00",
    "end":"2023-02-24T14:30:00"
  },
  {
    "id":"3",
    "text":"Calendar Event 3",
    "start":"2023-02-27T12:00:00",
    "end":"2023-02-27T16:00:00"
  }
]

PHP后端(backend_events.php):

<?php
require_once '_db.php';
    
$stmt = $db->prepare('SELECT * FROM events WHERE NOT ((end <= :start) OR (start >= :end))');

$stmt->bindParam(':start', $_GET['start']);
$stmt->bindParam(':end', $_GET['end']);

$stmt->execute();
$result = $stmt->fetchAll();

class Event {}
$events = array();

foreach($result as $row) {
  $e = new Event();
  $e->id = $row['id'];
  $e->text = $row['name'];
  $e->start = $row['start'];
  $e->end = $row['end'];
  $events[] = $e;
}

echo json_encode($events);

?>

ASP.NET Core后端(CalendarEventsController.cs):

// GET: api/CalendarEvents
[HttpGet]
public async Task<ActionResult<IEnumerable<CalendarEvent>>> 
       GetEvents([FromQuery] DateTime start, [FromQuery] DateTime end)
{
    return await _context.Events
        .Where(e => !((e.End <= start) || (e.Start >= end)))
        .ToListAsync();
} 

阅读有关加载日历事件数据的详细信息 [doc.daypilot.org]

5步:事件移动

默认情况下,拖放用户操作(选择时间范围、事件移动、事件大小调整)在调度程序中处于启用状态。

我们只需要添加自定义处理程序,即可使用AJAX调用将更改提交到服务器端。

JavaScript事件处理程序(用于PHP):

const dp = new DayPilot.Calendar("dp", {
  // ...
  onEventMoved: async (args) => {
    const data = {
      id: args.e.id(),
      newStart: args.newStart,
      newEnd: args.newEnd,
    };
    await DayPilot.Http.post(`backend_move.php`, data);
    console.log("The calendar event was moved.");
  }
});

PHP后端(backend_move.php):

<?php

require_once '_db.php';

$json = file_get_contents('php://input');
$params = json_decode($json);

$insert = "UPDATE events SET start = :start, end = :end WHERE id = :id";

$stmt = $db->prepare($insert);

$stmt->bindParam(':start', $params->newStart);
$stmt->bindParam(':end', $params->newEnd);
$stmt->bindParam(':id', $params->id);

$stmt->execute();

class Result {}

$response = new Result();
$response->result = 'OK';
$response->message = 'Update was successful';

header('Content-Type: application/json');
echo json_encode($response);

JavaScript事件处理程序(适用于ASP.NET Core):

const dp = new DayPilot.Calendar("dp", {
  // ...
  onEventMoved: async (args) => {
    const id = args.e.id();
    const data = {
        id: args.e.id(),
        start: args.newStart,
        end: args.newEnd,
        text: args.e.text()
    };
    await DayPilot.Http.put(`/api/CalendarEvents/${id}`, data);
    console.log("The calendar event was moved.");
  }
});

ASP.NET Core后端(CalendarEventsController.cs):

// PUT: api/CalendarEvents/5
[HttpPut("{id}")]
public async Task<IActionResult> PutCalendarEvent(int id, CalendarEvent calendarEvent)
{
    if (id != calendarEvent.Id)
    {
        return BadRequest();
    }

    _context.Entry(calendarEvent).State = EntityState.Modified;

    try
    {
        await _context.SaveChangesAsync();
    }
    catch (DbUpdateConcurrencyException)
    {
        if (!CalendarEventExists(id))
        {
            return NotFound();
        }
        else
        {
            throw;
        }
    }

    return NoContent();
} 

阅读有关拖放事件移动 [doc.daypilot.org] 的更多信息。

6步:事件编辑

您可以使用DayPilot Modal对话框来编辑事件详细信息。DayPilot Modal是一个开源库,用于从代码构建模态表单(也可用于可视化模态对话设计的在线模态对话框生成器应用程序)。

首先,我们添加一个onEventClick事件处理程序,当用户单击现有事件时,该事件处理程序将触发该处理程序。

我们的模式对话框将只有一个表单字段(称为Name的文本值):

const form = [
  {name: "Name", id: "text"}
];

现在我们可以使用DayPilot.Modal.form()方法打开模式对话框。第二个参数指定源数据对象。数据对象将用于填充初始值(表单项的id值指定数据对象的属性/字段)。

DayPilot.Modal.form()方法返回一个promise。这意味着我们可以使用await语法来等待结果并简化代码:

const modal = await DayPilot.Modal.form(form, args.e.data);
if (modal.canceled) {
  return;
}

结果可作为modal.result对象使用。它是原始对象的副本,并应用了更新的值。

这是我们的onEventClick事件处理程序:

const dp = new DayPilot.Calendar("dp", {
  // ...
  onEventClick: async (args) => {
    const form = [
      {name: "Name", id: "text"}
    ];

    const modal = await DayPilot.Modal.form(form, args.e.data);
    if (modal.canceled) {
      return;
    }

    // PHP

    const data = {
      id: args.e.id(),
      text: modal.result.text
    };
    await DayPilot.Http.post(`backend_update.php`, data);
    
    // .NET 7
    /*

    const id = args.e.id();
    const data = {
        id: args.e.id(),
        start: args.e.start(),
        end: args.e.end(),
        text: modal.result.text
    };
    await DayPilot.Http.put(`/api/CalendarEvents/${id}`, data);

    */

    dp.events.update({
      ...args.e.data,
      text: modal.result.text
    });
    console.log("The calendar event was updated.");

  }
});

PHP后端(backend_update.php):

<?php
require_once '_db.php';

$json = file_get_contents('php://input');
$params = json_decode($json);

$insert = "UPDATE events SET name = :text WHERE id = :id";

$stmt = $db->prepare($insert);

$stmt->bindParam(':text', $params->text);

$stmt->execute();

class Result {}

$response = new Result();
$response->result = 'OK';
$response->message = 'Update successful';

header('Content-Type: application/json');
echo json_encode($response);

7步:应用CSS主题

如果要使用自定义CSS主题,则需要包含样式表:

<link type="text/css" rel="stylesheet" href="themes/calendar_transparent.css" /> 

并在初始化期间设置theme属性:

<script type="text/javascript">
  const dp = new DayPilot.Calendar("dp", {
    viewType: "Week",
    theme: "calendar_transparent"
  });
  dp.init();
</script> 

您可以选择包含的CSS主题之一,也可以使用在线 CSS主题设计器创建自己的主题。

具有实时预览功能的Configurator应用程序

现在,您可以使用在线 UI Builder 应用程序轻松配置每日/每周和每月日历组件,该应用程序允许您预览实时DayPilot实例中的配置更改,并使用预配置的日历组件生成新项目(支持JavaScript/HTMLJavaScript/NPMTypeScriptAngularReactVue项目目标):

调度程序CSS主题

DayPilot Lite for JavaScript带有几个预构建的CSS主题。

您可以使用在线 CSS主题设计器 [themes.daypilot.org] 创建自己的主题。

默认CSS主题

绿色CSS主题

传统CSS主题

透明CSS主题

白色CSS主题

每月活动日历

DayPilot还包括每月事件日历视图。每月视图控件的API使用与每日/每周日历相同的设计:

<div id="dp"></div>

<script type="text/javascript">
  const dp = new DayPilot.Month("dp");
  dp.startDate = "2023-01-01";
  dp.init();
</script>

活动日历本地化

您可以使用.locale属性轻松切换事件日历区域设置:

<script type="text/javascript">
  const dp = new DayPilot.Calendar("dp");
  dp.locale = "de-de";
  dp.init();
</script>  

日历包括对许多以下区域设置[api.daypilot.org]的内置支持。

您还可以创建并注册自己的区域设置:

DayPilot.Locale.register(
  new DayPilot.Locale('en-us', 
  {
    'dayNames':['Sunday','Monday','Tuesday','Wednesday','Thursday','Friday','Saturday'],
    'dayNamesShort':['Su','Mo','Tu','We','Th','Fr','Sa'],
    'monthNames':['January','February','March','April','May',
                  'June','July','August','September','October','November','December'],
    'monthNamesShort':['Jan','Feb','Mar','Apr','May','Jun',
                       'Jul','Aug','Sep','Oct','Nov','Dec'],
    'timePattern':'h:mm tt',
    'datePattern':'M/d/yyyy',
    'dateTimePattern':'M/d/yyyy h:mm tt',
    'timeFormat':'Clock12Hours',
    'weekStarts':0
  }
)); 

使用日期选取器更改计划程序日期

可以使用DayPilot.Navigator日期选取器控件(在上面屏幕截图的左侧)更改计划程序日期(可见周):

<div id="nav"></div>

<script type="text/javascript">
  const datePicker = new DayPilot.Navigator("nav", {
    showMonths: 3,
    skipMonths: 3,
    selectMode: "Week",
    onTimeRangeSelected: args => {
      dp.update({startDate: args.day});
      app.loadEvents();
    }
  });
  datePicker.init();
</script>

持续时间栏

DayPilot Lite HTML5事件日历1.1版支持持续时间栏(事件左侧的真实日历事件持续时间指示器)。默认情况下,它处于启用状态,您可以使用CSS主题设置其样式。

事件自定义(HTMLCSS

从版本1.3 SP3开始,DayPilot Lite支持使用onBeforeEventRender事件处理程序进行事件自定义

<div id="dp"></div>

<script type="text/javascript">

    const dp = new DayPilot.Calendar("dp");

    // view
    dp.startDate = "2016-06-06";
    dp.viewType = "Week";
    dp.durationBarVisible = false;

    dp.events.list = [
        {
            "start": "2016-06-07T10:00:00",
            "end": "2016-06-07T13:00:00",
            "id": "29b7a553-d44f-8f2c-11e1-a7d5f62eb123",
            "text": "Event 3",
            "backColor": "#B6D7A8",
            "borderColor": "#6AA84F"
        },
        {
            "start": "2016-06-07T14:00:00",
            "end": "2016-06-07T17:00:00",
            "id": "ff968cfb-eba1-8dc1-7396-7f0d4f465c8a",
            "text": "Event 4",
            "backColor": "#EA9999",
            "borderColor": "#CC0000",
            "tags": {
                "type": "important"
            }
        }
    ];

    dp.onBeforeEventRender = args => {
        if (args.data.tags && args.data.tags.type === "important"){
            args.data.html = "<b>Important Event</b><br>" + args.data.text;
            args.data.fontColor = "#fff";
            args.data.backColor = "#E06666";
        }
    };

    dp.init();

</script>

您可以使用它来自定义以下属性:

  • backColor
  • barBackColor
  • barColor
  • barHidden
  • borderColor
  • cssClass
  • fontColor
  • html
  • toolTip

演示:

月历活动定制

DayPilot Lite for JavaScript 1.3 SP4 中的月历控件中添加了事件自定义支持。

DayPilot Month支持自定义以下事件属性:

  • backColor
  • borderColor
  • cssClass
  • fontColor
  • html
  • toolTip

演示:

例:

<div id="dp"></div>

<script type="text/javascript">
    const dp = new DayPilot.Month("dp");

    // ...
    
    dp.events.list = [
        {
            "start": "2021-03-03T00:00:00",
            "end": "2021-03-03T12:00:00",
            "id": "5a8376d2-8e3d-9739-d5d9-c1fba6ec02f9",
            "text": "Event 3"
        },
        {
            "start": "2021-02-25T00:00:00",
            "end": "2021-02-27T12:00:00",
            "id": "1fa34626-113a-ccb7-6a38-308e6cbe571e",
            "text": "Event 4",
            "tags": {
                "type": "important"
            }
        },
        // ...
    ];

    dp.onBeforeEventRender = args => {
        var type = args.data.tags && args.data.tags.type;
        switch (type) {
            case "important":
                args.data.fontColor = "#fff";
                args.data.backColor = "#E06666";
                args.data.borderColor = "#E06666";
                break;
            // ...
        }
    };

    dp.init();

</script>

支持AngularReactVue

DayPilot Lite 2022.1版本包括对AngularReactVue框架的支持。有关快速介绍和示例项目下载,请参阅以下教程:

资源日历

2022.2版本开始,DayPilot Lite包含一个资源日历视图,该视图将资源显示为列。

通过此视图,您可以安排事件或为多个资源进行预订,并排显示它们。

快速示例:

const calendar = new DayPilot.Calendar("calendar", {
  viewType: "Resources",
  columns: [
    { name: "Room 1", id: "R1" },
    { name: "Room 2", id: "R2" },
    { name: "Room 3", id: "R3" },
    { name: "Room 4", id: "R4" },
  ]
});
calendar.init();

 JavaScriptAngularReactVue 的资源日历教程中阅读更多内容。

图标和上下文菜单

从版本2022.4开始,日历组件支持事件上下文菜单和图标。

可以使用活动区域添加图标。活动区域是向事件添加元素的通用工具——您可以使用它们来添加图像、状态图标、操作按钮和拖动手柄。

例:

onBeforeEventRender: args => {
  args.data.areas = [
    {
      top: 5,
      right: 5,
      width: 16,
      height: 16,
      symbol: "icons/daypilot.svg#minichevron-down-4",
      fontColor: "#666",
      visibility: "Hover",
      action: "ContextMenu",
      style: "background-color: #f9f9f9; border: 1px solid #666; 
              cursor:pointer; border-radius: 15px;"
    }
  ];
},
contextMenu: new DayPilot.Menu({
  items: [
    {
      text: "Edit...",
      onClick: args => {
        app.editEvent(args.source);
      }
    },
    {
      text: "Delete",
      onClick: args => {
        app.deleteEvent(args.source);
      }
    },
    {
      text: "-"
    },
    {
      text: "Duplicate",
      onClick: args => {
        app.duplicateEvent(args.source);
      }
    },
  ]
})

//月日历视图切换

2023.2版本开始,DayPilot包含一个帮助程序,用于在定义的视图(日///自定义)之间轻松切换,并带有集成的日期选择器(视图与日期选择器同步)。

在以下教程中查看详细信息:

资源标头自定义

2023.3版本开始,DayPilot允许自定义列标题。现在,您可以使用onBeforeHeaderRender事件处理程序来修改文本/HTML、更改背景颜色、向标题添加图标、操作按钮和自定义元素。

这在资源日历/计划程序模式下特别有用,在该模式下,您可以将资源显示为列 - 您可以轻松地显示资源的图像、添加状态图标或编辑按钮

现场演示:

另见

https://www.codeproject.com/Articles/732679/HTML-Event-Calendar-Scheduler