已經很久沒有更新技術博客了,由於最近一直在作跨平臺web app應用的開發,因爲是剛作這個,也沒太多經驗同你們分享,可我是一個閒不住的人,我仍是決定於百忙之中抽空整理一篇,記錄下開發歷程......——前言javascript
能夠選擇日期,按月份分別查看應出勤數、已出勤數、遲到數、早退數,用特殊標記標出某天是遲到仍是早退等等,選中某天,直接加載該天的全部考勤記錄,看上去挺簡單的功能,要我寫js估計能夠寫到吐血,還好懂得拿來主義,網上找個開源的日曆組件,而後進行改造。日曆組件源碼地址Calendar.js因爲公司沒有平面和美工,也沒有前端,因此這些活我就兼作了,因此你們不要對界面吐槽,我已經盡力了,555~,下面的界面截圖我都是用的谷歌瀏覽器,模擬iphone6的效果,同真機上比天然會有必定的出入,一般來講真機上面要比模擬器上面更漂亮和清晰,界面效果以下:css
注:橙色表示當前日期,淺藍色表示選中日期,默認狀況下顯示當前日期,並加載當天的考勤記錄。html
以前原本打算使用區域滾動的,後面看見原型界面是整個頁面滾動,因此我就暫時註釋了這塊。前端
日曆支持左右滑動進行翻頁(按月進行翻),頂部按鈕也支持翻頁。vue
技術選型:mui、h五、h5+、vue.jsjava
html代碼以下:node
<!doctype html> <html> <head> <meta charset="UTF-8"> <title>個人考勤</title> <meta name="viewport" content="width=device-width,initial-scale=1,minimum-scale=1,maximum-scale=1,user-scalable=no" /> <link href="../../css/mui.min.css" rel="stylesheet" /> <link rel="stylesheet" href="../../css/base.css" /> <link rel="stylesheet" href="../../css/app/home/timeline.css" /> <link rel="stylesheet" href="../../css/app/my/punch-card.css" /> <link rel="stylesheet" href="../../css/calendar.css" /> </head> <body> <header class="mui-bar mui-bar-nav"> <a class="mui-action-back mui-icon mui-icon-left-nav mui-pull-left"></a> <h1 class="mui-title">個人考勤</h1><span id="bigTime" class="bigTime" style="visibility:hidden;"></span> </header> <div id="app" class="mui-content"> <div class="div-yearmonth"> <i id="prePage" class="mui-icon iconfont icon-shangyiye"></i> <span class="spn-today"><i class="mui-icon iconfont icon-rili"></i><span id="timeNow"></span></span> <i id="nextPage" class="mui-icon iconfont icon-xiayiye"></i> </div> <div class="div-operate"> <div class="mui-segmented-control ul-operate"> <a class="mui-control-item mui-active" v-on:tap="getDataByType(1)"> <p><span v-text="obj.attendance"></span>天</p> <p>應出勤</p> </a> <a class="mui-control-item" v-on:tap="getDataByType(2)"> <p><span v-text="obj.actualAttendance"></span>天</p> <p>實際出勤</p> </a> <a class="mui-control-item" v-on:tap="getDataByType(3)"> <p><span v-text="obj.beLate"></span>次</p> <p>遲到</p> </a> <a class="mui-control-item" v-on:tap="getDataByType(4)"> <p><span v-text="obj.leaveEarly"></span>次</p> <p>早退</p> </a> </div> </div> <div id="container"></div> <div class="div-list"> <div class="line"></div> <div class="date"><span class="spn-date"><i v-text="monthDay" class="monthDay"></i><i v-text="week">星期一</i></span></div> <!--<div id="mui-scroll-wrapper" class="mui-scroll-wrapper timeline"> <div class="mui-scroll">--> <!--這裏放置真實顯示的DOM內容--> <section v-if="list.length>0" id="cd-timeline" class="cd-container"> <div v-for="(item,index) in list" class="cd-timeline-block"> <div class="cd-timeline-img cd-picture" v-bind:class="{first:!index}"><span class="worktag">早班上班</span></div> <div class="cd-timeline-content"> <div class="timeline-head"> <span class="fl" v-text="item.name"></span> <span class="fl">打卡時間</span><span class="fl" v-text="item.time"></span> <span v-if="item.errorType!=''" class="mui-badge fl" v-bind:class="g.getTimeCardTypeBcByVal(item.errorType)" v-text="g.getTimeCardTypeByVal(item.errorType)"></span> </div> <div class="div-address"><i class="mui-icon mui-icon-location"></i><span v-text="item.address"></span></div> </div> </div> </section> <div v-else> <div class="emptyinfo"> <span class="mui-icon mui-icon-location"></span> <p>您今天未打卡哦~</p> </div> </div> <!--</div> </div>--> </div> </div> <script src="../../js/mui.min.js"></script> <script type="text/javascript" src="../../js/libs/vue.min.js"></script> <script type="text/javascript" src="../../js/common/config.js"></script> <script type="text/javascript" src="../../js/common/global.js"></script> <script type="text/javascript" src="../../js/libs/calendar.js"></script> <script type="text/javascript"> var canlendar = null; mui.init(); mui.ready(function () { //g.initScroll({ h: '300px' });//區域滾動 }); var app = new Vue({ el: "#app", data: { obj: { attendance: '', actualAttendance: '', beLate: '', leaveEarly: '' }, appData: { attendance: [], actualAttendance: [], beLate: [], leaveEarly: [] }, //不一樣考勤類型數據 monthDay: g.getDatePart('month') + '/' + g.getDatePart('day'), //月/日 week: g.getDatePart('week'), //星期幾 list: [] }, mounted: function () { var _self = this; eventListener(); initHandleData(_self); //1 canlendar = new Calendar({ parentNode: document.getElementById("container"), appData: _self.appData, sltDateFuc:_self.sltDateFuc }); //2注意順序 mui.plusReady(function () { var wv = plus.webview.currentWebview(); _self.userName = wv.userName; _self.roleName = wv.roleName; _self.imgUrl = wv.imgUrl; }) }, methods: { //回調函數,根據日期獲取考勤記錄 sltDateFuc: function (date) { //test console.log(date); var sltDate = g.convertDateFromString(date); this.monthDay = g.getDatePart('month', sltDate) + '/' + g.getDatePart('day', sltDate); //月/日 this.week = g.getDatePart('week', sltDate); //星期幾 if (date == '2017-11-11') { this.list = [{ name: '早班上班', address: '廣東省深圳市南山區學苑大道1001號南山智園C3棟5樓', time: '08:20', tag: 1, errorType: '1' }, { name: '早班上班', address: '廣東省深圳市南山區學苑大道1001號南山智園C3棟5樓', time: '09:20', tag: 1, errorType: '2' }, { name: '中班上班', address: '廣東省深圳市南山區學苑大道1001號南山智園C3棟5樓', time: '12:20', tag: 1, errorType: '' } ]; } else if (date == '2017-11-10') { this.list = [{ name: '晚班上班', address: '廣東省深圳市南山區學苑大道1001號南山智園C3棟5樓', time: '21:20', tag: 1, errorType: '1' }, { name: '晚班上班', address: '廣東省深圳市南山區學苑大道1001號南山智園C3棟5樓', time: '22:20', tag: 1, errorType: '2' }, { name: '晚班上班', address: '廣東省深圳市南山區學苑大道1001號南山智園C3棟5樓', time: '23:20', tag: 1, errorType: '' } ]; } else { this.list = []; } }, //切換考勤類型 getDataByType: function (t) { var result = []; switch (t) { case 1: //應出勤 app.appData.attendance = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 25, 27]; app.appData.beLate = []; app.appData.leaveEarly = []; app.appData.actualAttendance = []; break; case 2: //實際出勤 app.appData.actualAttendance = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 25, 27]; app.appData.attendance = []; app.appData.leaveEarly = []; app.appData.beLate = []; break; case 3: //遲到 app.appData.beLate = [3, 5]; app.appData.actualAttendance = []; app.appData.attendance = []; app.appData.leaveEarly = []; break; default: //早退 app.appData.leaveEarly = [11, 7, 21]; app.appData.attendance = []; app.appData.actualAttendance = []; app.appData.beLate = []; break; } app.list = result; canlendar = new Calendar({ parentNode: document.getElementById("container"), appData: app.appData, sltDateFuc: app.sltDateFuc }); } } }); function eventListener() { //上月 document.getElementById('prePage').addEventListener('tap', function () { console.log('prePage') canlendar.turnPre(); var str = canlendar.getPreMonth(g.id("bigTime").innerHTML); updateMonth(str); }) //下月 document.getElementById('nextPage').addEventListener('tap', function () { canlendar.turnNext(); var str = canlendar.getNextMonth(g.id("bigTime").innerHTML); updateMonth(str); }) } function updateMonth(str) { var year = str.substring(0, 4); var month = str.substr(5, 2); var r = year + '年' + month + '月'; g.id("bigTime").innerHTML = str; g.id("timeNow").innerHTML = r; } function initHandleData(app) { app.obj.attendance = 27; app.obj.actualAttendance = 26; app.obj.beLate = 2; app.obj.leaveEarly = 3; } </script> </body> </html>
數據我都是模擬的假數據,因此看見顯示有問題不要奇怪,實際項目天然是用ajax調用api接口進行數據填充。咋一看就知道這裏面用到了日期和垂直時間線。jquery
calendar.js我是在別人的calendar組件基礎之上進行修改的,代碼以下:android
/** * Created by zouqj on 17/11/10 */ var doc = window.document; var Calendar = function (options) { "use strict"; //默認參數 var defaults = { //中文格式內容 appData: { attendance: [], actualAttendance: [], beLate: [], leaveEarly: [] },//界面傳過來的數據 sltDateFuc: function (sltDate) { },//選中日期回調函數 monthNames: ['一月', '二月', '三月', '四月', '五月', '六月', '七月', '八月', '九月', '十月', '十一月', '十二月'], dayNames: ['週日', '週一', '週二', '週三', '週四', '週五', '週六'], dayLongNames: ['星期日', '星期一', '星期二', '星期三', '星期四', '星期五', '星期六'], holiday: { "1-1": "元旦", "2-2": "溼地日", "2-14": "情人節", "3-8": "婦女節", "3-12": "植樹節", "3-15": "消費者權益日", "4-1": "愚人節", "4-22": "地球日", "5-1": "勞動節", "5-4": "青年節", "5-12": "護士節", "5-18": "博物館日", "6-1": "兒童節", "6-5": "環境日", "6-23": "奧林匹克日", "6-24": "骨質疏鬆日", "7-1": "建黨節", "8-1": "建軍節", "9-3": "抗打敗利日", "9-10": "教師節", "10-1": "國慶節", "11-17": "學生日", "12-1": "艾滋病日", "12-24": "平安夜", "12-25": "聖誕節" }, firstDay: 1, // 從週一開始,計算 weekendDays: [0, 6], // 休息日爲:週六, 週日 dateFormat: 'yyyy-mm-dd', // 打印格式, formatDate 對應 limitDis: 80, // 拖拽限制距離,當大於該距離時,觸發頁面切換 weekHandler: "dayThead", // 星期title內容所在類 monthContainer: "dateUl", // 日期內容所在容器類 toolBar: "timeChoose", // 工具條所在類 parentNode: document.body, // 組件插入容器,默認body template: // '<div class="pannel" id="timePannel"></div>' //+ '<div class="aside">' //+ '<header class="timeNow"></header>' //+ '<div class="dateContain">' //+ '<div class="bigTime"></div>' //+ '<div class="noliDate"></div>' //+ '<div class="goodBad">' //+ '<div class="gooList"></div>' //+ '<div class="badList"></div>' //+ '</div>' //+ '</div>' //+ '</div>' '<div class="container">' + '<div class="main">' + '<div class="operator">' + '<div class="goPrev">' + '<i class="icon icon-left"></i>' + '</div>' + '<div class="goNext">' + '<i class="icon icon-right"></i>' + '</div>' + '<div class="timeChoose"></div>' + '</div>' + '<div class="datePicker">' + '<div class="dayThead"></div>' + '<div class="dateUlContainer">' + '<div class="dateUl">' + '<div class="dateLi">' //+ '<div class="dayTbody"></div>' + '</div>' + '</div>' + '</div>' + '</div>' + '</div>' + '</div>' }; //參數調整 options = options || {}; for (var prop in defaults) { if (typeof options[prop] === 'undefined') { options[prop] = defaults[prop]; } } this.attrs = options; //觸摸起始點記錄 this.touchesStart = {}; //初始化內容 this.init(); }; Calendar.prototype = { constructor: Calendar, init: function (id) { //初始化界面 this.render(id); //初始化事件 this.initEvents(); //初始佈局頁面 this.layout(); /** * 初始化參數 * this.index 切換頁面索引 * this._initEd 是否初始化完成 * this._interval 動畫切換鎖,防止動畫重複觸發 * this.offsetValue 切換容器寬度,頁面resize時,須要更新該值 */ this.index = 0; this._initEd = true; this._interval = true; this.offsetValue = this.monthEle.offsetWidth; //節點操做 this.timeNowEle = doc.querySelector("#timeNow"); this.bigTimeEle = doc.querySelector(".bigTime"); //this.noliDateEle = doc.querySelector(".noliDate"); //this.gooList = doc.querySelector(".gooList"); this.badList = doc.querySelector(".badList"); //this.timePannel = doc.getElementById("timePannel"); this.prevMonthEle = doc.querySelector(".prev-month-html"); this.currMonthEle = doc.querySelector(".current-month-html"); this.nextMonthEle = doc.querySelector(".next-month-html"); //初始化 aside頁面 this.setAside(); //默認加載當天的考勤記錄 var strDate = g.formatDate(new Date(), 'YMD'); this.attrs.sltDateFuc(strDate); }, render: function () { this.attrs.parentNode.innerHTML = this.attrs.template; }, pad2 : function (n) { return n < 10 ? '0' + n : n }, /** * 設置aside側邊欄內容 * @param date 指定日期 */ setAside: function (date) { date = date || new Date(); var year = date.getFullYear(), month = date.getMonth(), day = date.getDate(); var noli = Util.getLunarCalendar(year, month + 1, day); var suitTaboo = Util.getSuitAndTaboo(year, month + 1, day); //var gooStr = "<i>宜</i>"; //var badStr = "<i>忌</i>"; this.timeNowEle.innerHTML = year + "年" + this.pad2(month + 1) + "月"; //+ "<span>" + this.attrs.dayLongNames[date.getDay()] + "</span>"; this.bigTimeEle.innerHTML = year + '-' + (month + 1) + '-' + day; //this.noliDateEle.innerHTML = "<p>" + noli["month"] + noli["date"] +"</p>" // + "<p>" + Util.getSexagenaryCycle(year) + "【" +Util.getZodiac(year) + "】" +"</p>"; //for(var i = 0, len = suitTaboo["suit"].length; i < len; i++) { // gooStr += "<span>" + suitTaboo["suit"][i] +"</span>"; //} //for(var i = 0, len = suitTaboo["taboo"].length; i < len; i++) { // badStr += "<span>" + suitTaboo["taboo"][i] + "</span>"; //} //this.gooList.innerHTML = gooStr; //this.badList.innerHTML = badStr; }, /** * 初始化事件 */ initEvents: function () { var self = this; var monthEle = this.monthEle = doc.querySelector("." + this.attrs.monthContainer); this.timeChooseEle = doc.querySelector(".timeChoose"); this.goPrev = doc.querySelector(".goPrev"); this.goNext = doc.querySelector(".goNext"); monthEle.addEventListener("mousedown", this._handleTouchStart.bind(this), false); monthEle.addEventListener("mousemove", this._handleTouchMove.bind(this), false); monthEle.addEventListener("mouseup", this._handleTouchEnd.bind(this), false); monthEle.addEventListener("touchstart", this._handleTouchStart.bind(this), false); monthEle.addEventListener("touchmove", this._handleTouchMove.bind(this), false); monthEle.addEventListener("touchend", this._handleTouchEnd.bind(this), false); monthEle.addEventListener("tap", this._handleClick.bind(this), false);//click change to tap monthEle.addEventListener("touchstart", this._handleClick.bind(this), false); this.goPrev.addEventListener("tap", function (event) { self.turnPre(); }, false); this.goNext.addEventListener("tap", function (event) { self.turnNext(); }, false); /** * BUG: 問題, bind(this)的事件函數, 沒法removeEventListener * 監聽動畫完成事件 */ monthEle.addEventListener("transitionend", this._transformEnd.bind(this), false); monthEle.addEventListener("webkitTransitionEnd", this._transformEnd.bind(this), false); //操做表操做,事件委託處理 this.timeChooseEle.addEventListener("tap", this._handleTimeChoose.bind(this), false); document.addEventListener("tap", this._handleDocument.bind(this), false); //頁面resize監聽,函數節流,調整佈局 window.addEventListener("resize", this._handleResize.bind(this), false); }, /** * 關閉下拉菜單 * @param event * @private */ _handleDocument: function (event) { var target = event.target, cls = target.className; if (cls !== "pullDown") { var btns = document.querySelectorAll(".buttonGroup"); for (var i = 0, len = btns.length; i < len; i++) { btns[i].classList.remove("open"); } } }, /** * 工具欄事件綁定, 提供日期變動(年+月 ), 返回今天等功能 * @param event * @private */ _handleTimeChoose: function (event) { event.preventDefault(); var target = event.target, parentNode = target.parentNode, cls = target.className; //排除非元素節點 if (target.nodeType !== 1) { return; } if (cls === "pullDown") { var pCls = parentNode.className.split(" "); if (pCls.indexOf("open") === -1) { parentNode.classList.add("open"); } else { parentNode.classList.remove("open"); } } //返回今天 if (cls === "returnToday" || parentNode.className === "returnToday") { this.resetDate(new Date()); } //年份更新 if (cls === "list-year") { var year = parseInt(target.getAttribute("data-year")), month = parseInt(doc.getElementById("op-month-time").textContent) - 1; doc.getElementById("op-year-time").textContent = year + "年"; this.resetDate(new Date(year, month)); } //月份更新 if (cls === "list-month") { var year = parseInt(doc.getElementById("op-year-time").textContent), month = parseInt(target.getAttribute("data-month")); doc.getElementById("op-month-time").textContent = month + "月"; this.resetDate(new Date(year, month)); } }, _handleResize: function (event) { var self = this; //函數節流, 從新調整寬度 self.resizeInterval = setTimeout(function () { self.offsetValue = self.monthEle.offsetWidth; }, 300) }, _handleClick: function (event) { event.preventDefault(); var target = event.target, eleName = target.nodeName; if (eleName === "SPAN" || target.className === "dayTd") { var aim = eleName === "SPAN" ? target.parentNode : target; var year = parseInt(aim.getAttribute("data-year")), month = parseInt(aim.getAttribute("data-month")), day = parseInt(aim.getAttribute("data-day")); if (this._oldEle) { this._oldEle.classList.remove("date-selected"); } aim.classList.add("date-selected"); this._oldEle = aim; this.setAside(new Date(year, month, day)) if (event.type == 'tap') { //根據日期加載打卡記錄列表 var sltDate = year + '-' + this.pad2(month + 1) + '-' + day; this.attrs.sltDateFuc(sltDate); //執行回調 } } }, _handleTouchStart: function (event) { event.preventDefault(); //屏蔽屢次觸發 if (!this._interval) { return; } this.isTouched = true; if (event.type === "touchstart") { this.touchesStart.x = event.targetTouches[0].pageX; } else { this.touchesStart.x = event.pageX; } }, _handleTouchMove: function (event) { event.preventDefault(); if (!this.isTouched) { return; } this.isMoved = true; if (event.type === "touchmove") { var pageX = event.targetTouches[0].pageX; } else { var pageX = event.pageX; } //橫向移動距離 this.touchesDiff = pageX - this.touchesStart.x; this.endPos = pageX; //設置樣式 this.monthEle.style[Util.prefix + "transition"] = "all 0ms"; this.monthEle.style[Util.prefix + "transform"] = "translate3d(" + (this.index * this.offsetValue + this.touchesDiff) + "px, 0px, 0px)"; }, _handleTouchEnd: function (event) { event.preventDefault(); if (!this.isTouched || !this.isMoved) { this.isTouched = false; this.isMoved = false; return; } var comPos = this.endPos - this.touchesStart.x; //移動距離對比 if (Math.abs(comPos) < this.attrs.limitDis) { this._transformPage(); } else { if (comPos < 0) { this.turnNext(); //下一頁 } else { this.turnPre(); //上一頁 } } this.isTouched = false; this.isMoved = false; }, turnPre: function () { if (!this._interval) { return; } this.index++; this._isTurnPage = true; this._offset = "prev"; //鎖上操做, 防止屢次觸發 this._interval = false; this._transformPage(); }, turnNext: function () { if (!this._interval) { return; } this.index--; this._isTurnPage = true; this._offset = "next"; //鎖上操做, 防止屢次觸發 this._interval = false; this._transformPage(); }, _transformPage: function () { this.monthEle.style[Util.prefix + "transition"] = "300ms"; this.monthEle.style[Util.prefix + "transform"] = "translate3d(" + (this.index * 100) + "%, 0, 0)"; }, /** * 提示日期tip,僅在移動端有效(寬度 < 425px 觸發) * @private */ _tipPannel: function () { var self = this; if (this.offsetValue > 425) { return; } var year = this.value.getFullYear(), month = this.value.getMonth() + 1; this.timePannel.textContent = year + "年" + month + "月"; clearTimeout(this.tipInterval); this.timePannel.style["display"] = "block"; //強制relayout,不然動畫無效果 self.timePannel.offsetWidth; this.timePannel.style["opacity"] = 1; this.tipInterval = setTimeout(function () { self.timePannel.style["opacity"] = 0; self.timePannel.style["display"] = "none"; }, 800); }, /** * 翻頁結束後觸發回調事件 * @private */ _transformEnd: function () { //不是翻頁不行 var offset = this._offset; if (!this._isTurnPage) { return; } var date = new Date(this.value); var year = date.getFullYear(), month = date.getMonth(); //下個月 if (offset === 'next') { if (month === 11) { date = new Date(year + 1, 0); } else { date = new Date(year, month + 1, 1); } } //上個月 if (offset === 'prev') { if (month === 0) { date = new Date(year - 1, 11); } else { date = new Date(year, month - 1, 1); } } this.value = date; //this._tipPannel(); this.layout(); // 重定位 var index = this.index * -1; //從新獲取 時間容器節點 this.prevMonthEle = doc.querySelector(".prev-month-html"); this.currMonthEle = doc.querySelector(".current-month-html"); this.nextMonthEle = doc.querySelector(".next-month-html"); this.prevMonthEle.style[Util.prefix + "transform"] = "translate3d(" + (index - 1) * 100 + "%, 0px, 0px)"; this.currMonthEle.style[Util.prefix + "transform"] = "translate3d(" + (index) * 100 + "%, 0px, 0px)"; this.nextMonthEle.style[Util.prefix + "transform"] = "translate3d(" + (index + 1) * 100 + "%, 0px, 0px)"; doc.getElementById("op-year-time").textContent = this.value.getFullYear() + "年"; doc.getElementById("op-month-time").textContent = (this.value.getMonth() + 1) + "月"; //恢復鎖,能夠繼續觸發 this._interval = true; this._isTurnPage = false; }, /** * 指定時間,重置日期內容 * @param date 時間 */ resetDate: function (date) { this.value = date; this.index = 0; this.monthEle.style[Util.prefix + "transition"] = "all 0ms"; this.monthEle.style[Util.prefix + "transform"] = "translate3d(0 ,0 ,0)"; this.prevMonthEle.style[Util.prefix + "transform"] = "translate3d(-100%, 0px, 0px)"; this.currMonthEle.style[Util.prefix + "transform"] = "translate3d(0%, 0px, 0px)"; this.nextMonthEle.style[Util.prefix + "transform"] = "translate3d(100%, 0px, 0px)"; doc.getElementById("op-year-time").textContent = this.value.getFullYear() + "年"; doc.getElementById("op-month-time").textContent = (this.value.getMonth() + 1) + "月"; this.layout(); }, /** * 佈局函數 */ layout: function () { var layoutDate = this.value ? this.value : new Date().setHours(0, 0, 0, 0); this.value = layoutDate; //三個月的 HTML信息 var prevMonthHTML = this.monthHTML(layoutDate, 'prev'); var currentMonthHTML = this.monthHTML(layoutDate); var nextMonthHTML = this.monthHTML(layoutDate, 'next'); var monthHTML = '<div class="dateLi prev-month-html"><div class="dayTbody">' + prevMonthHTML + "</div></div>" + '<div class="dateLi current-month-html"><div class="dayTbody">' + currentMonthHTML + "</div></div>" + '<div class="dateLi next-month-html"><div class="dayTbody">' + nextMonthHTML + "</div></div>" if (!this._initEd) { //初次渲染的時候使用, 不然不使用 //渲染 星期頭部 var weekHeaderHTML = []; for (var i = 0; i < 7; i++) { var weekDayIndex = (i + this.attrs.firstDay > 6) ? (i - 7 + this.attrs.firstDay) : (i + this.attrs.firstDay); var dayName = this.attrs.dayNames[weekDayIndex]; if (this.attrs.weekendDays.indexOf(weekDayIndex) !== -1) { //休息日樣式 weekHeaderHTML.push('<div class="dayTd active">' + dayName + '</div>'); } else { weekHeaderHTML.push('<div class="dayTd">' + dayName + '</div>'); } } var yearSelectHTML = [], monthSelectHTML = []; for (var i = 1900; i <= 2050; i++) { var str = "<li class='list-year' data-year='" + i + "'>" + i + "年</li>"; yearSelectHTML.push(str); } for (var i = 1; i <= 12; i++) { var str = "<li class='list-month' data-month='" + (i - 1) + "'>" + i + "月</li>"; monthSelectHTML.push(str); } doc.querySelector("." + this.attrs.weekHandler).innerHTML = weekHeaderHTML.join(""); doc.querySelector("." + this.attrs.toolBar).innerHTML = '<div class="yearChoose">' + '<div class="chooseContainer">' + '<div class="buttonGroup">' + '<span class="yearTime" id="op-year-time">' + new Date().getFullYear() + '年</span>' + '<span class="pullDown">+</span>' + '</div>' + '<div class="pullSelect">' + '<ul>' + yearSelectHTML.join('') + '</ul>' + '</div>' + '</div>' + '</div>' + '<div class="monthChoose">' + '<div class="chooseContainer">' + '<div class="buttonGroup">' + '<span class="monthTime" id="op-month-time">' + (new Date().getMonth() + 1) + '月</span>' + '<span class="pullDown">+</span>' + '</div>' + '<div class="pullSelect">' + '<ul>' + monthSelectHTML.join('') + '</ul>' + '</div>' + '</div>' + '</div>' + '<div class="returnToday"><span>返回今天</span></div>' } doc.querySelector("." + this.attrs.monthContainer).innerHTML = monthHTML; }, /** * 獲取當月總天數 * @param date 日期 */ totalDaysInMonth: function (date) { var d = new Date(date); return new Date(d.getFullYear(), d.getMonth() + 1, 0).getDate(); }, /** * 日期HTML設置 * @param date 設置時間 * @param offset 設置偏移 ["next" -> "下個月" "prev" -> "上個月"] * @returns {string} 返回拼接好的HTML字符串 */ monthHTML: function (date, offset) { var date = new Date(date); var year = date.getFullYear(), month = date.getMonth(), day = date.getDate(); //下個月 if (offset === 'next') { if (month === 11) { date = new Date(year + 1, 0); } else { date = new Date(year, month + 1, 1); } } //上個月 if (offset === 'prev') { if (month === 0) { date = new Date(year - 1, 11); } else { date = new Date(year, month - 1, 1); } } //調整時間 if (offset === 'next' || offset === 'prev') { month = date.getMonth(); year = date.getFullYear(); } //上月 | 本月 總天數, 本月第一天索引 var daysInPrevMonth = this.totalDaysInMonth(new Date(date.getFullYear(), date.getMonth()).getTime() - 10 * 24 * 60 * 60 * 1000), daysInMonth = this.totalDaysInMonth(date), firstDayOfMonthIndex = new Date(date.getFullYear(), date.getMonth()).getDay(); if (firstDayOfMonthIndex === 0) { firstDayOfMonthIndex = 7; } var dayDate, rows = 5,//日曆行數 cols = 7, monthHTML = [], dayIndex = 0 + (this.attrs.firstDay - 1), today = new Date().setHours(0, 0, 0, 0); for (var i = 1; i <= rows; i++) { var row = i; var tdList = []; for (var j = 1; j <= cols; j++) { var col = j; dayIndex++; var dayNumber = dayIndex - firstDayOfMonthIndex; //要添加的類名, 默認dayTd var classNames = ["dayTd"]; if (dayNumber < 0) { //上個月日期 classNames.push("date-prev"); dayNumber = daysInPrevMonth + dayNumber + 1; dayDate = new Date(month - 1 < 0 ? year - 1 : year, month - 1 < 0 ? 11 : month - 1, dayNumber).getTime(); } else { dayNumber = dayNumber + 1; if (dayNumber > daysInMonth) { //下個月日期 classNames.push("date-next"); dayNumber = dayNumber - daysInMonth; dayDate = new Date(month + 1 > 11 ? year + 1 : year, month + 1 > 11 ? 0 : month + 1, dayNumber).getTime(); } else { dayDate = new Date(year, month, dayNumber).getTime(); } } //今天 date-current if (dayDate === today) { classNames.push("date-current"); } //週六日 date-reset if (dayIndex % 7 === this.attrs.weekendDays[0] || dayIndex % 7 === this.attrs.weekendDays[1]) { classNames.push("date-reset"); } dayDate = new Date(dayDate); var dayYear = dayDate.getFullYear(); var dayMonth = dayDate.getMonth(); //農曆日期 var ccalendar = Util.getLunarCalendar(dayYear, dayMonth + 1, dayNumber); var holiday = this.attrs.holiday[(dayMonth + 1) + "-" + dayNumber]; //節日顯示,優先級別:公曆節日 > 農曆節日 > 節氣 > 農曆 date-holiday if (holiday) { var alamanac = holiday; classNames.push("date-holiday"); } else { if (ccalendar["festival"]) { var alamanac = ccalendar["festival"]; classNames.push("date-holiday"); } else { if (ccalendar["solarTerm"]) { var alamanac = ccalendar["solarTerm"]; classNames.push("date-holiday"); } else { var alamanac = ccalendar["date"]; } } } //集合包含dayNumber var _appData = this.attrs.appData; var _tagHtml = ''; if (_appData.attendance.contains(dayNumber))//應出勤 { classNames.push("attendance"); } if (_appData.actualAttendance.contains(dayNumber)) {//實際出勤 classNames.push("actualAttendance"); } if (_appData.beLate.contains(dayNumber)) {//遲到 classNames.push("beLate"); _tagHtml = '<i class="fl font-danger">遲</i>'; } if (_appData.leaveEarly.contains(dayNumber)) {//早退 _tagHtml = '<i class="fl font-warning">退</i>'; classNames.push("leaveEarly"); } tdList.push( '<div class="' + classNames.join(" ") + '" data-year=' + dayYear + ' data-month=' + dayMonth + ' data-day=' + dayNumber + '>' + '<span class="dayNumber">' + _tagHtml +dayNumber + "</span>" + '<span class="almanac">' + alamanac + "</span>" + '</div>' ) } monthHTML.push( '<div class="dayTr">' + tdList.join("") + '</div>' ) } return monthHTML.join(""); }, /** * 格式化日期內容 * @param date * @returns {string|XML} */ formatDate: function (date) { date = new Date(date); var year = date.getFullYear(); var month = date.getMonth(); var month1 = month + 1; var day = date.getDate(); var weekDay = date.getDay(); return this.attrs.dateFormat .replace(/yyyy/g, year) .replace(/yy/g, (year + '').substring(2)) .replace(/mm/g, month1 < 10 ? '0' + month1 : month1) .replace(/m/g, month1) .replace(/MM/g, this.attrs.monthNames[month]) .replace(/dd/g, day < 10 ? '0' + day : day) .replace(/d/g, day) .replace(/DD/g, this.attrs.dayNames[weekDay]) }, /** * 獲取上一個月 * @date 格式爲yyyy-mm-dd的日期,如:2014-01-25 */ getPreMonth: function (date) { var arr = date.split('-'); var year = arr[0]; //獲取當前日期的年份 var month = arr[1]; //獲取當前日期的月份 var day = arr[2]; //獲取當前日期的日 var days = new Date(year, month, 0); days = days.getDate(); //獲取當前日期中月的天數 var year2 = year; var month2 = parseInt(month) - 1; if (month2 == 0) { year2 = parseInt(year2) - 1; month2 = 12; } var day2 = day; var days2 = new Date(year2, month2, 0); days2 = days2.getDate(); if (day2 > days2) { day2 = days2; } if (month2 < 10) { month2 = '0' + month2; } var t2 = year2 + '-' + month2 + '-' + day2; return t2; }, /** * 獲取下一個月 * @date 格式爲yyyy-mm-dd的日期,如:2014-01-25 */ getNextMonth: function (date) { var arr = date.split('-'); var year = arr[0]; //獲取當前日期的年份 var month = arr[1]; //獲取當前日期的月份 var day = arr[2]; //獲取當前日期的日 var days = new Date(year, month, 0); days = days.getDate(); //獲取當前日期中的月的天數 var year2 = year; var month2 = parseInt(month) + 1; if (month2 == 13) { year2 = parseInt(year2) + 1; month2 = 1; } var day2 = day; var days2 = new Date(year2, month2, 0); days2 = days2.getDate(); if (day2 > days2) { day2 = days2; } if (month2 < 10) { month2 = '0' + month2; } var t2 = year2 + '-' + month2 + '-' + day2; return t2; } }; var Util = { /** * css前綴判斷,僅執行一次 */ prefix: (function () { var div = document.createElement('div'); var cssText = '-webkit-transition:all .1s; -moz-transition:all .1s; -o-transition:all .1s; -ms-transition:all .1s; transition:all .1s;'; div.style.cssText = cssText; var style = div.style; if (style.transition) { return ''; } if (style.webkitTransition) { return '-webkit-'; } if (style.MozTransition) { return '-moz-'; } if (style.oTransition) { return '-o-'; } if (style.msTransition) { return '-ms-'; } })(), /** * 公曆轉化爲積日(積日:1900年1月0日到當天的天數 * @param year 年份 * @param month 月份 * @param day 日期 * @returns {number} * @private */ _gregorianCalendarToAccumulateDate: function (year, month, day) { var accumulateDate = 0; accumulateDate += (year - 1900) * 365; //假設每一年365天,計算天數 accumulateDate += parseInt((year - 1901) / 4); //將閏年數累加計數 for (var eachMonth = month - 1; eachMonth > 0; eachMonth--) { accumulateDate += (new Date(year, eachMonth, 0)).getDate(); //累加當年各月天數 } accumulateDate += day; //累加最後一月天數 return accumulateDate; //返回公曆日期對應積日 }, /** * 計算積日的農曆日期 * @param accumulateDate * @returns {number} * @private */ _getLunarDate: function (accumulateDate) { //逆推估算是第幾個朔日 var reverseCalends = parseInt((accumulateDate - 1.6) / 29.5306); var calends = reverseCalends - 1; do { calends++; //計算朔日積日 var calendsAccumulateDate = parseInt(1.6 + 29.5306 * calends + 0.4 * Math.sin(1 - 0.45058 * calends)); var solarTermDate = accumulateDate - calendsAccumulateDate + 1; } while (solarTermDate >= 30); //下一個朔日在當天的第二天,當月即爲大月,當日爲農曆三十 if (solarTermDate === 0) return 30; else return solarTermDate; }, /** * 計算某年某個節氣的積日(公式) * @param differenceYear * @param solarTermSerialNumber * @returns {Number} * @private */ _getSolarTermAccumulateDate: function (differenceYear, solarTermSerialNumber) { var solarTermAccumulateDate = parseInt(365.242 * differenceYear + 6.2 + 15.22 * solarTermSerialNumber - 1.9 * Math.sin(0.262 * solarTermSerialNumber)); return solarTermAccumulateDate; }, /** * 獲取農曆日期 * @param year * @param month * @param day * @returns {{month: string, date: string, solarTerm: string, festival: *}} */ getLunarCalendar: function (year, month, day) { //常量數組 var monthName = ["正月", "二月", "三月", "四月", "五月", "六月", "七月", "八月", "九月", "十月", "十一月", "臘月"]; var dateName = ["十", "一", "二", "三", "四", "五", "六", "七", "八", "九"]; var datePrefixName = ["初", "十", "廿", "三"]; var solarTermName = ["小寒", "大寒", "立春", "雨水", "驚蟄", "春分", "清明", "穀雨", "立夏", "小滿", "芒種", "夏至", "小暑", "大暑", "立秋", "處暑", "露水", "秋分", "寒露", "霜降", "立冬", "小雪", "大雪", "冬至"]; var festivalName = { "0101": "春節", "0115": "元宵節", "0202": "龍頭節", "0505": "端午", "0707": "七夕", "0715": "中元節", "0815": "中秋", "0909": "重陽節", "1001": "寒衣節", "1015": "下元節", "1208": "臘八節", "1223": "小年", "1230": "除夕" }; var differenceYear = year - 1900; //年份距1900年差值 var solarTermSerialNumber = month * 2 - 1; //節氣序號 var lunarCalendarMonth = (month - 1 + 12) % 12; //理論農曆月份 var accumulateDate = Util._gregorianCalendarToAccumulateDate(year, month, day); //計算當前日期積日 var lunarDate = Util._getLunarDate(accumulateDate); //計算農曆日期 //計算前一個月、當月、後一個月、前半個月以及後半個月的節氣日期(STLD)和節氣積日(STAD) var curSTLD = Util._getLunarDate(Util._getSolarTermAccumulateDate(differenceYear, solarTermSerialNumber)); var prevSTLD = Util._getLunarDate(Util._getSolarTermAccumulateDate(differenceYear, solarTermSerialNumber - 2)); var nextSTLD = Util._getLunarDate(Util._getSolarTermAccumulateDate(differenceYear, solarTermSerialNumber + 2)); var halfPrevSTLD = Util._getLunarDate(Util._getSolarTermAccumulateDate(differenceYear, solarTermSerialNumber - 1)); var halfNextSTLD = Util._getLunarDate(Util._getSolarTermAccumulateDate(differenceYear, solarTermSerialNumber + 1)); var curSTAD = Util._getSolarTermAccumulateDate(differenceYear, solarTermSerialNumber); var prevSTAD = Util._getSolarTermAccumulateDate(differenceYear, solarTermSerialNumber - 2); var nextSTAD = Util._getSolarTermAccumulateDate(differenceYear, solarTermSerialNumber + 2); var halfPrevSTAD = Util._getSolarTermAccumulateDate(differenceYear, solarTermSerialNumber - 1); var halfNextSTAD = Util._getSolarTermAccumulateDate(differenceYear, solarTermSerialNumber + 1); //經過節氣日期判斷閏月狀況,調整月份 if (accumulateDate < curSTAD && lunarDate + curSTAD - accumulateDate !== curSTLD) lunarCalendarMonth--; else if (accumulateDate > curSTAD && lunarDate - (accumulateDate - curSTAD) !== curSTLD && lunarDate + nextSTLD - accumulateDate === nextSTAD) lunarCalendarMonth++; //判斷是不是節氣 if (curSTAD === accumulateDate) var solarTerm = solarTermName[solarTermSerialNumber]; else if (halfPrevSTAD === accumulateDate) var solarTerm = solarTermName[solarTermSerialNumber - 1]; else if (halfNextSTAD === accumulateDate) var solarTerm = solarTermName[solarTermSerialNumber + 1]; //計算是否節日 var monthNumber = lunarCalendarMonth; if (monthNumber < 10) var festivalNumber = "0" + monthNumber; else var festivalNumber = monthNumber; if (lunarDate < 10) festivalNumber += "0" + lunarDate; else festivalNumber += lunarDate; //拼接字符串 var festivalString = festivalName[festivalNumber]; //調用節日 //計算農曆名稱 var monthString = monthName[(monthNumber + 11) % 12]; //月份名稱 var prefix = parseInt((lunarDate - 1) / 10); if (lunarDate === 20 || lunarDate === 30) var dateString = datePrefixName[prefix + 1]; else var dateString = datePrefixName[prefix]; dateString += dateName[lunarDate % 10]; //日期名稱 //返回結果 var result = { 'month': monthString, 'date': dateString, 'solarTerm': solarTerm, 'festival': festivalString }; return result; }, /** * 判斷年份干支 * @param year 公曆年份 * @returns {string} 返回干支 */ getSexagenaryCycle: function (year) { //常量數組 var heavenlyStems = ["癸", "甲", "乙", "丙", "丁", "戊", "己", "庚", "辛", "壬"]; var earthlyBranches = ["亥", "子", "醜", "寅", "卯", "辰", "巳", "午", "未", "申", "酉", "戌"]; //計算與1963年的差值(1964年爲甲子年) var yearSerialNumber = year - 1863; //拼接該年干支 var sexagenaryCycle = heavenlyStems[yearSerialNumber % 10]; sexagenaryCycle += earthlyBranches[yearSerialNumber % 12]; sexagenaryCycle += "年"; return sexagenaryCycle; }, /** * 獲取生肖年份 * @param year * @returns {string} */ getZodiac: function (year) { //常量數組 var zodiacName = ["豬年", "鼠年", "牛年", "虎年", "兔年", "龍年", "蛇年", "馬年", "羊年", "猴年", "雞年", "狗年"]; //計算與1963年的差值(1964年爲甲子年) var yearSerialNumber = year - 1863; return zodiacName[yearSerialNumber % 12]; }, /** * 玄學啊,獲取禁忌事情 * @param year * @param month * @param day * @returns {{suit: string, taboo: string}} */ getSuitAndTaboo: function (year, month, day) { var suit = ["開光", "嫁娶", "入宅", "上樑", "祭祀", "出行", "做竈", "破土", "訂盟", "祈福"]; var taboo = ["納采", "冠笄", "豎柱", "掘井", "伐木", "理髮", "交易", "探病", "雕刻", "齋醮"]; var dateString = parseInt((year * month * day) % 1025).toString(2); var len = dateString.length; if (len < 10) for (; len < 10 ; len++) dateString = "0" + dateString; dateString = dateString.split("").reverse().join(""); var dateNum = parseInt(dateString, 2); var suitResult = []; var tabooResult = []; for (var i = 0; i < 10; i++) { if (dateNum % 2) suitResult.push(taboo[i]); else tabooResult.push(suit[i]); dateNum = parseInt(dateNum / 2); } var suitString = suitResult; var tabooString = tabooResult; var result = { 'suit': suitString, 'taboo': tabooString } return result; } };
calendar.css也是同樣,我進行了改造,代碼以下:css3
html { font-size: 16px;-ms-text-size-adjust: 100%; -webkit-text-size-adjust: 100%;/*不用10px 62.5% 由於chrome只支持12px最小*/ } *,*:before,*:after { box-sizing: border-box;-webkit-tap-highlight-color: rgba(0, 0, 0, 0); } [hidden],template {display: none;} a {background-color: transparent;text-decoration: none;} a:active,a:hover {outline: 0;} abbr[title] {border-bottom: 1px dotted;} b,strong {font-weight: bold;} dfn {font-style: italic;} mark {background: #ff0;color: #000;} small{font-size: 80%;} sub,sup {font-size: 75%;line-height: 0;position: relative;vertical-align: baseline;} sup {top: -0.5em;} sub {bottom: -0.25em;} img {border: 0;} svg:not(:root) {overflow: hidden;} figure {margin: 1em 40px;} hr {box-sizing: content-box;height: 0;} pre {overflow: auto;} code,kbd,pre,samp { font-family: monospace, monospace;font-size: 1em; } button,input,optgroup,select,textarea { color: inherit;font: inherit;margin: 0; } a,input,textarea,select,button { outline: 0; } button {overflow: visible;} button,select {text-transform: none;} button,html input[type="button"],input[type="reset"],input[type="submit"] { -webkit-appearance: button;cursor: pointer; } button[disabled],html input[disabled] { cursor: default; } button::-moz-focus-inner,input::-moz-focus-inner { border: 0;padding: 0; } input { line-height: normal; } input[type="checkbox"], input[type="radio"] { box-sizing: border-box;padding: 0; } input[type="number"]::-webkit-inner-spin-button, input[type="number"]::-webkit-outer-spin-button { height: auto; } input[type="search"] { -webkit-appearance: textfield;box-sizing: content-box; } input[type="search"]::-webkit-search-cancel-button, input[type="search"]::-webkit-search-decoration { -webkit-appearance: none; } fieldset { border: 1px solid #c0c0c0;margin: 0 2px;padding: 0.35em 0.625em 0.75em; } legend {border: 0;padding: 0;} textarea {overflow: auto;} optgroup {font-weight: bold;} .button:active {color: #0a8ddf;border-color: #0a8ddf;} /*p {margin: 1em 0;}*/ body { position: absolute;top: 0;right: 0;bottom: 0;left: 0;overflow: hidden; } @font-face { font-family: "icon-yuan";src: url("../fonts/icomoon.ttf"); } .icon { font-family: icon-yuan !important;font-style: normal;display: inline-block;vertical-align: -2px; } .icon-left:after {content: '\f053';} .icon-right:after {content: '\f054';} html {height: 100%;} .container { width: 100%; display: -webkit-box;display: -webkit-flex;display: -ms-flexbox;display: flex; -webkit-flex-wrap: wrap; -ms-flex-wrap: wrap;flex-wrap: wrap;height: 100%; } .container > div {height: 100%;} .container .aside { color: #ffffff;width: 35%;padding: 15px 20px; } .container .main {width: 65%;padding-left: 15px;padding-right: 15px;} .timeNow {text-align: center;font-size: 0.85rem;} .timeNow span:first-child {margin-right: 10px;} .operator {position: relative;} .operator .goPrev { position: absolute;top: 0px;left: 0px; } .operator .goNext {position: absolute;top: 0px; right: 0px;} .operator i {color: #e02d2d;line-height: 2.2rem;cursor: pointer;} .operator i:hover {color: #fb0;} .dateContain {position: relative;} .dateContain .bigTime { text-align: center;font-family: arial;font-size: 10rem; } .dateContain .bigTime span { text-shadow: 2px 2px 1px rgba(0, 0, 0, 0.1); } .dateContain .noliDate > p { font-size: 0.85rem;text-align: center; } .dateContain .goodBad { border-top: 2px solid #94c9ff;padding: 10px 7px; } .dateContain .goodBad > div i { font-style: normal;text-shadow: 2px 2px 1px rgba(0, 0, 0, 0.1); text-align: center;color: #fff;font-size: 1.1rem; } .dateContain .goodBad > div span { font-size: 0.7rem;margin-left: 8px; } .aside { background: #D2456A;background: -webkit-gradient(linear, 0 0, 0 100%, from(#D2456A), to(#e42355)); } .operator { height: 2.2rem;border-bottom: 2px solid #D2456A; } .datePicker { height: calc(100% - 4.4rem);overflow: hidden; } .dateUl {height: 100%;position: relative;} .dateUl .dateLi {height: 100%;position: absolute; width: 100%;} .dayThead,.dayTbody,.dayTr { display: -webkit-box;display: -webkit-flex;display: -ms-flexbox;display: flex; -webkit-flex-wrap: wrap; -ms-flex-wrap: wrap;flex-wrap: wrap; } .dayTbody {height: calc(100% - 40px);} .dayTbody .dayTr { width: 100%;border-top: 1px solid #c8cacc; height: calc(100% / 5); } .dayTbody .dayTr .dayTd { display: -webkit-box; display: -webkit-flex;display: -ms-flexbox;display: flex; -webkit-box-orient: vertical;-webkit-box-direction: normal;-webkit-flex-direction: column; -ms-flex-direction: column; flex-direction: column;-webkit-box-pack: center; -webkit-justify-content: center;-ms-flex-pack: center;justify-content: center;width: calc(14.28571429%); } .dayTbody .dayTr .dayTd .almanac { width: 100%;overflow: hidden;text-overflow: ellipsis;white-space: nowrap; } .dayTbody .dayTr .dayTd span.dayNumber { font-family: arial;color: #000;font-size: 1.2rem; line-height: 21px;height: 18px; } .dayTbody .dayTr .dayTd span.almanac { color: #616161;font-size: 0.7rem;line-height: 25px; height: 21px; } .dayTbody .dayTr .dayTd.date-reset span:first-child { color: #7FAEF5; } .dayTbody .dayTr .dayTd.date-holiday span:last-child { color: #7FAEF5; } .dayTbody .dayTr .dayTd.date-prev span:first-child, .dayTbody .dayTr .dayTd.date-next span:first-child, .dayTbody .dayTr .dayTd.date-prev span:last-child, .dayTbody .dayTr .dayTd.date-next span:last-child { color: #bfbfbf; } .dayTbody .dayTr .dayTd.date-selected { background-color: #47D5FF; } .dayTbody .dayTr .dayTd.date-selected span:first-child, .dayTbody .dayTr .dayTd.date-selected span:last-child { color: #fff; } .dayTbody .dayTr .dayTd.date-current { background-color: #fb0; } .dayTbody .dayTr .dayTd.date-current span:first-child, .dayTbody .dayTr .dayTd.date-current span:last-child { color: #ffffff !important; } .prev-month-html { -webkit-transform: translate3d(-100%, 0, 0);transform: translate3d(-100%, 0, 0); } .current-month-html { -webkit-transform: translate3d(0, 0, 0);transform: translate3d(0, 0, 0); } .next-month-html { -webkit-transform: translate3d(100%, 0, 0);transform: translate3d(100%, 0, 0); } .dayThead {height: 40px;} .dayThead .dayTd { line-height: 40px;border: none;color: #2c9bb3; } .dayThead .dayTd.active {color: #e02d2d;} .dayTbody .dayTd:hover {box-shadow: inset 0px 0px 4px #47D5FF;} .dayTd { height: 100%;-webkit-box-flex: 1;-webkit-flex: 1; -ms-flex: 1;flex: 1;text-align: center;cursor: pointer; } .dayTd .currentDay { background-color: #fb0;} .dayTd .restDay {background-color: #fff0f0;} .pannel { position: fixed;width: 100%;top: 30%;left: 0px;text-align: center;line-height: 40px;height: 40px; background-color: rgba(227, 36, 85, 0.86);color: #ffffff;opacity: 0;display: none;-webkit-transition: opacity 300ms;transition: opacity 300ms; } @media only screen and (min-width: 701px) { .container{height:500px;} } @media only screen and (max-width: 700px) { .container { -webkit-box-orient: vertical; -webkit-box-direction: normal; -webkit-flex-direction: column; -ms-flex-direction: column;flex-direction: column;height:305px; } .container .aside { width: 100%;height: 30%; padding: 5px; } .container .main { width: 100%;height: 100%;} .bigTime {line-height: 1;font-size: 5.3rem !important;} .operator { display: none; } .datePicker { height: calc(100% - 10px);} .noliDate { display: -webkit-box;display: -webkit-flex;display: -ms-flexbox; display: flex; -webkit-box-pack: center;-webkit-justify-content: center;-ms-flex-pack: center;justify-content: center; } .noliDate p {margin: 0 10px;} .goodBad { display: none;} } .dateUlContainer { height: 100%;width: 100%;overflow: hidden; } .yearChoose,.monthChoose,.returnToday { display: inline-block;font-size: 0.7rem;margin-right: 10%; } .returnToday { background-color: #f2f2f2;border: 1px solid #999;padding: 2px 10px;cursor: default; } .timeChoose { width: 100%;display: -webkit-box;display: -webkit-flex;display: -ms-flexbox;display: flex; -webkit-box-pack: center;-webkit-justify-content: center;-ms-flex-pack: center;justify-content: center;padding: 0.5rem 20px; } .chooseContainer { position: relative;font-size: 0.7rem;color: #333; } .chooseContainer .buttonGroup { border: 1px solid #999;border-bottom-color: #d8d8d8;border-right-color: #d8d8d8;padding-left: 5px;line-height: 1; } .chooseContainer .buttonGroup span { display: inline-block; } .chooseContainer .buttonGroup span.yearTime, .chooseContainer .buttonGroup span.monthTime { margin: 0px 8px; } .chooseContainer .buttonGroup span.pullDown { width: 1.2rem;line-height: 1.2rem;cursor: default;text-align: center;border-left: 1px solid #d8d8d8;background-color: #f2f2f2; } .chooseContainer .pullSelect { display: none;width: 100%; position: absolute; z-index: 20; height: 432px;border: 1px solid #bbb;background: #fff;overflow-y: scroll; } .chooseContainer .pullSelect.open { display: block; } .chooseContainer .pullSelect ul { background-color: #fff;list-style: none; } .chooseContainer .pullSelect ul li { padding: 5px 10px; } .chooseContainer .pullSelect ul li:hover { cursor: default;background-color: #f2f2f2; } .buttonGroup.open ~ .pullSelect { display: block; } @media only screen and (min-width: 700px) { html {font-size: 21.33333333px !important;} .dateContain .bigTime { font-size: 9rem;} } @media only screen and (min-width: 800px) { html {font-size: 21.6px !important;} .dateContain .bigTime {font-size: 9rem;} } @media only screen and (min-width: 998px) { html {font-size: 25.6px !important;} } /*page css*/ .div-yearmonth,.div-operate,.ul-operate{background-color: #449DED;text-align: center;color: #FFFFFF;} .div-yearmonth{height: 42px;line-height: 42px;font-size: 16px;} .div-yearmonth .mui-icon{font-size: 20px;} .spn-today{margin: 0 10px;} #timeNow{margin-left: 5px;} .div-operate{height:56px;line-height:56px;} .ul-operate{height:56px;width:100%;} .ul-operate a{height:56px;width:25%;} .ul-operate a p{height:28px;color:#ffffff;line-height:22px;} .ul-operate a p:first-child{line-height:36px;} #container{margin-top:8px;} .mui-segmented-control .mui-control-item.mui-active:after { /*display: block;content: '';width: 70%;border-width: 1px;border-style: solid; border-color: #ffffff;position: relative;bottom: 1px;margin: 0 auto;left: 0%;*/ /*細下劃線*/ content: '';width: 0;display: block;height: 0;bottom: 1px;margin: 0 auto; border-right: 8px solid transparent;border-bottom: 8px solid #FFFFFF;border-left: 8px solid transparent;/*三角形*/ } .dayTbody .dayTr .dayTd.attendance{background-color:#F2F9FF;} .dayTbody .dayTr .dayTd.actualAttendance{background-color:#F2F9FF;} .dayTbody .dayTr .dayTd.beLate{background-color:#FFE1E1;} .dayTbody .dayTr .dayTd.leaveEarly{background-color:#FFF1D4;} .dayTbody .dayTr .dayTd.attendance.date-selected,.dayTbody .dayTr .dayTd.actualAttendance.date-selected, .dayTbody .dayTr .dayTd.beLate.date-selected,.dayTbody .dayTr .dayTd.leaveEarly.date-selected { background-color:#47D5FF; } .dayTbody .dayTr .dayTd.attendance.date-current,.dayTbody .dayTr .dayTd.actualAttendance.date-current, .dayTbody .dayTr .dayTd.beLate.date-current,.dayTbody .dayTr .dayTd.leaveEarly.date-current { background-color:#fb0; } .dayTbody .dayTr .dayTd.date-next, .dayTbody .dayTr .dayTd.date-prev /*.dayTbody .dayTr .dayTd.date-next.date-selected, .dayTbody .dayTr .dayTd.date-prev.date-selected*/ { background-color:#fff;color:#bfbfbf; } .dayTbody .dayTr .dayTd.date-next.date-selected, .dayTbody .dayTr .dayTd.date-prev.date-selected { background-color:#47D5FF;color:#fff; } /*.dayTbody .dayTr .dayTd.date-next.date-selected span:first-child,.dayTbody .dayTr .dayTd.date-prev.date-selected span:last-child{ color:#bfbfbf !important; }*/ .date-next .dayNumber i.fl,.date-prev .dayNumber i.fl { display:none; } .dayNumber i.fl{font-size:12px;margin-top: -5px;margin-right: 10px;line-height: 0.8;position: absolute;display: block;} .font-warning{color:#FBD06B;} .font-danger{color:#FA6768;} .mui-scroll-wrapper.timeline{top:505px;} .emptyinfo{margin-top:10px;} .emptyinfo span.mui-icon{margin-bottom: 15px;} @media only screen and (max-height: 568px) { .emptyinfo {margin-top: 0px;} .emptyinfo span.mui-icon{font-size: 36px;margin-bottom: 5px;} }
做爲一個後臺開發人員來講,寫js還不是最痛苦的,最痛苦的是調css樣式,尤爲是還須要兼容iso和android以及不一樣的移動設備,更要命的是不一樣的css樣式寫法,一樣的效果,渲染速度還不同......
項目開發完成以後,我會將前端代碼開源,目前還在開發中,敬請關注!
關於更多MUI跨平臺開發的資料,能夠參考個人上一篇文章:MUI開發大全
其它部分頁面參考:2017-11-1 今天完成的界面,包括js交互實現
最後,無可避免的,我花了大半天作的東西不符合客戶需求...無語...從新改造...