HTML
CSS
JavaScript
HTML
<!DOCTYPE html>
<html lang="zh">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no" />
<title>日程 - 光年(Light Year Admin)后台管理系统模板</title>
<link rel="icon" href="favicon.ico" type="image/ico">
<meta name="keywords" content="LightYear,光年,后台模板,后台管理系统,光年HTML模板">
<meta name="description" content="LightYear是一个基于Bootstrap v3.3.7的后台管理系统的HTML模板。">
<meta name="author" content="yinqi">
<link href="http://lyear.itshubao.com/iframe/css/bootstrap.min.css" rel="stylesheet">
<link href="http://example.itshubao.com/demo/css/materialdesignicons.min.css" rel="stylesheet">
<!--时间选择插件-->
<link rel="stylesheet" href="http://lyear.itshubao.com/iframe/js/bootstrap-datetimepicker/bootstrap-datetimepicker.min.css">
<!--日期选择插件-->
<link rel="stylesheet" href="http://lyear.itshubao.com/iframe/js/bootstrap-datepicker/bootstrap-datepicker3.min.css">
<link href="http://libs.itshubao.com/fullcalendar/core/main.css" rel="stylesheet">
<link href='http://libs.itshubao.com/fullcalendar/daygrid/main.css' rel='stylesheet' />
<link href='http://libs.itshubao.com/fullcalendar/timegrid/main.css' rel='stylesheet' />
<link href='http://libs.itshubao.com/fullcalendar/list/main.css' rel='stylesheet' />
<link href="http://lyear.itshubao.com/iframe/css/style.min.css" rel="stylesheet">
</head>
  
<body>
<div class="container-fluid">
  
  <div class="row">
    <div class="col-md-12">
      <div class="card">
        <div class="card-body">
          
          <div id="calendar" data-provide="fullcalendar"></div>
          
        </div>
      </div>
    </div>
    
  </div>
  
</div>

<!-- 编辑日程 -->
<div class="modal fade" id="modal-event" tabindex="-1">
  <div class="modal-dialog">
    <div class="modal-content">
      <form action="#!" method="post" onsubmit="return false;" id="event_form">
      <div class="modal-header">
        <button type="button" class="close" data-dismiss="modal">
          <span aria-hidden="true">&times;</span>
        </button>
        <h5 class="modal-title">编辑一个日程</h5>
      </div>

      <div class="modal-body">
        <div class="form-group">
          <label>标题</label>
          <input type="text" class="form-control" name="title" id="title" placeholder="日程标题">
        </div>

        <div class="form-group">
          <label>开始日期和时间</label>
          <div class="input-group">
            <input class="form-control js-datepicker" data-date-format="yyyy-mm-dd" type="text" placeholder="日期" name="start_day" id="start_day">
            <span class="input-group-addon">~</span>
            <input class="form-control js-datetimepicker" data-side-by-side="true" data-locale="zh-cn" data-format="HH:mm" type="text" placeholder="具体时间" name="start_time" id="start_time">
          </div>
        </div>

        <div class="form-group">
          <label>结束日期和时间</label>
          <div class="input-group">
            <input class="form-control js-datepicker" data-date-format="yyyy-mm-dd" type="text" placeholder="结束日期,如果全天则不设置结束日期" name="end_day" id="end_day">
            <span class="input-group-addon">~</span>
            <input class="form-control js-datetimepicker" data-side-by-side="true" data-locale="zh-cn" data-format="HH:mm" type="text" placeholder="具体时间" name="end_time" id="end_time">
          </div>
        </div>

        <div class="form-group">
          <label>备注</label>
          <textarea class="form-control" rows="3" name="remark" id="remark" placeholder="简要说明"></textarea>
        </div>

        <div class="text-center">
          <div class="drop-skin-li clearfix">
            <span>
              <input type="radio" name="event_bg" value="bg-primary" checked id="event_primary">
              <label for="event_primary" class="bg-primary"></label>
            </span>
            <span>
              <input type="radio" name="event_bg" value="bg-success" id="event_success">
              <label for="event_success" class="bg-success"></label>
            </span>
            <span>
              <input type="radio" name="event_bg" value="bg-info" id="event_info">
              <label for="event_info" class="bg-info"></label>
            </span>
            <span>
              <input type="radio" name="event_bg" value="bg-warning" id="event_warning">
              <label for="event_warning" class="bg-warning"></label>
            </span>
            <span>
              <input type="radio" name="event_bg" value="bg-danger" id="event_danger">
              <label for="event_danger" class="bg-danger"></label>
            </span>
            <span>
              <input type="radio" name="event_bg" value="bg-pink" id="event_pink">
              <label for="event_pink" class="bg-pink"></label>
            </span>
            <span>
              <input type="radio" name="event_bg" value="bg-purple" id="event_purple">
              <label for="event_purple" class="bg-purple"></label>
            </span>
            <span>
              <input type="radio" name="event_bg" value="bg-brown" id="event_brown">
              <label for="event_brown" class="bg-brown"></label>
            </span>
            <span>
              <input type="radio" name="event_bg" value="bg-cyan" id="event_cyan">
              <label for="event_cyan" class="bg-cyan"></label>
            </span>
            <span>
              <input type="radio" name="event_bg" value="bg-yellow" id="event_yellow">
              <label for="event_yellow" class="bg-yellow"></label>
            </span>
            <span>
              <input type="radio" name="event_bg" value="bg-gray" id="event_gray">
              <label for="event_gray" class="bg-gray"></label>
            </span>
            <span>
              <input type="radio" name="event_bg" value="bg-dark" id="event_dark">
              <label for="event_dark" class="bg-dark"></label>
            </span>
          </div>
        </div>
      </div>

      <div class="modal-footer">
        <input type="hidden" name="event_id" id="event_id" value="0" />
        <button type="button" class="btn btn-secondary" data-dismiss="modal">取消</button>
        <button type="button" class="btn btn-primary" onclick="saveEvent();">保存</button>
      </div>
      </form>
    </div>
  </div>
