You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在FullCalendar v3中实现EaseMyTrip移动端日历的节假日展示

FullCalendar v3 实现节假日标注效果

需求说明

  • 在月视图顶部标题旁显示当月节假日总数
  • 有节假日的日期单元格上展示带数字的圆形徽章(1、2、3...)
  • 月视图底部添加节假日数字对应的名称说明栏

完整实现代码

HTML 代码

<link href="https://cdnjs.cloudflare.com/ajax/libs/fullcalendar/3.10.2/fullcalendar.min.css" rel="stylesheet"/>

<script src="https://code.jquery.com/jquery-3.6.0.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.29.4/moment.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/fullcalendar/3.10.2/fullcalendar.min.js"></script>

<div id="calendar"></div>

CSS 代码

.circle_dot {
    font-size: 9px;
    width: 12px;
    height: 12px;
    background: #FFE3A2;
    border-radius: 50%;
    color: #000;
    align-items: center;
    justify-content: center;
    font-weight: 500;
    position: absolute;
    top: 0px;
    opacity: 1;
    display: flex; /* 确保数字居中显示 */
}

/* 底部节假日说明栏样式 */
.holiday-legend {
    padding: 10px;
    text-align: center;
    background: #f8f8f8;
    margin-top: 10px;
    border-radius: 4px;
}
.holiday-legend-item {
    display: inline-block;
    margin: 0 15px;
    font-size: 14px;
}
.holiday-legend-badge {
    display: inline-block;
    width: 12px;
    height: 12px;
    border-radius: 50%;
    background: #FFE3A2;
    margin-right: 5px;
    vertical-align: middle;
    text-align: center;
    font-size: 9px;
    line-height: 12px;
    color: #000;
}

JavaScript 代码

$(document).ready(function () {
    // 维护节假日数据:日期 => [{数字标识: 节假日名称}, ...]
    const holidayData = {
        "2023-06-11": [{num: 1, name: "端午节"}],
        "2023-06-12": [{num: 2, name: "父亲节"}],
        "2023-06-20": [{num: 3, name: "夏至"}]
    };

    // 计算指定月份的节假日总数
    function getMonthHolidayCount(year, month) {
        let count = 0;
        Object.keys(holidayData).forEach(dateStr => {
            const date = moment(dateStr);
            if (date.year() === year && date.month() === month) {
                count += holidayData[dateStr].length;
            }
        });
        return count;
    }

    // 生成节假日徽章事件数组
    function generateHolidayEvents() {
        let events = [];
        Object.keys(holidayData).forEach(dateStr => {
            holidayData[dateStr].forEach(item => {
                events.push({
                    title: item.num.toString(),
                    start: dateStr,
                    className: 'circle_dot',
                    allDay: true,
                    holidayName: item.name // 自定义字段存储节假日名称
                });
            });
        });
        return events;
    }

    // 生成底部节假日说明栏HTML
    function generateLegendHtml() {
        let html = '<div class="holiday-legend">';
        let legendItems = [];
        Object.keys(holidayData).forEach(dateStr => {
            holidayData[dateStr].forEach(item => {
                legendItems.push(`<span class="holiday-legend-item"><span class="holiday-legend-badge">${item.num}</span>${item.name}</span>`);
            });
        });
        // 去重处理(避免重复展示相同数字的说明)
        const uniqueItems = [...new Set(legendItems)];
        html += uniqueItems.join('');
        html += '</div>';
        return html;
    }

    $('#calendar').fullCalendar({
        header: {
            left: 'today',
            center: 'title',
            right: 'prev,next'
        },
        views: {
            month: {
                titleFormat: function(date) {
                    const year = date.year();
                    const month = date.month();
                    const count = getMonthHolidayCount(year, month);
                    return `${date.format('MMM YYYY')} (节假日${count}个)`;
                }
            }
        },
        buttonText: {
            today: '今天',
            prev: '<',
            next: '>'
        },
        defaultDate: '2023-06-09',
        fixedWeekCount: false,
        showNonCurrentDates: false,
        navLinks: false,
        editable: false,
        eventLimit: false,
        selectable: true,
        selectHelper: true,
        dayClick: function(date) {
            alert(date.format('YYYY-MM-DD'));
        },
        eventClick: function(calEvent) {
            if (calEvent.holidayName) {
                alert(calEvent.holidayName);
            }
        },
        eventSources: [
            // 原有业务状态事件
            {
                events: [
                    {title: 'FULL', start: '2023-06-11', color: '#e66d1d'},
                    {title: 'AVAILABLE', start: '2023-06-12', color: '#257e4a', textColor: '#ffffff'},
                    {title: 'FULL', start: '2023-06-23', color: '#e66d1d'},
                    {title: 'AVAILABLE', start: '2023-06-28'}
                ]
            },
            // 节假日徽章事件
            {
                events: generateHolidayEvents()
            }
        ],
        // 月视图渲染完成后添加底部说明栏
        viewRender: function(view, element) {
            if (view.name === 'month') {
                $('.holiday-legend').remove();
                $(element).after(generateLegendHtml());
            }
        }
    });
});

实现逻辑说明

  1. 顶部节假日总数:通过月视图的titleFormat函数,实时计算当前视图月份的节假日数量并追加到标题中。
  2. 日期数字徽章:将节假日数据转换为FullCalendar事件,使用自定义circle_dot类实现圆形数字徽章样式,同时通过自定义字段holidayName存储节假日名称。
  3. 底部说明栏:在viewRender钩子中,当月视图渲染完成后生成并插入说明栏,确保数字与节假日名称一一对应,样式与徽章保持统一。

内容的提问来源于stack exchange,提问作者Nikhil

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.19 22:32:06