当前位置: 首页 > news >正文

【VUE】某时间某空间占用情况效果展示,vue2+element ui实现。场景:会议室占用、教室占用等。

某时间某空间占用情况效果展示,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,鼠标悬浮展示这三条。

实现效果:

具体展示效果可以根据代码调整。
在这里插入图片描述

代码实现:

<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, // time00078: 1, 9: 2, 10: 3, 11: 4, // time08, time09, time10, time1112: 5, 13: 6, 14: 7, 15: 8, 16: 9, 17: 10, 18: 11, // time12-time1819: 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。

http://www.lryc.cn/news/572693.html

相关文章:

  • PVE使用ubuntu-cloud-24.img创建虚拟机并制作模板
  • NVIDIA开源Fast-dLLM!解析分块KV缓存与置信度感知并行解码技术
  • 旋转图像C++
  • json.Unmarshal精度丢失问题分析
  • vue3组件式开发示例
  • 大模型与搜索引擎的技术博弈及未来智能范式演进
  • MySQL查询语句的通配符*
  • 组态王工程运行时间显示
  • 【案例拆解】米客方德 SD NAND 在车联网中(有方模块)的应用:破解传统 TF 卡振动脱落与寿命短板
  • 在VTK中捕捉体绘制图像进阶(同步操作)
  • 零基础入门PCB设计 一实践项目篇 第三章(STM32开发板原理图设计)
  • 云计算处理器选哪款?性能与能效的平衡艺术
  • 【网络安全】文件上传型XSS攻击解析
  • 特征金字塔在Vision Transformer中的创新应用:原理、优势与实现分析
  • AS32系列MCU芯片I2C模块性能解析与调试
  • 408第二季 - 组成原理 - 流水线
  • Linux之线程同步与互斥
  • Rust 学习笔记:Unsafe Rust
  • 使用 .NET Core 8.0 和 SignalR 构建实时聊天服务
  • OPENPPP2 VMUX 技术探秘(高级指南)
  • 北京京东,看看难度
  • 解锁决策树:数据挖掘的智慧引擎
  • ffmpeg 给视频画圆圈
  • Electron (02)集成 SpringBoot:服务与桌面程序协同启动方案
  • 大白话说目标检测中的IOU(Intersection over Union)
  • Maven并行构建
  • 单点登录进阶:基于芋道(yudao)授权码模式的单点登录流程、代码实现与安全设计
  • SAP-ABAP:LOOP ... ASSIGNING高效处理内表数据详解
  • pandas polars 数据类型转换
  • 【pdf】Java代码生成PDF