</div>
<!-- end 编辑日程 -->
<!-- 展示日程 -->
<div class="modal fade" id="modal-view-event" tabindex="-1">
  <div class="modal-dialog modal-sm">
    <div class="modal-content">
      <div class="modal-header">
        <button type="button" class="close" data-dismiss="modal">
          <span aria-hidden="true">&times;</span>
        </button>
        <h5 class="modal-title">title</h5>
      </div>

      <div class="modal-body">
        <div class="m-b-10">
          <label>时间</label>
          <div class="event-time"></div>
        </div>

        <div class="m-b-10">
          <label>备注</label>
          <div class="event-remark"></div>
        </div>
      </div>

      <div class="modal-footer">
        <button class="btn btn-primary" data-id="0" id="open-modal-edit">去编辑</button>
      </div>
    </div>
  </div>
</div>
<!-- end 展示日程 -->

<script type="text/javascript" src="http://lyear.itshubao.com/iframe/js/jquery.min.js"></script>
<script type="text/javascript" src="http://lyear.itshubao.com/iframe/js/bootstrap.min.js"></script>
<!--时间选择插件-->
<script src="http://lyear.itshubao.com/iframe/js/bootstrap-datetimepicker/moment.min.js"></script>
<script src="http://lyear.itshubao.com/iframe/js/bootstrap-datetimepicker/bootstrap-datetimepicker.min.js"></script>
<script src="http://lyear.itshubao.com/iframe/js/bootstrap-datetimepicker/locale/zh-cn.js"></script>
<!--日期选择插件-->
<script src="http://lyear.itshubao.com/iframe/js/bootstrap-datepicker/bootstrap-datepicker.min.js"></script>
<script src="http://lyear.itshubao.com/iframe/js/bootstrap-datepicker/locales/bootstrap-datepicker.zh-CN.min.js"></script>
<!--日程插件-->
<script type="text/javascript" src="http://libs.itshubao.com/fullcalendar/core/main.min.js"></script>
<script type="text/javascript" src="http://libs.itshubao.com/fullcalendar/core/locales/zh-cn.js"></script>
<script type="text/javascript" src="http://libs.itshubao.com/fullcalendar/interaction/main.min.js"></script>
<script type="text/javascript" src="http://libs.itshubao.com/fullcalendar/daygrid/main.min.js"></script>
<script type="text/javascript" src="http://libs.itshubao.com/fullcalendar/timegrid/main.min.js"></script>
<script type="text/javascript" src="http://libs.itshubao.com/fullcalendar/list/main.min.js"></script>
<script type="text/javascript" src="http://libs.itshubao.com/fullcalendar/rrule/main.min.js"></script>
<script type="text/javascript" src="http://lyear.itshubao.com/iframe/js/main.min.js"></script>
</body>
</html>
CSS

  
JavaScript
var calendarEl = document.getElementById('calendar');

// 定义时间点(避免时间变化导致示例不显示)
var thisDate     = new Date();
var thisFullYear = thisDate.getFullYear();
var thisMonth    = thisDate .getMonth() + 1;
if (thisMonth < 10) thisMonth = '0' + thisMonth;

