vue实现一个简单的日程表:
写在home.vue文件中了
<template> <div class="homeBox"> <table> <!-- 时间轴 --> <tr> <td ><div :style="{2*tableWidth+'px',height:tableHeight+'px'}"></div></td> <td v-for="(item,index) in arrLength" :key="index"> <div class="timeWrap" :style="{tableWidth+'px',height:tableHeight+'px'}"> <span>{{minTOhm(index,step,startTime)}}</span> </div> </td> </tr> <!-- 表格 --> <tr v-for="(tableItem,index) in sessionDataArr" :key="'table'+index"> <td ><div class="roomName" :style="{2*tableWidth+'px',height:tableHeight+'px',lineHeight:tableHeight+'px'}">{{tableItem.roomName}}</div></td> <td v-for="(item,index) in tableItem.sessionArr" class="itemcell" :key="index+'tableItem'" :colspan="item.colspan?item.colspan:''"> <div class="itemTd" :style="{item.colspan?(item.colspan*tableWidth)+'px':tableWidth+'px',height:tableHeight+'px'}" :title="item.text"> <a class="linkEle" href="javascript:"> <span class="session_text">{{item.text}}</span> </a> </div> </td> </tr> </table> </div> </template> <script> // @ is an alias to /src import tools from "@/util/tools.js"; import global from "@/util/global.js"; import api from "@/util/api.js"; export default { name: "home", components: { }, data(){ return{ tableWidth:50, tableHeight:50, startTime:"08:00",//日程开始时间 endTime:"22:15",//日程结束时间 step:10,//时间间隔 sessionData:[//模拟的session数据 { roomName:"多功能厅A", sessionArr:[ {startTime:"08:00",endTime:"08:30",text:"心血管研究心血管研究",colspan:""}, {startTime:"09:00",endTime:"09:10",text:"心血管研究",colspan:""}, {startTime:"09:20",endTime:"09:30",text:"是打发",colspan:""}, {startTime:"09:40",endTime:"10:00",text:"分发大时分发时分发送到",colspan:""}, ] }, { roomName:"多功能厅B", sessionArr:[ {startTime:"08:00",endTime:"08:50",text:"sessionB心血管研究",colspan:""}, {startTime:"09:00",endTime:"09:10",text:"大脑研究",colspan:""}, {startTime:"15:20",endTime:"15:50",text:"哈哈哈",colspan:""}, {startTime:"21:00",endTime:"21:20",text:"分发大时",colspan:""}, ] }, { roomName:"多功能厅C", sessionArr:[ {startTime:"08:00",endTime:"08:50",text:"sessionB心血管研究",colspan:""}, {startTime:"09:00",endTime:"09:10",text:"大脑研究",colspan:""}, {startTime:"15:20",endTime:"15:50",text:"哈哈哈",colspan:""}, {startTime:"21:00",endTime:"21:20",text:"分发大时",colspan:""}, ] }, ], arrLength:0,//总共与多上格子(不用后台传,是计算出来的)) sessionDataArr:[],//根据后台数据 生成的最终表格数据(不用后台传) } }, created(){ this.generaterAllTable(this.sessionData);//生成整个表格数据 }, mounted(){ }, methods:{ hmTOmin(hm){//hh:mm=>分钟或则秒 var arr=hm.split(":"),H,M,sum={M:'',S:''}; if(/^0[0-9]$/.test(arr[0])){ H=Number(arr[0].replace("0",'')); }else{ H=Number(arr[0]); } if(/^0[0-9]$/.test(arr[1])){ M=Number(arr[1].replace("0",'')); }else{ M=Number(arr[1]); } sum.M=Number(H*60+M); sum.S=Number((H*60+M)*60); return sum; }, minTOhm(index,step,startTime){//计算时间轴 var str="",h,m,self=this; if(index==0){ str=startTime; }else{ var sumMIn=self.hmTOmin(startTime).M+(step*index); h=parseInt(sumMIn/60); m=sumMIn%60; if(h<10){ h='0'+h; } if(m<10){ m='0'+m; } str=h+":"+m; } return str; }, generaterCol(sessionArr){//生成某一列的session数组 var self=this,colArr=[]; self.generaterArrLength();//计算时间轴的长度 下面能用到 var sessionTd=0;//session所占的总格数 sessionArr.forEach((item,index,arr)=>{ item.colspan=Math.ceil((self.hmTOmin(item.endTime).M-self.hmTOmin(item.startTime).M)/self.step); sessionTd+=item.colspan; }) var tableColArrLength=self.arrLength-sessionTd+sessionArr.length;//日程某一列有多少个单元格,也就是某一列数组的长度 for(let i=0,len=tableColArrLength;i<len;i++){//可以考虑抽离出去 var obj={startTime:"",endTime:"",text:"",colspan:""}; colArr[i]=obj; } function addData(){//向某一列数组中添加数据 var count=0;//计算每个session前面有 sessionArr.forEach((item,index,arr)=>{ var itemIndex=Math.floor((self.hmTOmin(item.startTime).M-self.hmTOmin(self.startTime).M)/self.step); colArr[itemIndex-count].startTime=item.startTime; colArr[itemIndex-count].endTime=item.endTime; colArr[itemIndex-count].text=item.text; colArr[itemIndex-count].colspan=item.colspan; count+=(item.colspan-1); }) } addData(); return colArr;//将生成的某一列数据返回出去 }, generaterArrLength(){//计算出事件轴的长度 var self=this; var sumMIN=self.hmTOmin(self.endTime).M-self.hmTOmin(self.startTime).M; self.arrLength=Math.ceil(sumMIN/self.step);//总共有多少格子 }, generaterAllTable(sessionData){//生成整个session表 var self=this,arr=[]; sessionData.forEach((item,index,arr)=>{ var obj={ roomName:"", sessionArr:[], }; obj.roomName=item.roomName; obj.sessionArr=self.generaterCol(item.sessionArr); self.sessionDataArr.push(obj); }); console.log(self.sessionDataArr); } } }; </script> <style scoped> .homeBox{ } @media screen and (max-768px){ .min768{ display:block; } .max768{ display: none; } } @media screen and (min-768px){ .min768{ display:none; } .max768{ display: block; } } .timeWrap{ position: relative; } .timeWrap span{ position: absolute; bottom:0; left:0; transform-origin: left bottom; transform:rotateZ(-45deg) } .itemTd{ border:2px solid #ffffff; border-radius:5px; background:brown; box-sizing: border-box; text-align: center; position: relative; } .session_text{ position: absolute; top:50%; width:100%; transform: translateY(-50%); display: -webkit-box; overflow: hidden; white-space: normal; text-overflow: ellipsis; word-wrap: break-word; -webkit-line-clamp: 2; -webkit-box-orient: vertical; } .itemcell{ vertical-align: middle; } .roomName{ border:2px solid #ffffff; border-radius:5px; background:yellow; text-align: center; box-sizing: border-box; } .linkEle{ text-decoration: none; color:black; } </style>
。。。
另一种实现:
<template> <div class="scheduleBox"> <div class="contentBox padding0"> <div class="topImgBox"> <img :src="bannerImgUrl" alt="banner图"> </div> <!-- 检索框 --> <div class="row paddingTB bottomBorder margin0"> <div class="col col-xs-1 title lineHeight text-right">模糊搜索:</div> <div class="col col-xs-6"> <div> <el-input v-show="searchPattern=='姓名'" placeholder="请输入专家姓名/讲题进行搜索" v-model="realName" class="input-with-select"> <el-select v-model="searchPattern" slot="prepend" style="130px;" placeholder="请选择"> <el-option label="姓名" value="姓名"></el-option> <el-option label="讲题名称" value="讲题名称"></el-option> </el-select> <el-button @click="clickSearch()" slot="append" icon="el-icon-search"></el-button> </el-input> <el-input v-show="searchPattern=='讲题名称'" placeholder="请输入专家姓名/讲题进行搜索" v-model="jiangti" class="input-with-select"> <el-select v-model="searchPattern" slot="prepend" style="130px;" placeholder="请选择"> <el-option label="姓名" value="姓名"></el-option> <el-option label="讲题名称" value="讲题名称"></el-option> </el-select> <el-button @click="clickSearch()" slot="append" icon="el-icon-search"></el-button> </el-input> </div> </div> <div class="col col-xs-5"> </div> </div> <!-- 选择日期 --> <div class="row paddingTB bottomBorder margin0"> <div class="col col-xs-1 title lineHeight28 text-right">选择日期:</div> <div class="col col-xs-11"> <ul class="timeBox"> <li class="time_item" @click="clickDate('')" :class="{'dateActive':date==''}">不限</li> <li class="time_item" @click="clickDate(item.value)" :class="{'dateActive':date==item.value}" v-for="(item,index) in dateList" :key="'date'+index"> <a href="javascript:">{{item.value}}</a> </li> </ul> </div> </div> <!-- 日程一览表 --> <div class="schedule_wraper" v-if="schedule_show"> <table> <tr class="topBox"> <td> <div class="table_header_box" style="border-radius:0;" :style="{height:tableHeight+'px'}"></div> </td> <td> <div class="timeRow" :style="{(sumMin*control)+'px',height:tableHeight+'px'}"> <div class="timeCol" v-for="(item,index) in arrLength" :key="index" :style="{left:(index*step*control)+'px'}"> <span class="timeText">{{minTOhm(index,step,startTime)}}</span> </div> </div> </td> </tr> <tr class="scheduleRows" v-for="(parentItem,index) in sessionDataArr" :key="'parent'+index"> <td> <div :style="{height:tableHeight+'px'}"class="table_header_box" :title="parentItem.cn_name"> <span class="room_name"> {{parentItem.cn_name}} </span> </div> </td> <td > <div class="eleRow" :style="{(sumMin*control)+'px',height:tableHeight+'px'}"> <div class="eleCol" :title="childItem.cn_name" v-for="(childItem,index) in parentItem.sessionArr" :key="'child'+index" :style="{left:(childItem.startMin*control)+'px',(childItem.sumMin*control)+'px',height:(tableHeight-2)+'px'}" > <span class="eleCol_text"> {{childItem.cn_name}} </span> </div> </div> </td> </tr> </table> </div> </div> </div> </template> <script> import api from "@/util/api.js"; import global from "@/util/global.js"; import tools from "@/util/tools.js"; export default { watch:{ searchPattern:{ handler(newVal,oldVal){ if(newVal=='姓名'){ this.jiangti=""; }else{ this.realName=""; } }, immediate:true, } }, data(){ return { searchPattern:"姓名",//用户是按'姓名'精确检索的还是按'讲题'精确搜索的 jiangti:"",//讲题名 realName:"",//姓名(模糊搜索时) date:"",//会场日期 dateList:[],//日期列表 mid:this.$route.params.mid,//会议id schedule_show:false,//控制一览表的显示隐藏 //以下是日程一览相关 control:1,//精度值 1分钟代表多少像素、有总宽度和总分钟计算得出 fixedWidth:0,//后端后去的表的总宽度(px) tableHeight:50, startTime:"08:00",//日程开始时间 endTime:"18:00",//日程结束时间 step:30,//时间间隔 arrLength:0,//总共与多上格子(不用后台传,是计算出来的)) sumMin:0,//session总共有多少分钟 sessionDataArr:[],//根据后台数据 生成的最终表格数据(不用后台传) sessionData:[//模拟的session数据 { cn_name:"多功能厅A", sessionArr:[ {startTime:"08:00",endTime:"08:30",text:"心血管研究心血管研究",colspan:""}, {startTime:"09:00",endTime:"09:10",text:"心血管研究",colspan:""}, {startTime:"09:20",endTime:"09:30",text:"是打发",colspan:""}, {startTime:"09:40",endTime:"10:00",text:"分发大时分发时分发送到",colspan:""}, ] }, { cn_name:"多功能厅B", sessionArr:[ {startTime:"08:00",endTime:"08:50",text:"sessionB心血管研究",colspan:""}, {startTime:"09:00",endTime:"09:10",text:"大脑研究",colspan:""}, {startTime:"15:20",endTime:"15:50",text:"哈哈哈",colspan:""}, {startTime:"21:00",endTime:"21:20",text:"分发大时",colspan:""}, ] }, { cn_name:"多功能厅C", sessionArr:[ {startTime:"08:00",endTime:"08:50",text:"sessionB心血管研究",colspan:""}, {startTime:"09:00",endTime:"09:10",text:"大脑研究",colspan:""}, {startTime:"15:20",endTime:"15:50",text:"哈哈哈",colspan:""}, {startTime:"21:00",endTime:"21:20",text:"分发大时",colspan:""}, ] }, ], } }, created(){ var self=this; self.scheduleInit(); }, mounted(){ }, methods:{ scheduleInit(){//初始化 var self=this; self.getMeetingInfo();//获取会议信息 self.getMeetingDateList().then(()=>{//获取会议日期列表, // console.log(self.dateList); if(self.dateList.length>0){//默认显示 第一个时间的一览表 self.date=self.dateList[0].value; } self.oncegeneraterSchedule(self.date);//根据日期 生成一览表 }); }, oncegeneraterSchedule(date){//根据日期 一次性生成一览表 var self=this; self.getScheduleData(date).then((data)=>{//获取日程一览表数据 //生成日程表 self.generaterArrLength();//计算出格子总数 self.sessionDataArr=self.generaterScheduleData(data);//生成最终数据 self.control=self.fixedWidth/self.sumMin;//后端给一个指定的宽度,计算出1分钟=多少像素 self.schedule_show=true;//显示一览表 }); }, getMeetingInfo(){//获取会议信息 var self=this; var obj={ mid:self.mid } api.get(global.xuehui+"/pcRcInterface/getMeet",obj,res=>{ console.log(res) if(res.data.success){ self.bannerImgUrl=res.data.data.cn_banner_img; }else{ tools.msgErr(res.data.message); } },err=>{ console.log(err); }) }, getMeetingDateList(){//获取会议日期列表 var self=this; return new Promise((resolve,reject)=>{ api.get(global.xuehui+"/pcRcInterface/listDate",{mid:self.mid},res=>{ if(res.data.success){ self.dateList=res.data.data; resolve(); }else{ self.dateList=[]; tools.msgErr(res.data.message||'error'); } },err=>{ console.log(err); }) }) }, clickDate(date){//点击日期项 var self=this; self.schedule_show=false;//隐藏一览表 self.date=date; if(!date){ if(self.dateList.length>0){//默认显示 第一个时间的一览表 self.date=self.dateList[0].value; } } self.oncegeneraterSchedule(self.date); }, //以下是日程一览相关 getScheduleData(date){//获取日程一览表数据 var self=this; console.log(date); return new Promise((resolve,reject)=>{ var obj={ mid:self.mid,//会议唯一标识 date:date,//所需一栏表的日期 lang:1,//中英文 1:中文 2:英文 } api.get(global.xuehui+"/pcRcInterface/getScheduleAll",obj,res=>{ self.startTime=res.data.data.startTime; self.endTime=res.data.data.endTime; self.fixedWidth=res.data.data.fixedWidth?res.data.data.fixedWidth:1200;//拿到最大表的宽度 self.step=res.data.data.step; self.tableHeight=res.data.data.tableHeight resolve(res.data.data.RoomData); },err=>{ console.log(err); }) }) }, hmTOmin(hm){//hh:mm=>分钟或则秒 var arr=hm.split(":"),H,M,sum={M:'',S:''}; if(/^0[0-9]$/.test(arr[0])){ H=Number(arr[0].replace("0",'')); }else{ H=Number(arr[0]); } if(/^0[0-9]$/.test(arr[1])){ M=Number(arr[1].replace("0",'')); }else{ M=Number(arr[1]); } sum.M=Number(H*60+M); sum.S=Number((H*60+M)*60); return sum; }, minTOhm(index,step,startTime){//计算时间轴 var str="",h,m,self=this; if(index==0){ str=startTime.slice(0,5); }else{ var sumMIn=self.hmTOmin(startTime).M+(step*index); h=parseInt(sumMIn/60); m=sumMIn%60; if(h<10){ h='0'+h; } if(m<10){ m='0'+m; } str=h+":"+m; } return str; }, generaterArrLength(){//计算出事件轴的长度 var self=this; self.sumMin=self.hmTOmin(self.endTime).M-self.hmTOmin(self.startTime).M; self.arrLength=Math.ceil(self.sumMin/self.step);//总共有多少格子 }, generaterColArr(sessionArr){//生成某一列的session数组 var self=this; var array=[]; sessionArr.forEach((item,index,arr)=>{ item.startMin=self.hmTOmin(item.startTime).M-self.hmTOmin(self.startTime).M; item.sumMin=self.hmTOmin(item.endTime).M-self.hmTOmin(item.startTime).M; }); array=sessionArr; return array; }, generaterScheduleData(sessionData){//生成整个session表数据 var self=this; var array=[]; sessionData.forEach((item,index,arr)=>{ var obj={}; obj.cn_name=item.cn_name; obj.sessionArr=self.generaterColArr(item.sessionArr); array.push(obj); }); return array; }, } } </script> <style scoped> .scheduleBox{ } .contentBox{ width:100%; margin:0 auto; box-shadow:0px 0px 0px 0px #e0e0e0, /*上边阴影*/ -5px 0px 10px 0px #e0e0e0, /*左边阴影*/ 5px 0px 10px 0px #e0e0e0, /*右边阴影*/ 0px 0px 0px 0px #e0e0e0; /*下边阴影*/ background:#ffffff; } /* 检索块 */ .padding0{ padding:0; } .paddingTB{ padding:10px 0; } .lineHeight{ line-height:40px; } .lineHeight28{ line-height:28px; } .bottomBorder{ border-bottom: 1px solid #dddddd; } .margin0{ margin:0; } .title{ color:#777; font-weight: bold; font-size:14px; } /* 顶部图 */ .topImgBox img{ width:100%; height:auto; } /* 选择日期 */ .timeBox{ overflow: hidden; } .timeBox .dateActive{ background:#ff7b00; color:#ffffff; padding: 0 10px; border-radius:5px; cursor: pointer; } .timeBox .dateActive a{ color:#ffffff; } .time_item{ float: left; line-height:28px; color:#333333; margin-right:20px; padding: 0 10px; border-radius:5px; cursor: pointer; } .time_item a{ text-decoration: none; color:#333333; } .time_item:hover{ color:#ffffff; background:#ff7b00; } .time_item:hover a{ color:#ffffff; } /* 日程一览表 */ .schedule_wraper{ width:100%; overflow-x: auto; text-align:center; padding:20px 20px 50px; } .schedule_wraper>table{ margin:0 auto; } .topBox{ background:#0d8cdd; } .eleRow{ background:#f1f5f9; margin:0 auto; position: relative; border-bottom:2px solid #ffffff; border-radius:6px; } .eleCol{ position: absolute; /* background:red; */ border-left:1px solid #ffffff; border-right:1px solid #ffffff; border-radius:6px; top:0; background:rgba(1,54,126,.8); padding:2px; box-sizing: border-box; color:#ffffff; cursor: pointer; } .eleCol:hover{ background:rgba(1,54,126,1); } .eleCol .eleCol_text{ position: absolute; width:100%; top:50%; left:0; transform: translateY(-50%); display: -webkit-box; overflow: hidden; white-space: normal; text-overflow: ellipsis; word-wrap: break-word; -webkit-line-clamp: 2; -webkit-box-orient: vertical; } .timeRow{ height:50px; margin:0 auto; position: relative; border-bottom:2px solid #ffffff; } .timeCol{ width:2px; height:4px; position: absolute; bottom:0; background:#ffffff; } .timeText{ position: absolute; bottom:0; left:0; transform-origin: left bottom; transform:rotateZ(-45deg); color:#ffffff; } .table_header_box{ width:120px; border-bottom:2px solid #ffffff; border-radius:6px; background:#0d8cdd; text-align: center; position: relative; color:#ffffff; } .room_name{ position: absolute; width:100%; top:50%; left:0; transform: translateY(-50%); display: -webkit-box; overflow: hidden; white-space: normal; text-overflow: ellipsis; word-wrap: break-word; -webkit-line-clamp: 2; -webkit-box-orient: vertical; } </style>