实现效果图
框架:vue3+FullcalendaV6版本 官方地址
插件安装
npm i @fullcalendar/core @fullcalendar/daygrid @fullcalendar/timegrid @fullcalendar/list @fullcalendar/interaction
其他工具依赖 dayjs
npm i dayjs
插件引入
import { Calendar } from '@fullcalendar/core';
import dayGridPlugin from '@fullcalendar/daygrid';
import timeGridPlugin from '@fullcalendar/timegrid';
import listPlugin from '@fullcalendar/list';
import interactionPlugin from '@fullcalendar/interaction';
import dayjs from 'dayjs';
完整代码(直接复制就能看到效果)
<template>
<div class="container">
<a-card class="general-card">
<div class="top-button">
<a-space>
<a-typography-title :heading="6">
{{ currentData }}
</a-typography-title>
<a-space>
<a-button
@click="
Tcalendar.prev();
dayTime();
"
><icon-left
/></a-button>
<a-button
@click="
Tcalendar.next();
dayTime();
"
>
<icon-right
/></a-button>
<a-button
type="primary"
@click="
Tcalendar.today();
dayTime();
"
>今天</a-button
>
</a-space>
</a-space>
<a-radio-group v-model="type" type="button" @change="changeType">
<a-radio value="dayGridMonth">月</a-radio>
<a-radio value="timeGridWeek">周</a-radio>
<a-radio value="timeGridDay">天</a-radio>
<a-radio value="listWeek">列</a-radio>
</a-radio-group>
</div>
<div ref="fullcalendar" class="card"> </div>
</a-card>
<!-- 详情抽屉 -->
<a-drawer
:width="480"
:visible="visible"
@ok="handleOk"
@cancel="visible = false"
title="面试详情"
>
<template #title> </template>
<div
>You can customize modal body text by the current situation. This modal
will be closed immediately once you press the OK button.
</div>
</a-drawer>
</div>
</template>
<script setup lang="ts">
import { ref, nextTick, onMounted } from 'vue';
import { Calendar } from '@fullcalendar/core';
import dayGridPlugin from '@fullcalendar/daygrid';
import timeGridPlugin from '@fullcalendar/timegrid';
import listPlugin from '@fullcalendar/list';
import interactionPlugin from '@fullcalendar/interaction';
import dayjs from 'dayjs';
const state = {
infoList: [
{
id: '1',
title: '第一个任务12312312312312312',
name: '小李',
start: '2024-04-01 13:00:00',
end: '2024-04-01 13:30:00',
class: 'tag_1',
job: '产品经理',
hr: '唐老鸭',
},
{
id: '2',
title: '第一个任务12312312312312312',
name: '小李',
start: '2024-04-01 13:30:00',
end: '2024-04-01 14:00:00',
class: 'tag_1',
job: '产品经理',
hr: '唐老鸭',
},
],
Tcalendar: ref(),
};
const fullcalendar = ref();
const Tcalendar = ref();
const type = ref('dayGridMonth');
const currentData = ref();
const visible = ref(false);
const initCalendar = () => {
Tcalendar.value = new Calendar(fullcalendar.value, {
plugins: [dayGridPlugin, timeGridPlugin, listPlugin, interactionPlugin],
initialView: type.value,
aspectRatio: 2.2,
locale: 'zh-cn',
handleWindowResize: true,
// loading: loading //控制表格加载
editable: false, // 允许编辑表格
droppable: false, //允许从外部拖拽进入日历
eventDurationEditable: false, //控制时间段是否可以拖动
eventResizableFromStart: false, //控制事件是否可以拖动
selectable: false, // 允许用户通过单击和拖动来突出显示多个日期或时间段
firstDay: 1, // 设置一周中显示的第一天是哪天,周日是0,周一是1,类推。
unselectAuto: true, // 当点击页面日历以外的位置时,是否自动取消当前的选中状态
dayMaxEvents: true, //在dayGrid视图中,给定日期内的最大事件数
headerToolbar: false, // 关闭默认日历头部,采取自定义的方式切换日历视图
allDaySlot: false,
nowIndicator: true,
eventMaxStack: 2,
events: state.infoList, //主要数据
slotMinTime: '09:00:00', //时间最大范围
slotMaxTime: '21:00:00', //时间最小范围
slotDuration: '00:15:00', //时间间段
slotLabelFormat: {
hour: '2-digit',
minute: '2-digit',
omitZeroMinute: false,
meridiem: 'short',
},
eventClassNames: function (arg) {
// 添加自定义class
return [arg.event.extendedProps.class];
},
eventContent: function (arg) {
// 日历上event显示的样式
const italicEl = document.createElement('div');
// 列表才显示
if (type.value === 'listWeek') {
// 标题
const nameEl = document.createElement('h4');
nameEl.setAttribute('class', `h4`);
nameEl.innerHTML = arg.event.extendedProps.name;
italicEl.append(nameEl);
// 岗位
const text1El = document.createElement('p');
text1El.innerHTML = arg.event.extendedProps.job;
italicEl.append(text1El);
// 面试官
const text2El = document.createElement('p');
text2El.innerHTML = '面试官:' + arg.event.extendedProps.job;
italicEl.append(text2El);
} else {
// 标题
const titleEl = document.createElement('div');
titleEl.setAttribute('class', `plan_title`);
const nameEl = document.createElement('h5');
nameEl.innerHTML = arg.event.extendedProps.name;
titleEl.append(nameEl);
// 时间
const timeEl = document.createElement('span');
timeEl.innerHTML =
dayjs(arg.event.start).format('HH:mm') +
'-' +
dayjs(arg.event.end).format('HH:mm');
titleEl.append(timeEl);
italicEl.append(titleEl);
}
italicEl.setAttribute('class', `plan_card`);
return { domNodes: [italicEl] };
},
noEventsContent: function () {
const noEl = document.createElement('div');
noEl.innerHTML = '暂无日程安排,请安排相关日程';
return { domNodes: [noEl] };
},
// 点击查看时触发
eventClick: function (info) {
handleClick(info);
},
// 视图选择日期触发
// select: function (info) {
// handleSelectDate(info);
// },
// }
// 拖拽event大小时触发
// eventResize: function (info) {
// handleEventResize(info);
// },
// 拖拽停止时触发
// eventDrop: function(info) {
// handleDrap(info)
// },
});
Tcalendar.value.render();
};
// 切换类型
const changeType = (type: any) => {
Tcalendar.value.changeView(type);
dayTime();
};
const dayTime = () => {
if (type.value === 'dayGridMonth') {
currentData.value = dayjs(Tcalendar.value.getDate()).format('YYYY年MM月');
} else if (type.value === 'timeGridWeek' || type.value === 'listWeek') {
currentData.value =
dayjs(Tcalendar.value.getDate()).format('YYYY年MM月DD日') +
' - ' +
dayjs(Tcalendar.value.getDate()).add(6, 'day').format('DD日');
} else if (type.value === 'timeGridDay') {
currentData.value = dayjs(Tcalendar.value.getDate()).format(
'YYYY年MM月DD日'
);
}
};
const handleClick = (info) => {
visible.value = true;
};
const handleOk = () => {};
onMounted(() => {
nextTick(() => {
initCalendar();
dayTime();
});
});
</script>
<style lang="less">
.card {
width: 100%;
height: 600px;
margin-top: 20px;
}
.top-button {
display: flex;
justify-content: space-between;
}
.fc-col-header-cell {
height: 26px;
line-height: 26px;
background-color: var(--color-neutral-2);
}
.fc-v-event {
border: none;
box-shadow: 0 4px 10px rgb(var(--gray-2)) !important;
}
.fc-event {
cursor: pointer;
}
.tag_1 {
background-color: rgb(var(--danger-1));
border-left: 3px solid rgb(var(--danger-6));
padding-left: 4px;
.fc-daygrid-event-dot {
display: none;
}
.fc-event-time {
color: rgb(var(--danger-6));
}
.fc-event-title {
color: var(--color-text-1);
font-weight: 400;
}
}
.tag_2 {
background-color: rgb(var(--success-1));
border-left: 3px solid rgb(var(--success-6));
padding-left: 4px;
.fc-daygrid-event-dot {
display: none;
}
.fc-event-time {
color: rgb(var(--success-6));
}
.fc-event-title {
color: var(--color-text-1);
font-weight: 400;
}
}
.tag_3 {
background-color: rgb(var(--warning-1));
border-left: 3px solid rgb(var(--warning-6));
padding-left: 4px;
.fc-daygrid-event-dot {
display: none;
}
.fc-event-time {
color: rgb(var(--warning-6));
}
.fc-event-title {
color: var(--color-text-1);
font-weight: 400;
}
}
.tag_4 {
background-color: rgb(var(--primary-1));
border-left: 3px solid rgb(var(--primary-6));
padding-left: 4px;
.fc-daygrid-event-dot {
display: none;
}
.fc-event-time {
color: rgb(var(--primary-6));
}
.fc-event-title {
color: var(--color-text-1);
font-weight: 400;
}
}
:root {
--fc-border-color: rgb(229, 230, 235) !important;
--fc-today-bg-color: rgb(232, 243, 255) !important;
--fc-more-link-bg-color: rgb(232, 243, 255);
}
.fc .fc-daygrid-day-top {
flex-direction: column;
}
.fc-list-event-dot {
display: none !important;
}
.fc-timegrid-event-harness > .fc-timegrid-event {
position: relative;
}
.plan_card {
width: 100%;
color: var(--color-text-2);
.plan_title {
display: flex;
width: 100%;
justify-content: space-between;
color: var(--color-text-1);
line-height: 22px;
padding-right: 4px;
span {
color: var(--color-text-2);
}
}
p {
line-height: 22px;
font-size: 12px;
}
}
.h4 {
color: var(--color-text-2);
line-height: 24px;
}
</style>
功能待完善 保留了拖拽事件触发 可以支持拖拽日期 拖拽添加日期事件
大家根据自身需求做出对应改动 👏欢迎各位同学自行讨论