找了很久vue3的element样式一直没办法修改实现。只能手写日历了。借鉴了一些大佬的代码
调用:
再要使用的地方引入
import calendarelement from './calendarelement.vue' //日历组件
<div >
<calendarelement /> //日历
</div>
效果:
<template>
<div class="plan-zone">
<div class="btn-group">
<div class="left-btn">
<el-button-group>
<el-button @click="prevMonth" type="primary">上一个月</el-button>
<el-button type="primary" @click="goToCurrentDay">回到今天</el-button>
<el-button @click="nextMonth" type="primary">下一个月</el-button>
</el-button-group>
</div>
<div class="right-btn">
<button class="new">长箱</button>
<button class="ing">短箱</button>
<button class="finish">双箱</button>
</div>
</div>
<table class="parent-table">
<thead>
<th>周一</th>
<th>周二</th>
<th>周三</th>
<th>周四</th>
<th>周五</th>
<th>周六</th>
<th>周日</th>
</thead>
<tbody>
<tr v-for="(week, windex) in weeks" :key="windex">
<td v-for="(day, dindex) in week" :class="{ highlight: isToday(day.date) }" :key="dindex">
<div class="content"
:class="{
faded: !isCurrentMonth(day.date),
hovered: isHovered(day.date),
selected: isSelected(day.date)
}"
@mouseenter="hoveredDay = day.date"
@mouseleave="hoveredDay = null"
@click="selectDay(day.date)"
>
<div class="top-day">{{ day.date.getDate() }}日 </div>
<div class="middle-event">
<div>
<span style="color: #409eef;">长箱</span>:<span>123</span>
</div>
</div>
<div class="bottom-event">
<div>
<span style="color: #ff974a;">短箱</span>:<span>123</span>
</div>
</div>
<div class="bottom-event">
<div>
<span style="color: #3dd599;">双箱</span>:<span>123</span>
</div>
</div>
</div>
</td>
</tr>
</tbody>
</table>
</div>
</template>
<script setup>
import { ref, computed } from 'vue';
const current = ref(new Date());
const today = ref(new Date());
const getCurDate = () => {
const date = new Date();
const year = date.getFullYear();
let month = date.getMonth() + 1;
if (month < 10) {
month = "0" + month;
}
return `${year}-${month}`;
};
const isToday = (date) => {
const todayDate = new Date();
return (
date.getDate() === todayDate.getDate() &&
date.getMonth() === todayDate.getMonth() &&
date.getFullYear() === todayDate.getFullYear()
);
};
const goToCurrentDay = () => {
current.value = new Date(today.value);
};
const isCurrentMonth = (date) => {
return date.getMonth() === current.value.getMonth();
};
const prevMonth = () => {
current.value.setMonth(current.value.getMonth() - 1);
current.value = new Date(current.value);
};
const nextMonth = () => {
current.value.setMonth(current.value.getMonth() + 1);
current.value = new Date(current.value);
};
const hoveredDay = ref(null);
const selectedDay = ref(null);
const isHovered = (date) => hoveredDay.value && hoveredDay.value.getTime() === date.getTime();
const isSelected = (date) => selectedDay.value && selectedDay.value.getTime() === date.getTime();
const selectDay = (date) => selectedDay.value = date;
const getMonthData = (year, month) => {
const weeks = [];
const firstDay = new Date(year, month - 1, 1);
const lastDayOfCurrentMonth = new Date(year, month, 0);
const lastDayOfPrevMonth = new Date(year, month - 1, 0);
let startDayOfWeek = firstDay.getDay() === 0 ? 7 : firstDay.getDay();
let dayCount = 1;
let prevMonthDayCount = lastDayOfPrevMonth.getDate() - startDayOfWeek + 2;
for (let i = 0; i < 6; i++) {
const week = [];
for (let j = 0; j < 7; j++) {
if (i === 0 && j < startDayOfWeek - 1) {
week.push({ date: new Date(year, month - 2, prevMonthDayCount++) });
} else if (dayCount > lastDayOfCurrentMonth.getDate()) {
week.push({
date: new Date(year, month, dayCount++ - lastDayOfCurrentMonth.getDate()),
});
} else {
week.push({ date: new Date(year, month - 1, dayCount++) });
}
}
weeks.push(week);
}
return weeks;
};
const weeks = computed(() => getMonthData(current.value.getFullYear(), current.value.getMonth() + 1));
</script>
<style lang="scss" scoped>
.faded {
opacity: 0.3;
}
.highlight {
background: rgba(255, 220, 40, 0.15);
}
.plan-zone {
margin-top: 10px;
.btn-group {
display: flex;
justify-content: space-between;
.right-btn {
button.new {
background-color: #fff;
border: 1px solid #fff;
color: #409eef;
position: relative;
&::before {
content: "";
width: 8px;
height: 8px;
border-radius: 50%;
position: absolute;
top: 7px;
left: -3px;
background-color: #409eef;
}
}
button.ing {
background-color: #fff;
border: 1px solid #fff;
color: #ff974a;
position: relative;
&::before {
content: "";
width: 8px;
height: 8px;
border-radius: 50%;
position: absolute;
top: 7px;
left: -3px;
background-color: #ff974a;
}
}
button.finish {
background-color: #fff;
border: 1px solid #fff;
color: #3dd599;
position: relative;
&::before {
content: "";
width: 8px;
height: 8px;
border-radius: 50%;
position: absolute;
top: 7px;
left: -3px;
background-color: #3dd599;
}
}
}
}
}
.parent-table {
border-collapse: collapse;
table-layout: fixed;
width: 100%;
margin-top: 20px;
th,
td {
width: 14.4%;
border: 1px solid #ddd;
}
td {
padding: 2px 3px;
.content {
position: relative;
min-height: 80px;
transition: background-color 0.3s ease;
}
vertical-align: top;
.top-day {
text-align: right;
font-size: 16px;
}
}
}
.table-date {
display: flex;
> div {
flex: 1;
}
}
.hovered {
background-color: rgba(64, 56, 180, 0.1);
}
.selected {
background-color: rgba(70, 168, 40, 0.2);
}
</style>