Files
klp-oa/klp-ui/src/components/HomeModules/MiniCalendar.vue
砂糖 c657dad4d3 feat: 重构首页布局并添加新功能模块
- 重构首页布局,移除旧图表组件,添加流程表格和迷你日历
- 新增常用应用组件,支持收藏和管理常用功能
- 新增流程表格组件,展示我的流程和待办任务
- 新增迷你日历组件,支持不同类型日期标记
- 优化统计卡片组件,拆分客户和供应商统计
- 调整部分表格列名显示更准确
2025-10-31 13:14:10 +08:00

239 lines
6.2 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>
<!-- 外层容器占用 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>