基于 Vue3 + FullCalendar 实现融合农历与节日的多功能日历
·
在现代 Web应用开发中,日历组件是一个非常常见的功能模块。无论是日程管理、预约系统还是活动安排,都离不开一个直观易用的日历界面。本文将介绍如何使用Vue3 结合 FullCalendar 和农历库,打造一个既支持公历又能显示农历、节气和节日的多功能日历组件。
1. 实现效果
- 支持多月份年度视图展示
- 同时显示公历日期和农历信息
- 自动标记传统节日和法定节假日
- 显示二十四节气
- 支持年份切换和快速回到当前年份
- 节假日特殊样式显示
日历效果
2. 核心技术栈
- Vue3 + Vite:前端框架和构建工具
- FullCalendar:功能强大的 JavaScript 日历
- @fullcalendar/multimonth:FullCalendar 的多月份视图插件
- lunar-javascript:农历转换库,用于获取农历日期、节气和节日
- Element Plus:提供选择器组件
- Less:CSS预处理器,用于样式定制
3. 功能实现详解
3.1 环境准备与依赖安装
fullcalendar官网: https://fullcalendar.io/
element-plus官网:https://element-plus.org/
npm install @fullcalendar/core
npm install @fullcalendar/multimonth
npm install lunar-javascript
npm install element-plus
3.2 组件结构设计
- 年份选择器:用于快速切换日历年份
- 日历主体:使用 FullCalendar 实现的核心日历展示
- 样式定制:美化日历显示效果
3.3 核心功能实现
<script setup>
import { ref,onMounted,watch } from 'vue'
import { Calendar } from '@fullcalendar/core'
import multiMonthPlugin from '@fullcalendar/multimonth'
import { Solar } from "lunar-javascript";
const selectYear = ref('')
const options = [
{
value: '2025',
label: '2025',
},
{
value: '2024',
label: '2024',
},
{
value: '2023',
label: '2023',
},
{
value: '2022',
label: '2022',
},
{
value: '2021',
label: '2021',
},
{
value: '2020',
label: '2020',
},
]
const calendar = ref(null)
// 公历节日:只保留中国法定的
const chinaSolarHolidays = {
"01-01": "元旦",
"05-01": "劳动节",
"10-01": "国庆节",
};
const calendarOptions = ref({
plugins: [multiMonthPlugin],
initialView: 'multiMonthYear',
locale: 'zh-cn', // 中文
headerToolbar: {
left: '',
center: 'title',
right: 'prev,next today',
},
buttonText: {
today: '今天',
day: '日',
week: '周',
month: '月'
},
slotMinTime: '00:00:00',
slotMaxTime: '23:59:00',
customButtons: {
prev: {
text: '前一年',
click: () => switchYear(-1)
},
next: {
text: '后一年',
click: () => switchYear(1)
},
today: {
text: '今年',
click: () => {
const thisYear = new Date().getFullYear()
selectYear.value = thisYear.toString()
calendar.value.gotoDate(new Date(thisYear, 0, 1))
}
}
},
dayCellContent: (arg) => {
const date = arg.date;
const dayNumber = date.getDate();
// 阳历 & 农历
const solar = Solar.fromDate(date);
const lunar = solar.getLunar();
// 1. 农历日期(初一、十五…)
const lunarDay = lunar.getDayInChinese();
const lunarMonth = lunar.getMonthInChinese(); // 正月、二月…
// 2. 节气
const term = lunar.getJieQi(); // 例如 "清明"
// 3. 农历节日(春节、端午、中秋…)
const lunarFestivals = lunar.getFestivals();
// 4. 公历节日(只挑中国法定)
const solarKey =
String(solar.getMonth()).padStart(2, "0") +
"-" +
String(solar.getDay()).padStart(2, "0");
const solarHoliday = chinaSolarHolidays[solarKey] || "";
// 5. 优先级:节日 > 节气 > 农历月份(初一) > 农历日
let displayText = lunarDay;
if (lunarFestivals.length > 0) {
displayText = lunarFestivals[0];
} else if (solarHoliday) {
displayText = solarHoliday;
} else if (term) {
displayText = term;
} else if (lunarDay === "初一") {
displayText = lunarMonth + '月'; // 正月、二月…
}
const isHoliday = lunarFestivals.length > 0 || !!solarHoliday;
return {
html: `
<div class="fc-daygrid-day-number">${dayNumber}</div>
<div class="fc-daygrid-lunar ${isHoliday ? "holiday" : ""}">
${displayText}
</div>
`,
};
},
})
// 下拉选择年份监听
watch(selectYear, (newYear) => {
if (calendar.value) {
calendar.value.gotoDate(new Date(parseInt(newYear), 0, 1))
}
})
onMounted(() => {
initCalendar()
})
// 初始化日历
function initCalendar() {
let calendarEl = document.getElementById('calendar');
calendar.value = new Calendar(calendarEl, calendarOptions.value)
calendar.value.render()
}
// 添加年份切换函数
function switchYear(diff) {
const currentYear = parseInt(selectYear.value || new Date().getFullYear())
const newYear = currentYear + diff
selectYear.value = newYear.toString()
// 跳转日历到新年份
if (calendar.value) {
calendar.value.gotoDate(new Date(newYear, 0, 1)) // 1 月 1 日
}
}
</script>
<template>
<div class="select-year">
<el-select v-model="selectYear" placeholder="Select" style="width: 240px" clearable>
<el-option
v-for="item in options"
:key="item.value"
:label="item.label"
:value="item.value"
/>
</el-select>
</div>
<div class="calendar-wrapper">
<div id="calendar"></div>
</div>
</template>
<style scoped lang="less">
.calendar-wrapper /deep/ .fc .fc-daygrid-day-top {
justify-content: center;
}
.calendar-wrapper /deep/ .fc .fc-daygrid-day-number {
text-align: center;
}
.calendar-wrapper /deep/.fc-daygrid-lunar {
font-size: 12px;
color: #666;
}
.calendar-wrapper /deep/.fc-daygrid-lunar.holiday {
color: red;
font-weight: bold;
}
</style>
更多推荐

所有评论(0)