var testDate1 = thisFullYear + '-' + thisMonth + '-01';
var testDate2 = thisFullYear + '-' + thisMonth + '-07';
var testDate3 = thisFullYear + '-' + thisMonth + '-10';
var testDate4 = thisFullYear + '-' + thisMonth + '-09T16:00:00';
var testDate5 = thisFullYear + '-' + thisMonth + '-16T16:00:00';
var testDate6 = thisFullYear + '-' + thisMonth + '-11';
var testDate7 = thisFullYear + '-' + thisMonth + '-13';
var testDate8 = thisFullYear + '-' + thisMonth + '-12T10:30:00';
var testDate9 = thisFullYear + '-' + thisMonth + '-12T12:30:00';
var testDate10 = thisFullYear + '-' + thisMonth + '-12T12:00:00';
var testDate11 = thisFullYear + '-' + thisMonth + '-12T14:30:00';
var testDate12 = thisFullYear + '-' + thisMonth + '-12T17:30:00';
var testDate13 = thisFullYear + '-' + thisMonth + '-12T20:00:00';
var testDate14 = thisFullYear + '-' + thisMonth + '-12T19:00:00';
var testDate15 = thisFullYear + '-' + thisMonth + '-28';

var calendar = new FullCalendar.Calendar(calendarEl, {
    plugins: [ 'interaction', 'dayGrid', 'timeGrid', 'list', 'rrule' ],
    //height: 'parent',
    header: {
        left: 'today prev,next day',
        center: 'title',
        right: 'dayGridMonth,timeGridWeek,timeGridDay,listWeek'
    },
    buttonText: {
        today:    '今天',
        month:    '月',
        week:     '周',
        day:      '天',
        list:     '列表'
    },
    defaultView: 'dayGridMonth',
    //navLinks: true, // 可以单击日/周名称导航视图。
    //selectable: true, // 允许用户通过单击和拖动突出显示多天或多个时间段。
    editable: true, // 确定是否可以修改日历上的事件。
    eventLimit: true, // 当事件太多时允许“更多”链接
    events: [
    {
      id: 1,
      title: '公司召开年会',
      start: testDate1,
    },
    {
      id: 2,
      title: '话剧全国巡演第二场',
      start: testDate2,
      end: testDate3
    },
    {
      id: 3,
      title: '工作报告',
      start: testDate4
    },
    {
      id: 4,
      title: '工作报告',
      start: testDate5
    },
    {
      id: 5,
      title: '研讨会',
      start: testDate6,
      end: testDate7
    },
    {
      id: 6,
      title: '会议',
      start: testDate8,
      end: testDate9,
      className: 'bg-danger'
    },
    {
      id: 7,
      title: '午餐',
      start: testDate10
    },
    {
      id: 8,
      title: '会议',
      start: testDate11,
      className: 'bg-danger'
    },
    {
      id: 9,
      title: '休息一会',
      start: testDate12,
    },
    {
      id: 10,
      title: '晚餐',
      start: testDate13
    },
    {
      id: 11,
      title: '生日宴会',
      start: testDate14,
      remark: '一定要记得参加',
      className: 'bg-purple'
    },
    {
      id: 12,
      title: '打开百度',
      url: 'https://www.baidu.com/',
      start: testDate15
    }],
    dateClick: function(date, jsEvent, view) {
        $('#modal-event').modal('show');
    },
    eventClick: function(date, jsEvent, view) {
        $('#modal-view-event').find('.modal-title').text(date.event.title);
        var time_str = formatDate(date.event.start, 'yyyy-MM-dd HH:mm:ss');
        if (date.event.hasOwnProperty('end')) {
            time_str += ' - ' + formatDate(date.event.end, 'yyyy-MM-dd HH:mm:ss'); // 根据自己的需求格式化时间显示
        }
        $('#modal-view-event').find('.event-time').text(time_str);
        if (date.event.extendedProps.hasOwnProperty('remark')) {
            $('#modal-view-event').find('.event-remark').text(date.event.extendedProps.remark);
        }
        $('#open-modal-edit').attr('data-id', date.event.id);
        $('#modal-view-event').modal('show');
    }
});

calendar.render();
calendar.setOption('locale', 'zh');

