项目结构:
实体类:
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"))
(
t
h
i
s
)
.
d
a
t
a
(
"
q
t
i
p
"
)
)
(this).qtip(“destroy”);
updateEventOnDropResize(event);
}
function eventResized(event, dayDelta, minuteDelta, revertFunc) {
if (
(this).data("qtip"))
(
t
h
i
s
)
.
d
a
t
a
(
"
q
t
i
p
"
)
)
(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 () {
//更新对话框
(document).ready(function () { //更新对话框
(‘#updatedialog’).dialog({
autoOpen: false,
width: 470,
buttons: {
“更新”: function () {
//alert(currentUpdateEvent.title);
var eventToUpdate = {
id: currentUpdateEvent.id,
title: (“#eventName”).val(),
description:
(“#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('点击了自定义按钮!