vue3鼠标移动矩形选择组件
vue3实现鼠标按下后开始移动鼠标选择,移动到的数据就选中,如果已经是被选中则反选。
实例
demo组件
<template>
<div style="width: 100%;">
<div class="time">
<div class="timeleft">周/小时</div>
<div class="timeright">
<div class="timeright_cell">
<el-row :gutter="0">
<el-col :span="12">
<div class="topitem">00:00~12:00</div>
</el-col>
<el-col :span="12">
<div class="topitem">12:00~24:00</div>
</el-col>
</el-row>
</div>
<div class="timeright_cell">
<el-row :gutter="0">
<el-col :span="1" v-for="(item, index) in 24" :key="item" @click="clicktime(index)">
<div class="topitem" :style="{ '--bgColor': bgColor }" :class="{ 'is_selected': isTimeSelected(index) }">
{{ index }}</div>
</el-col>
</el-row>
</div>
</div>
</div>
<div class="time">
<div style="width: 8%;">
<div class="timelefts" :style="{ '--bgColor': bgColor }" :class="{ 'is_selected': isDaySelected(index) }"
v-for="(dayName, index) in ['星期一', '星期二', '星期三', '星期四', '星期五', '星期六', '星期日']" :key="dayName"
@click="clickDay(index)">{{
dayName }}</div>
</div>
<div class="objects" ref="objectsRef" @mousedown="handleMouseDown">
<!-- 矩形选择框 -->
<div class="mask" ref="maskRef" v-show="maskPosition.show" :style="'width:' +
maskWidth +
'left:' +
maskLeft +
'height:' +
maskHeight +
'top:' +
maskTop
" />
<!-- 选择对象内容的目标插槽 -->
<!-- <slot name="selcetObject" /> -->
<div class="objects_content">
<div v-for="item in weekData" :key="item.id" class="select_object" :day_index="item.daynum"
:time_index="item.timenum" :object_id="item.id" :class="{ 'is_selected': item.status }"
:style="{ '--bgColor': bgColor }">
<!-- {{ item.id }} -->
</div>
</div>
</div>
</div>
<!-- 鼠标画矩形选择对象 -->
</div>
</template>
<script lang="ts" setup>
import { reactive, toRefs, ref, computed } from "vue";
const clientX = ref(0);
const clientY = ref(0);
const hasHandleObjectIds = ref<number[]>([]);//已处理id数组
const isDaySelected = computed(() => {
return (index) => {
if (props.weekData && props.weekData.length > 0) {
return props.weekData
.filter(t => t.daynum === index + 1)
.every(item => item.status === true);
}
return false;
};
})
const isTimeSelected = computed(() => {
return (index) => {
if (props.weekData && props.weekData.length > 0) {
return props.weekData
.filter(t => t.timenum === index + 1)
.every(item => item.status === true);
}
return false;
};
})
const props = withDefaults(
defineProps<{
objectClassName?: string; // 选择对象的class name,用于定义如何获取对象
objectIdName?: string; // 选择对象的id name,用于定义如何获取对象的id
weekData?: Array<any>; // 选中的对象
useCtrlSelect?: boolean; // 是否支持按住Ctrl多选
bgColor?: string; //选中的背景色
}>(),
{
objectClassName: 'select_object',
objectIdName: 'object_id',
bgColor: '#409eff',
useCtrlSelect: false // 默认支持按住Ctrl多选
}
);
const objectsRef = ref();
const maskRef = ref();
const emits = defineEmits(["update:weekData"]);
const state = reactive({
maskPosition: {
show: false,
startX: 0,
startY: 0,
endX: 0,
endY: 0
}, // 矩形框位置
isPressCtrlKey: false // 是否按下了Ctrl键
});
const { maskPosition, isPressCtrlKey } = toRefs(state);
// 若支持按住Ctrl多选,监听Ctrl事件
if (props.useCtrlSelect) {
// 释放
document.addEventListener("keyup", event => {
if (event.keyCode === 17) {
isPressCtrlKey.value = false;
}
});
// 按下
document.addEventListener("keydown", event => {
if (event.keyCode === 17) {
isPressCtrlKey.value = true;
}
});
}
//点击星期天数的事件
const clickDay = (index) => {
var weekData: Array<any> = [];
weekData = props.weekData === undefined ? [] : props.weekData;
// const hours = weekData[index].hours;
// const allIn = hasHandleObjectIds.value.every(item => weekData.includes(item));
const arr = weekData.filter(t => t.daynum == index + 1);
const allIn = arr.every(item => item.status === true);
if (allIn) {
arr.forEach(e => {
e.status = false;
hasHandleObjectIds.value.splice(hasHandleObjectIds.value.findIndex(t => t == e.id), 1);
});
} else {
arr.forEach(e => {
e.status = true;
hasHandleObjectIds.value.push(e.id);
});
}
}
// 点击时间点数
const clicktime = (index) => {
var weekData: Array<any> = [];
weekData = props.weekData === undefined ? [] : props.weekData;
const arr = weekData.filter(t => t.timenum == index + 1);
const allIn = arr.every(item => item.status === true);
if (allIn) {
arr.forEach(e => {
e.status = false;
hasHandleObjectIds.value.splice(hasHandleObjectIds.value.findIndex(t => t == e.id), 1);
});
} else {
arr.forEach(e => {
e.status = true;
hasHandleObjectIds.value.push(e.id);
});
}
}
/** 鼠标按下 */
const handleMouseDown = event => {
//点下时清空已处理数组
hasHandleObjectIds.value.length = 0;
var id = Number(event.target.getAttribute(props.objectIdName))
var weekData: Array<any> = [];
weekData = props.weekData === undefined ? [] : props.weekData;
// const hourItem = weekData.flatMap(day => day.hours).find(item => item.id === id);
const index = weekData.findIndex(t => t.id == id);
if (index > -1) {
weekData[index].status = !weekData[index].status;
}
if (!hasHandleObjectIds.value.includes(id)) {
hasHandleObjectIds.value.push(id);
} else {
hasHandleObjectIds.value.splice(hasHandleObjectIds.value.findIndex(t => t == id), 1);
}
// 展示矩形框,通过坐标位置来画出矩形
maskPosition.value.show = true;
maskPosition.value.startX = event.clientX;
maskPosition.value.startY = event.clientY;
maskPosition.value.endX = event.clientX;
maskPosition.value.endY = event.clientY;
// 监听鼠标移动事件和抬起离开事件
objectsRef.value.addEventListener("mousemove", handleMouseMove);
objectsRef.value.addEventListener("mouseup", handleMouseUp);
};
/** 鼠标移动 */
const handleMouseMove = event => {
if (clientX.value !== event.clientX || clientY.value !== event.clientY) {
clientX.value = event.clientX
clientY.value = event.clientY
maskPosition.value.endX = event.clientX;
maskPosition.value.endY = event.clientY;
var weekData: Array<any> = [];
weekData = props.weekData === undefined ? [] : props.weekData;
const selectedObjects = objectsRef.value.querySelectorAll(`.${props.objectClassName}`);
// 获取鼠标画出的矩形框位置
const rectanglePosition = maskRef.value.getClientRects()[0];
var rectangleSelObjects: Array<number> = [];//矩形框内的id数组
selectedObjects.forEach(item => {
const objectPosition = item.getClientRects()[0];
// 这里获取的id的方式定义于父组件的objectIdName
if (compareObjectPosition(objectPosition, rectanglePosition)) {
let id = item.getAttribute(props.objectIdName);
rectangleSelObjects.push(Number(id));
}
});
let handle = (id: number) => {
const index = weekData.findIndex(t => t.id == id);
if (index > -1) weekData[index].status = !weekData[index].status;
// let index = tempSelectObjectIds.findIndex(t => t == id);
}
// rectangleSelObjects.forEach(id => {
// if (!hasHandleObjectIds.value.includes(id)) {
// handle(id);
// hasHandleObjectIds.value.push(id);
// }
// })
// hasHandleObjectIds.value.forEach(id => {
// console.log(rectangleSelObjects);
// if (!rectangleSelObjects.includes(id)) {
// console.log(id);
// handle(id);
// hasHandleObjectIds.value.splice(hasHandleObjectIds.value.findIndex(t => t == id), 1);
// }
// })
// 处理存在于 hasHandleObjectIds 中但不在 rectangleSelObjects 中的元素
for (let i = hasHandleObjectIds.value.length - 1; i >= 0; i--) {
const id = hasHandleObjectIds.value[i];
if (!rectangleSelObjects.includes(id)) {
handle(id);
hasHandleObjectIds.value.splice(i, 1);
}
}
// 处理存在于 rectangleSelObjects 中但不在 hasHandleObjectIds 中的元素
for (const id of rectangleSelObjects) {
if (!hasHandleObjectIds.value.includes(id)) {
handle(id);
hasHandleObjectIds.value.push(id);
}
}
// emits("update:weekData", weekData);
// emits("update:selectObjectIds", tempSelectObjectIds);
}
};
/** 鼠标抬起离开 */
const handleMouseUp = () => {
// 移除鼠标监听事件
objectsRef.value.removeEventListener("mousemove", handleMouseMove);
objectsRef.value.removeEventListener("mouseup", handleMouseUp);
maskPosition.value.show = false;
handleResetMaskPosition();
};
/**
* 判断对象坐标是否在鼠标画出的矩形框坐标位置内
* @param objectPosition 对象坐标位置
* @param rectanglePosition 鼠标画出的矩形框坐标位置
*/
const compareObjectPosition = (objectPosition, rectanglePosition) => {
const maxX = Math.max(
objectPosition.x + objectPosition.width,
rectanglePosition.x + rectanglePosition.width
);
const maxY = Math.max(
objectPosition.y + objectPosition.height,
rectanglePosition.y + rectanglePosition.height
);
const minX = Math.min(objectPosition.x, rectanglePosition.x);
const minY = Math.min(objectPosition.y, rectanglePosition.y);
return (
maxX - minX <= objectPosition.width + rectanglePosition.width &&
maxY - minY <= objectPosition.height + rectanglePosition.height
);
};
/** 重置鼠标位置 */
const handleResetMaskPosition = () => {
maskPosition.value.startX = 0;
maskPosition.value.startY = 0;
maskPosition.value.endX = 0;
maskPosition.value.endY = 0;
};
/** 通过鼠标位置实时计算矩形框大小 */
const maskWidth = computed(() => {
return `${Math.abs(maskPosition.value.endX - maskPosition.value.startX)}px;`;
});
const maskHeight = computed(() => {
return `${Math.abs(maskPosition.value.endY - maskPosition.value.startY)}px;`;
});
const maskLeft = computed(() => {
return `${Math.min(maskPosition.value.startX, maskPosition.value.endX)}px;`;
});
const maskTop = computed(() => {
return `${Math.min(maskPosition.value.startY, maskPosition.value.endY)}px;`;
});
</script>
<style scoped lang="scss">
.time {
width: 100%;
display: flex;
align-items: center;
// border: #999 1px solid;
.timeleft {
width: 7.95%;
height: 80px;
display: flex;
align-items: center;
justify-content: center;
background: #dad8d8;
border-bottom: #999 1px solid;
border-top: #999 1px solid;
border-left: #999 1px solid;
box-sizing: border-box;
}
.timeright {
height: 80px;
background: #dad8d8;
width: 92%;
border-right: #999 1px solid;
box-sizing: border-box;
border-top: #999 1px solid;
.timeright_cell {
border-bottom: #999 1px solid;
box-sizing: border-box;
.topitem {
height: 38.6px;
display: flex;
align-items: center;
justify-content: center;
border-left: #999 1px solid;
text-align: center;
box-sizing: border-box;
}
.is_selected {
background: var(--bgColor);
color: #fff;
}
}
}
.timelefts {
height: 40px;
display: flex;
align-items: center;
justify-content: center;
background: #dad8d8;
border-bottom: #999 1px solid;
border-left: #999 1px solid;
border-right: #999 1px solid;
box-sizing: border-box;
}
.is_selected {
background: var(--bgColor);
color: #fff;
}
.objects {
height: 100%;
width: 92%;
// overflow-y: auto;
.mask {
position: fixed;
background: #409eff;
opacity: 0;
z-index: 100;
}
.objects_content {
user-select: none;
display: flex;
flex-wrap: wrap;
>div {
display: flex;
align-items: center;
justify-content: center;
width: 2.083%;
height: 40px;
box-sizing: border-box;
border-bottom: #999 1px solid;
border-right: #999 1px solid;
}
.is_selected {
color: #fff;
background-color: var(--bgColor);
}
}
}
}
</style>
数组不传的话就是这个
<template>
<div style="width: 100%;">
<div class="time">
<div class="timeleft">周/小时</div>
<div class="timeright">
<div class="timeright_cell">
<el-row :gutter="0">
<el-col :span="12">
<div class="topitem">00:00~12:00</div>
</el-col>
<el-col :span="12">
<div class="topitem">12:00~24:00</div>
</el-col>
</el-row>
</div>
<div class="timeright_cell">
<el-row :gutter="0">
<el-col :span="1" v-for="(item, index) in 24" :key="item" @click="clicktime(index)">
<div class="topitem" :style="{ '--bgColor': bgColor }" :class="{ 'is_selected': isTimeSelected(index) }">
{{ index }}</div>
</el-col>
</el-row>
</div>
</div>
</div>
<div class="time">
<div style="width: 8%;">
<div class="timelefts" :style="{ '--bgColor': bgColor }" :class="{ 'is_selected': isDaySelected(index) }"
v-for="(dayName, index) in ['星期一', '星期二', '星期三', '星期四', '星期五', '星期六', '星期日']" :key="dayName"
@click="clickDay(index)">{{
dayName }}</div>
</div>
<div class="objects" ref="objectsRef" @mousedown="handleMouseDown">
<!-- 矩形选择框 -->
<div class="mask" ref="maskRef" v-show="maskPosition.show" :style="'width:' +
maskWidth +
'left:' +
maskLeft +
'height:' +
maskHeight +
'top:' +
maskTop
" />
<!-- 选择对象内容的目标插槽 -->
<!-- <slot name="selcetObject" /> -->
<div class="objects_content">
<div v-for="item in weekData" :key="item.id" class="select_object" :day_index="item.daynum"
:time_index="item.timenum" :object_id="item.id" :class="{ 'is_selected': item.status }"
:style="{ '--bgColor': bgColor }">
<!-- {{ item.id }} -->
</div>
</div>
</div>
</div>
<!-- 鼠标画矩形选择对象 -->
</div>
</template>
<script lang="ts" setup>
import { reactive, toRefs, ref, computed, onMounted } from "vue";
const clientX = ref(0);
const clientY = ref(0);
const hasHandleObjectIds = ref<number[]>([]);//已处理id数组
// 全局计数器
let uniqueId = 1;
// 初始化 weekData
const weekData = ref([] as any);
// 初始化 weekData 中的 hours
onMounted(() => {
for (let i = 0; i < 7; i++) {
for (let hour = 0, timenum = 1; hour < 48; hour += 2) {
weekData.value.push({ id: uniqueId++, status: false, daynum: i + 1, timenum: timenum });
weekData.value.push({ id: uniqueId++, status: false, daynum: i + 1, timenum: timenum });
timenum = (timenum % 24) + 1; // 使 timenum 在 1 到 24 之间循环
}
}
});
const isDaySelected = computed(() => {
return (index) => {
if (weekData.value && weekData.value.length > 0) {
return weekData.value
.filter(t => t.daynum === index + 1)
.every(item => item.status === true);
}
return false;
};
})
const isTimeSelected = computed(() => {
return (index) => {
if (weekData.value && weekData.value.length > 0) {
return weekData.value
.filter(t => t.timenum === index + 1)
.every(item => item.status === true);
}
return false;
};
})
const props = withDefaults(
defineProps<{
objectClassName?: string; // 选择对象的class name,用于定义如何获取对象
objectIdName?: string; // 选择对象的id name,用于定义如何获取对象的id
useCtrlSelect?: boolean; // 是否支持按住Ctrl多选
bgColor?: string; //选中的背景色
}>(),
{
objectClassName: 'select_object',
objectIdName: 'object_id',
bgColor: '#409eff',
useCtrlSelect: false // 默认支持按住Ctrl多选
}
);
const objectsRef = ref();
const maskRef = ref();
const emits = defineEmits(["update:weekData"]);
const state = reactive({
maskPosition: {
show: false,
startX: 0,
startY: 0,
endX: 0,
endY: 0
}, // 矩形框位置
isPressCtrlKey: false // 是否按下了Ctrl键
});
const { maskPosition, isPressCtrlKey } = toRefs(state);
// 若支持按住Ctrl多选,监听Ctrl事件
if (props.useCtrlSelect) {
// 释放
document.addEventListener("keyup", event => {
if (event.keyCode === 17) {
isPressCtrlKey.value = false;
}
});
// 按下
document.addEventListener("keydown", event => {
if (event.keyCode === 17) {
isPressCtrlKey.value = true;
}
});
}
//点击星期天数的事件
const clickDay = (index) => {
// var weekData: Array<any> = [];
// weekData = weekData === undefined ? [] : weekData;
// const hours = weekData[index].hours;
// const allIn = hasHandleObjectIds.value.every(item => weekData.includes(item));
const arr = weekData.value.filter(t => t.daynum == index + 1);
const allIn = arr.every(item => item.status === true);
if (allIn) {
arr.forEach(e => {
e.status = false;
hasHandleObjectIds.value.splice(hasHandleObjectIds.value.findIndex(t => t == e.id), 1);
});
} else {
arr.forEach(e => {
e.status = true;
hasHandleObjectIds.value.push(e.id);
});
}
}
// 点击时间点数
const clicktime = (index) => {
const arr = weekData.value.filter(t => t.timenum == index + 1);
const allIn = arr.every(item => item.status === true);
if (allIn) {
arr.forEach(e => {
e.status = false;
hasHandleObjectIds.value.splice(hasHandleObjectIds.value.findIndex(t => t == e.id), 1);
});
} else {
arr.forEach(e => {
e.status = true;
hasHandleObjectIds.value.push(e.id);
});
}
}
/** 鼠标按下 */
const handleMouseDown = event => {
//点下时清空已处理数组
hasHandleObjectIds.value.length = 0;
var id = Number(event.target.getAttribute(props.objectIdName))
// var weekData: Array<any> = [];
// weekData = weekData === undefined ? [] : weekData;
// const hourItem = weekData.flatMap(day => day.hours).find(item => item.id === id);
const index = weekData.value.findIndex(t => t.id == id);
if (index > -1) {
weekData.value[index].status = !weekData.value[index].status;
}
if (!hasHandleObjectIds.value.includes(id)) {
hasHandleObjectIds.value.push(id);
} else {
hasHandleObjectIds.value.splice(hasHandleObjectIds.value.findIndex(t => t == id), 1);
}
// 展示矩形框,通过坐标位置来画出矩形
maskPosition.value.show = true;
maskPosition.value.startX = event.clientX;
maskPosition.value.startY = event.clientY;
maskPosition.value.endX = event.clientX;
maskPosition.value.endY = event.clientY;
// 监听鼠标移动事件和抬起离开事件
objectsRef.value.addEventListener("mousemove", handleMouseMove);
objectsRef.value.addEventListener("mouseup", handleMouseUp);
};
/** 鼠标移动 */
const handleMouseMove = event => {
if (clientX.value !== event.clientX || clientY.value !== event.clientY) {
clientX.value = event.clientX
clientY.value = event.clientY
maskPosition.value.endX = event.clientX;
maskPosition.value.endY = event.clientY;
// var weekData: Array<any> = [];
// weekData = props.weekData === undefined ? [] : props.weekData;
const selectedObjects = objectsRef.value.querySelectorAll(`.${props.objectClassName}`);
// 获取鼠标画出的矩形框位置
const rectanglePosition = maskRef.value.getClientRects()[0];
var rectangleSelObjects: Array<number> = [];//矩形框内的id数组
selectedObjects.forEach(item => {
const objectPosition = item.getClientRects()[0];
// 这里获取的id的方式定义于父组件的objectIdName
if (compareObjectPosition(objectPosition, rectanglePosition)) {
let id = item.getAttribute(props.objectIdName);
rectangleSelObjects.push(Number(id));
}
});
let handle = (id: number) => {
const index = weekData.value.findIndex(t => t.id == id);
if (index > -1) weekData.value[index].status = !weekData.value[index].status;
// let index = tempSelectObjectIds.findIndex(t => t == id);
}
// rectangleSelObjects.forEach(id => {
// if (!hasHandleObjectIds.value.includes(id)) {
// handle(id);
// hasHandleObjectIds.value.push(id);
// }
// })
// hasHandleObjectIds.value.forEach(id => {
// console.log(rectangleSelObjects);
// if (!rectangleSelObjects.includes(id)) {
// console.log(id);
// handle(id);
// hasHandleObjectIds.value.splice(hasHandleObjectIds.value.findIndex(t => t == id), 1);
// }
// })
// 处理存在于 hasHandleObjectIds 中但不在 rectangleSelObjects 中的元素
for (let i = hasHandleObjectIds.value.length - 1; i >= 0; i--) {
const id = hasHandleObjectIds.value[i];
if (!rectangleSelObjects.includes(id)) {
handle(id);
hasHandleObjectIds.value.splice(i, 1);
}
}
// 处理存在于 rectangleSelObjects 中但不在 hasHandleObjectIds 中的元素
for (const id of rectangleSelObjects) {
if (!hasHandleObjectIds.value.includes(id)) {
handle(id);
hasHandleObjectIds.value.push(id);
}
}
// emits("update:weekData", weekData);
// emits("update:selectObjectIds", tempSelectObjectIds);
}
};
/** 鼠标抬起离开 */
const handleMouseUp = () => {
// 移除鼠标监听事件
objectsRef.value.removeEventListener("mousemove", handleMouseMove);
objectsRef.value.removeEventListener("mouseup", handleMouseUp);
maskPosition.value.show = false;
handleResetMaskPosition();
};
/**
* 判断对象坐标是否在鼠标画出的矩形框坐标位置内
* @param objectPosition 对象坐标位置
* @param rectanglePosition 鼠标画出的矩形框坐标位置
*/
const compareObjectPosition = (objectPosition, rectanglePosition) => {
const maxX = Math.max(
objectPosition.x + objectPosition.width,
rectanglePosition.x + rectanglePosition.width
);
const maxY = Math.max(
objectPosition.y + objectPosition.height,
rectanglePosition.y + rectanglePosition.height
);
const minX = Math.min(objectPosition.x, rectanglePosition.x);
const minY = Math.min(objectPosition.y, rectanglePosition.y);
return (
maxX - minX <= objectPosition.width + rectanglePosition.width &&
maxY - minY <= objectPosition.height + rectanglePosition.height
);
};
/** 重置鼠标位置 */
const handleResetMaskPosition = () => {
maskPosition.value.startX = 0;
maskPosition.value.startY = 0;
maskPosition.value.endX = 0;
maskPosition.value.endY = 0;
};
/** 通过鼠标位置实时计算矩形框大小 */
const maskWidth = computed(() => {
return `${Math.abs(maskPosition.value.endX - maskPosition.value.startX)}px;`;
});
const maskHeight = computed(() => {
return `${Math.abs(maskPosition.value.endY - maskPosition.value.startY)}px;`;
});
const maskLeft = computed(() => {
return `${Math.min(maskPosition.value.startX, maskPosition.value.endX)}px;`;
});
const maskTop = computed(() => {
return `${Math.min(maskPosition.value.startY, maskPosition.value.endY)}px;`;
});
</script>
<style scoped lang="scss">
.time {
width: 100%;
display: flex;
align-items: center;
// border: #999 1px solid;
.timeleft {
width: 7.95%;
height: 80px;
display: flex;
align-items: center;
justify-content: center;
background: #dad8d8;
border-bottom: #999 1px solid;
border-top: #999 1px solid;
border-left: #999 1px solid;
box-sizing: border-box;
}
.timeright {
height: 80px;
background: #dad8d8;
width: 92%;
border-right: #999 1px solid;
box-sizing: border-box;
border-top: #999 1px solid;
.timeright_cell {
border-bottom: #999 1px solid;
box-sizing: border-box;
.topitem {
height: 38.6px;
display: flex;
align-items: center;
justify-content: center;
border-left: #999 1px solid;
text-align: center;
box-sizing: border-box;
}
.is_selected {
background: var(--bgColor);
color: #fff;
}
}
}
.timelefts {
height: 40px;
display: flex;
align-items: center;
justify-content: center;
background: #dad8d8;
border-bottom: #999 1px solid;
border-left: #999 1px solid;
border-right: #999 1px solid;
box-sizing: border-box;
}
.is_selected {
background: var(--bgColor);
color: #fff;
}
.objects {
height: 100%;
width: 92%;
// overflow-y: auto;
.mask {
position: fixed;
background: #409eff;
opacity: 0;
z-index: 100;
}
.objects_content {
user-select: none;
display: flex;
flex-wrap: wrap;
>div {
display: flex;
align-items: center;
justify-content: center;
width: 2.083%;
height: 40px;
box-sizing: border-box;
border-bottom: #999 1px solid;
border-right: #999 1px solid;
}
.is_selected {
color: #fff;
background-color: var(--bgColor);
}
}
}
}
</style>
组件使用
<demo v-model:weekData="weekData"></demo>
import Demo from "./components/test/tests.vue";
// 全局计数器
let uniqueId = 1;
// 初始化 weekData
const weekData = ref([] as any);
// 初始化 weekData 中的 hours
onMounted(() => {
for (let i = 0; i < 7; i++) {
for (let hour = 0, timenum = 1; hour < 48; hour += 2) {
weekData.value.push({ id: uniqueId++, status: false, daynum: i + 1, timenum: timenum });
weekData.value.push({ id: uniqueId++, status: false, daynum: i + 1, timenum: timenum });
timenum = (timenum % 24) + 1; // 使 timenum 在 1 到 24 之间循环
}
}
});
结束