实现效果如下图:
月视图
周视图
日视图
官方文档地址:Vue Component - Docs | FullCalendar
1、安装与FullCalendar相关的依赖项
npm install --save @fullcalendar/vue @fullcalendar/core @fullcalendar/daygrid @fullcalendar/timegrid @fullcalendar/list
npm install --save @fullcalendar/interaction
npm install --save @fullcalendar/core @fullcalendar/resource-timeline
2.使用日历的页面需要导入
import FullCalendar from "@fullcalendar/vue";
import dayGridPlugin from "@fullcalendar/daygrid";
import timeGridPlugin from "@fullcalendar/timegrid";
import listPlugin from "@fullcalendar/list";
import interactionPlugin from "@fullcalendar/interaction";
// import resourceTimelinePlugin from "@fullcalendar/resource-timeline";
完整代码
<template>
<div>
<div class="fc-toolbar">
<div class="fc-left">
<el-button-group>
<el-button @click="month"> 月 </el-button>
<el-button @click="week"> 周 </el-button>
<el-button @click="today"> 今天 </el-button>
</el-button-group>
</div>
<div class="fc-center">
<el-button icon="el-icon-arrow-left" @click="prev"/>
<p class="title">
{{ title }}
</p>
<el-button icon="el-icon-arrow-right" @click="next" />
</div>
<div>
<el-select v-model="type" style="margin-right: 20px" @change="handleType">
<el-option v-for="item in options" :key="item.value" :label="item.label" :value="item.value" />
</el-select>
<el-button class="search" style="margin-right: 20px" type="button" @click="addEvent">
新增
</el-button>
<el-button class="search" type="button" @click="search">
查询
</el-button>
</div>
</div>
<el-dialog title="添加日程" :visible.sync="dialogFormVisible" width="600px">
<el-form :model="form">
<el-form-item label="事件">
<el-input v-model="form.content" autocomplete="off" placeholder="请输入事件"></el-input>
</el-form-item>
</el-form>
<div slot="footer" class="dialog-footer">
<el-button @click="dialogFormVisible = false">取 消</el-button>
<el-button type="primary" @click="navConfirm">确 定</el-button>
</div>
</el-dialog>
<div v-if="showFullcalendar">加载数据中......</div>
<FullCalendar v-else
id="calendar"
ref="fullCalendar"
class="demo-app-calendar"
:options="calendarOptions"
>
<template v-slot:eventContent="arg">
<el-popover placement="top-start" title="标题" width="200" :visible-arrow="false" trigger="click">
<i class="title">{{ arg.event.title }}</i>
<el-button @click="more(arg.event)"> 更多 </el-button>
<div slot="reference" class="popper-content">
<span>{{ arg.timeText }}</span>
<i>{{ arg.event.title }}</i>
</div>
</el-popover>
</template>
<template v-slot:dayCellContent="arg">
{{ arg.dayNumberText }}
</template>
<template v-slot:resourceLabelContent="arg">
{{ arg.resource.id }}
</template>
</FullCalendar>
</div>
</template>
<script>
import FullCalendar from "@fullcalendar/vue";
import dayGridPlugin from "@fullcalendar/daygrid";
import timeGridPlugin from "@fullcalendar/timegrid";
import listPlugin from "@fullcalendar/list";
import interactionPlugin from "@fullcalendar/interaction";
// import resourceTimelinePlugin from "@fullcalendar/resource-timeline";
let clickCount = 0;
let prev = ""; // 上一次点击的dom节点
export default {
components: {
FullCalendar, // make the <FullCalendar> tag available
},
data() {
return {
showFullcalendar: true,
title: "",
currentView: {},
options: [
{ value: "timeline", label: "resource-timeline" },
{ value: "dategrid", label: "agenda" },
],
type: "dategrid",
calendarOptions: {
locale: "zh",
timeZone: "UTC",
plugins: [
dayGridPlugin,
timeGridPlugin,
listPlugin,
// resourceTimelinePlugin,
interactionPlugin,
],
buttonText: {
// 设置按钮
today: "今天",
month: "月",
week: "周",
dayGrid: "天",
},
initialView: "dayGridMonth", // 设置默认显示月,可选周、日
resourceAreaWidth: 200,
contentHeight: 600,
slotMinWidth: 70,
resourceOrder: "number",
editable: true,
dayMaxEvents: true, // allow "more" link when too many events
eventDurationEditable: true, // 可以调整事件的时间
selectable: true, // 日历格子可选择
nowIndicator: true, // 现在的时间线显示
eventDisplay: "block", // 争对全天的情况下,以块状显示
headerToolbar: false, // 隐藏头部的导航栏
selectMirror: false,
displayEventEnd: true, // like 08:00 - 13:00
eventTimeFormat: {
// like '14:30:00'
hour: "2-digit",
minute: "2-digit",
meridiem: false,
hour12: false, // 设置时间为24小时
},
events: [],
eventColor: "#378006",
allDayText: "全天",
dateClick: this.handleDateClick, //点击日程事件
eventClick: this.handleEventClick, //点击日历中的某一日程
select:this.handleDateSelect, // 监听用户选择的时间段,
eventDrop:this.handleEventDrop, //监听事件被拖动的操作
eventResize:this.handleEventResize, //监听事件调整大小的操作
resourceAreaHeaderContent: "Rooms",
resources: [
{
id: "111",
title: "asas",
number: 1,
},
],
schedulerLicenseKey: "GPL-My-Project-Is-Open-Source",
resourceLabelContent(arg) {
return {
html: `<div>id: ${arg.resource.id}</div><div>title: ${arg.resource.title}</div>`,
};
},
views: {
customTimeLineWeek: {
type: "resourceTimeline",
duration: { weeks: 1 },
slotDuration: { days: 1 },
buttonText: "Custom Week",
slotLabelFormat: {
weekday: "long",
// month: 'numeric',
// day: 'numeric',
omitCommas: true,
},
},
customTimeLineMonth: {
type: "resourceTimeline",
duration: { month: 1 },
slotLabelFormat: {
// month: 'numeric',
day: "numeric",
// omitCommas: true,
},
},
customGridWeek: {
type: "timeGridWeek",
dayHeaderFormat: {
weekday: "long",
},
slotLabelFormat: {
// 左侧时间格式
hour: "2-digit",
minute: "2-digit",
meridiem: "lowercase",
hour12: false, // false设置时间为24小时
},
},
},
// 切换视图调用的方法
datesSet() { },
},
calendarApi: null,
monthEvent: [
{
id: "1",
resourceId: "1",
title: "待办",
start: "2024-01-04 09:00",
end: "2024-01-04 18:00",
color: "red",
},
{
resourceId: "2",
id: "2",
title: "待办",
start: "2024-01-15",
color: "purple",
},
{ title: "待办", start: "2024-01-09" },
{ title: "待办", start: "2024-01-17" },
{ title: "待办", start: "2024-01-07" },
{ title: "待办", start: "2024-01-07", color: "pink" },
{ title: "待办", start: "2024-01-07" },
{ title: "待办", start: "2024-01-07" },
{
id: "3",
resourceId: "number_3",
title: "待办",
start: "20240111",
end: "20240113",
color: "blue",
extendedProps: {
description: "测试测试测试测试",
},
},
{
id: 4,
title: "待办",
start: "2024-01-15",
extendedProps: {
description: "test test test test test",
},
},
],
weekEvent: [
{
id: "4",
resourceId: "4",
title: "周待办",
start: "2024-01-11",
color: "red",
},
{
id: "5",
resourceId: "5",
title: "待办1",
start: "2024-01-04 10:00",
end: "2024-01-04 18:00",
color: "orange",
},
],
dayDate:'',
dialogFormVisible:false,
form:{
content:'',
},
selectInfo:{},
};
},
mounted() {
setTimeout(() => {
this.showFullcalendar = false;
this.$nextTick(() => {
this.calendarApi = this.$refs.fullCalendar.getApi();
this.title = this.calendarApi.view.title;
this.getDtata();
});
}, 1000);
},
watch: {
// 切换视图显示不同的事件
"calendarApi.view.type"(newVal) {
this.getDtata();
},
},
methods: {
// 监听用户选择的时间段,当用户选择了一段时间后会触发该回调,可以在这里处理创建新的日程。
handleDateSelect(selectInfo) {
console.log('selectInfo: ', selectInfo);
this.selectInfo = selectInfo;
this.form.content = '';
// 用户选择了一个日期范围时触发
this.dialogFormVisible = true;
},
// 用户拖动移动事件时触发
handleEventDrop(dropInfo) {
console.log('dropInfo: ', dropInfo);
const updatedEvent = { ...dropInfo.event };
updatedEvent.start = dropInfo.revertDuration ? dropInfo.oldEvent.start : dropInfo.event.start;
updatedEvent.end = dropInfo.event.end;
// 更新服务器上的事件或者重新排序你的事件数组
// 示例:this.updateEventOnServer(updatedEvent);
// 如果是在内存中维护事件,则更新本地数据
const index = this.events.findIndex(e => e.id === updatedEvent.id);
if (index !== -1) {
this.events.splice(index, 1, updatedEvent);
}
},
// 用户调整事件长度时触发
handleEventResize(resizeInfo) {
console.log('resizeInfo: ', resizeInfo);
const updatedEvent = { ...resizeInfo.event };
updatedEvent.end = resizeInfo.event.end;
// 同样更新服务器或本地数据
// 示例:this.updateEventOnServer(updatedEvent);
const index = this.events.findIndex(e => e.id === updatedEvent.id);
if (index !== -1) {
this.events.splice(index, 1, updatedEvent);
}
},
getDtata() {
setTimeout(() => {
this.calendarOptions.events =
this.calendarApi.view.type === "dayGridMonth"
? this.monthEvent
: this.weekEvent;
}, 200);
},
// 点击更多
more(e) {
console.log('more ', e)
},
//确认弹框按钮
navConfirm(){
this.dialogFormVisible = false;
if (this.form.content) {
this.calendarOptions.events.push({
title: this.form.content,
start: this.selectInfo.startStr,
end: this.selectInfo.endStr,
});
// 更新日历视图以显示新添加的事件
this.$refs.fullCalendar.getApi().addEvent({ //等同于 this.calendarApi.addEvent
title: this.form.content,
start: this.selectInfo.startStr,
end: this.selectInfo.endStr,
});
}
},
// 增加事件
addEvent() {
this.form.content = '';
this.dialogFormVisible = true;
// this.monthEvent
},
//点击日历中的某一日程
handleEventClick(clickInfo) {
console.log('clickInfo:', clickInfo);
// 用户点击事件时触发,用于编辑或删除事件
const event = clickInfo.event;
console.log('Clicked on:', event.title);
// 这里可以弹出模态框进行编辑或调用删除函数等操作
},
// 单击事件(日历中的某一天)
handleDateClick(e) {
this.dayDate = e.dateStr;
if (e.dateStr !== prev) {
clickCount = 0;
}
clickCount += 1;
prev = e.dateStr;
setTimeout(() => {
if (clickCount === 2) {
console.log("db click");
} else if (clickCount === 1) {
console.log("one click");
}
clickCount = 0;
}, 300);
},
// 切换
prev() {
this.calendarApi.prev();
this.title = this.calendarApi.view.title;
},
next() {
this.calendarApi.next();
this.title = this.calendarApi.view.title;
},
// 今天
today(date, jsEvent, view) {
// if (this.type === "timeline") {
// this.calendarApi.changeView("customTimeLineWeek");
// } else {
// this.calendarApi.changeView("customGridWeek");
// }
this.calendarApi.today();
this.title = this.calendarApi.view.title;
this.calendarApi.changeView("timeGridDay");
// this.calendarApi.today();
// this.title = this.calendarApi.view.title;
},
// 月
month() {
if (this.type === "timeline") {
this.calendarApi.changeView("customTimeLineMonth");
} else {
this.calendarApi.changeView("dayGridMonth");
}
this.calendarApi.today();
this.title = this.calendarApi.view.title;
},
// 周
week() {
if (this.type === "timeline") {
this.calendarApi.changeView("customTimeLineWeek");
} else {
this.calendarApi.changeView("customGridWeek");
}
this.calendarApi.today();
this.title = this.calendarApi.view.title;
},
// 天
day() {
this.calendarApi.today();
this.title = this.calendarApi.view.title;
},
// 查询
search() {
this.calendarApi.changeView("dayGrid", {
start: "2022-07-07",
end: "2022-07-09",
});
},
// 选择时间线、日程
handleType() {
if (this.type === "timeline") {
this.calendarApi.changeView("customTimeLineMonth");
this.calendarOptions.slotLabelFormat = null;
} else {
this.calendarApi.changeView("dayGridMonth");
}
},
},
};
</script>
<style scoped>
.demo-app {
display: flex;
min-height: 100%;
font-family: Arial, Helvetica Neue, Helvetica, sans-serif;
font-size: 14px;
}
.demo-app-sidebar {
width: 300px;
line-height: 1.5;
background: #eaf9ff;
border-right: 1px solid #d3e2e8;
}
.demo-app-sidebar-section {
padding: 2em;
}
.demo-app-main {
flex-grow: 1;
padding: 3em;
}
.fc {
/* the calendar root */
max-width: 1100px;
margin: 0 auto;
}
.fc-toolbar {
width: 100%;
margin: 30px auto;
display: flex;
flex: 1;
justify-content: space-around;
align-content: center;
}
.fc-center {
/* height: 40px; */
display: flex;
align-content: center;
}
.fc-center .title {
font-size: 16px;
padding: 0 15px;
font-weight: 700;
/* height: 40px; */
/* line-height: 40px; */
}
</style>