开篇
本篇文章旨在实现一个基于el-table的表格点选和框选功能,除此之外,还支持多种模式的切换、自定义勾选日期等。且,该表格后续可能还会持续优化!
功能介绍
- 表格点选和框选功能(没有点击ctrl键的情况下)
- 表格点选和框选功能的互斥功能,意思是当现在选择了该单元格后,按住ctrl键再次点击,就会取消选择
- 当前日期高亮
- 周、双周、月份模式的切换以及自定义日期的选择
- 对于可点选和框选功能的范围判断(表头和名称不可选择)
代码实现
index.vue
<template>
<div class="container">
<!-- 顶部功能栏区域 -->
<data class="top-bar">
<!-- 切换模式按钮 -->
<el-button size="mini" type="primary" @click="turnWeek">周</el-button>
<el-button size="mini" type="primary" @click="turnTwoWeeks"
>两周</el-button
>
<el-button size="mini" type="primary" @click="turnMonth">月</el-button>
<!-- 自定义时间范围选择器 -->
<div class="time-range-picker">
<span class="arrow-icon">
<el-icon><ArrowLeftBold /></el-icon>
</span>
<!-- 起始日期 -->
<el-date-picker
class="time-picker"
v-model="dateForm.startDate"
type="datetime"
:shortcuts="shortcuts"
@change="(value) => handleDateChange('startDate', value)"
/>
<span style="padding: 0 10px">-</span>
<!--结束日期 -->
<el-date-picker
class="time-picker"
v-model="dateForm.endDate"
type="datetime"
:shortcuts="shortcuts"
@change="(value) => handleDateChange('endDate', value)"
/>
<span class="arrow-icon">
<el-icon><ArrowRightBold /></el-icon>
</span>
</div>
</data>
<!-- 表格区域 -->
<div class="table-container">
<!-- 月份选择 -->
<month-schedule-table
:table-data="tableData"
:switch-model="switchModel"
:dateForm="dateForm"
:customDateFlag="customDateFlag"
@updateDateForm="handleUpdateDateForm"
:table-width="tableWidth"
></month-schedule-table>
</div>
</div>
</template>
<script>
import {
defineComponent,
onMounted,
reactive,
toRefs,
ref,
watchEffect,
onUpdated,
onUnmounted,
nextTick,
} from "vue";
import MonthScheduleTable from "./components/MonthScheduleTable.vue";
export default defineComponent({
name: "DepartmentScheduleConfig",
components: {
MonthScheduleTable,
},
setup() {
const state = reactive({
tableData: [],
switchModel: "month",
// 自定义日期选择相关
dateForm: {
startDate: "",
endDate: "",
},
customDateFlag: false, // 是否在自定义切换日期的标识
});
const tableWidth = ref(0);
onMounted(() => {
// 先初始化一些假数据用着
initData();
nextTick(() => {
getTableWidth();
});
});
const getTableWidth = () => {
// 求表格宽度
let container = document.querySelector(".container");
if (container) {
const observer = new ResizeObserver(() => {
tableWidth.value = container.clientWidth;
});
observer.observe(container);
// 初始获取一次宽度
tableWidth.value = container.clientWidth;
}
};
// 每次更新表格时,也要重新获取表格宽度
onUpdated(() => {
getTableWidth();
});
window.addEventListener("resize", getTableWidth);
// 页面关闭时,移除事件监听器
onUnmounted(() => {
window.removeEventListener("resize", getTableWidth);
});
// 切换成周模式
const turnWeek = () => {
state.switchModel = "week";
state.customDateFlag = false;
};
// 切换成两周模式
const turnTwoWeeks = () => {
state.switchModel = "twoWeeks";
state.customDateFlag = false;
};
// 切换成月模式
const turnMonth = () => {
state.switchModel = "month";
state.customDateFlag = false;
};
// 初始化数据
const initData = () => {
const obj = {
};
for (let i = 0; i <= 31; i++) {
obj[`date${
i}`] = null;
}
const arr = [];
for (let j = 1; j < 10; j++) {
const tmpObj = {
...obj };
tmpObj.id = j;
tmpObj.name = `zzz${
j}`;
arr.push(tmpObj);
}
console.log("arr", arr);
arr[0].date1 = "X";
arr[3].date3 = "Y";
state.tableData = arr;
};
/**
* 自定义日期相关
*/
// 日期选择面板扩展
const shortcuts = [
{
text: "今天",
value: new Date(),
},
{
text: "昨天",
value: () => {
const date = new Date();
date.setDate(date.getDate() - 1);