/** * 主题所用工具类 * @date 2020/12/21 * @author LIlGG * @version 1.0 */ var Util = { _version: '1.3.4', /** * 获取当前浏览器语言 * 使用当前方法,只会得到语言前两个字符 * @return zh、cn 等 */ getNavLangSub: function () { var currentLang = navigator.language; // 只获取前两个字符 currentLang = currentLang.substr(0, 2); //判断IE浏览器使用语言 if (!currentLang) { currentLang = navigator.browserLanguage; } return currentLang; }, /** * 存储数据到浏览器的 cookie 内 * 不建议向 cookie 内存入大量数据,如果有大数据需求的话 * 或许可以考虑 {@link Util#setLocalStorageByJSON} * @param {String} key 需要存储的 key * @param {String} value 需要存储在 cookie 内的值 * @param {Number} days 存储时间。单位/天。不输入则为永久存储 */ setCookie: function (key, value, days) { var keyVE = key + Util._version, expires = ""; if (days) { var date = new Date(); date.setTime(date.getTime() + days * 24 * 60 * 60 * 1000); expires = "; expires=" + date.toUTCString(); } document.cookie = keyVE + "=" + (value || "") + expires + "; path=/"; }, /** * 获取存储在浏览器 cookie 内的数据 * @param {String} key * @return 如果没能获取到数据,则返回 null。否则,返回目标数据字符串 */ getCookie: function (key) { var keyVE = key + Util._version + "="; var ca = document.cookie.split(";"); for (var i = 0; i < ca.length; i++) { var c = ca[i]; while (c.charAt(0) == " ") c = c.substring(1, c.length); if (c.indexOf(keyVE) == 0) return c.substring(keyVE.length, c.length); } return null; }, /** * 删除存储在浏览器 cookie 内的数据 * @param {String} key 需要删除的 key */ removeCookie: function (key) { var keyVE = key + Util._version + "="; document.cookie = keyVE + "=; Max-Age=-99999999;"; }, /** * 存储 JSON 数据到浏览器的 localstorage 里 * 当前方法不支持永久存储 * @param {String} key 需要存储的 key * @param {JSON} value 需要存储的JSON数据 * @param {Number} expires 存储时间。单位/秒。【默认 3600秒(一小时)】 */ setLocalStorage: function (key, value, expires = 3600) { var keyVE = key + Util._version; var date = new Date(); try { localStorage.setItem(keyVE, JSON.stringify({ expires: date.valueOf() + expires * 1000, data: value })); } catch (e) { if (e.name === 'QuotaExceededError') { console.log("数据已满,自动清空"); localStorage.clear(); setLocalStorage(key, value, expires); } } }, /** * 根据 key 获取存储在 localstorage 内的 JSON 数据【KEY 会自动加上 util 的版本号】 * @param {String} key 需要读取数据的 key * @return 返回 JSON 格式的数据,如果不存在或者过期了,则返回 null */ getLocalStorage: function (key) { var keyVE = key + Util._version; var result = JSON.parse(localStorage.getItem(keyVE)); var date = new Date(); if (result && result.expires > date) { return result.data; } else { localStorage.removeItem(keyVE); return null; } }, /** * 删除保存在 localStorage 中的数据 * @param {*} key 需要删除的 key【会自动加上 util 的版本号】 */ removeLocalStorage: function (key) { var keyVE = key + Util._version; localStorage.removeItem(keyVE); }, /** * 异步加载 JS * @param {*} url 需要加载 JS 地址 * @param {*} callback 加载完成回调 */ loadJS: function (url, callback) { Util._loadRes("script", url, callback); }, /** * 异步加载 CSS * @param {*} url 需要加载的 CSS 地址 * @param {*} callback 加载完成回调 */ loadCSS: function (url, callback) { Util._loadRes("link", url, callback); }, /** * 异步加载资源 *私有方法(不建议直接调用)* * @param {*} type 当前需要加载的资源类型 * @param {*} url 资源 链接地址 * @param {*} callback 加载完成回调函数 */ _loadRes: function (type, url, callback) { var dom, fn = callback || function () { }; switch (type) { case 'script': dom = document.createElement(type); dom.type = 'text/javascript'; dom.src = url; break; case 'link': dom = document.createElement(type); dom.type = 'text/css'; dom.type = 'stylesheet' dom.href = url; break; default: console.warn("暂不支持:" + type + " 类型"); return; } //IE if (dom.readyState) { dom.onreadystatechange = function () { if (dom.readyState == 'loaded' || dom.readyState == 'complete') { dom.onreadystatechange = null; fn(); } }; } else { //其他浏览器 dom.onload = function () { fn(); }; } var head = document.getElementsByTagName('head')[0]; head.appendChild(dom); }, /** * 获取随机颜色值 * 当获取的值越小,色调越偏冷 * @param {Number} min 色调值,0 - 1 之间的值 * @param {Number} max 色调值,需要大于min且为0 - 1之间的值 */ getRandomColor: function (min = 0, max = 1) { if (!min) { min = 0; } if (!max) { max = 0; } min = isNaN(min) ? 0 : Number(min); max = isNaN(max) ? 1 : Number(max); min = Math.min(Math.max(Math.abs(min), 0), 1); max = Math.min(Math.max(Math.abs(max), 0), 1); max = max < min ? 1 : max; return ( "#" + (function (h) { return new Array(7 - h.length).join("0") + h; })((((Math.random() * (max - min) + min) * 0x1000000) << 0).toString(16)) ); }, /** * 关键帧搜索 * @param {*} keyframesIndex 关键帧索引 * @param {*} milliseconds 秒 */ getNearestKeyframe: function (keyframesIndex, milliseconds) { var keyframeIdx = this._search(keyframesIndex.times, milliseconds); return { index: keyframeIdx, milliseconds: table.times[keyframeIdx], fileposition: table.filepositions[keyframeIdx] }; }, /** * 字节搜索方式 * @param {Array} list 需要搜索的字节数组 * @param {Number} value 当前所处秒 */ _search: function (list, value) { var idx = 0; var last = list.length - 1; var mid = 0; var lbound = 0; var ubound = last; if (value < list[0]) { idx = 0; lbound = ubound + 1; } while (lbound <= ubound) { mid = lbound + Math.floor((ubound - lbound) / 2); if (mid === last || (value >= list[mid] && value < list[mid + 1])) { idx = mid; break; } else if (list[mid] < value) { lbound = mid + 1; } else { ubound = mid - 1; } } return idx; }, /** * 删除元素的 class,可根据前缀来删除 * @param {*} el 需要删除的 dom 元素 * @param {*} prefix 需要删除的 class,可以仅为前缀 */ removeClassByPrefix: function (el, prefix) { var classes = el.className.split(" ").filter(function(c) { return c.lastIndexOf(prefix, 0) !== 0; }) el.className = classes.join(" ").trim(); }, /** * 根据文章字数,计算预计阅读时间,单位 秒 * @param count 文章字数 * @param coefficient 文章难度系数,默认难度为 3,最小为 1,最大为 6。值越小代表越难以理解 */ caclEstimateReadTime: function (count, coefficient = 3) { // 默认阅读速度 200 字每分钟 const defaultSpeed = 400; coefficient = Math.min(6, Math.max(1, coefficient)); // 每降低一个难度,就提升每分钟 100 的阅读速度。 var speed = defaultSpeed + (coefficient - 1) * 100; // 根据字数计算所需秒数 // 将分钟转化为对应的时间 return Math.ceil((count / speed) * 60); }, /** * 将秒转换为时间串。最大值为天 * 例如: * 10 -> 10 秒 * 60 -> 1 分钟 * 3600 -> 1 小时 * 3600 * 24 -> 1 天 * @param s 秒 */ minuteToTimeString: function (s) { var timeStr = ""; var day = Math.floor(s / 3600 / 24); if (day !== 0) { timeStr = timeStr + day + " 天 "; } var hours = Math.floor(s / 3600 % 24); if (day !== 0 || hours !== 0) { timeStr = timeStr + hours + " 小时 "; } var points = Math.floor(s / 60 % 60); if (hours !== 0 || points !== 0) { timeStr = timeStr + points + " 分钟 "; } var seconds = Math.floor(s % 60); if (points !== 0 || seconds !== 0) { timeStr = timeStr + seconds + " 秒"; } return timeStr; }, /** * 将时间转化为距目前多长时间的格式 * @param time 时间字符戳 * @returns {string|*} 距离时间格式的字符串形式 */ timeAgo: function (time) { var currentTime = new Date().getTime(); var between = currentTime - time; var days = Math.floor(between / (24 * 3600 * 1000)); if (days === 0) { var leave1 = between % (24 * 3600 * 1000); var hours = Math.floor(leave1 / (3600 * 1000)); if (hours === 0) { var leave2 = leave1 % (3600 * 1000); var minutes = Math.floor(leave2 / (60 * 1000)); if (minutes === 0) { var leave3 = leave2 % (60 * 1000); var seconds = Math.round(leave3 / 1000); return seconds + ' 秒前'; } return minutes + ' 分钟前'; } return hours + ' 小时前'; } if (days < 0) { return '刚刚'; } if (days < 30) { return days + ' 天前'; } var years = Math.floor(days / (30 * 12)); if (years === 0) { var months = Math.floor(days / 30); return months + ' 月前'; } return years + ' 年前'; }, /** * 格式化时间 * @param date 需要格式化的时间 * @param fmt 格式化文本 * @returns {*} 格式化后的时间串 */ formatDate: function (date, fmt) { date = new Date(date); if (/(y+)/.test(fmt)) { fmt = fmt.replace(RegExp.$1, (date.getFullYear() + '').substr(4 - RegExp.$1.length)); } let o = { 'M+': date.getMonth() + 1, 'd+': date.getDate(), 'h+': date.getHours(), 'm+': date.getMinutes(), 's+': date.getSeconds() }; for (let k in o) { if (new RegExp(`(${k})`).test(fmt)) { let str = o[k] + ''; fmt = fmt.replace(RegExp.$1, (RegExp.$1.length === 1) ? str : Util.padLeftZero(str)); } } return fmt; }, /** * 补位 * @param str * @returns {string} */ padLeftZero: function (str) { return ('00' + str).substr(str.length); } } /** * 封装的toast组件(使用纯js,可以单独拿出去使用) * @author LIlGG */ var Toast = function () { _classCallCheck(this, Toast); this._t = null; this._timeOut = null; this._settings = { duration: 2000, width: 260, height: 60, top: "top", background: "#fe9600", color: "#fff", "font-size": 14, }; Toast.prototype.init = function (opt) { _extend(this._settings, opt); }; /** * 创建Toast * @param {*} text 显示的文本 * @param {*} duration 持续时间 */ Toast.prototype.create = function (text, duration) { // 清除原有的Toast if (this._timeOut) { clearTimeout(this._timeOut); document.body.removeChild(this._t); this._t = null; } if (!text) { console.error("提示文本不能为空"); return; } this._t = document.createElement("div"); this._t.className = "t-toast"; this._t.innerHTML = '

' + text + "

"; document.body.appendChild(this._t); this.setStyle(); var _that = this; this._timeOut = setTimeout(function () { // 移除 document.body.removeChild(_that._t); _that._timeOut = null; _that._t = null; }, duration || this._settings.duration); }; Toast.prototype.setStyle = function () { this._t.style.width = this._settings.width + "px"; this._t.style.height = this._settings.height + "px"; this._t.style.position = "fixed"; this._t.style["text-align"] = "center"; this._t.style["z-index"] = "20200531"; if (isNaN(Number(this._settings.top))) { if (this._settings.top == "centent") { this._t.style.top = _viewHeight() / 2 + "px"; } else if (this._settings.top == "top") { this._t.style.top = "0px"; } } else { this._t.style.top = this._settings.top + "px"; } this._t.style.left = "50%"; this._t.style["margin-left"] = "-" + this._settings.width / 2 + "px"; this._t.style.background = this._settings.background; this._t.style.color = this._settings.color; this._t.style["border-bottom-left-radius"] = "4px"; this._t.style["border-bottom-right-radius"] = "4px"; this._t.style["font-size"] = this._settings["font-size"] + "px"; this._t.style.display = "flex"; this._t.style["justify-content"] = "center"; this._t.style["align-items"] = "center"; }; function _viewHeight() { return document.documentElement.clientHeight; } function _extend(o1, o2) { for (var attr in o2) { o1[attr] = o2[attr]; } } }; /** * 自定义日志 */ var Log = function () { return { e: function (msg, tag) { if (!tag || Log.FORCE_GLOBAL_TAG) tag = Log.GLOBAL_TAG; let str = `[${tag}] > ${msg}`; if (!Log.ENABLE_ERROR) { return; } if (console.error) { console.error(str); } else if (console.warn) { console.warn(str); } else { console.log(str); } }, i: function (msg, tag) { if (!tag || Log.FORCE_GLOBAL_TAG) tag = Log.GLOBAL_TAG; let str = `[${tag}] > ${msg}`; if (!Log.ENABLE_INFO) { return; } if (console.info) { console.info(str); } else { console.log(str); } }, w: function (msg, tag) { if (!tag || Log.FORCE_GLOBAL_TAG) tag = Log.GLOBAL_TAG; let str = `[${tag}] > ${msg}`; if (!Log.ENABLE_WARN) { return; } if (console.warn) { console.warn(str); } else { console.log(str); } }, d: function (msg, tag) { if (!tag || Log.FORCE_GLOBAL_TAG) tag = Log.GLOBAL_TAG; let str = `[${tag}] > ${msg}`; if (!Log.ENABLE_DEBUG) { return; } if (console.debug) { console.debug(str); } else { console.log(str); } }, v: function (msg, tag) { if (!tag || Log.FORCE_GLOBAL_TAG) tag = Log.GLOBAL_TAG; let str = `[${tag}] > ${msg}`; if (!Log.ENABLE_VERBOSE) { return; } console.log(str); }, } }(); Log.GLOBAL_TAG = 'Sakura'; Log.FORCE_GLOBAL_TAG = false; Log.ENABLE_ERROR = true; Log.ENABLE_INFO = true; Log.ENABLE_WARN = true; Log.ENABLE_DEBUG = true; Log.ENABLE_VERBOSE = true; /** * 自定义异常 * @param {*} message */ var RuntimeException = function (message) { this._message = message; RuntimeException.prototype = { get name() { return 'RuntimeException'; }, get message() { return this._message; }, toString() { return this.name + ': ' + this.message; } } }