// 编辑日程
function saveEvent() {
    var title        = $('#title').val(),
        start_day    = $('#start_day').val(),
        start_time   = $('#start_time').val(),
        end_day      = $('#end_day').val(),
        end_time     = $('#end_time').val(),
        remark       = $('#remark').val(), // 按个人需求,可记录到数据库
        event_bg     = $("input[name='event_bg']:checked").val(),
        event_id     = $('#event_id').val(),
        event_params = {};
    
    if (title.length == 0) {
        alert('标题不能为空');  // 自行修改消息插件提示
        return false;
    } else {
        event_params.title = title;
    }
    if (start_day.length == 0 ) {
        alert('开始时间不能为空');
        return false;
    }
    var start_str  = start_day;
    if (start_time.length > 0) {
        start_str  = start_day + 'T' + start_time + ':00';// 示例中只到分,如需设置秒,则自行更改,input配置HH:mm:ss
    }
    var start_date = new Date(start_str);
    if (!isNaN(start_date.valueOf())) {
        event_params.start = start_str;
    } else {
        alert('开始日期格式错误');
        return false;
    }
    if (end_day.length > 0) {
        var end_str = end_day;
        if (end_time.length > 0) {
            end_str = end_day + 'T' + end_time + ':00'; // 示例中只到分,如需设置秒,则自行更改,input配置HH:mm:ss
        }
        var end_date = new Date(end_str);
        if (!isNaN(end_date.valueOf())) {
            event_params.end = end_str;
        } else {
            alert('结束日期格式错误');
            return false;
        }
    }
    if (event_bg.length > 0) {
        event_params.className = event_bg;
    }
    if ($.trim(remark).length > 0) {
        event_params.remark = remark;
    }
    
    if (event_id > 0) {
        // 提交修改
        var eventObj = calendar.getEventById(event_id);
        eventObj.setProp('title', event_params.title);
        eventObj.setProp('classNames', event_params.className);
        eventObj.setStart(event_params.start);
        if (event_params.hasOwnProperty('end')) {
            eventObj.setStart(event_params.end);
        }
        if (event_params.hasOwnProperty('remark')) {
            eventObj.setExtendedProp('remark', event_params.remark);
        }
    } else {
        // 提交新增
        calendar.addEvent(event_params);
    }
    $('#event_form')[0].reset(); // 重置表单
    $('#event_id').val('0'); // 重置为零
    $('#modal-event').modal('hide');
}

// 打开编辑窗口
$('#open-modal-edit').click(function(){
    var event_id = $(this).attr('data-id'),
        eventObj = calendar.getEventById(event_id);
    
    $("#modal-event").find('#title').val(eventObj.title);
    var start_day  = formatDate(eventObj.start, 'yyyy-MM-dd'),
        start_time = formatDate(eventObj.start, 'HH:mm');

    $("#start_day").val(start_day);
    $("#start_time").val(start_time);
    if (eventObj.extendedProps.hasOwnProperty('remark')) {
        $("#remark").val(eventObj.extendedProps.remark);
    }
    $("input:radio[value='" + eventObj.classNames[0] + "']").prop('checked','true');
    $('#event_id').val(event_id); // 重置为零
    $('#modal-view-event').modal('hide');
    $('#modal-event').modal('show');
});

// 点击关闭按钮的处理
$('.close').click(function(){
    if ($(this).parents('.modal').has('#event_form')) {
        $('#event_form')[0].reset(); // 重置表单
        $('#event_id').val('0'); // 重置为零
    }
});

// 点击取消的处理
$('[data-dismiss]').click(function(){
    if ($(this).parents('.modal').has('#event_form')) {
        $('#event_form')[0].reset(); // 重置表单
        $('#event_id').val('0'); // 重置为零
    }
});

// 时间格式化
function formatDate(date = new Date(), fmt = 'yyyy-MM-dd HH:mm:ss') {
  date = (typeof date === 'number' || typeof date === 'string') ? new Date(date) : date;

  var o = {
    'M+': date.getMonth() + 1, // 月份
    'd+': date.getDate(), // 日
    'h+': date.getHours() % 12 === 0 ? 12 : date.getHours() % 12, // 小时
    'H+': date.getHours(), // 小时
    'm+': date.getMinutes(), // 分
    's+': date.getSeconds(), // 秒
    'q+': Math.floor((date.getMonth() + 3) / 3), // 季度
    'S': date.getMilliseconds() // 毫秒
  };
  var week = {
    '0': '\u65e5',
    '1': '\u4e00',
    '2': '\u4e8c',
    '3': '\u4e09',
    '4': '\u56db',
    '5': '\u4e94',
    '6': '\u516d'
  };

  if (/(y+)/.test(fmt)) {
    fmt = fmt.replace(RegExp.$1, (date.getFullYear() + '').substr(4 - RegExp.$1.length));
  }

  if (/(E+)/.test(fmt)) {
    fmt = fmt.replace(RegExp.$1, ((RegExp.$1.length > 1) ? (RegExp.$1.length > 2 ? '\u661f\u671f' : '\u5468') : '') + week[date.getDay() + '']);
  }

  for (var k in o) {
    if (new RegExp('(' + k + ')').test(fmt)) {
      fmt = fmt.replace(RegExp.$1, (RegExp.$1.length === 1) ? (o[k]) : (('00' + o[k]).substr(('' + o[k]).length)));
    }
  }

  return fmt;
}