65.9K
CodeProject 正在变化。 阅读更多。
Home

JavaScript 事件日历用于资源调度

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.95/5 (154投票s)

2014 年 2 月 24 日

Apache

11分钟阅读

viewsIcon

906417

downloadIcon

5977

每周 HTML5 事件日历,支持 CSS 主题、拖放功能和日期导航器。后端为 PHP 和 ASP.NET Core REST API。

Open-Source JavaScript/HTML5 Event Calendar/Scheduler

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

特点

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

我们将使用开源的 DayPilot Lite for JavaScript [javascript.daypilot.org] 来构建事件日历。DayPilot Lite for JavaScript 可在 Apache License 2.0 下获得。

新功能:日期选择器(导航器)响应式模式

JavaScript Date Picker Responsive Mode

版本 2024.3.547 中引入的新的 响应式模式 允许 日期选择器(导航器)填充可用宽度,而不是使用固定的日期单元格宽度。

新教程:React 日历(日/周/月视图)

React Calendar with Day/Week/Month Views (Open-Source)

React 日/周/月视图日历(开源)》教程展示了如何在 React 中集成带日期选择器的日、周和月日历视图。

  • 日/周/月按钮用于切换日历视图。
  • “今天”按钮方便返回当前日期。
  • 与日历视图和日/周/月按钮同步的日期选择器。
  • 带源代码下载的 React 应用程序。

步骤 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 主题

HTML5 Event Calendar - CSS Theme

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

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

并在初始化期间设置主题属性。

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

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

带实时预览的配置器应用程序

现在,您可以使用在线 UI 生成器 应用程序轻松配置日/周/月日历组件。该应用程序允许您在实时 DayPilot 实例中预览配置更改,并生成一个带有预配置日历组件的新项目(支持 JavaScript/HTML、JavaScript/NPM、TypeScript、Angular、React 和 Vue 项目目标)。

调度器 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>

持续时间条

HTML5 event calendar with duration bar support

DayPilot Lite HTML5 事件日历的 1.1 版支持持续时间条(事件左侧的实际日历事件持续时间指示器)。默认启用,您可以使用 CSS 主题进行样式设置。

事件自定义(HTML、CSS)

HTML5 Event Calendar Customization

自 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 月历支持以下事件属性的自定义:

  • 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>

支持 Angular、React 和 Vue

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,更改背景颜色,向标题添加图标、操作按钮和自定义元素。

这在资源日历/调度器模式中尤其有用,您在该模式中将资源显示为列 - 您可以轻松显示资源的图像,添加状态图标或编辑按钮

实时演示

教程:ASP.NET Core 维护调度

一篇解释如何使用 DayPilot 在 ASP.NET Core 中创建彩色编码维护计划的新教程现已推出。

此维护调度应用程序具有以下功能:

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

Next.js 日历

Next.js Weekly Calendar (Open-Source)

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

另请参阅

历史

© . All rights reserved.