组件的模板内容
<template>
<div class="calender_wrapper">
<el-scrollbar>
<div class="month_box_wrapper">
<div class="month_box" v-for="item in allMonthObj.allMonthList">
<h3 class="month_tit">{{ item.month }}月</h3>
<table class="tb">
<!--星期几;-->
<tr class="tr tit">
<td>周</td>
<td>一</td>
<td>二</td>
<td>三</td>
<td>四</td>
<td>五</td>
<td style="color: #e51f1f">六</td>
<td style="color: #e51f1f">日</td>
</tr>
<!--日期展示;-->
<tr class="tr" v-for="itemTr in item.dayList">
<td class="week_num">{{ itemTr.week }}</td>
<td v-for="itemTd in itemTr.weekData" :class="{ current_month: itemTd.currentMonth, today: itemTd.today }">
<template v-if="itemTd.today">
<span class="today_text">{{ itemTd.date }}</span>
</template>
<template v-else>{{ itemTd.date }}</template>
</td>
</tr>
</table>
</div>
</div>
</el-scrollbar>
</div>
</template>
组件js代码实现
<script lang="ts" setup>
import { reactive, watch } from 'vue';
interface props {
year: number | string;
monthList: number[];
}
let propsData = defineProps<props>();
const { year, monthList } = propsData;
let allMonthObj: any = reactive({
allMonthList: [],
});
/**
* 生成日历;
*/
const getcalendar = (year: number, month: number) => {
let allDayList: any[] = [];
year = year ? year : new Date().getFullYear();
//month是0开始到11结束的,获取当前月份必须加1
month = month ? month : new Date().getMonth() + 1;
let last = new Date(year, month - 1, 0);
let lastdate = last.getDate(); //获取上个月的最大日期
let lastday = last.getDay(); //获取上个月最大日期的星期几
let months = new Date(year, month, 0);
let Maxdate = months.getDate(); //获取这个月最大的日期
let today = new Date().getDate();
let thisyear = new Date().getFullYear();
let thismonth = new Date().getMonth() + 1;
//获取上个月在这个月份中存在的最后日期
var remainlastdate = lastdate - lastday + 1;
var t = 1;
var week = 1;
// 首行数据解析;
allDayList.push({ week: null, weekData: [] });
for (var g = 1; g <= 7; g++) {
if (g <= lastday) {
allDayList[0].weekData.push({ date: remainlastdate++, currentMonth: false });
} else {
if (thisyear == year && thismonth == month && today == t) {
allDayList[0].weekData.push({ date: t++, today: true });
} else {
allDayList[0].weekData.push({ date: t++, currentMonth: true });
}
allDayList[0].week = getYearWeek(year, month.toString(), t - 1);
}
}
var remainlastday = 7 - lastday + 1;
var nextMonthday = 1; //下一个月份的开始日期
for (var i = 1; i <= 5; i++) {
allDayList.push({ week: null, weekData: [] });
for (var j = 0; j < 7; j++) {
if (remainlastday <= Maxdate) {
if (thisyear == year && thismonth == month && today == remainlastday) {
allDayList[i].weekData.push({ date: remainlastday++, today: true });
allDayList[i].week = getYearWeek(year, month.toString(), remainlastday - 1);
} else {
allDayList[i].weekData.push({ date: remainlastday++, currentMonth: true });
allDayList[i].week = getYearWeek(year, month.toString(), remainlastday - 1);
}
} else {
allDayList[i].weekData.push({ date: nextMonthday++, currentMonth: false });
month < 12 && (allDayList[i].week = getYearWeek(year, (month + 1).toString(), nextMonthday - 1));
}
}
}
return allDayList;
};
/**
* 生成每个月的日历;
*/
const getMonthscalendar = (year: number) => {
monthList.map((item) => {
allMonthObj.allMonthList.push({ month: item, dayList: getcalendar(year, item) });
});
};
/**
* 获取年第几周;
*/
const getYearWeek = (year: number, month: string, day: number | undefined) => {
let date1 = new Date(year, parseInt(month) - 1, day),
date2 = new Date(year, 0, 1),
d = Math.round((date1.valueOf() - date2.valueOf()) / 86400000);
return Math.ceil((d + (date2.getDay() + 1 - 1)) / 7);
};
getMonthscalendar(Number(year));
watch(
() => propsData.year,
(newVal) => {
allMonthObj.allMonthList = [];
getMonthscalendar(Number(newVal));
},
);
</script>
组件样式
src/components/Calender/style/index.scss:
.calender_wrapper {
width: 100%;
overflow: hidden;
.month_box_wrapper {
margin-top: 20px;
margin-left: 25px;
height: calc(100vh - 145px);
overflow-y: scroll;
.month_box {
margin-left: 10px;
margin-right: 10px;
margin-bottom: 20px;
float: left;
.month_tit {
margin-top: 10px;
margin-bottom: 10px;
text-align: center;
}
.tb {
margin: auto;
border-collapse: collapse;
.tr {
td {
padding: 15px;
border: 1px solid #aaaaaa63;
&.week_num {
color: #fff !important;
background-color: #ff6702;
}
}
&:not(.tit) {
td {
color: #b7b7b7;
&.current_month {
color: #000;
}
&.today {
padding: 0px;
text-align: center;
.today_text {
display: inline-block;
width: 25px;
height: 25px;
line-height: 25px;
border-radius: 50%;
text-align: center;
color: #fff;
background: #ff6702;
}
}
}
}
}
}
}
}
}
完整的代码
src/components/Calender/index.vue:
<template>
<div class="calender_wrapper">
<el-scrollbar>
<div class="month_box_wrapper">
<div class="month_box" v-for="item in allMonthObj.allMonthList">
<h3 class="month_tit">{{ item.month }}月</h3>
<table class="tb">
<!--星期几;-->
<tr class="tr tit">
<td>周</td>
<td>一</td>
<td>二</td>
<td>三</td>
<td>四</td>
<td>五</td>
<td style="color: #e51f1f">六</td>
<td style="color: #e51f1f">日</td>
</tr>
<!--日期展示;-->
<tr class="tr" v-for="itemTr in item.dayList">
<td class="week_num">{{ itemTr.week }}</td>
<td v-for="itemTd in itemTr.weekData" :class="{ current_month: itemTd.currentMonth, today: itemTd.today }">
<template v-if="itemTd.today">
<span class="today_text">{{ itemTd.date }}</span>
</template>
<template v-else>{{ itemTd.date }}</template>
</td>
</tr>
</table>
</div>
</div>
</el-scrollbar>
</div>
</template>
<script lang="ts" setup>
import { reactive, watch } from 'vue';
interface props {
year: number | string;
monthList: number[];
}
let propsData = defineProps<props>();
const { year, monthList } = propsData;
let allMonthObj: any = reactive({
allMonthList: [],
});
/**
* 生成日历;
*/
const getcalendar = (year: number, month: number) => {
let allDayList: any[] = [];
year = year ? year : new Date().getFullYear();
//month是0开始到11结束的,获取当前月份必须加1
month = month ? month : new Date().getMonth() + 1;
let last = new Date(year, month - 1, 0);
let lastdate = last.getDate(); //获取上个月的最大日期
let lastday = last.getDay(); //获取上个月最大日期的星期几
let months = new Date(year, month, 0);
let Maxdate = months.getDate(); //获取这个月最大的日期
let today = new Date().getDate();
let thisyear = new Date().getFullYear();
let thismonth = new Date().getMonth() + 1;
//获取上个月在这个月份中存在的最后日期
var remainlastdate = lastdate - lastday + 1;
var t = 1;
var week = 1;
// 首行数据解析;
allDayList.push({ week: null, weekData: [] });
for (var g = 1; g <= 7; g++) {
if (g <= lastday) {
allDayList[0].weekData.push({ date: remainlastdate++, currentMonth: false });
} else {
if (thisyear == year && thismonth == month && today == t) {
allDayList[0].weekData.push({ date: t++, today: true });
} else {
allDayList[0].weekData.push({ date: t++, currentMonth: true });
}
allDayList[0].week = getYearWeek(year, month.toString(), t - 1);
}
}
var remainlastday = 7 - lastday + 1;
var nextMonthday = 1; //下一个月份的开始日期
for (var i = 1; i <= 5; i++) {
allDayList.push({ week: null, weekData: [] });
for (var j = 0; j < 7; j++) {
if (remainlastday <= Maxdate) {
if (thisyear == year && thismonth == month && today == remainlastday) {
allDayList[i].weekData.push({ date: remainlastday++, today: true });
allDayList[i].week = getYearWeek(year, month.toString(), remainlastday - 1);
} else {
allDayList[i].weekData.push({ date: remainlastday++, currentMonth: true });
allDayList[i].week = getYearWeek(year, month.toString(), remainlastday - 1);
}
} else {
allDayList[i].weekData.push({ date: nextMonthday++, currentMonth: false });
month < 12 && (allDayList[i].week = getYearWeek(year, (month + 1).toString(), nextMonthday - 1));
}
}
}
return allDayList;
};
/**
* 生成每个月的日历;
*/
const getMonthscalendar = (year: number) => {
monthList.map((item) => {
allMonthObj.allMonthList.push({ month: item, dayList: getcalendar(year, item) });
});
};
/**
* 获取年第几周;
*/
const getYearWeek = (year: number, month: string, day: number | undefined) => {
let date1 = new Date(year, parseInt(month) - 1, day),
date2 = new Date(year, 0, 1),
d = Math.round((date1.valueOf() - date2.valueOf()) / 86400000);
return Math.ceil((d + (date2.getDay() + 1 - 1)) / 7);
};
getMonthscalendar(Number(year));
watch(
() => propsData.year,
(newVal) => {
allMonthObj.allMonthList = [];
getMonthscalendar(Number(newVal));
},
);
</script>
<style lang="scss" scoped>
@import './style/index.scss';
</style>
组件使用
<Calender :year="2023" :monthList="[1,2,3,4,5,6,7,8,9,10,11,12]"></Calender>