Files
klp-oa/klp-ui/src/components/HomeModules/MiniCalendar.vue

239 lines
6.2 KiB
Vue
Raw Normal View History

<template>
<!-- 外层容器占用 30% 宽度可根据需要自行调样式 -->
<div class="mini-calendar" style="">
<!-- 日历头部显示YYYY年M月 -->
<div class="calendar-header">
<div>个人日历</div>
<div>{{ currentMonthYear }}</div>
</div>
<!-- 日历主体使用 table 简易排版每周 7 只显示当前月的日期 -->
<table class="calendar-body">
<thead>
<tr>
<th v-for="(day, index) in weekDays" :key="index">{{ day }}</th>
</tr>
</thead>
<tbody>
<tr v-for="(row, rowIndex) in calendarRows" :key="rowIndex">
<td
v-for="(cell, cellIndex) in row"
:key="cellIndex"
:class="getDayClass(cell.type)"
>
<!-- 只显示数字不含任何额外文本 -->
<span>{{ cell.dayNum }}</span>
</td>
</tr>
</tbody>
</table>
<!-- legend 区域展示不同 type 的色块与说明 -->
<div class="calendar-legend">
<div class="legend-item" v-for="legend in legends" :key="legend.type">
<span
class="color-box"
:style="{ backgroundColor: legend.color }"
></span>
<span class="legend-text">{{ legend.label }}</span>
</div>
</div>
</div>
</template>
<script>
export default {
name: "MiniCalendar",
/**
* 父组件可以通过 :daysData 传入当前月的具体日期和 type
* 示例[{ date: '2025-03-01', type: 1 }, { date: '2025-03-02', type: 2 }, ...]
*/
props: {
daysData: {
type: Array,
default: () => []
}
},
data() {
return {
// 星期栏
weekDays: ["日", "一", "二", "三", "四", "五", "六"],
// legend 配置type对应的背景色 + 说明
legends: [
{ type: 1, label: "休息日", color: "#d3f6f3" },
{ type: 2, label: "节假日", color: "#ffe7ba" },
{ type: 3, label: "调休", color: "#ffdede" },
{ type: 4, label: "出差", color: "#fa18bc" },
{ type: 5, label: "请假", color: "#c4c4eb" }
]
};
},
computed: {
/**
* 当前日期对象默认为今天也可自行改成其它月份
*/
currentDate() {
return new Date();
},
currentMonth() {
return this.currentDate.getMonth(); // 0-11
},
currentYear() {
return this.currentDate.getFullYear();
},
// 用于在日历头部显示“YYYY年M月”
currentMonthYear() {
return `${this.currentYear}${this.currentMonth + 1}`;
},
/**
* 生成一个二维数组每一行代表一周单元格中有 { dayNum, dateStr, type }
* 只显示当月的日期如果第一天不是周日前面会插入空格
*/
calendarRows() {
// 当前月1号
const firstDayOfMonth = new Date(this.currentYear, this.currentMonth, 1);
const firstDayIndex = firstDayOfMonth.getDay(); // 0=周日,1=周一, ...
// 本月总天数
const daysInMonth = new Date(this.currentYear, this.currentMonth + 1, 0).getDate();
// 准备一个空数组,往里放 dayNum 和 type
const cells = [];
// 1) 填充本月第一天前面的空白单元格
for (let i = 0; i < firstDayIndex; i++) {
cells.push({ dayNum: "", dateStr: "", type: null });
}
// 2) 填充本月每一天
for (let day = 1; day <= daysInMonth; day++) {
const dateObj = new Date(this.currentYear, this.currentMonth, day);
const dateStr = this.formatDate(dateObj); // YYYY-MM-DD
// 根据 daysData 查找 type
const dayType = this.findDayType(dateStr);
cells.push({
dayNum: day,
dateStr,
type: dayType
});
}
// 3) 将 cells 拆分成多行每行7列
const rows = [];
for (let i = 0; i < cells.length; i += 7) {
rows.push(cells.slice(i, i + 7));
}
return rows;
}
},
methods: {
/**
* 格式化 Date => "YYYY-MM-DD"
*/
formatDate(d) {
const year = d.getFullYear();
const month = String(d.getMonth() + 1).padStart(2, "0");
const day = String(d.getDate()).padStart(2, "0");
return `${year}-${month}-${day}`;
},
/**
* daysData 中找对应日期的 type找不到就默认为 0工作日
*/
findDayType(dateStr) {
const item = this.daysData.find((day) => day.date === dateStr);
return item ? item.type : 0; // 默认工作日(0)
},
/**
* 返回一个 class 用于设置对应背景色
*/
getDayClass(type) {
switch (type) {
case 0: return "type-workday"; // 工作日
case 1: return "type-rest"; // 休息日
case 2: return "type-holiday"; // 节假日
case 3: return "type-adjust"; // 调休
case 4: return "type-trip"; // 出差
case 5: return "type-leave"; // 请假
default: return "";
}
}
}
};
</script>
<style scoped>
.mini-calendar {
border: 1px solid #ccc;
padding: 10px;
background-color: white;
box-sizing: border-box;
/* 若需要更细节的布局控制,可以加上 float 或 display 属性,比如 float: left; */
}
/* 日历头部 */
.calendar-header {
text-align: center;
font-size: 16px;
font-weight: bold;
margin-bottom: 8px;
}
/* 日历主体样式 */
.calendar-body {
width: 100%;
border-collapse: collapse;
margin-bottom: 8px;
}
.calendar-body th,
.calendar-body td {
width: 14.28%; /* 7天 */
height: 40px;
text-align: center;
vertical-align: middle;
}
/* 不同 type 的背景色 */
.type-workday {
background-color: transparent;
}
.type-rest {
background-color: #d3f6f3;
}
.type-holiday {
background-color: #ffe7ba;
}
.type-adjust {
background-color: #ffdede;
}
.type-trip {
background-color: #c6ebf5;
}
.type-leave {
background-color: #c4c4eb;
}
/* legend 部分:展示各类型色块和说明 */
.calendar-legend {
margin-top: 12px;
display: flex;
flex-wrap: wrap;
gap: 10px;
}
.legend-item {
display: flex;
align-items: center;
}
.color-box {
display: inline-block;
width: 14px;
height: 14px;
margin-right: 4px;
}
.legend-text {
font-size: 12px;
}
</style>