在ASP.NET中的JQuery FullCalendar实现

来源:互联网 发布:第一网红 知乎 编辑:程序博客网 时间:2024/06/05 06:10

项目结构:

这里写图片描述


实体类:

CalendarEvent.cs:

using System;using System.Collections.Generic;using System.Linq;using System.Web;namespace test.Model{    public class CalendarEvent    {        public int id { get; set; }        public string title { get; set; }        public string description { get; set; }        public DateTime start { get; set; }        public DateTime end { get; set; }        public bool allDay { get; set; }    }}

ImproperCalendarEvent.cs:

using System;using System.Collections.Generic;using System.Linq;using System.Web;namespace test.Model{    public class ImproperCalendarEvent    {        public int id { get; set; }        public string title { get; set; }        public string description { get; set; }        public string start { get; set; }        public string end { get; set; }        public bool allDay { get; set; }    }}

EventDAO.cs

using System;using System.Collections.Generic;using System.Linq;using System.Web;using System.Configuration;using System.Data.SqlClient;using System.Data;namespace test.Model{    public class EventDAO    {        //根据您的数据库连接更改连接字符串        private static string connectionString = ConfigurationManager.AppSettings["DBConnString"];        //这个方法检索范围start-end内的所有事件        public static List<CalendarEvent> getEvents(DateTime start, DateTime end)        {            List<CalendarEvent> events = new List<CalendarEvent>();            SqlConnection con = new SqlConnection(connectionString);            SqlCommand cmd = new SqlCommand("SELECT event_id, description, title, event_start, event_end, all_day FROM Event where event_start>=@start AND event_end<=@end", con);            cmd.Parameters.Add("@start", SqlDbType.DateTime).Value = start;            cmd.Parameters.Add("@end", SqlDbType.DateTime).Value = end;            using (con)            {                con.Open();                SqlDataReader reader = cmd.ExecuteReader();                while (reader.Read())                {                    events.Add(new CalendarEvent()                    {                        id = Convert.ToInt32(reader["event_id"]),                        title = Convert.ToString(reader["title"]),                        description = Convert.ToString(reader["description"]),                        start = Convert.ToDateTime(reader["event_start"]),                        end = Convert.ToDateTime(reader["event_end"]),                        allDay = Convert.ToBoolean(reader["all_day"])                    });                }            }            return events;            //注意:如果你只想显示与特定用户相关的事件,            //如果该用户的用户标识存储在会话中作为Session["userid"]            //事件表还包含一个名为'user_id'的额外字段来标记该特定用户的事件            //然后你可以修改SQL为:            //SELECT event_id, description, title, event_start, event_end FROM event where user_id=@user_id AND event_start>=@start AND event_end<=@end            //然后添加参数为:cmd.Parameters.AddWithValue("@user_id", HttpContext.Current.Session["userid"]);        }        //此方法更新事件标题和说明        public static void updateEvent(int id, String title, String description)        {            SqlConnection con = new SqlConnection(connectionString);            SqlCommand cmd = new SqlCommand("UPDATE Event SET title=@title, description=@description WHERE event_id=@event_id", con);            cmd.Parameters.Add("@title", SqlDbType.VarChar).Value = title;            cmd.Parameters.Add("@description", SqlDbType.VarChar).Value = description;            cmd.Parameters.Add("@event_id", SqlDbType.Int).Value = id;            using (con)            {                con.Open();                cmd.ExecuteNonQuery();            }        }        //此方法更新为FullCalendar 2.x添加的事件开始和结束时间... allDay参数        public static void updateEventTime(int id, DateTime start, DateTime end, bool allDay)        {            SqlConnection con = new SqlConnection(connectionString);            SqlCommand cmd = new SqlCommand("UPDATE Event SET event_start=@event_start, event_end=@event_end, all_day=@all_day WHERE event_id=@event_id", con);            cmd.Parameters.Add("@event_start", SqlDbType.DateTime).Value = start;            cmd.Parameters.Add("@event_end", SqlDbType.DateTime).Value = end;            cmd.Parameters.Add("@event_id", SqlDbType.Int).Value = id;            cmd.Parameters.Add("@all_day", SqlDbType.Bit).Value = allDay;            using (con)            {                con.Open();                cmd.ExecuteNonQuery();            }        }        //这个方法用传入的id删除事件        public static void deleteEvent(int id)        {            SqlConnection con = new SqlConnection(connectionString);            SqlCommand cmd = new SqlCommand("DELETE FROM Event WHERE (event_id = @event_id)", con);            cmd.Parameters.Add("@event_id", SqlDbType.Int).Value = id;            using (con)            {                con.Open();                cmd.ExecuteNonQuery();            }        }        //此方法将事件添加到数据库        public static int addEvent(CalendarEvent cevent)        {            //将事件添加到数据库并返回添加的事件行的主键            //增加            SqlConnection con = new SqlConnection(connectionString);            SqlCommand cmd = new SqlCommand("INSERT INTO Event(title, description, event_start, event_end, all_day) VALUES(@title, @description, @event_start, @event_end, @all_day)", con);            cmd.Parameters.Add("@title", SqlDbType.VarChar).Value = cevent.title;            cmd.Parameters.Add("@description", SqlDbType.VarChar).Value = cevent.description;            cmd.Parameters.Add("@event_start", SqlDbType.DateTime).Value = cevent.start;            cmd.Parameters.Add("@event_end", SqlDbType.DateTime).Value = cevent.end;            cmd.Parameters.Add("@all_day", SqlDbType.Bit).Value = cevent.allDay;            int key = 0;            using (con)            {                con.Open();                cmd.ExecuteNonQuery();                //获取插入行的主键                cmd = new SqlCommand("SELECT max(event_id) FROM Event where title=@title AND description=@description AND event_start=@event_start AND event_end=@event_end AND all_day=@all_day", con);                cmd.Parameters.Add("@title", SqlDbType.VarChar).Value = cevent.title;                cmd.Parameters.Add("@description", SqlDbType.VarChar).Value = cevent.description;                cmd.Parameters.Add("@event_start", SqlDbType.DateTime).Value = cevent.start;                cmd.Parameters.Add("@event_end", SqlDbType.DateTime).Value = cevent.end;                cmd.Parameters.Add("@all_day", SqlDbType.Bit).Value = cevent.allDay;                key = (int)cmd.ExecuteScalar();            }            return key;        }    }}

CrudData.asmx:

using System;using System.Collections.Generic;using System.Linq;using System.Web;using System.Web.Services;using test.Model;using System.Text.RegularExpressions;using System.Web.Script.Services;namespace test{    [WebService(Namespace = "http://tempuri.org/")]    [WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]    [System.ComponentModel.ToolboxItem(false)]    // 若要允许使用 ASP.NET AJAX 从脚本中调用此 Web 服务,请取消对下行的注释。    [System.Web.Script.Services.ScriptService]    public class CrudData : System.Web.Services.WebService    {        //这个方法只更新标题和描述        //在日历上单击事件时调用此方法        [WebMethod(true)]        public  string UpdateEvent(CalendarEvent cevent)        {            List<int> idList = (List<int>)System.Web.HttpContext.Current.Session["idList"];            if (idList != null && idList.Contains(cevent.id))            {                if (CheckAlphaNumeric(cevent.title) && CheckAlphaNumeric(cevent.description))                {                    EventDAO.updateEvent(cevent.id, cevent.title, cevent.description);                    return "updated event with id:" + cevent.id + " update title to: " + cevent.title +                    " update description to: " + cevent.description;                }            }            return "unable to update event with id:" + cevent.id + " title : " + cevent.title +                " description : " + cevent.description;        }        //此方法只更新开始和结束时间        //在日历中拖动或调整事件大小时调用此方法        [WebMethod(true)]        public  string UpdateEventTime(ImproperCalendarEvent improperEvent)        {            List<int> idList = (List<int>)System.Web.HttpContext.Current.Session["idList"];            if (idList != null && idList.Contains(improperEvent.id))            {                EventDAO.updateEventTime(improperEvent.id,                                         Convert.ToDateTime(improperEvent.start),                                         Convert.ToDateTime(improperEvent.end),                                         improperEvent.allDay);  //为FullCalendar 2.x添加allDay参数                return "updated event with id:" + improperEvent.id + " update start to: " + improperEvent.start +                    " update end to: " + improperEvent.end;            }            return "unable to update event with id: " + improperEvent.id;        }        //按下删除按钮时调用        [WebMethod(true)]        public  String deleteEvent(int id)        {            //由于安全原因,idList由JsonResponse.ashx存储在Session中            //每当有任何事件被更新或删除,事件ID被检查            //它是否存在于idList中,如果它不存在于idList中,那么它可能是一个恶意用户试图删除某人elses事件,因此这种检查防止滥用            List<int> idList = (List<int>)System.Web.HttpContext.Current.Session["idList"];            if (idList != null && idList.Contains(id))            {                EventDAO.deleteEvent(id);                return "删除事件,用id:" + id;            }            return "删除事件,无法用ID: " + id;        }        //单击添加按钮时调用        //当在任何一天的开放空间上点击鼠标或者在多天的时间拖动时,这被调用        [WebMethod]        public  int addEvent(ImproperCalendarEvent improperEvent)        {            CalendarEvent cevent = new CalendarEvent()            {                title = improperEvent.title,                description = improperEvent.description,                start = Convert.ToDateTime(improperEvent.start),                end = Convert.ToDateTime(improperEvent.end),                allDay = improperEvent.allDay            };            if (CheckAlphaNumeric(cevent.title) && CheckAlphaNumeric(cevent.description))            {                int key = EventDAO.addEvent(cevent);                if (System.Web.HttpContext.Current.Session["idList"] != null)                {                    List<int> idList = (List<int>)System.Web.HttpContext.Current.Session["idList"];                    idList.Add(key);                }                return key; //返回添加的cevent对象的主键            }            return -1; //返回一个负数表示没有添加任何内容        }        private static bool CheckAlphaNumeric(string str)        {            return Regex.IsMatch(str, @"^[a-zA-Z0-9 ]*$");        }    }}

Index.aspx

<%@ Page Language="C#" AutoEventWireup="true" CodeBehind="Index.aspx.cs" Inherits="test.Index" %><!DOCTYPE html><html><head id="Head1" runat="server">    <title>ASP.NET完整日历</title>    <link href="css/jquery-ui.css" rel="stylesheet" type="text/css" />    <link href="css/fullcalendar.min.css" rel="stylesheet" type="text/css" />    <link href="css/jquery.qtip.min.css" rel="stylesheet" type="text/css" />    <style type='text/css'>        body        {            margin-top: 40px;            text-align: center;            font-size: 14px;            font-family: "Lucida Grande" ,Helvetica,Arial,Verdana,sans-serif;        }        #calendar        {            width: 900px;            margin: 0 auto;        }        /* css for timepicker */        .ui-timepicker-div dl        {            text-align: left;        }        .ui-timepicker-div dl dt        {            height: 25px;        }        .ui-timepicker-div dl dd        {            margin: -25px 0 10px 65px;        }        .style1        {            width: 100%;        }        /* table fields alignment*/        .alignRight        {            text-align: right;            padding-right: 10px;            padding-bottom: 10px;        }        .alignLeft        {            text-align: left;            padding-bottom: 10px;        }    </style></head><body>    <form id="form1" runat="server">    <%--<asp:ScriptManager ID="ScriptManager1" runat="server" EnablePageMethods="true">    </asp:ScriptManager>--%>    <div id="calendar">    </div>    <div id="updatedialog" style="font: 70% 'Trebuchet MS', sans-serif; margin: 50px;        display: none;" title="更新或删除事件">        <table class="style1">            <tr>                <td class="alignRight">                    名称:                </td>                <td class="alignLeft">                    <input id="eventName" type="text" size="33" /><br />                </td>            </tr>            <tr>                <td class="alignRight">                    描述:                </td>                <td class="alignLeft">                    <textarea id="eventDesc" cols="30" rows="3"></textarea>                </td>            </tr>            <tr>                <td class="alignRight">                    开始:                </td>                <td class="alignLeft">                    <span id="eventStart"></span>                </td>            </tr>            <tr>                <td class="alignRight">                    结束:                </td>                <td class="alignLeft">                    <span id="eventEnd"></span>                    <input type="hidden" id="eventId" />                </td>            </tr>        </table>    </div>    <div id="addDialog" style="font: 70% 'Trebuchet MS', sans-serif; margin: 50px;" title="添加事件">        <table class="style1">            <tr>                <td class="alignRight">                    名称:                </td>                <td class="alignLeft">                    <input id="addEventName" type="text" size="33" /><br />                </td>            </tr>            <tr>                <td class="alignRight">                    描述:                </td>                <td class="alignLeft">                    <textarea id="addEventDesc" cols="30" rows="3"></textarea>                </td>            </tr>            <tr>                <td class="alignRight">                    开始:                </td>                <td class="alignLeft">                    <span id="addEventStartDate"></span>                </td>            </tr>            <tr>                <td class="alignRight">                    结束:                </td>                <td class="alignLeft">                    <span id="addEventEndDate"></span>                </td>            </tr>        </table>    </div>    <div runat="server" id="jsonDiv" />    <input type="hidden" id="hdClient" runat="server" />    </form>    <script src="js/moment.min.js" type="text/javascript"></script>    <script src="js/jquery.min.js" type="text/javascript"></script>    <script src="js/jquery-ui.min.js" type="text/javascript"></script>    <script src="js/jquery.qtip.min.js" type="text/javascript"></script>    <script src="js/fullcalendar.min.js" type="text/javascript"></script>    <script src="scripts/calendarscript.js" type="text/javascript"></script></body></html>

calendarscript.js:

var currentUpdateEvent;var addStartDate;var addEndDate;var globalAllDay;function updateEvent(event, element) {    //alert(event.description);    if ($(this).data("qtip")) $(this).qtip("destroy");    currentUpdateEvent = event;    $('#updatedialog').dialog('open');    $("#eventName").val(event.title);    $("#eventDesc").val(event.description);    $("#eventId").val(event.id);    $("#eventStart").text("" + event.start.toLocaleString());    if (event.end === null) {        $("#eventEnd").text("");    }    else {        $("#eventEnd").text("" + event.end.toLocaleString());    }    return false;}function updateSuccess(updateResult) {    alert(updateResult.d);}function deleteSuccess(deleteResult) {    alert(deleteResult.d);}function addSuccess(addResult) {    // if addresult is -1, means event was not added    //    alert("added key: " + addResult);    if (addResult != -1) {        $('#calendar').fullCalendar('renderEvent',                        {                            title: $("#addEventName").val(),                            start: addStartDate,                            end: addEndDate,                            id: addResult,                            description: $("#addEventDesc").val(),                            allDay: globalAllDay                        },                        true // make the event "stick"                    );        $('#calendar').fullCalendar('unselect');    }}function UpdateTimeSuccess(updateResult) {    alert(updateResult);}function selectDate(start, end, allDay) {    $('#addDialog').dialog('open');    $("#addEventStartDate").text("" + start.toLocaleString());    $("#addEventEndDate").text("" + end.toLocaleString());    addStartDate = start;    addEndDate = end;    globalAllDay = allDay;    //alert(allDay);}function updateEventOnDropResize(event, allDay) {    //alert("allday: " + allDay);    var eventToUpdate = {        id: event.id,        start: event.start    };    if (event.end === null) {        eventToUpdate.end = eventToUpdate.start;    }    else {        eventToUpdate.end = event.end;    }    var endDate;    if (!event.allDay) {        endDate = new Date(eventToUpdate.end + 60 * 60000);        endDate = endDate.toJSON();    }    else {        endDate = eventToUpdate.end.toJSON();    }    eventToUpdate.start = eventToUpdate.start.toJSON();    eventToUpdate.end = eventToUpdate.end.toJSON(); //endDate;    eventToUpdate.allDay = event.allDay;    PageMethods.UpdateEventTime(eventToUpdate, UpdateTimeSuccess);}function eventDropped(event, dayDelta, minuteDelta, allDay, revertFunc) {    if ($(this).data("qtip")) $(this).qtip("destroy");    updateEventOnDropResize(event);}function eventResized(event, dayDelta, minuteDelta, revertFunc) {    if ($(this).data("qtip")) $(this).qtip("destroy");    updateEventOnDropResize(event);}function checkForSpecialChars(stringToCheck) {    var pattern = /[^A-Za-z0-9 ]/;    return pattern.test(stringToCheck);}function isAllDay(startDate, endDate) {    var allDay;    if (startDate.format("HH:mm:ss") == "00:00:00" && endDate.format("HH:mm:ss") == "00:00:00") {        allDay = true;        globalAllDay = true;    }    else {        allDay = false;        globalAllDay = false;    }    return allDay;}function qTipText(start, end, description) {    var text;    if (end !== null)        text = "<strong>开始:</strong> " + start.format("MM/DD/YYYY hh:mm T") + "<br/><strong>结束:</strong> " + end.format("MM/DD/YYYY hh:mm T") + "<br/><br/>" + description;    else        text = "<strong>开始:</strong> " + start.format("MM/DD/YYYY hh:mm T") + "<br/><strong>结束:</strong><br/><br/>" + description;    return text;}$(document).ready(function () {    //更新对话框    $('#updatedialog').dialog({        autoOpen: false,        width: 470,        buttons: {            "更新": function () {                //alert(currentUpdateEvent.title);                var eventToUpdate = {                    id: currentUpdateEvent.id,                    title: $("#eventName").val(),                    description: $("#eventDesc").val()                };                if (checkForSpecialChars(eventToUpdate.title) || checkForSpecialChars(eventToUpdate.description)) {                    alert("请输入字符: A to Z, a to z, 0 to 9, spaces");                }                else {                    //PageMethods.UpdateEvent(eventToUpdate, updateSuccess);                    var d = '{"cevent":' + JSON.stringify(eventToUpdate) + '}';                    $.ajax({                        'url': '../CrudData.asmx/UpdateEvent',                        'type': 'POST',                        'contentType': "application/json;charset=utf-8",                        'data': d,                        'success': updateSuccess                    });                    $(this).dialog("close");                    currentUpdateEvent.title = $("#eventName").val();                    currentUpdateEvent.description = $("#eventDesc").val();                    $('#calendar').fullCalendar('updateEvent', currentUpdateEvent);                }            },            "删除": function () {                if (confirm("你真的想删除这个事件吗?")) {                    //PageMethods.deleteEvent($("#eventId").val(), deleteSuccess);                    var id = $("#eventId").val();                    $.ajax({                        'url': '../CrudData.asmx/deleteEvent',                        'type': 'POST',                        'contentType': "application/json;charset=utf-8",                        'data': "{'id':" + id + "}",                        'success': deleteSuccess                    });                    $(this).dialog("close");                    $('#calendar').fullCalendar('removeEvents', $("#eventId").val());                }            }        }    });    //添加对话框    $('#addDialog').dialog({        autoOpen: false,        width: 470,        buttons: {            "添加": function () {                //alert("sent:" + addStartDate.format("dd-MM-yyyy hh:mm:ss tt") + "==" + addStartDate.toLocaleString());                var eventToAdd = {                    title: $("#addEventName").val(),                    description: $("#addEventDesc").val(),                    start: addStartDate.toJSON(),                    end: addEndDate.toJSON(),                    allDay: isAllDay(addStartDate, addEndDate)                };                if (checkForSpecialChars(eventToAdd.title) || checkForSpecialChars(eventToAdd.description)) {                    alert("请输入字符: A to Z, a to z, 0 to 9, spaces");                }                else {                    //alert("sending " + eventToAdd.title);                    //PageMethods.addEvent(eventToAdd, addSuccess);                    var d = '{"improperEvent":' + JSON.stringify(eventToAdd) + '}';                    $.ajax({                        'url': '../CrudData.asmx/addEvent',                        'type': 'POST',                        'contentType': "application/json;charset=utf-8",                        'data': d,                        'success': addSuccess                    });                    $(this).dialog("close");                }            }        }    });    var date = new Date();    var d = date.getDate();    var m = date.getMonth();    var y = date.getFullYear();    var options = {        weekday: "long", year: "numeric", month: "short",        day: "numeric", hour: "2-digit", minute: "2-digit"    };    $('#calendar').fullCalendar({        buttonText: {            today: '今天',            month: '月视图',            week: '周视图',            day: '日视图'        },        allDayText: "全天",        //  timeFormat: {        //        '': 'H:mm{-H:mm}'  //设置显示的日程事件的时间格式,如timeFormat: 'H:mm' 则显示24小时制的像10:30        //   },        weekMode: "variable",  //不固定周数,但高度固定        monthNames: ['一月', '二月', '三月', '四月', '五月', '六月', '七月', '八月', '九月', '十月', '十一月', '十二月'],        monthNamesShort: ['一月', '二月', '三月', '四月', '五月', '六月', '七月', '八月', '九月', '十月', '十一月', '十二月'],        dayNames: ["星期天", "星期一", "星期二", "星期三", "星期四", "星期五", "星期六"],        dayNamesShort: ["日", "一", "二", "三", "四", "五", "六"],        weekNumberTitle: "W",        theme: true,        header: {            left: 'prev,next  prevYear,nextYear today myCustomButton',            center: 'title',            right: 'month,agendaWeek,agendaDay'        },        customButtons: {  //可以为header部分自定义按钮。自定义按钮,然后在header部分引用            myCustomButton: {                text: '自定义按钮',                click: function () {                    alert('点击了自定义按钮!��!');                }            }        },        defaultView: 'agendaWeek', //日历初始化时默认视图        eventClick: updateEvent,   //当点击日历中的某一日程(事件)时,触发此操作        selectable: true,   //是否允许用户通过单击或拖动选择日历中的对象,包括天和时间        selectHelper: true, //当点击或拖动选择时间时,显示默认加载的提示信息,该属性只在周/天视图里可用。        select: selectDate,        editable: true,  //是否可编辑,即进行可拖动和缩放操作。        events: "JsonResponse.ashx",        eventDrop: eventDropped,  //callback,当拖拽完成并且时间改变时触发        eventResize: eventResized, //callback,在日程事件改变大小并成功后调用, 参数和eventDrop参数用法一致        eventRender: function (event, element) {            //alert(event.title);            element.qtip({                content: {                    text: qTipText(event.start, event.end, event.description),                    title: '<strong>' + event.title + '</strong>'                },                position: {                    my: 'bottom left',                    at: 'top right'                },                style: { classes: 'qtip-shadow qtip-rounded' }            });        }    });});

JsonResponse.ashx

<%@ WebHandler Language="C#" Class="JsonResponse" %>using System;using System.Web;using System.Collections;using System.Collections.Generic;using System.Web.SessionState;using test.Model;public class JsonResponse : IHttpHandler, IRequiresSessionState{    public void ProcessRequest(HttpContext context)    {        context.Response.ContentType = "text/plain";        DateTime start = Convert.ToDateTime(context.Request.QueryString["start"]);        DateTime end = Convert.ToDateTime(context.Request.QueryString["end"]);        List<int> idList = new List<int>();        List<ImproperCalendarEvent> tasksList = new List<ImproperCalendarEvent>();        //生成JSON序列化事件        foreach (CalendarEvent cevent in EventDAO.getEvents(start, end))        {            tasksList.Add(new ImproperCalendarEvent            {                id = cevent.id,                title = cevent.title,                start = String.Format("{0:s}", cevent.start),                end = String.Format("{0:s}", cevent.end),                description = cevent.description,                allDay = cevent.allDay,            });            idList.Add(cevent.id);        }        context.Session["idList"] = idList;        //将事件序列化为字符串        System.Web.Script.Serialization.JavaScriptSerializer oSerializer = new System.Web.Script.Serialization.JavaScriptSerializer();        string sJSON = oSerializer.Serialize(tasksList);        //将JSON写入响应对象        context.Response.Write(sJSON);    }    public bool IsReusable    {        get { return false; }    }}

运行结果如图:

这里写图片描述


这里写图片描述


这里写图片描述