课程表插件(vue直接引入样式)timeTables
<!doctype html> <html lang="en"> <head> <meta charset="utf-8"> <meta name="viewport" content="width=device-width,initial-scale=1,user-scalable=0"> <script src="./Timetables.min.js"></script> <title>课表</title> <style> #coursesTable { padding: 15px 10px; } .Courses-head > div { text-align: center; font-size: 14px; line-height: 28px; } .left-hand-TextDom, .Courses-head { background-color: #f2f6f7; } .Courses-leftHand { background-color: #f2f6f7; font-size: 12px; } .Courses-leftHand .left-hand-index { color: #9c9c9c; margin-bottom: 4px !important; } .Courses-leftHand p { text-align: center; font-weight: 900; } .Courses-leftHand > div { padding-top: 5px; border-bottom: 1px dashed rgb(219, 219, 219); } .Courses-leftHand > div:last-child { border-bottom: none !important; } .left-hand-TextDom, .Courses-head { border-bottom: 1px solid rgba(0, 0, 0, 0.1) !important; } .Courses-content > ul { border-bottom: 1px dashed rgb(219, 219, 219); box-sizing: border-box; } .Courses-content > ul:last-child { border-bottom: none !important; } .highlight-week { color: #02a9f5 !important; } .Courses-content li { text-align: center; color: #fff; font-size: 14px; line-height: 50px; } .stage_1, .left-hand-1 { background-color: #FF6666; } .stage_2, .left-hand-2 { background-color: #3399CC; } .stage_3, .left-hand-3 { background-color: #66CCCC; } .Courses-leftHand { border-right: 1px solid #e0e0e0; color: #fff; } .Courses-leftHand > div { writing-mode: vertical-lr; text-align: center; line-height: 50px; font-size: 16px; letter-spacing: 10px; } </style> </head> <body> <div id="coursesTable"></div> <script> var courseList = [ ['', '语文', '英语', '物理', '语文', '数学', '英语', '物理', '物理', '数学', '英语', '物理'], ['数学', '语文', '物理', '物理', '语文', '语文', '语文', '物理', '数学', '语文', '语文', '体育'], ['语文', '数学', '英语', '物理', '', '数学', '英语', '物理', '语文', '数学', '英语', '物理'], ['数学', '语文', '物理', '物理', '语文', '语文', '语文', '英语', '数学', '语文', '语文', '体育'], ['语文', '数学', '英语', '物理', '语文', '数学', '英语', '物理', '语文', '数学', '英语', '物理'], ['数学', '语文', '物理', '物理', '语文', '语文', '语文', '英语', '数学', '语文', '语文', '体育'], ['体育', '数学', '', '物理', '语文', '数学', '英语', '物理', '语文', '数学', '英语', '物理'] ]; var week = window.innerWidth > 360 ? ['周一', '周二', '周三', '周四', '周五', '周六', '周日'] : ['一', '二', '三', '四', '五', '六', '日']; var now = new Date(); var day = now.getDay(); var courseType = [ ['上午', 4], ['下午', 4], ['晚上', 4] ]; var times = new Timetables({ el: '#coursesTable', timetables: courseList, week: week, merge: false, timetableType: courseType, highlightWeek: day, gridOnClick: function (e) { console.log(e); }, styles: { leftHandWidth: 50, Gheight: 50, palette: false } }); </script> </body> </html>
demo2:
<!doctype html> <html lang="en"> <head> <meta charset="utf-8"> <meta name="viewport" content="width=device-width,initial-scale=1,user-scalable=0"> <script src="./Timetables.min.js"></script> <title>大学课表</title> <style> #coursesTable { padding: 15px 10px; } .Courses-head { background-color: #edffff; } .Courses-head > div { text-align: center; font-size: 14px; line-height: 28px; } .left-hand-TextDom, .Courses-head { background-color: #f2f6f7; } .Courses-leftHand { background-color: #f2f6f7; font-size: 12px; } .Courses-leftHand .left-hand-index { color: #9c9c9c; margin-bottom: 4px !important; } .Courses-leftHand .left-hand-name { color: #666; } .Courses-leftHand p { text-align: center; font-weight: 900; } .Courses-head > div { border-left: none !important; } .Courses-leftHand > div { padding-top: 5px; border-bottom: 1px dashed rgb(219, 219, 219); } .Courses-leftHand > div:last-child { border-bottom: none !important; } .left-hand-TextDom, .Courses-head { border-bottom: 1px solid rgba(0, 0, 0, 0.1) !important; } .Courses-content > ul { border-bottom: 1px dashed rgb(219, 219, 219); box-sizing: border-box; } .Courses-content > ul:last-child { border-bottom: none !important; } .highlight-week { color: #02a9f5 !important; } .Courses-content li { text-align: center; color: #666666; font-size: 14px; line-height: 50px; } .Courses-content li span { padding: 6px 2px; box-sizing: border-box; line-height: 18px; border-radius: 4px; white-space: normal; word-break: break-all; cursor: pointer; } .grid-active { z-index: 9999; } .grid-active span { box-shadow: 0px 2px 4px rgba(0, 0, 0, 0.2); } </style> </head> <body> <div id="coursesTable"></div> <button onclick="onChange()" style="background-color: #00a2ae; color: #fff; padding: 5px 10px; border-radius: 4px;border: none"> 切换课表 </button> <script> var courseList = [ ['大学英语(Ⅳ)@10203', '大学英语(Ⅳ)@10203', '', '', '', '', '毛概@14208', '毛概@14208', '', '', '', '选修'], ['', '', '信号与系统@11302', '信号与系统@11302', '模拟电子技术基础@16204', '模拟电子技术基础@16204', '', '', '', '', '', ''], ['大学体育(Ⅳ)', '大学体育(Ⅳ)', '形势与政策(Ⅳ)@15208', '形势与政策(Ⅳ)@15208', '', '', '电路、信号与系统实验', '电路、信号与系统实验', '', '', '', ''], ['', '', '', '', '电装实习@11301', '电装实习@11301', '', '', '', '大学体育', '大学体育', ''], ['', '', '数据结构与算法分析', '数据结构与算法分析', '', '', '', '', '信号与系统', '信号与系统', '', ''], ]; var week = window.innerWidth > 360 ? ['周一', '周二', '周三', '周四', '周五'] : ['一', '二', '三', '四', '五']; var day = new Date().getDay(); var courseType = [ [{index: '1', name: '8:30'}, 1], [{index: '2', name: '9:30'}, 1], [{index: '3', name: '10:30'}, 1], [{index: '4', name: '11:30'}, 1], [{index: '5', name: '12:30'}, 1], [{index: '6', name: '14:30'}, 1], [{index: '7', name: '15:30'}, 1], [{index: '8', name: '16:30'}, 1], [{index: '9', name: '17:30'}, 1], [{index: '10', name: '18:30'}, 1], [{index: '11', name: '19:30'}, 1], [{index: '12', name: '20:30'}, 1] ]; // 实例化(初始化课表) var Timetable = new Timetables({ el: '#coursesTable', timetables: courseList, week: week, timetableType: courseType, highlightWeek: day, gridOnClick: function (e) { alert(e.name + ' ' + e.week + ', 第' + e.index + '节课, 课长' + e.length + '节'); console.log(e); }, styles: { Gheight: 50 } }); //切换课表 function onChange() { var courseListOther = [ ['', '', '', '', '毛概@14208', '毛概@14208', '', '', '', '选修', '', ''], ['大学英语(Ⅳ)@10203', '大学英语(Ⅳ)@10203', '', '', '模拟电子技术基础@16204', '模拟电子技术基础@16204', '', '', '', '', '', ''], ['', '', '信号与系统@11302', '信号与系统@11302', '', '', '电路、信号与系统实验', '电路、信号与系统实验', '', '', '', ''], ['形势与政策(Ⅳ)@15208', '形势与政策(Ⅳ)@15208', '', '', '电装实习@11301', '电装实习@11301', '', '', '', '大学体育', '大学体育', ''], ['大学体育(Ⅳ)', '大学体育(Ⅳ)', '', '', '数据结构与算法分析', '数据结构与算法分析', '', '', '信号与系统', '信号与系统', '', ''], ]; Timetable.setOption({ timetables: courseListOther, week: ['一', '二', '三', '四', '五', '六', '日'], styles: { palette: ['#dedcda', '#ff4081'] }, timetableType: courseType, gridOnClick: function (e) { console.log(e); } }); }; </script> </body> </html>
Timetables.min.js
(function(global){var Timetables=function(option){this.el=document.querySelector(option.el);this.Timetables=option.timetables||[];this.week=option.week||[];this.merge=typeof option.merge==="boolean"?option.merge:true;this.TimetableType=option.timetableType||[];this.leftHandText=[];this.highlightWeek=option.highlightWeek||"";this.gridOnClick=typeof option.gridOnClick==="function"?option.gridOnClick:undefined;var styles=option.styles||{};this.leftHandWidth=styles.leftHandWidth||40;this.Gheight=styles.Gheight||48;this.defaultPalette=["#f05261","#48a8e4","#ffd061","#52db9a","#70d3e6","#52db9a","#3f51b5","#f3d147","#4adbc3","#673ab7","#f3db49","#76bfcd","#b495e1","#ff9800","#8bc34a"];this.palette=(typeof styles.palette==="boolean"&&!styles.palett)?false:(styles.palette||[]).concat(this.defaultPalette);this._init()};Timetables.prototype={_init:function(option){var option=option||{};var style=option.styles||{};var gridOnClick=option.gridOnClick||this.gridOnClick;var merge=typeof option.merge==="boolean"?option.merge:this.merge;var highlightWeek=option.highlightWeek||this.highlightWeek;var leftHandText=this.leftHandText;var leftHandWidth=style.leftHandWidth||this.leftHandWidth;var Gheight=style.Gheight||this.Gheight;var palette;if(typeof style.palette==="boolean"&&!style.palette){palette=false}else{palette=style.palette?(style.palette||[]).concat(this.defaultPalette):this.palette}var Timetables=option.timetables||this.Timetables;var week=option.week||this.week;var TimetableType=JSON.parse(JSON.stringify(option.timetableType||this.TimetableType));var deepCopyTimetableType=option.timetableType||this.TimetableType;var TimetableTypeLength=TimetableType.length;Timetables.forEach(function(item,index){if(item.length<TimetableTypeLength){for(var i=0;i<TimetableTypeLength-item.length;i++){item.push("")}}});if(option.setNewOption){this.el.removeChild(this.el.childNodes[0])}var courseWrapper=document.createElement("div");courseWrapper.id="courseWrapper";courseWrapper.style.position="relative";courseWrapper.style.paddingLeft=leftHandWidth+"px";courseWrapper.style.border="1px solid #dbdbdb";TimetableType.forEach(function(item,index){item.unshift(index+1)});var leftHand=document.createElement("div");leftHand.className="Courses-leftHand";leftHand.style.position="absolute";leftHand.style.left=0;leftHand.style.top=0;leftHand.style.width=leftHandWidth+"px";var timetable=Timetables[0].map(function(v,i){return[]});timetable.forEach(function(item,index){Timetables.forEach(function(val,i){timetable[index].push(val[index])})});var listMerge=[];if(merge){Timetables.forEach(function(list,i){if(!listMerge[i]){listMerge[i]=[]}list.forEach(function(item,index){if(!index){return listMerge[i].push({name:item,length:1})}if(item===(listMerge[i][index-1]||{}).name&&item){var sameIndex=(listMerge[i][index-1]||{}).sameIndex;if(sameIndex||sameIndex===0){listMerge[i][sameIndex].length++;return listMerge[i].push({name:item,length:0,sameIndex:sameIndex})}listMerge[i][index-1].length++;return listMerge[i].push({name:item,length:0,sameIndex:index-1})}else{return listMerge[i].push({name:item,length:1})}})})}var head=document.createElement("div");head.style.overflow="hidden";head.className="Courses-head";week.forEach(function(item,index){var weekItem=document.createElement("div");var highlightClass=highlightWeek===(index+1)?"highlight-week ":"";weekItem.className=highlightClass+"Courses-head-"+(index+1);weekItem.innerText=item;weekItem.style.cssFloat="left";weekItem.style.boxSizing="border-box";weekItem.style.whiteSpace="nowrap";weekItem.style.width=100/week.length+"%";head.appendChild(weekItem)});courseWrapper.appendChild(head);var courseListContent=document.createElement("div");courseListContent.className="Courses-content";var paletteIndex=0;timetable.forEach(function(values,index){var courseItems=document.createElement("ul");courseItems.style.listStyle="none";courseItems.style.padding="0px";courseItems.style.margin="0px";courseItems.style.minHeight=Gheight+"px";courseItems.className="stage_"+((TimetableType[0]||[])[0]||"none");--(TimetableType[0]||[])[2];if(!((TimetableType[0]||[])[2])){TimetableType.shift()}values.forEach(function(item,i){if(i>week.length-1){return}var courseItem=document.createElement("li");courseItem.style.cssFloat="left";courseItem.style.width=100/week.length+"%";courseItem.style.height=Gheight+"px";courseItem.style.boxSizing="border-box";courseItem.style.position="relative";if(merge&&listMerge[i][index].length>1){var mergeDom=document.createElement("span");mergeDom.style.position="absolute";mergeDom.style.zIndex=9;mergeDom.style.width="100%";mergeDom.style.height=Gheight*listMerge[i][index].length+"px";mergeDom.style.left=0;mergeDom.style.top=0;if(palette){mergeDom.style.backgroundColor=palette[paletteIndex];mergeDom.style.color="#fff";paletteIndex++;if(paletteIndex>palette.length){paletteIndex=0}}mergeDom.innerText=listMerge[i][index].name;mergeDom.className="course-hasContent";courseItem.appendChild(mergeDom)}else{if(merge&&listMerge[i][index].length===0){courseItem.innerText="" }else{if(item&&palette){courseItem.style.backgroundColor=palette[paletteIndex];courseItem.style.color="#fff";paletteIndex++;if(paletteIndex>palette.length){paletteIndex=0}}else{if(item){courseItem.className="course-hasContent"}}courseItem.innerText=item||""}}courseItem.onclick=function(e){var allList=document.querySelectorAll(".Courses-content ul li").forEach(function(v,i){v.classList.remove("grid-active")});this.className="grid-active";var info={name:item,week:week[i],index:index+1,length:merge?listMerge[i][index].length:1};gridOnClick&&gridOnClick(info)};courseItems.appendChild(courseItem)});courseListContent.appendChild(courseItems)});courseWrapper.appendChild(courseListContent);courseWrapper.appendChild(leftHand);this.el.appendChild(courseWrapper);var courseItemDomHeight=(document.querySelector(".stage_1 li")||document.querySelector(".stage_none li")).offsetHeight;var coursesHeadDomHeight=document.querySelector(".Courses-head").offsetHeight;var leftHandTextDom=document.createElement("div");leftHandTextDom.className="left-hand-TextDom";leftHandTextDom.style.height=coursesHeadDomHeight+"px";leftHandTextDom.style.boxSizing="border-box";leftHandText.forEach(function(item){var leftHandTextItem=document.createElement("div");leftHandTextItem.innerText=item;leftHandTextDom.appendChild(leftHandTextItem)});leftHand.appendChild(leftHandTextDom);deepCopyTimetableType.forEach(function(item,index){var handItem=document.createElement("div");handItem.style.width="100%";handItem.style.height=courseItemDomHeight*item[1]+"px";handItem.style.boxSizing="border-box";if(typeof item[0]==="object"){for(var v in item[0]){var handItemInner=document.createElement("p");handItemInner.innerText=item[0][v];handItemInner.style.margin="0px";handItemInner.className="left-hand-"+v;handItem.appendChild(handItemInner)}}else{handItem.innerText=item[0]||""}handItem.className="left-hand-"+(index+1);leftHand.appendChild(handItem)})},setOption:function(option){(option||{}).setNewOption=true;this._init(option)}};if(typeof module!=="undefined"&&module.exports){module.exports=Timetables}if(typeof define==="function"){define(function(){return Timetables})}global.Timetables=Timetables})(this);
vue中直接使用命令:
npm install timetables
<template> <div> <div id="coursesTable" ></div> </div> </template> <script> import timetable from 'timetables' export default { components: {}, data () { return { styles: { Gheight: 50, leftHandWidth: 50, palette: ['#ff6633', '#eeeeee'] }, courselist: [ ['大学英语(Ⅳ)@10203', '大学英语(Ⅳ)@10203', '', '', '', '', '毛概@14208', '毛概@14208', '', '', '', '选修'], ['', '', '信号与系统@11302', '信号与系统@11302', '模拟电子技术基础@16204', '模拟电子技术基础@16204', '', '', '', '', '', ''], ['大学体育(Ⅳ)', '大学体育(Ⅳ)', '形势与政策(Ⅳ)@15208', '形势与政策(Ⅳ)@15208', '', '', '电路、信号与系统实验', '电路、信号与系统实验', '', '', '', ''], ['', '', '', '', '电装实习@11301', '电装实习@11301', '', '', '', '大学体育', '大学体育', ''], ['', '', '数据结构与算法分析', '数据结构与算法分析', '', '', '', '', '信号与系统', '信号与系统', '', ''] ], timetableType: [ [{index: '1', name: '8:30'}, 1], [{index: '2', name: '9:30'}, 1], [{index: '3', name: '10:30'}, 1], [{index: '4', name: '11:30'}, 1], [{index: '5', name: '12:30'}, 1], [{index: '6', name: '14:30'}, 1], [{index: '7', name: '15:30'}, 1], [{index: '8', name: '16:30'}, 1], [{index: '9', name: '17:30'}, 1], [{index: '10', name: '18:30'}, 1], [{index: '11', name: '19:30'}, 1], [{index: '12', name: '20:30'}, 1] ], week: ['周一', '周二', '周三', '周四', '周五', '周六', '周日'], timetable: null } }, mounted () { this.timetable = // eslint-disable-next-line new-cap new timetable({ el: '#coursesTable', timetables: this.courselist, week: this.week, highlightWeek: new Date().getDay(), timetableType: this.timetableType, styles: this.styles }) } } </script> <style> #coursesTable { padding: 15px 10px; } .Courses-head { background-color: #edffff; } .Courses-head > div { text-align: center; font-size: 14px; line-height: 28px; } .left-hand-TextDom, .Courses-head { background-color: #f2f6f7; } .Courses-leftHand { background-color: #f2f6f7; font-size: 12px; } .Courses-leftHand .left-hand-index { color: #9c9c9c; margin-bottom: 4px !important; } .Courses-leftHand .left-hand-name { color: #666; } .Courses-leftHand p { text-align: center; font-weight: 900; } .Courses-head > div { border-left: none !important; } .Courses-leftHand > div { padding-top: 5px; border-bottom: 1px dashed rgb(219, 219, 219); } .Courses-leftHand > div:last-child { border-bottom: none !important; } .left-hand-TextDom, .Courses-head { border-bottom: 1px solid rgba(0, 0, 0, 0.1) !important; } .Courses-content > ul { border-bottom: 1px dashed rgb(219, 219, 219); box-sizing: border-box; } .Courses-content > ul:last-child { border-bottom: none !important; } .highlight-week { color: #02a9f5 !important; } .Courses-content li { text-align: center; color: #666666; font-size: 14px; line-height: 50px; } .Courses-content li span { padding: 6px 2px; box-sizing: border-box; line-height: 18px; border-radius: 4px; white-space: normal; word-break: break-all; cursor: pointer; } .grid-active { z-index: 9999; } .grid-active span { box-shadow: 0px 2px 4px rgba(0, 0, 0, 0.2); } </style>