某时间某空间占用情况效果展示,vue2+element ui实现。场景:会议室占用、教室占用等。
场景说明:
现在需要基于vue2和el-table实现每日会议室个时间点占用情况。
已知数据:
1、会议室数据(名称,id)
2、会议计划数据(id,名称,会议室id,开始时间,结束时间)
表格展示内容:
表头构成:日期,会议室,00-07,08,09,10...19-23(小时格子对应24小时)。
1、日期列:代表从今天开始到未来7天的日期,因此一天对应多个会议室,需要合并相同日期。
2、格子占用规则:会议室时间开始时间向下取整,结束时间向上取整,跨时间合并小时格子。
3、格子显示内容:展示对应会议数据的数据量,鼠标悬浮上去需要弹出显示会议数据列表。
具体如:2025-05-21 8:23-9:00 就占08的格子,8:23-9:30就占08和09的格子并合并,
特殊情况如有3个会议数据对应时间 18-19:30,20-20:30,21-23,就需要合并18和19-23的格子并显示数量3,鼠标悬浮展示这三条。
实现效果:
具体展示效果可以根据代码调整。
代码实现:
javascript
<template>
<div class="meeting-room-table">
<el-table :data="tableData" :span-method="objectSpanMethod" border tooltip-effect="light" style="width: 100%">
<el-table-column prop="date" label="时间" width="120"></el-table-column>
<el-table-column prop="roomName" label="会议室" width="120"></el-table-column>
<el-table-column prop="time0007" label="00-07">
<template slot-scope="scope">
<el-tooltip content="" :disabled="scope.row.time0007 === 0" effect="light" placement="top">
<div slot="content">
<div v-if="scope.row.time0007Meetings.length" v-for="(meeting, index) in scope.row.time0007Meetings"
:key="index" class="tooltip-item">
<span>主持人:{{ meeting.userName }}</span>
<span>主题: {{ meeting.theme }}</span>
<span>会议时间:{{ formatTime(meeting.beginSta) }}-{{ formatTime(meeting.beginEnd) }}</span>
<span>会议状态:{{meeting.state|statefitler}}</span>
</div>
</div>
<div class="time-cell" :class="{ 'occupied': scope.row.time0007 > 0 }"
@mouseenter="showTooltip(scope.$index, 'time0007')">
<i v-if="scope.row.time0007" class="el-icon-user"/> {{ scope.row.time0007 || '' }}
</div>
</el-tooltip>
</template>
</el-table-column>
<el-table-column prop="time08" label="08">
<template slot-scope="scope">
<el-tooltip content="" :disabled="scope.row.time08 === 0" effect="light" placement="top">
<div slot="content">
<div v-if="scope.row.time08Meetings.length" v-for="(meeting, index) in scope.row.time08Meetings"
:key="index" class="tooltip-item">
<span>主持人:{{ meeting.userName }}</span>
<span>主题: {{ meeting.theme }}</span>
<span>会议时间:{{ formatTime(meeting.beginSta) }}-{{ formatTime(meeting.beginEnd) }}</span>
<span>会议状态:{{meeting.state|statefitler}}</span>
</div>
</div>
<div class="time-cell" :class="{ 'occupied': scope.row.time08 > 0 }"
@mouseenter="showTooltip(scope.$index, 'time08')">
<i v-if="scope.row.time08" class="el-icon-user"/> {{ scope.row.time08 || '' }}
</div>
</el-tooltip>
</template>
</el-table-column>
<el-table-column prop="time09" label="09">
<template slot-scope="scope">
<el-tooltip content="" :disabled="scope.row.time09 === 0" effect="light" placement="top">
<div slot="content">
<div v-if="scope.row.time09Meetings.length" v-for="(meeting, index) in scope.row.time09Meetings"
:key="index" class="tooltip-item">
<span>主持人:{{ meeting.userName }}</span>
<span>主题: {{ meeting.theme }}</span>
<span>会议时间:{{ formatTime(meeting.beginSta) }}-{{ formatTime(meeting.beginEnd) }}</span>
<span>会议状态:{{meeting.state|statefitler}}</span>
</div>
</div>
<div class="time-cell" :class="{ 'occupied': scope.row.time09 > 0 }"
@mouseenter="showTooltip(scope.$index, 'time09')">
<i v-if="scope.row.time09" class="el-icon-user"/> {{ scope.row.time09 || '' }}
</div>
</el-tooltip>
</template>
</el-table-column>
<el-table-column prop="time10" label="10">
<template slot-scope="scope">
<el-tooltip content="" :disabled="scope.row.time10 === 0" effect="light" placement="top">
<div slot="content">
<div v-if="scope.row.time10Meetings.length" v-for="(meeting, index) in scope.row.time10Meetings"
:key="index" class="tooltip-item">
<span>主持人:{{ meeting.userName }}</span>
<span>主题: {{ meeting.theme }}</span>
<span>会议时间:{{ formatTime(meeting.beginSta) }}-{{ formatTime(meeting.beginEnd) }}</span>
<span>会议状态:{{meeting.state|statefitler}}</span>
</div>
</div>
<div class="time-cell" :class="{ 'occupied': scope.row.time10 > 0 }"
@mouseenter="showTooltip(scope.$index, 'time10')">
<i v-if="scope.row.time10" class="el-icon-user"/> {{ scope.row.time10 || '' }}
</div>
</el-tooltip>
</template>
</el-table-column>
<el-table-column prop="time11" label="11">
<template slot-scope="scope">
<el-tooltip content="" :disabled="scope.row.time11 === 0" effect="light" placement="top">
<div slot="content">
<div v-if="scope.row.time11Meetings.length" v-for="(meeting, index) in scope.row.time11Meetings"
:key="index" class="tooltip-item">
<span>主持人:{{ meeting.userName }}</span>
<span>主题: {{ meeting.theme }}</span>
<span>会议时间:{{ formatTime(meeting.beginSta) }}-{{ formatTime(meeting.beginEnd) }}</span>
<span>会议状态:{{meeting.state|statefitler}}</span>
</div>
</div>
<div class="time-cell" :class="{ 'occupied': scope.row.time11 > 0 }"
@mouseenter="showTooltip(scope.$index, 'time11')">
<i v-if="scope.row.time11" class="el-icon-user"/> {{ scope.row.time11 || '' }}
</div>
</el-tooltip>
</template>
</el-table-column>
<el-table-column prop="time12" label="12">
<template slot-scope="scope">
<el-tooltip content="" :disabled="scope.row.time12 === 0" effect="light" placement="top">
<div slot="content">
<div v-if="scope.row.time12Meetings.length" v-for="(meeting, index) in scope.row.time12Meetings"
:key="index" class="tooltip-item">
<span>主持人:{{ meeting.userName }}</span>
<span>主题: {{ meeting.theme }}</span>
<span>会议时间:{{ formatTime(meeting.beginSta) }}-{{ formatTime(meeting.beginEnd) }}</span>
<span>会议状态:{{meeting.state|statefitler}}</span>
</div>
</div>
<div class="time-cell" :class="{ 'occupied': scope.row.time12 > 0 }"
@mouseenter="showTooltip(scope.$index, 'time12')">
<i v-if="scope.row.time12" class="el-icon-user"/> {{ scope.row.time12 || '' }}
</div>
</el-tooltip>
</template>
</el-table-column>
<el-table-column prop="time13" label="13">
<template slot-scope="scope">
<el-tooltip content="" :disabled="scope.row.time13 === 0" effect="light" placement="top">
<div slot="content">
<div v-if="scope.row.time13Meetings.length" v-for="(meeting, index) in scope.row.time13Meetings"
:key="index" class="tooltip-item">
<span>主持人:{{ meeting.userName }}</span>
<span>主题: {{ meeting.theme }}</span>
<span>会议时间:{{ formatTime(meeting.beginSta) }}-{{ formatTime(meeting.beginEnd) }}</span>
<span>会议状态:{{meeting.state|statefitler}}</span>
</div>
</div>
<div class="time-cell" :class="{ 'occupied': scope.row.time13 > 0 }"
@mouseenter="showTooltip(scope.$index, 'time13')">
<i v-if="scope.row.time13" class="el-icon-user"/> {{ scope.row.time13 || '' }}
</div>
</el-tooltip>
</template>
</el-table-column>
<el-table-column prop="time14" label="14">
<template slot-scope="scope">
<el-tooltip content="" :disabled="scope.row.time14 === 0" effect="light" placement="top">
<div slot="content">
<div v-if="scope.row.time14Meetings.length" v-for="(meeting, index) in scope.row.time14Meetings"
:key="index" class="tooltip-item">
<span>主持人:</span>
<span>主题:</span>
<span>会议时间:</span>
<span>会议状态:</span>
<span>主持人:{{ meeting.userName }}</span>
<span>主题: {{ meeting.theme }}</span>
<span>会议时间:{{ formatTime(meeting.beginSta) }}-{{ formatTime(meeting.beginEnd) }}</span>
<span>会议状态:{{meeting.state|statefitler}}</span>
</div>
</div>
<div class="time-cell" :class="{ 'occupied': scope.row.time14 > 0 }"
@mouseenter="showTooltip(scope.$index, 'time14')">
<i v-if="scope.row.time14" class="el-icon-user"/> {{ scope.row.time14 || '' }}
</div>
</el-tooltip>
</template>
</el-table-column>
<el-table-column prop="time15" label="15">
<template slot-scope="scope">
<el-tooltip content="" :disabled="scope.row.time15 === 0" effect="light" placement="top">
<div slot="content">
<div v-if="scope.row.time15Meetings.length" v-for="(meeting, index) in scope.row.time15Meetings"
:key="index" class="tooltip-item">
<span>主持人:{{ meeting.userName }}</span>
<span>主题: {{ meeting.theme }}</span>
<span>会议时间:{{ formatTime(meeting.beginSta) }}-{{ formatTime(meeting.beginEnd) }}</span>
<span>会议状态:{{meeting.state|statefitler}}</span>
</div>
</div>
<div class="time-cell" :class="{ 'occupied': scope.row.time15 > 0 }"
@mouseenter="showTooltip(scope.$index, 'time15')">
<i v-if="scope.row.time15" class="el-icon-user"/> {{ scope.row.time15 || '' }}
</div>
</el-tooltip>
</template>
</el-table-column>
<el-table-column prop="time16" label="16">
<template slot-scope="scope">
<el-tooltip content="" :disabled="scope.row.time16 === 0" effect="light" placement="top">
<div slot="content">
<div v-if="scope.row.time16Meetings.length" v-for="(meeting, index) in scope.row.time16Meetings"
:key="index" class="tooltip-item">
<span>主持人:{{ meeting.userName }}</span>
<span>主题: {{ meeting.theme }}</span>
<span>会议时间:{{ formatTime(meeting.beginSta) }}-{{ formatTime(meeting.beginEnd) }}</span>
<span>会议状态:{{meeting.state|statefitler}}</span>
</div>
</div>
<div class="time-cell" :class="{ 'occupied': scope.row.time16 > 0 }"
@mouseenter="showTooltip(scope.$index, 'time16')">
<i v-if="scope.row.time16" class="el-icon-user"/> {{ scope.row.time16 || '' }}
</div>
</el-tooltip>
</template>
</el-table-column>
<el-table-column prop="time17" label="17">
<template slot-scope="scope">
<el-tooltip content="" :disabled="scope.row.time17 === 0" effect="light" placement="top">
<div slot="content">
<div v-if="scope.row.time17Meetings.length" v-for="(meeting, index) in scope.row.time17Meetings"
:key="index" class="tooltip-item">
<span>主持人:{{ meeting.userName }}</span>
<span>主题: {{ meeting.theme }}</span>
<span>会议时间:{{ formatTime(meeting.beginSta) }}-{{ formatTime(meeting.beginEnd) }}</span>
<span>会议状态:{{meeting.state|statefitler}}</span>
</div>
</div>
<div class="time-cell" :class="{ 'occupied': scope.row.time17 > 0 }"
@mouseenter="showTooltip(scope.$index, 'time17')">
<i v-if="scope.row.time17" class="el-icon-user"/> {{ scope.row.time17 || '' }}
</div>
</el-tooltip>
</template>
</el-table-column>
<el-table-column prop="time18" label="18">
<template slot-scope="scope">
<el-tooltip content="" :disabled="scope.row.time18 === 0" effect="light" placement="top">
<div slot="content">
<div v-if="scope.row.time18Meetings.length" v-for="(meeting, index) in scope.row.time18Meetings"
:key="index" class="tooltip-item">
<span>主持人:{{ meeting.userName }}</span>
<span>主题: {{ meeting.theme }}</span>
<span>会议时间:{{ formatTime(meeting.beginSta) }}-{{ formatTime(meeting.beginEnd) }}</span>
<span>会议状态:{{meeting.state|statefitler}}</span>
</div>
</div>
<div class="time-cell" :class="{ 'occupied': scope.row.time18 > 0 }"
@mouseenter="showTooltip(scope.$index, 'time18')">
<i v-if="scope.row.time18" class="el-icon-user"/> {{ scope.row.time18 || '' }}
</div>
</el-tooltip>
</template>
</el-table-column>
<el-table-column prop="time1923" label="19-23">
<template slot-scope="scope">
<el-tooltip content="" :disabled="scope.row.time1923 === 0" effect="light" placement="top">
<div slot="content">
<div v-if="scope.row.time1923Meetings.length" v-for="(meeting, index) in scope.row.time1923Meetings"
:key="index" class="tooltip-item">
<span>主持人:{{ meeting.userName }}</span>
<span>主题: {{ meeting.theme }}</span>
<span>会议时间:{{ formatTime(meeting.beginSta) }}-{{ formatTime(meeting.beginEnd) }}</span>
<span>会议状态:{{meeting.state|statefitler}}</span>
</div>
</div>
<div class="time-cell" :class="{ 'occupied': scope.row.time1923 > 0 }"
@mouseenter="showTooltip(scope.$index, 'time1923')">
<i v-if="scope.row.time1923" class="el-icon-user"/> {{ scope.row.time1923 || '' }}
</div>
</el-tooltip>
</template>
</el-table-column>
</el-table>
</div>
</template>
<script>
//按需引入接口
// import {listMeeting,listMeetingRoom } from "@/api/meeting";
export default {
name: 'MeetingRoomTable',
data() {
return {
rooms: [],
meetings: [],
tableData: [],
dateSpanArr: [],
roomSpanArr: [],
meetingSpanMap: new Map() // 存储会议合并信息
}
},
//可作为组件接收外部入参
props: {
roomList: {
type: Array,
default: null
},
meetingList: {
type: Array,
default: null
}
},
filters: {
statefitler(value) {
if (value == '1') {
return '召开中';
}
if (value == '2') {
return '已结束';
}
if (value == '3') {
return '待召开';
}
if (value == '4') {
return '已取消';
}
}
},
watch: {
roomList: {
handler(newVal) {
if(newVal){
this.rooms = newVal;
this.generateTableData();
}
},
deep: true,
immediate: true
},
meetingList: {
handler(newVal) {
if(newVal){
this.meetings = newVal;
this.generateTableData();
}
},
deep: true,
immediate: true
}
},
created() {
// 如果没有传入数据,使用默认数据
if (this.roomList == null) {
// this.getRealeRooms()
this.rooms = this.getDefaultRooms();
}
if (this.meetingList == null) {
// this.getRealeMeetings()
this.meetings = this.getDefaultMeetings();
}
setTimeout(()=>{this.generateTableData()},500)
},
methods: {
generateTableData() {
// 初始化会议合并信息
this.meetingSpanMap.clear();
// 生成未来7天日期
const dates = [];
for (let i = 0; i < 7; i++) {
const date = new Date();
date.setDate(date.getDate() + i);
dates.push(this.formatDate(date));
}
// 时间段映射
const timeSlotMap = {
0: 'time0007',
1: 'time0007',
2: 'time0007',
3: 'time0007',
4: 'time0007',
5: 'time0007',
6: 'time0007',
7: 'time0007',
8: 'time08',
9: 'time09',
10: 'time10',
11: 'time11',
12: 'time12',
13: 'time13',
14: 'time14',
15: 'time15',
16: 'time16',
17: 'time17',
18: 'time18',
19: 'time1923',
20: 'time1923',
21: 'time1923',
22: 'time1923',
23: 'time1923'
};
// 初始化表格数据
this.tableData = [];
dates.forEach(date => {
this.rooms.forEach(room => {
this.tableData.push({
date,
meetingRoom: room.id,
roomName: room.name,
time0007: 0,
time08: 0,
time09: 0,
time10: 0,
time11: 0,
time12: 0,
time13: 0,
time14: 0,
time15: 0,
time16: 0,
time17: 0,
time18: 0,
time1923: 0,
time0007Meetings: [],
time08Meetings: [],
time09Meetings: [],
time10Meetings: [],
time11Meetings: [],
time12Meetings: [],
time13Meetings: [],
time14Meetings: [],
time15Meetings: [],
time16Meetings: [],
time17Meetings: [],
time18Meetings: [],
time1923Meetings: []
});
});
});
// 处理会议数据
this.meetings.forEach(meeting => {
// 查找对应的表格行
const rowIndex = this.tableData.findIndex(item => {
return item.date === this.formatDate(new Date(meeting.beginSta)) && item.meetingRoom == meeting.meetingRoom;
});
if (rowIndex !== -1) {
// 计算会议占用的时间段
const startHour = new Date(meeting.beginSta).getHours();
const endHour = new Date(meeting.beginEnd).getHours();
const startMinute = new Date(meeting.beginSta).getMinutes();
const endMinute = new Date(meeting.beginEnd).getMinutes();
// 开始时间:如果分钟数大于0,占用下一个完整小时
// 结束时间:如果分钟数大于0,占用当前小时;否则占用前一小时
let startTimeSlot = startHour;
let endTimeSlot = endHour + (endMinute > 0 ? 0 : -1);
// 记录该会议占用的时间段
const timeSlots = new Set();
// 生成所有被占用的时间段
for (let hour = startTimeSlot; hour <= endTimeSlot; hour++) {
if (hour in timeSlotMap) {
timeSlots.add(timeSlotMap[hour]);
}
}
// 更新表格数据和合并信息
if (timeSlots.size > 0) {
// 转换为有序数组
const orderedTimeSlots = Array.from(timeSlots);
// 记录时间段与会议的映射关系
orderedTimeSlots.forEach(slot => {
// 更新占用计数
this.tableData[rowIndex][slot]++; // 这里是关键:对每个时间段的占用计数+1
// 添加会议信息
this.tableData[rowIndex][`${slot}Meetings`].push(meeting);
console.log(slot, this.tableData[rowIndex][slot])
});
// 记录会议合并信息
if (orderedTimeSlots.length > 1) {
this.meetingSpanMap.set(`${rowIndex}-${meeting.meetingId}`, orderedTimeSlots);
}
}
}
});
// 处理合并单元格
this.handleSpan();
console.log("tableData", this.tableData)
},
handleSpan() {
// 重置合并数组
this.dateSpanArr = [];
this.roomSpanArr = [];
let datePos = 0;
let roomPos = 0;
// 处理日期列合并
this.tableData.forEach((item, index) => {
if (index === 0) {
this.dateSpanArr.push(1);
datePos = 0;
} else {
// 如果当前行日期和上一行日期相同,则合并
if (item.date === this.tableData[index - 1].date) {
this.dateSpanArr[datePos] += 1;
this.dateSpanArr.push(0);
} else {
this.dateSpanArr.push(1);
datePos = index;
}
}
});
// 处理会议室列合并
this.tableData.forEach((item, index) => {
if (index === 0) {
this.roomSpanArr.push(1);
roomPos = 0;
} else {
// 如果当前行日期和上一行日期相同,且会议室也相同,则合并
if (item.date === this.tableData[index - 1].date && item.meetingRoom === this.tableData[index - 1].meetingRoom) {
this.roomSpanArr[roomPos] += 1;
this.roomSpanArr.push(0);
} else {
this.roomSpanArr.push(1);
roomPos = index;
}
}
});
//===========================合并格子进行会议数据合并去重共享============================================
// 时间段列
const timeProps = [
'time0007', 'time08', 'time09', 'time10', 'time11',
'time12', 'time13', 'time14', 'time15', 'time16',
'time17', 'time18', 'time1923'
];
// 处理时间段列的会议数据合并
this.tableData.forEach((row, rowIndex) => {
// 检查是否有需要合并的会议
const meetingsToMerge = [];
// 遍历所有时间段,收集需要合并的会议
timeProps.forEach(timeProp => {
const meetings = row[`${timeProp}Meetings`] || [];
meetings.forEach(meeting => {
// 如果会议已经在列表中,跳过
if (meetingsToMerge.some(m => m.meetingId === meeting.meetingId)) {
return;
}
// 计算会议覆盖的时间段
const startHour = new Date(meeting.beginSta).getHours();
const endHour = new Date(meeting.beginEnd).getHours();
const endMinute = new Date(meeting.beginEnd).getMinutes();
// 确定会议覆盖的时间段索引范围
const startTimeSlot = this.getTimeSlotIndex(startHour);
const endTimeSlot = this.getTimeSlotIndex(endHour + (endMinute > 0 ? 0 : -1));
// 如果会议跨多个时间段,添加到合并列表
if (endTimeSlot > startTimeSlot) {
meetingsToMerge.push({
...meeting,
startTimeSlot,
endTimeSlot
});
}
});
});
// 处理需要合并的会议
meetingsToMerge.forEach(meeting => {
// 收集会议覆盖的所有时间段的会议数据
const allMeetings = [];
const meetingIds = new Set();
for (let i = meeting.startTimeSlot; i <= meeting.endTimeSlot; i++) {
const timeProp = timeProps[i];
const slotMeetings = row[`${timeProp}Meetings`] || [];
slotMeetings.forEach(m => {
if (!meetingIds.has(m.meetingId)) {
meetingIds.add(m.meetingId);
allMeetings.push(m);
}
});
}
// 更新所有相关时间段的会议数据
for (let i = meeting.startTimeSlot; i <= meeting.endTimeSlot; i++) {
const timeProp = timeProps[i];
row[timeProp] = allMeetings.length;
row[`${timeProp}Meetings`] = allMeetings;
}
});
});
//===========================合并格子进行会议数据合并去重共享============================================
},
// 根据小时获取时间段索引
getTimeSlotIndex(hour) {
const timeSlotMap = {
0: 0, 1: 0, 2: 0, 3: 0, 4: 0, 5: 0, 6: 0, 7: 0, // time0007
8: 1, 9: 2, 10: 3, 11: 4, // time08, time09, time10, time11
12: 5, 13: 6, 14: 7, 15: 8, 16: 9, 17: 10, 18: 11, // time12-time18
19: 12, 20: 12, 21: 12, 22: 12, 23: 12 // time1923
};
return timeSlotMap[hour] || 0;
},
//el-table表格合并方法
objectSpanMethod({
row,
column,
rowIndex,
columnIndex
}) {
// 处理日期列和会议室列的合并
if (columnIndex === 0) {
return {
rowspan: this.dateSpanArr[rowIndex],
colspan: 1
};
} else if (columnIndex === 1) {
return {
rowspan: this.roomSpanArr[rowIndex],
colspan: 1
};
}
// 处理时间段列的会议合并
const timePropIndex = columnIndex - 2; // 时间段列从第3列开始
if (timePropIndex < 0) return {
rowspan: 1,
colspan: 1
};
const timeProps = [
'time0007', 'time08', 'time09', 'time10', 'time11',
'time12', 'time13', 'time14', 'time15', 'time16',
'time17', 'time18', 'time1923'
];
const timeProp = timeProps[timePropIndex];
if (!timeProp) return {
rowspan: 1,
colspan: 1
};
// 检查当前单元格是否属于某个需要合并的会议
for (const [key, timeSlots] of this.meetingSpanMap.entries()) {
const [rowIdx, meetingId] = key.split('-');
if (parseInt(rowIdx) === rowIndex && timeSlots.includes(timeProp)) {
const firstSlot = timeSlots[0];
const lastSlot = timeSlots[timeSlots.length - 1];
// 如果是会议的第一个时间段,设置合并
if (timeProp === firstSlot) {
// 找出合并范围内数量最多的时间段
const timePropIdx = timeProps.indexOf(timeProp);
const lastSlotIdx = timeProps.indexOf(lastSlot);
return {
rowspan: 1,
colspan: lastSlotIdx - timePropIdx + 1
};
} else {
// 否则不显示
return {
rowspan: 0,
colspan: 0
};
}
}
}
// 默认不合并
return {
rowspan: 1,
colspan: 1
};
},
formatDate(date) {
const year = date.getFullYear();
const month = String(date.getMonth() + 1).padStart(2, '0');
const day = String(date.getDate()).padStart(2, '0');
return `${year}-${month}-${day}`;
},
formatTime(dateTime) {
const date = new Date(dateTime);
const hour = String(date.getHours()).padStart(2, '0');
const minute = String(date.getMinutes()).padStart(2, '0');
return `${hour}:${minute}`;
},
showTooltip(rowIndex, timeKey) {
// 处理鼠标悬停事件
},
//会议室数据
getRealeRooms() {
//获取真实数据接口
listMeetingRoom().then(response => {
this.rooms = response.rows;
this.generateTableData();
});
},
//会议数据
getRealeMeetings() {
//获取今天及今天之后的数据
const today = new Date();
listMeeting().then(response => {
this.meetings = response.rows;
this.generateTableData();
});
},
getDefaultRooms() {
return [{
id: 1,
name: '会议室A'
},
{
id: 2,
name: '会议室B'
},
{
id: 3,
name: '会议室C'
}
];
},
getDefaultMeetings() {
const today = new Date();
return [{
meetingId: 1,
theme: '周会',
userName: '张三',
meetingRoom: 1,
state:1,
beginSta: new Date(today.setHours(4, 30, 0)).toISOString(),
beginEnd: new Date(today.setHours(5, 0, 0)).toISOString()
},
{
meetingId: 2,
theme: '技审',
userName: '张三',
meetingRoom: 1,
state:1,
beginSta: new Date(today.setHours(6, 0, 0)).toISOString(),
beginEnd: new Date(today.setHours(9, 30, 0)).toISOString()
},
{
meetingId: 3,
theme: '技审3',
userName: '张三',
meetingRoom: 1,
state:2,
beginSta: new Date(today.setHours(8, 0, 0)).toISOString(),
beginEnd: new Date(today.setHours(9, 30, 0)).toISOString()
},
{
meetingId: 6,
theme: '跨时1',
userName: '张三',
meetingRoom: 3,
state:2,
beginSta: new Date(today.setHours(18, 0, 0)).toISOString(),
beginEnd: new Date(today.setHours(20, 30, 0)).toISOString()
},
{
meetingId: 7,
theme: '跨时2',
userName: '张三',
meetingRoom: 3,
state:1,
beginSta: new Date(today.setHours(20, 0, 0)).toISOString(),
beginEnd: new Date(today.setHours(21, 30, 0)).toISOString()
},
{
meetingId: 9,
theme: '跨19-23',
userName: '张三',
meetingRoom: 3,
state:3,
beginSta: new Date(today.setHours(20, 30, 0)).toISOString(),
beginEnd: new Date(today.setHours(22, 30, 0)).toISOString()
},
{
meetingId: 10,
theme: '跨列测试1',
userName: '张三',
meetingRoom: 3,
state:4,
beginSta: new Date(today.setHours(18, 0, 0)).toISOString(),
beginEnd: new Date(today.setHours(19, 30, 0)).toISOString()
},
{
meetingId: 11,
theme: '跨列测试2',
userName: '张三',
meetingRoom: 2,
state:1,
beginSta: new Date(today.setHours(20, 0, 0)).toISOString(),
beginEnd: new Date(today.setHours(21, 0, 0)).toISOString()
},
{
meetingId: 12,
theme: '重叠测试1',
userName: '张三',
meetingRoom: 3,
state:1,
beginSta: new Date(today.setHours(19, 0, 0)).toISOString(),
beginEnd: new Date(today.setHours(20, 30, 0)).toISOString()
},
{
meetingId: 13,
theme: '重叠测试2',
userName: '张三',
meetingRoom: 3,
state:1,
beginSta: new Date(today.setHours(20, 0, 0)).toISOString(),
beginEnd: new Date(today.setHours(21, 30, 0)).toISOString()
}
];
}
}
}
</script>
<style scoped>
.meeting-room-table {
margin: 20px;
}
.time-cell {
text-align: center;
padding: 5px;
height: 100%;
border-radius: 4px;
cursor: pointer;
}
.time-cell.occupied {
background-color: #55aaff;
color: white;
}
.tooltip-item {
padding: 5px 0;
display: flex;
align-content: flex-start;
flex-direction: column;
font-size: 14px;
border-bottom: 1px solid #eee;
}
.tooltip-item:last-child {
border-bottom: none;
}
</style>
参考DeepSeek和豆包AI。