需求:日历以面板形式展示,且以小红点表示当天有任务
<div class="calendar">
<div class="calendar-title">
<b class="b">日程安排</b>
<el-date-picker
v-model="times"
size="mini"
type="month"
:clearable="false"
style="width: 120px"
@change="handleChange">
</el-date-picker>
</div>
<div class="mg-evt-calendar-body">
<div class="calendar-head">
<div class="calendar-head-item" v-for="(item, index) in weeksList" :key="index">
{{ item.label }}
</div>
</div>
<div class="calendar-body">
<div class="calendar-module" v-for="(item, index) in daysList" :key="index">
<div
class="calendar-module-item"
v-for="(_item, _index) in item"
:key="_index"
:class="[
_item.date && _item.date === currentDate ? 'active' : '',
setDateClass(_item.date),
setDateBadge(_item.date)
]"
@click="handleClickDay(_item.date)"
>
<span>{{ _item.date ? formatCalendarDay(_item.date) : "" }}</span>
</div>
</div>
</div>
</div>
</div>
html部分代码如上,setDateClass设置当天日期样式,setDateBadge给有任务的日期设置样式,handleClickDay为日期点击事件可获取当前点击日期
下面是js部分,时间插件用的是dayjs
data() {
return {
// 右侧日历相关
weeksList: [
{ label: "日", value: 0, fullName: "星期日" },
{ label: "一", value: 1, fullName: "星期一" },
{ label: "二", value: 2, fullName: "星期二" },
{ label: "三", value: 3, fullName: "星期三" },
{ label: "四", value: 4, fullName: "星期四" },
{ label: "五", value: 5, fullName: "星期五" },
{ label: "六", value: 6, fullName: "星期六" },
],
daysList: [],
year: "",
month: "",
times: new Date(),
renderDateList: [],
currentDate: "",
}
},
methods: {
// 切换月份
handleChange(time) {
if(time) {
this.year = dayjs(time).format("YYYY");
this.month = dayjs(time).format("MM");
this.setDaysData();
this.renderDateList = [];
this.query.startTime = dayjs(time).startOf("month").startOf("day").toISOString();
this.query.endTime = dayjs(time).endOf("month").endOf("day").toISOString();
}
},
// 设置某月每天数据
setDaysData() {
let days = new Date(this.year, this.month, 0).getDate(); //获取某月的总天数
let daysList = Array.from({length: days}).map((_, index) => {
let _index = index > 8 ? index + 1 : `0${index+1}`;
let day = `${this.year}-${this.month}-${_index}`;
return {
date: day,
weekValue: new Date(day).getDay(), //获取某天对应的星期几
}
});
// 获取某月第一天对应的星期几
let currentIndex = this.weeksList.findIndex(item => item.value == daysList[0].weekValue);
// 往总天数中添加currentIndex个对象用于错位
let addList = Array.from({length: currentIndex}).map((_, index) => {
return {
date: "",
weekValue: ""
}
});
// 合并
let mergeArr = [...addList, ...daysList];
let resultList = [];
let index = 0;
// 将数组分为长度为7的数组方便页面循环
while(index < days) {
resultList.push(mergeArr.slice(index, index += 7));
}
this.daysList = resultList;
},
// 格式化日历中的日期
formatCalendarDay(date) {
return dayjs(date).format("D");
},
// 设置当天日期样式
setDateClass(date) {
if(date) {
return dayjs().format("YYYY-MM-DD") === date ? "current" : "";
}
},
// 设置日期小红点
setDateBadge(date) {
if(date) {
return this.renderDateList.includes(date) ? "badge" : "";
}
},
// 日历点击事件
handleClickDay(date) {
if(date) {
// 设置选中样式
if(this.currentDate !== date) {
this.currentDate = date;
}else{
// 去除选中样式
this.currentDate = "";
}
}
},
// 渲染日历时间
renderDates(times) {
this.renderDateList = times;
},
}
下面是相关样式
.calendar{
width: 580px;
background: #fff;
.calendar-head{
display: flex;
margin-bottom: 10px;
.calendar-head-item{
display: flex;
width: calc((100% - 6px) / 7);
height: 30px;
color: #fff;
line-height: 1;
align-items: center;
justify-content: center;
background-color: #4B7EFE;
&:not(:last-child) {
margin-right: 1px;
}
}
}
.calendar-body{
.calendar-module{
display: flex;
margin-bottom: 10px;
}
.calendar-module-item{
display: flex;
position: relative;
width: calc((100% - 6px) / 7);
height: 35px;
line-height: 35px;
text-align: center;
align-items: center;
justify-content: center;
cursor: pointer;
&:not(:last-child) {
margin-right: 1px;
}
span{
position: relative;
display: block;
width: 25px;
height: 25px;
line-height: 25px;
}
&.current{
span{
border-radius: 100%;
border: 1px solid #4B7EFE;
}
}
&.active{
border-bottom: none;
span{
color: #fff;
border-radius: 100%;
background-color: #4B7EFE;
}
}
&.badge{
span::after{
position: absolute;
top: -4px;
right: -4px;
width: 8px;
height: 8px;
border-radius: 100%;
background-color: red;
content: "";
}
}
}
}
}
最终的效果图如下: