Files
maintenance_system/src/views/integratedManage/attendManage/components/leftBox/calendar.vue

320 lines
7.5 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<template>
<div class="box">
<div class="chart-header">
<TitleComponent title="日历" :font-level="2" />
</div>
<div class="calendar-container">
<div class="calendar-header">
<el-button size="small" type="text" @click="prevMonth">
<el-icon><ArrowLeft /></el-icon>
</el-button>
<span class="current-month">{{ currentYear }} {{ currentMonthName }}</span>
<el-button size="small" type="text" @click="nextMonth">
<el-icon><ArrowRight /></el-icon>
</el-button>
</div>
<div class="calendar-weekdays">
<span v-for="day in weekdays" :key="day" class="weekday">{{ day }}</span>
</div>
<div class="calendar-days">
<!-- 上月剩余天数 -->
<div v-for="(day, index) in prevMonthDays" :key="'prev-' + index" class="day prev-month-day">
{{ day }}
</div>
<!-- 当月天数 -->
<div
v-for="day in currentMonthDays"
:key="day"
class="day current-month-day"
:class="{
'current-day': isCurrentDay(day),
'selected-day': isSelectedDay(day)
}"
@click="selectDay(day)"
>
{{ day }}
<!-- 今天有红点标记 -->
<span v-if="isToday(day)" class="today-marker"></span>
<!-- 考勤状态标记 -->
<span v-if="getAttendanceStatus(day)" class="attendance-marker" :class="getAttendanceStatus(day)"></span>
</div>
<!-- 下月开始天数 -->
<div v-for="(day, index) in nextMonthDays" :key="'next-' + index" class="day next-month-day">
{{ day }}
</div>
</div>
</div>
</div>
</template>
<script setup>
import TitleComponent from '@/components/TitleComponent/index.vue';
import { ArrowLeft, ArrowRight } from '@element-plus/icons-vue';
import { ref, computed } from 'vue';
import { ElMessage } from 'element-plus';
// 初始化当前日期
const today = new Date();
const currentDate = ref(new Date(2025, 8, 27)); // 2025年9月27日截图中显示的日期
const selectedDate = ref(new Date(2025, 8, 27));
// 模拟考勤数据
const attendanceData = ref({
2025: {
9: {
1: 'normal',
4: 'late',
8: 'absent',
10: 'leave',
15: 'normal',
20: 'normal',
25: 'late',
27: 'normal'
}
}
});
// 星期几的显示
const weekdays = ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'];
const monthNames = ['January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December'];
// 计算属性
const currentYear = computed(() => currentDate.value.getFullYear());
const currentMonth = computed(() => currentDate.value.getMonth());
const currentMonthName = computed(() => monthNames[currentMonth.value]);
// 获取当月的天数
const currentMonthDays = computed(() => {
return new Date(currentYear.value, currentMonth.value + 1, 0).getDate();
});
// 获取当月第一天是星期几0-60是星期日
const firstDayOfMonth = computed(() => {
return new Date(currentYear.value, currentMonth.value, 1).getDay();
});
// 获取上月剩余天数
const prevMonthDays = computed(() => {
const days = [];
const prevMonth = new Date(currentYear.value, currentMonth.value, 0).getDate(); // 上月最后一天
for (let i = firstDayOfMonth.value - 1; i >= 0; i--) {
days.push(prevMonth - i);
}
return days;
});
// 获取下月开始天数
const nextMonthDays = computed(() => {
const days = [];
const totalDays = prevMonthDays.value.length + currentMonthDays.value;
const nextDays = 35 - totalDays; // 显示5周共35天
for (let i = 1; i <= nextDays; i++) {
days.push(i);
}
return days;
});
// 方法
const prevMonth = () => {
currentDate.value = new Date(currentYear.value, currentMonth.value - 1, 1);
};
const nextMonth = () => {
currentDate.value = new Date(currentYear.value, currentMonth.value + 1, 1);
};
const selectDay = (day) => {
selectedDate.value = new Date(currentYear.value, currentMonth.value, day);
// 显示选择的日期和考勤状态
let message = `Selected: ${currentMonthName.value} ${day}, ${currentYear.value}`;
const status = getAttendanceStatus(day);
if (status) {
const statusMap = {
normal: '正常',
late: '迟到',
absent: '缺勤',
leave: '请假'
};
message += ` - 考勤状态: ${statusMap[status] || '未知'}`;
}
ElMessage.success(message);
};
// 获取考勤状态
const getAttendanceStatus = (day) => {
if (attendanceData.value[currentYear.value] &&
attendanceData.value[currentYear.value][currentMonth.value + 1] &&
attendanceData.value[currentYear.value][currentMonth.value + 1][day]) {
return attendanceData.value[currentYear.value][currentMonth.value + 1][day];
}
return null;
};
const isToday = (day) => {
return day === today.getDate() &&
currentMonth.value === today.getMonth() &&
currentYear.value === today.getFullYear();
};
const isCurrentDay = (day) => {
return day === today.getDate() &&
currentMonth.value === today.getMonth() &&
currentYear.value === today.getFullYear();
};
const isSelectedDay = (day) => {
return day === selectedDate.value.getDate() &&
currentMonth.value === selectedDate.value.getMonth() &&
currentYear.value === selectedDate.value.getFullYear();
};
</script>
<style scoped lang="scss">
.chart-header {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 20px;
}
.chart-header h3 {
margin: 0;
font-size: 16px;
font-weight: 500;
color: #333;
}
.chart-header span {
color: #186DF5;
font-size: 14px;
cursor: pointer;
}
.calendar-container {
background: white;
border-radius: 8px;
padding: 16px;
// border: 1px solid #F2F3F5;
}
.calendar-header {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 16px;
padding: 8px 0;
}
.current-month {
font-size: 16px;
font-weight: 500;
color: #333;
}
.calendar-weekdays {
display: grid;
grid-template-columns: repeat(7, 1fr);
gap: 8px;
margin-bottom: 8px;
}
.weekday {
text-align: center;
font-size: 14px;
color: #666;
font-weight: 500;
padding: 8px 0;
}
.calendar-days {
display: grid;
grid-template-columns: repeat(7, 1fr);
gap: 8px;
height: 350px;
}
.day {
position: relative;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
height: 40px;
border-radius: 4px;
font-size: 14px;
cursor: pointer;
transition: all 0.3s ease;
}
.prev-month-day,
.next-month-day {
color: #C0C4CC;
}
.current-month-day {
color: #333;
}
.current-month-day:hover {
background-color: #ECF5FF;
color: #186DF5;
}
.current-day {
position: relative;
}
.today-marker {
position: absolute;
bottom: 4px;
width: 4px;
height: 4px;
border-radius: 50%;
background-color: #FF6B3B;
}
.selected-day {
background-color: #186DF5;
color: white !important;
font-weight: 500;
}
.selected-day:hover {
background-color: #4096ff;
color: white !important;
}
// 考勤状态标记样式
.attendance-marker {
position: absolute;
bottom: 2px;
width: 6px;
height: 6px;
border-radius: 50%;
}
.attendance-marker.normal {
background-color: #52c41a;
}
.attendance-marker.late {
background-color: #faad14;
}
.attendance-marker.absent {
background-color: #f5222d;
}
.attendance-marker.leave {
background-color: #1890ff;
}
</style>