Vue项目使用
<template>
<div class="M_container">
<FullCalendar
class="fullcalendar"
ref="myCalendar"
:options="calendarOptions"
>
</FullCalendar>
</div>
</template>
<script>
import { GetDayList } from "@/api/schedule/index";
import {formateDate} from "@/utils/schedule/formate";
import FullCalendar from "@fullcalendar/vue";
import dayGridPlugin from "@fullcalendar/daygrid";
import timeGridPlugin from "@fullcalendar/timegrid";
import interactionPlugin from "@fullcalendar/interaction";
import {eventContetFun,changeStartEnd,slotLabelContent,eventMouseEnter} from "@/utils/schedule/fullcalendarHandler"
export default {
name: "byDay",
components: {
FullCalendar
},
props:['filterDate'],
data() {
return {
selectDate:'',
calendarOptions: {
plugins: [dayGridPlugin, interactionPlugin, timeGridPlugin],
initialView: "timeGridDay",
events: [],
locale: "zh-cn",
themeSystem: "bootstrap", // 主题色(本地测试未能生效)expandRows: true,
expandRows: true,
contentHeight: 870,
timeGridEventMinHeight: "26", // 设置事件的最小高度
// 设置日历单元格宽度与高度的比例。
eventLimit: true, // 设置月日程,与all-day slot的最大显示数量,超过的通过弹窗显示
headerToolbar: false,
allDaySlot: true,
allDayText: "全天",
scrollTimeReset:true,
scrollTime:"12:00:00",
slotDuration:"01:00",
slotMinTime: "07:00:00",
slotMaxTime: "20:00:00",
dayHeaders: false,
slotEventOverlap: false,//是否重叠
showNonCurrentDates: false,
eventMouseEnter:eventMouseEnter,
slotLabelContent:slotLabelContent,
eventContent:eventContetFun,
views: {
timeGridDay: {
eventLimit:5,
dayMaxEventRows: 4,
/* eventMaxStack:30, */
moreLinkContent: "更多",
moreLinkClick: "popover",
},
},
slotLabelFormat: {
hour: "2-digit",
minute: "2-digit",
meridiem: false,
hour12: false, // 设置时间为24小时
},
eventLimitNum: {
// 事件显示数量限制(本地测试未能生效)
dayGrid: {
eventLimit: 3,
},
timeGrid: {
eventLimit: 2, // adjust to 6 only for timeGridWeek/timeGridDay
},
},
eventClick: this.handleEventClick,
},
};
},
watch: {
filterDate: {
handler(newValue,oldValue) {
if(newValue&&newValue!=oldValue){
/* this.$emit('changeDayDate',newValue); */
this.selectDate=newValue;
this.getDayData();
}else{
this.$alert("请选择日期", "提示");
}
},
immediate: true
},
},
mounted() {
this.$nextTick(()=>{
this.selectDate=this.filterDate;
})
},
methods: {
changeSelect(){
this.$emit('changeDayDate',this.selectDate);
},
getDayData() {
const _this = this;
this.$nextTick(()=>{
let calendarApi = this.$refs.myCalendar.getApi();
calendarApi.gotoDate( _this.filterDate );
})
GetDayList({
startDate: _this.filterDate,
}).then((res) => {
let resData = res.data,
result = resData.flat(Infinity);
const handleData = result.map((item) => {
let timeObj=changeStartEnd(_this.filterDate,item);
return {
start: timeObj.itemStart,
end: timeObj.itemEnd,
startTimes:new Date(item.startTime?item.startTime:item.allDayStartTime),
endTimes:new Date(item.endTime?item.endTime:item.allDayEndTime),
title: item.sysScheduleContent,
classNames: item.actualCompleteTime ? "blue" : "orange",
sysScheduleArrangeAllRecordId:item.sysScheduleArrangeAllRecordId,
sysScheduleArrangeId:item.sysScheduleArrangeId,
status:item.status,
actualCompleteTime:item.actualCompleteTime,
important:item.important,
};
});
_this.calendarOptions.events =handleData;
});
},
/**
* 点击日历日程事件
*
* info: 事件信息
* event是日程(事件)对象
* jsEvent是个javascript事件
* view是当前视图对象。
*/
handleEventClick(info) {
const data=info.event._def.extendedProps;
const scheduleID={sysScheduleArrangeAllRecordId:data.sysScheduleArrangeAllRecordId,sysScheduleArrangeId:data.sysScheduleArrangeId,status:data.status};
this.$emit('getScheduleID',scheduleID)
},
},
};
</script>
依赖包版本如下
页面效果:
纵坐标时间轴处理:
首先,设置
slotMinTime: "07:00:00",
slotMaxTime: "20:00:00",
设置后08:00-18:00前后只剩下一格位置,再结合slotLabelContent:function(arg){}对时间轴文字处理
function slotLabelContent(arg){
if (Number(arg.time.milliseconds) < 28800000) {
return "08:00前";
}
if (
Number(arg.time.milliseconds) >= 28800000 &&
Number(arg.time.milliseconds) <= 64800000
) {
return arg.text;
}
if (Number(arg.time.milliseconds) > 64800000) {
return "19:00后";
}
}
这下出现了20:00后或者07:00前的数据无法呈现,因为该部分时间并没有对应的时间轴
这时候就要对Events:[]的数据进行处理,同时结合eventContent:function(arg){}
以下代码是对start和end进行处理
function changeStartEnd(day, item) {
if(item.startTime&&item.endTime){//非全天
let startTime = new Date(day + " " + '08:00');
let endTime = new Date(day + " " + '20:00');
let endTime1 = new Date(day + " " + '19:00');
let itemStart = new Date(item.startTime);
let itemEnd = new Date(item.endTime);
if (itemStart < startTime) {
itemStart = new Date(day + " " + '07:00');
}
if (itemStart > endTime1) {
itemStart = new Date(day + " " + '19:00')
}
if (itemEnd < startTime) {
itemEnd = startTime;
}
if (itemEnd > endTime1) {
itemEnd = endTime;
}
if(new Date(itemEnd)-new Date(itemStart)==0){//开始时间和结束时间一样 只占用半格
let Hour=itemStart.getHours()<10?'0'+itemStart.getHours():itemStart.getHours()
let time=itemStart.getFullYear()+"-"+(itemStart.getMonth()+1)+"-"+itemStart.getDate()+" "+Hour
itemStart=time+":00";
itemEnd=time+":30"
}
return {itemEnd,itemStart}
}else{//全天日程
return {
itemStart:item.allDayStartTime,
itemEnd: item.allDayEndTime
}
}
}
startTimes和endTimes用于页面文字展示时间段
fullcalendar插槽的使用
1.自定义dayHeaderContent
<FullCalendar
ref="fullCalendar"
class="fullcalendar week"
:options="calendarOptions"
>
<template v-slot:dayHeaderContent='arg'>
<div class="top" @click="changeToDay(arg.date)">
{{arg|formateHeaderContent}}
<span v-if="weekEventNumObj[arg.dow]>1" class="moreTips">更多日程</span>
</div>
</template>
</FullCalendar>
2.自定义eventContent
<template v-slot:eventContent='arg'>
<el-tooltip
class="box-item"
effect="dark"
placement="top-start"
>
<template #content>
<span>
{{ parseTime(arg.event.start,'{m}月{d}日 {h}:{i}') }}-{{ parseTime(arg.event.end,'{m}月{d}日 {h}:{i}') }} 预约时长:{{arg.event.extendedProps.num}}小时</span>
</template>
<div :class="[type !='check' ? 'text-box':'text-box check']">
<span @click="changeInfo(arg.event)">
{{ parseTime(arg.event.start,'{m}月{d}日') == parseTime(arg.event.end,'{m}月{d}日') ? parseTime(arg.event.start,'{h}:{i}') : parseTime(arg.event.start,'{m}月{d}日 {h}:{i}') }} -
{{ parseTime(arg.event.end,'{m}月{d}日') == parseTime(arg.event.start,'{m}月{d}日') ? parseTime(arg.event.end,'{h}:{i}') : parseTime(arg.event.end,'{m}月{d}日 {h}:{i}')}}
时长:{{arg.event.extendedProps.num}}h
</span>
<el-button v-if="type !='check'" type="danger" circle @click="deleteItem(arg.event.id)"><el-icon size="10"><close-bold /></el-icon></el-button>
</div>
</el-tooltip>
</template>
<template v-slot:eventContent="arg">
<el-popover
:append-to-body="true"
ref="popover1"
placement="top-start"
width="220"
:visible-arrow="true"
trigger="hover"
:teleported="false"
popper-class="popover"
:open-delay="100"
@show="showPic(arg)"
@hide="popoverPicReset(arg)"
>
</el-popover>
</template>
3.自定义slotLabelContent
tips: slotDuration:"01:00",设置为一个小时,时间垂直居中显示,不然偏上
<FullCalendar
ref="fullCalendar"
class="fullcalendar week"
:options="calendarOptions"
>
<template v-slot:slotLabelContent='arg'>
<div class="top" @click="changeToDay(arg.date)">
{{arg|formateHeaderContent}}
<span v-if="weekEventNumObj[arg.dow]>1" class="moreTips">更多日程</span>
</div>
</template>
</FullCalendar>