一、引言
FullCalendar 是一个功能强大的 JavaScript 日历插件,它提供了丰富的功能和高度的可定制性,可以轻松地集成到各种 Web 应用程序中。本文将分享 FullCalendar 的基本用法、主要功能以及一些实际应用中的经验。
二、特点
(1)丰富的视图模式
FullCalendar 支持多种视图模式,包括月视图、周视图、日视图和列表视图等。用户可以根据自己的需求选择合适的视图来查看日程安排。
(2)事件管理
- 可以轻松地添加、编辑和删除事件。
- 支持设置事件的标题、描述、开始时间、结束时间等属性。
- 可以对事件进行分类和分组,方便用户管理和查看。
(3)可定制性强
- 可以通过 CSS 和 JavaScript 进行高度定制,包括颜色、字体、布局等方面。
- 支持自定义事件渲染器,允许用户根据自己的需求来显示事件。
(4)响应式设计
FullCalendar 具有良好的响应式设计,可以在不同尺寸的设备上良好地显示,包括桌面电脑、平板电脑和手机等。
三、基本用法
(1)安装 FullCalendar及月视图、周视图、日视图和列表视图插件
bash
npm install @fullcalendar/vue
npm install @fullcalendar/code
npm install @fullcalendar/daygrid
npm install @fullcalendar/timegrid
npm install @fullcalendar/interaction
npm install @fullcalendar/list
// npm install @fullcalendar/resource-timeline
(2)在页面中引入
javascript
import FullCalendar from '@fullcalendar/vue'
import dayGridPlugin from '@fullcalendar/daygrid'
import timeGridPlugin from '@fullcalendar/timegrid'
import interactionPlugin from '@fullcalendar/interaction'
import listPlugin from '@fullcalendar/list'
(3)应用
ini
<full-calendar
ref="fullCalendar"
style="height: 100%"
:options="calendarOptions" // 参数
>
</full-calendar>
kotlin
data() {
return {
calendarOptions: {
height: 780,
contentHeight: 800,
aspectRatio: 2, // 设置日历单元格宽度与高度的比例。感觉没啥用
handleWindowResize: true,
axisFormat: 'h(:mm)tt',
firstHour: 0,
plugins: [dayGridPlugin, timeGridPlugin, interactionPlugin, listPlugin],
headerToolbar: { // 设置表头
left: '',
center: 'title',
right: 'timeGridWeek,dayGridMonth'
},
buttonText: {
// 设置按钮
// today: '今天',
month: '月',
week: '周'
// dayGrid: '天'
},
// allDaySlot: false, // 是否需要全天一栏
editable: true,
selectable: true,
navLinks: true,
// displayEventEnd: true,//所有视图显示结束时间
initialView: 'timeGridWeek', // 设置默认显示周日历,可选月、日
eventDurationEditable: true, // 可以调整事件的时间
dateClick: this.handleDateClick,
eventClick: this.handleEventClick,
eventsSet: this.handleEvents,
select: this.handleDateSelect,
// 设置日程事件
events: [
{
id: 1,
title: '黄',
start: '2024-07-24 09:30:20',
end: '2024-07-25 15:30:10',
color: '#f08f00',
overlap: true,
editable: true
},
......
],
eventColor: '#f08f00', // 修改日程背景色
locale: 'zh-cn', // 设置语言
// weekNumberCalculation: 'ISO', // 周数
initialDate: this.$moment().format('YYYY-MM-DD HH:mm:ss'),
// 日历触发拖拽的钩子
drop: this.newEventDrop,
droppable: true,
displayEventTime: false, // 不显示日程时间,只显示title
eventMouseout: this.handleMouseLeave,
// eventClick: this.handleEventClick, // 日程事件点击
eventDrop: this.handleEventDrop, // 拖动事件
allDaySlot: false, // 不显示all-day那一行
firstDay: 0,
customButtons: {},
minTime: '00:00',
scrollTime: '00:00',
// 时间轴间距
slotMinTime: '00:00',
slotMaxTime: '24:00',
slotEventOverlap: false,
timeFormat: 'H:mmtt{-H:mmtt }'
}
}
},
效果图:
四、根据需求定制化
(1)表头定制化
1、左边显示日历日期,中间空白不显示,右边显示切换日历按钮
kotlin
headerToolbar: {
left: 'title',
center: '',
right: 'timeGridWeek,dayGridMonth'
},
buttonText: {
// 设置按钮
// today: '今天',
month: '月',
week: '周'
// dayGrid: '天'
},
customButtons: {
dayGridMonth: {
text: '月',
click: (data) => {
console.log(data)
this.$refs.fullCalendar.getApi().changeView('dayGridMonth')
this.dateType = 'month'
}
},
timeGridWeek: {
text: '周',
click: (data) => {
console.log(data)
this.$refs.fullCalendar.getApi().changeView('timeGridWeek')
this.dateType = 'week'
}
}
},
2、调整样式
css
::v-deep .fc-header-toolbar {
margin-bottom: 12px;
.fc-toolbar-title {
font-size: 16px;
font-weight: 700;
line-height: 28px;
color: #333;
margin-left: 10px;
}
}
::v-deep .fc-button {
height: 28px;
font-size: 14px;
display: flex;
align-items: center;
border: 1px solid rgb(45, 140, 240);
border-radius: 2px;
background: rgba(45, 140, 240, 0.1);
color: #2d8cf0;
box-shadow: none !important;
&:hover {
border: 1px solid rgb(45, 140, 240) !important;
border-radius: 2px;
background: rgb(45, 140, 240) !important;
color: #fff;
}
}
::v-deep .fc-button-active {
border: 1px solid rgb(45, 140, 240) !important;
border-radius: 2px;
background: rgb(45, 140, 240) !important;
}
(2)周日历定制化
1、自定义顶部日期
在参数calendarOptions中添加views
kotlin
views: {
timeGridWeek: { // 周日历
dayHeaderContent(item) {
// 自定义表头,高亮显示当天日期
return {
html: `<div class="day-header"><div class="day ${
item.isToday ? 'today' : ''
}">${item.date.getDate()}</div><div class="week">星期${
item.text?.split('周')[1]
}</div></div>`
}
}
// eventMaxStack: 4 // 同一时段最多展示事件数
// moreLinkClick: 'week',
// moreLinkClick: this.moreLinkClick,
}
}
css
// 周视图
.day-header {
display: flex;
align-items: center;
color: #333;
.day {
color: rgb(51, 51, 51);
font-size: 28px;
}
.week {
color: rgb(153, 153, 153);
line-height: 21px;
letter-spacing: 1px;
margin-left: 8px;
font-size: 14px;
}
.today {
display: flex;
justify-content: center;
align-items: center;
width: 32px;
height: 32px;
border-radius: 50%;
background-color: #2d8cf0;
color: #fff;
font-size: 18px;
}
}
2、调整左侧时间轴样式
arduino
// 添加参数
scrollTime: '00:00', // 默认从00:00开始显示、滚动
slotDuration: '01:00', // 时间间隔
slotEventOverlap: false, // 重叠时间段不覆盖
3、自定义日程事件样式
需要与后台接口联调,获取当前周的日程数据,根据岗位颜色显示排班颜色
csharp
// 查询值班信息
async getScheduleInfo() {
const url = `/api/xxx`
const params = {
dateType: this.dateType,
scheduleDate: this.currentDate
}
const res = await this.$http.get(url, { params })
if (res.successful) {
this.calendarOptions.events = res?.data.map((item) => ({
...item,
title: item.userName, // 标题
start: item.scheduleStartTime, // 开始时间
end: item.scheduleEndTime, // 结束时间
color: item.postColor || '#999999', // 颜色
textColor: item.postColor || '#999999', // 字体颜色
visible: false, // 是否弹出详情弹框
overlap: false,
editable: false
}))
} else {
this.$message.error(res.msg, 5)
}
},
perl
<full-calendar ref="fullCalendar" :options="calendarOptions">
<template v-slot:eventContent="arg">
<div
class="event-content text-ellipsis"
:style="
arg.view.type === 'timeGridWeek'
? {
borderTop: `2px solid ${arg.event.borderColor}`,
borderColor: arg.event.borderColor,
backgroundColor: `${hexToRgba(arg.event.borderColor, 0.1)}`
}
: {
borderLeft: `2px solid ${arg.event.borderColor}`,
backgroundColor: `${hexToRgba(arg.event.borderColor, 0.1)}`,
color: arg.event.borderColor
}
"
:title="
arg.view.type === 'timeGridWeek'
? arg.event.title
: `${$moment(arg.event.start).format('HH:mm')}~${$moment(arg.event.end).format(
'HH:mm'
)} ${arg.event.title}`
"
>
{{
arg.view.type === 'timeGridWeek'
? arg.event.title
: `${$moment(arg.event.start).format('HH:mm')}~${$moment(arg.event.end).format(
'HH:mm'
)} ${arg.event.title}`
}}
</div>
</template>
</full-calendar>
css
.event-content {
width: 100%;
height: 100%;
text-align: center;
padding-top: 3px;
}
4、点击日程事件弹出详情弹框
在参数中定义点击事件
kotlin
eventClick: this.handleEventClick, // 日程事件点击
实现点击事件方法
javascript
handleEventClick(e) {
const result = this.calendarOptions.events.map((item) => {
return {
...item,
visible: item.id === e.event.id // 将当前日程的visible设置为true
}
})
this.calendarOptions.events = result
},
定义日程事件的详情弹框
ini
<full-calendar ref="fullCalendar" :options="calendarOptions">
<template v-slot:eventContent="arg">
<div
class="event-content text-ellipsis"
:style="
arg.view.type === 'timeGridWeek'
? {
borderTop: `2px solid ${arg.event.borderColor}`,
borderColor: arg.event.borderColor,
backgroundColor: `${hexToRgba(arg.event.borderColor, 0.1)}`
}
: {
borderLeft: `2px solid ${arg.event.borderColor}`,
backgroundColor: `${hexToRgba(arg.event.borderColor, 0.1)}`,
color: arg.event.borderColor
}
"
:title="
arg.view.type === 'timeGridWeek'
? arg.event.title
: `${$moment(arg.event.start).format('HH:mm')}~${$moment(arg.event.end).format(
'HH:mm'
)} ${arg.event.title}`
"
>
{{
arg.view.type === 'timeGridWeek'
? arg.event.title
: `${$moment(arg.event.start).format('HH:mm')}~${$moment(arg.event.end).format(
'HH:mm'
)} ${arg.event.title}`
}}
</div>
<a-popover
title=""
v-model="arg.event.extendedProps.visible"
:zIndex="100"
placement="bottom"
>
<template slot="content">
<popper :dataInfo="arg.event" @success="handleSuccess"></popper>
</template>
</a-popover>
</template>
</full-calendar>
import Popper from './Modal/Popper.vue'
Popper.vue
xml
<template>
<div id="popper" ref="popper" class="popper-container">
<div class="container-item">
<div class="label">值班时间</div>
<div class="content">
{{ dataInfo?.extendedProps?.scheduleDate }} {{ $moment(dataInfo.start).format('HH:mm') }} ~
{{ $moment(dataInfo.end).format('HH:mm') }}
</div>
</div>
<div class="container-item user-info">
<div class="label">值班人员</div>
<div class="content">{{ dataInfo.extendedProps.postName || '-' }}:{{ dataInfo.title }}</div>
</div>
<div
class="footer"
v-if="
dataInfo.extendedProps.scheduleDate > $moment().format('YYYY-MM-DD') && dutyLevel === '1'
"
>
<a-divider />
<a-popconfirm title="确定删除?" @confirm="handleDelete">
<a><a-icon type="delete" /></a>
</a-popconfirm>
</div>
</div>
</template>
<script>
import Cookies from 'js-cookie'
export default {
name: 'Popper',
props: {
dataInfo: {
type: Object,
required: false,
default: () => {}
}
},
data() {
return {
dutyLevel: Cookies.get('dutyLevel')
}
},
methods: {
async handleDelete() {
const url = `/api/xxx`
const params = {
scheduleIdList: [this.dataInfo?.id]
}
const res = await this.$http.post(url, params)
if (res.successful) {
this.$message.success('删除成功', 5)
this.$emit('success')
} else {
this.$message.error(res.msg, 5)
}
}
}
}
</script>
<style lang="scss" scoped>
::v-deep .ant-divider {
margin: 12px 0 !important;
}
.popper-container {
background: #fff;
border-radius: 4px;
width: 207px;
.container-item {
.label {
color: rgb(153, 153, 153);
font-size: 14px;
line-height: 21px;
letter-spacing: 1px;
}
.content {
color: rgb(51, 51, 51);
font-size: 14px;
line-height: 21px;
letter-spacing: 1px;
}
}
.user-info {
margin-top: 15px;
}
.footer {
text-align: center;
}
.anticon-delete {
color: red;
}
}
</style>
点击其他任意地方关闭详情弹框
javascript
// 关闭排班气泡弹框
handleEventVisible() {
const result = this.calendarOptions.events.map((item) => {
return {
...item,
visible: false
}
})
this.calendarOptions.events = result
}
(3)月日历定制化
1、自定义顶部星期
在参数views中添加月视图dayGridMonth
javascript
views: {
// 月视图阳历转农历
dayGridMonth: {
displayEventTime: true, // 是否显示时间
dayHeaderContent(item) {
// 自定义表头
return {
html: `<div class="day-header">星期${item.text?.split('周')[1]}</div>`
}
}
},
}
2、自定义日期单元格
重写dayCellContent,添加农历日期,使用插件js-calendar-converter的solar2lunar方法将日期转为农历日期,并且高亮显示当天日期
kotlin
views: {
// 月视图阳历转农历
dayGridMonth: {
dayCellContent: (item) => {
const year = this.$moment(item.date).format('YYYY')
const month = this.$moment(item.date).format('MM')
const day = this.$moment(item.date).format('DD')
const newDate = calendarConverter.solar2lunar(year, month, day)
return {
html: `<div class="month-date"><div class="cDay">${newDate.cDay}</div><div class="lunar">${newDate.IDayCn}</div></div>`
}
},
},
}
css
.fc-daygrid-day-number {
width: 100%;
.month-date {
width: 100%;
display: flex;
justify-content: space-between;
.lunar {
color: #999999;
}
}
}
3、自定义日程事件样式
通过判断当前日历的类型是周日历(timeGridWeek)还是月日历(dayGridMonth)来分别定制样式,日程事件详情弹框与周日历一样
ini
<full-calendar ref="fullCalendar" :options="calendarOptions">
<template v-slot:eventContent="arg">
<div
class="event-content text-ellipsis"
:style="
arg.view.type === 'timeGridWeek'
? {
borderTop: `2px solid ${arg.event.borderColor}`,
borderColor: arg.event.borderColor,
backgroundColor: `${hexToRgba(arg.event.borderColor, 0.1)}`
}
: {
borderLeft: `2px solid ${arg.event.borderColor}`,
backgroundColor: `${hexToRgba(arg.event.borderColor, 0.1)}`,
color: arg.event.borderColor
}
"
:title="
arg.view.type === 'timeGridWeek'
? arg.event.title
: `${$moment(arg.event.start).format('HH:mm')}~${$moment(arg.event.end).format(
'HH:mm'
)} ${arg.event.title}`
"
>
{{
arg.view.type === 'timeGridWeek'
? arg.event.title
: `${$moment(arg.event.start).format('HH:mm')}~${$moment(arg.event.end).format(
'HH:mm'
)} ${arg.event.title}`
}}
</div>
<a-popover
title=""
v-model="arg.event.extendedProps.visible"
:zIndex="100"
placement="bottom"
>
<template slot="content">
<popper :dataInfo="arg.event" @success="handleSuccess"></popper>
</template>
</a-popover>
</template>
</full-calendar>
4、点击当前日期弹框显示当前日期所有日程事件
在参数中定义日期点击事件
kotlin
dateClick: this.handleDateClick,
ini
handleDateClick(e) {
if (e.view.type === 'dayGridMonth') {
const dateList = this.calendarOptions.events.filter(
(item) => item.scheduleDate === e?.dateStr
)
if (dateList && dateList?.length > 0) {
this.$refs.eventModalRef.visible = true
this.$refs.eventModalRef.scheduleDate = e?.dateStr
this.$refs.eventModalRef.getScheduleList()
}
}
},
(4)数据更新
日历视图的日期跟随选择的日期跳转(这里用到了日历的gotoDate方法,跳转到指定日期范围),并且在切换日历视图的时候也进行更新
javascript
watch: {
currentDate: {
handler(newVal) {
if (newVal) {
const fullCalendar = this.$refs.fullCalendar.calendar
fullCalendar.gotoDate(newVal) // 日历视图跟随日期跳转
this.getScheduleInfo()
}
},
deep: true
// immediate: true
},
dateType: {
handler(newVal) {
if (newVal) {
this.getScheduleInfo()
}
}
}
},
五、完整代码
vue:
xml
<template>
<div class="full-calendar">
<full-calendar ref="fullCalendar" :options="calendarOptions">
<template v-slot:eventContent="arg">
<div
class="event-content text-ellipsis"
:style="
arg.view.type === 'timeGridWeek'
? {
borderTop: `2px solid ${arg.event.borderColor}`,
borderColor: arg.event.borderColor,
backgroundColor: `${hexToRgba(arg.event.borderColor, 0.1)}`
}
: {
borderLeft: `2px solid ${arg.event.borderColor}`,
backgroundColor: `${hexToRgba(arg.event.borderColor, 0.1)}`,
color: arg.event.borderColor
}
"
:title="
arg.view.type === 'timeGridWeek'
? arg.event.title
: `${$moment(arg.event.start).format('HH:mm')}~${$moment(arg.event.end).format(
'HH:mm'
)} ${arg.event.title}`
"
>
{{
arg.view.type === 'timeGridWeek'
? arg.event.title
: `${$moment(arg.event.start).format('HH:mm')}~${$moment(arg.event.end).format(
'HH:mm'
)} ${arg.event.title}`
}}
</div>
<a-popover
title=""
v-model="arg.event.extendedProps.visible"
:zIndex="100"
placement="bottom"
>
<template slot="content">
<popper :dataInfo="arg.event" @success="handleSuccess"></popper>
</template>
</a-popover>
</template>
</full-calendar>
<eventModal ref="eventModalRef" @success="handleSuccess" />
</div>
</template>
<script>
import calendarConverter from 'js-calendar-converter'
import FullCalendar from '@fullcalendar/vue'
import dayGridPlugin from '@fullcalendar/daygrid'
import timeGridPlugin from '@fullcalendar/timegrid'
import interactionPlugin from '@fullcalendar/interaction'
import listPlugin from '@fullcalendar/list'
// import resourceTimelinePlugin from '@fullcalendar/resource-timeline'
import dispatchPlan from '@/mixins/dispatch-plan'
import eventModal from './Modal/eventModal.vue'
import Popper from './Modal/Popper.vue'
export default {
name: 'Rota',
components: { FullCalendar, eventModal, Popper },
mixins: [dispatchPlan],
props: ['currentDate'],
data() {
return {
dateType: 'week',
calendarOptions: {
height: 715,
contentHeight: 800,
aspectRatio: 1, // 设置日历单元格宽度与高度的比例。
handleWindowResize: true, // 是否随浏览器窗口大小变化而自动变化
plugins: [dayGridPlugin, timeGridPlugin, interactionPlugin, listPlugin],
initialView: 'timeGridWeek', // 设置默认显示月,可选周、日
headerToolbar: {
left: 'title',
center: '',
right: 'timeGridWeek,dayGridMonth'
},
buttonText: {
// 设置按钮
// today: '今天',
month: '月',
week: '周'
// dayGrid: '天'
},
customButtons: {
dayGridMonth: {
text: '月',
click: (data) => {
console.log(data)
this.$refs.fullCalendar.getApi().changeView('dayGridMonth')
this.dateType = 'month'
}
},
timeGridWeek: {
text: '周',
click: (data) => {
console.log(data)
this.$refs.fullCalendar.getApi().changeView('timeGridWeek')
this.dateType = 'week'
}
}
},
// allDaySlot: false,
// editable: true, // 是否可以编辑,影响拖动
selectable: true,
navLinks: false, // 天链接
dayMaxEvents: false, // 限制事件最大数量
// displayEventEnd: true,//所有视图显示结束时间
eventDurationEditable: true, // 可以调整事件的时间
dateClick: this.handleDateClick,
eventClick: this.handleEventClick, // 日程事件点击
eventsSet: this.handleEvents,
select: this.handleDateSelect,
// nowIndicator: true, // 显示当前时间线
// 设置日程
events: this.getScheduleInfo(),
eventColor: '#f08f00', // 修改日程背景色
locale: 'zh-cn', // 设置语言
initialDate: this.$moment().format('YYYY-MM-DD HH:mm:ss'),
displayEventTime: false, // 不显示日程时间,只显示title
// eventMouseEnter: this.eventMouseEnter,
// eventMouseLeave: this.eventMouseLeave,
// 日历触发拖拽的钩子
// drop: this.newEventDrop,
// droppable: false, // 拖拽
// eventDrop: this.handleEventDrop, // 拖动事件
allDaySlot: false, // 不显示all-day那一行
scrollTime: '00:00',
slotDuration: '01:00', // 时间间隔
slotEventOverlap: false, // 重叠时间段不覆盖
slotLabelFormat: {
hour: '2-digit',
minute: '2-digit',
omitZeroMinute: false, // 分钟为00时仍显示
hour12: false
},
eventTimeFormat: {
hour: '2-digit',
minute: '2-digit',
omitZeroMinute: false,
hour12: false
},
firstDay: 1,
// weekNumbers: true, // 启用周编号
// weekNumberContent: (arg) => {
// return `第${arg.num}周`
// },
weekNumberCalculation: 'ISO', // 周编号的计算方式
// dayMaxEventRows: true,
// datesSet: this.datesSet, // 切换视图时触发
slotMinTime: '00:00', // 时间轴开始时间
// slotMaxTime: '24:00',
// 视图的一些基本设置
views: {
// 月视图阳历转农历
dayGridMonth: {
displayEventTime: true, // 是否显示时间
// dayMaxEventRows: 5, // adjust to 6 only for timeGridWeek/timeGridDay
// titleFormat: { year: "numeric", month: "2-digit", day: "2-digit" }, //控制日历显示的标题
// moreLinkClick: 'popover',
dayCellContent: (item) => {
const year = this.$moment(item.date).format('YYYY')
const month = this.$moment(item.date).format('MM')
const day = this.$moment(item.date).format('DD')
const newDate = calendarConverter.solar2lunar(year, month, day)
return {
html: `<div class="month-date"><div class="cDay">${newDate.cDay}</div><div class="lunar">${newDate.IDayCn}</div></div>`
}
},
dayHeaderContent(item) {
// 自定义表头
return {
html: `<div class="day-header">星期${item.text?.split('周')[1]}</div>`
}
}
},
timeGridWeek: {
dayHeaderContent(item) {
// 自定义表头
return {
html: `<div class="day-header"><div class="day ${
item.isToday ? 'today' : ''
}">${item.date.getDate()}</div><div class="week">星期${
item.text?.split('周')[1]
}</div></div>`
}
}
// eventMaxStack: 4 // 同一时段最多展示事件数
// moreLinkClick: 'week',
// moreLinkClick: this.moreLinkClick,
}
}
}
}
},
mounted() {},
watch: {
currentDate: {
handler(newVal) {
if (newVal) {
const fullCalendar = this.$refs.fullCalendar.calendar
fullCalendar.gotoDate(newVal) // 日历视图跟随日期跳转
this.getScheduleInfo()
}
},
deep: true
// immediate: true
},
dateType: {
handler(newVal) {
if (newVal) {
this.getScheduleInfo()
}
}
}
},
methods: {
// 查询值班信息
async getScheduleInfo() {
const url = `/api/xxx`
const params = {
dateType: this.dateType,
scheduleDate: this.currentDate
}
const res = await this.$http.get(url, { params })
if (res.successful) {
this.calendarOptions.events = res?.data.map((item) => ({
...item,
title: item.userName,
start: item.scheduleStartTime,
end: item.scheduleEndTime,
color: item.postColor || '#999999',
textColor: item.postColor || '#999999',
visible: false,
overlap: false,
editable: false
}))
} else {
this.$message.error(res.msg, 5)
}
},
// 删除单个排班成功回调
handleSuccess() {
this.$emit('success')
},
handleEventClick(e) {
const result = this.calendarOptions.events.map((item) => {
return {
...item,
visible: item.id === e.event.id
}
})
this.calendarOptions.events = result
console.log(e, 'handleEventClick=====')
},
handleDateClick(e) {
this.handleEventVisible()
if (e.view.type === 'dayGridMonth') {
const dateList = this.calendarOptions.events.filter(
(item) => item.scheduleDate === e?.dateStr
)
if (dateList && dateList?.length > 0) {
this.$refs.eventModalRef.visible = true
this.$refs.eventModalRef.scheduleDate = e?.dateStr
this.$refs.eventModalRef.getScheduleList()
}
}
},
// 关闭排班气泡弹框
handleEventVisible() {
const result = this.calendarOptions.events.map((item) => {
return {
...item,
visible: false
}
})
this.calendarOptions.events = result
}
}
}
</script>
<style lang="less" scoped>
.full-calendar {
padding: 20px 10px 10px 10px;
height: 100%;
.event-content {
width: 100%;
height: 100%;
text-align: center;
padding-top: 3px;
}
::v-deep .fc-header-toolbar {
margin-bottom: 12px;
.fc-toolbar-title {
font-size: 16px;
font-weight: 700;
line-height: 28px;
color: #333;
margin-left: 10px;
}
}
::v-deep .fc-theme-standard {
height: 100% !important;
overflow-y: scroll;
th,
td {
border-right: none;
border-bottom: none;
}
.fc-button {
height: 28px;
font-size: 14px;
display: flex;
align-items: center;
}
.fc-scrollgrid {
border: none;
.fc-col-header {
tr th {
height: 48px;
border: none;
}
}
// 周视图
.day-header {
display: flex;
align-items: center;
color: #333;
.day {
color: rgb(51, 51, 51);
font-size: 28px;
}
.week {
color: rgb(153, 153, 153);
line-height: 21px;
letter-spacing: 1px;
margin-left: 8px;
font-size: 14px;
}
.today {
display: flex;
justify-content: center;
align-items: center;
width: 32px;
height: 32px;
border-radius: 50%;
background-color: #2d8cf0;
color: #fff;
font-size: 18px;
}
}
.fc-timegrid-body {
height: 100%;
border: 1px solid #f0f3fd;
.fc-timegrid-slots {
height: 100%;
table {
height: 100%;
}
}
tr td {
min-height: 26px;
font-size: 14px;
border-color: #f0f3fd !important;
}
.fc-timegrid-slot-label {
width: 50px !important;
border: none !important;
display: flex;
justify-content: center;
align-items: start;
color: #999;
}
.fc-event {
background-color: transparent !important;
border: none;
}
.fc-day-today {
background-color: transparent;
}
.fc-timegrid-cols .fc-day {
border-bottom: 1px solid #f0f3fd;
}
}
// 月视图
.fc-col-header-cell-cushion {
color: #333333 !important;
}
.fc-daygrid-day-number {
color: #333333 !important;
}
.fc-daygrid-body {
border: 1px solid #f0f3fd;
tr td {
font-size: 14px;
border-color: #f0f3fd !important;
}
.fc-day-other {
background: rgb(248, 248, 248);
}
.fc-event {
background-color: transparent !important;
border: none;
}
.fc-day-today {
background-color: #fff;
.cDay {
width: 20px;
height: 20px;
text-align: center;
line-height: 20px;
border-radius: 50%;
color: #fff;
background: #2d8cf0;
}
.lunar {
color: #2d8cf0 !important;
}
}
.fc-daygrid-day-events {
height: 100px;
overflow-y: scroll;
&::-webkit-scrollbar {
width: 3px !important;
height: 3px !important;
}
}
.fc-daygrid-day-number {
width: 100%;
.month-date {
width: 100%;
display: flex;
justify-content: space-between;
.lunar {
color: #999999;
}
}
}
.event-content {
width: 100%;
height: 30px;
line-height: 30px;
text-align: left !important;
text-align: center;
padding: 0 0 0 5px;
}
}
}
}
::v-deep .fc-button {
border: 1px solid rgb(45, 140, 240);
border-radius: 2px;
background: rgba(45, 140, 240, 0.1);
color: #2d8cf0;
box-shadow: none !important;
&:hover {
border: 1px solid rgb(45, 140, 240) !important;
border-radius: 2px;
background: rgb(45, 140, 240) !important;
color: #fff;
}
}
::v-deep .fc-button-active {
border: 1px solid rgb(45, 140, 240) !important;
border-radius: 2px;
background: rgb(45, 140, 240) !important;
}
}
</style>