feat: 重构首页布局并添加新功能模块
- 重构首页布局,移除旧图表组件,添加流程表格和迷你日历 - 新增常用应用组件,支持收藏和管理常用功能 - 新增流程表格组件,展示我的流程和待办任务 - 新增迷你日历组件,支持不同类型日期标记 - 优化统计卡片组件,拆分客户和供应商统计 - 调整部分表格列名显示更准确
This commit is contained in:
238
klp-ui/src/components/HomeModules/MiniCalendar.vue
Normal file
238
klp-ui/src/components/HomeModules/MiniCalendar.vue
Normal file
@@ -0,0 +1,238 @@
|
||||
<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>
|
||||
Reference in New Issue
Block a user