window.rootUrl = window.location.protocol + '//' + window.location.host; window._AUTH_INFO_ = "AUTH_MANAGER"; window._CONFIG_ = {}; // 后台管理配置. window._UPLOAD_TOKEN_ = 'GAkucH8'; // 上传通信token window._UPLOAD_SERVER_CONFIG_ = {}; // 上传服务器配置信息. window._PLUP_PATH_ = rootUrl + 'app/assets/js/plupload-2.3.7/'; // Plupload 引用资源相对路径. window._PLUP_SERVER_URI_ = ''; // Plupload服务端URI,有配置以来,预先空字符串. window._PLUP_FILE_FIELD_NAME_ = 'upload_files'; // 上传文件的表单字段名 window._AES_KEY_ = 'Iz9IhtcyKbYJynAd'; // AES加密的key layui.extend({ mhttp: "{/}"+ rootUrl +"/app/modules/mhttp", // ajax请求组件 madmin: "{/}"+ rootUrl +"/app/modules/madmin", // admin组件 }); String.prototype.trim = function (char, type) { if (char) { if (type == 'left') { return this.replace(new RegExp('^\\'+char+'+', 'g'), ''); } else if (type == 'right') { return this.replace(new RegExp('\\'+char+'+$', 'g'), ''); } return this.replace(new RegExp('^\\'+char+'+|\\'+char+'+$', 'g'), ''); } return this.replace(/^\s+|\s+$/g, ''); }; String.prototype.rtrim = function (s) { return this.trim(s, 'right'); }; String.prototype.ltrim = function (s) { return this.trim(s, 'left'); }; /** * 获取应用环境. * @returns */ function getAppEnv() { var appEnv = 'prod'; var hostAndPort = window.location.host; var devReg = /(127\.0\.0\.1|localhost)/; var qaReg = /(test)/; // 设置应用所在环境. if (devReg.test(hostAndPort)) { appEnv = 'dev'; } else if (qaReg.test(hostAndPort)) { appEnv = 'test'; } else { appEnv = 'prod'; } return appEnv; } /** * 获取应用配置. * @returns */ function getAppConfigPath() { var path = 'config/ignore/pear.config.yml'; var url = window.location.protocol + '//' + window.location.host + '/' + path; return url; } /** * 格式化时长,格式00:00:00 * @param {*} duration * @returns */ function formatDuration(duration) { duration = parseFloat(duration); var hour = 60 * 60; var pHour = duration / hour; var strHour = '0'; if (pHour > 0) { strHour = parseInt(pHour).toString() } strHour = strHour.padStart(2, '0'); var pMinute = parseInt(duration % hour / 60); var strMinute = pMinute.toString().padStart(2, '0'); var pSecond = parseInt(duration % hour % 60); var strSecond = pSecond.toString().padStart(2, '0'); var result = strHour + ":" + strMinute + ":" + strSecond; return result; } function httpRequestPostData(data) { return { "data": data, "handshake": "" }; } function httpRequestPagesParseData(res) { let total = 0; if (res.data.total){ total = res.data.total; } return { "code": res.code, "msg": res.message, "data" : res.data.data, "count": total }; } function cbRespnseRedirectLogin(data) { localStorage.removeItem(window._AUTH_INFO_); layer.alert('['+ data.code +']' + data.msg + ', 请重新登陆', { title: '错误信息', icon: 2, closeBtn: 1, shade: 0.5, shadeClose: false, end: function () { parent.location.href = window.rootUrl + '/login.html'; } }); } function cbRespnse401(data) { // refreshToken(); localStorage.removeItem(window._AUTH_INFO_); layer.alert('['+ data.code +']' + data.msg + ', 请重新登陆', { title: '错误信息', icon: 2, closeBtn: 1, shade: 0.5, shadeClose: false, end: function () { parent.location.href = window.rootUrl + '/login.html'; } }); } function cbRespnseReloadPage(data, message) { // localStorage.removeItem(window._AUTH_INFO_); layer.alert('请求异常,请联系客服!', { title: '错误信息', icon: 2, closeBtn: 1, shade: 0.5, shadeClose: false, end: function () { // parent.location.reload(); } }); } function getMyDetail() { var info = localStorage.getItem(window._AUTH_INFO_); return JSON.parse(info); } function getMyUid() { var detail = getMyDetail(); if (detail) { return detail.manager_uid; } else { return ''; } } function refreshToken() { layui.use(['mhttp', 'popup'], function () { var mhttp = layui.mhttp; var popup = layui.popup; var postData = { "manager_uid": getMyUid(), "old_token": mhttp.ajax.getToken() }; var ret = mhttp.ajax({ url: "/auth/refresh/token", data : postData, // 同步. async: false }); ret.then((data) => { if (data.code == 200) { // 设置token mhttp.ajax.setToken(data.data.token); } else { console.log('刷新token'); // 错误提示. popup.failure('['+ data.code +']' + data.message); } }); }); } function threadBizCodeNoParams(code, func) { // if (code == 401) { // func.call(null); // } } /** * 格式化为相对协议. * @param {*} url * @returns */ function slashesUrl(url) { var pattern = /^(http|https)\:\/\/(.*?)$/i; var arr = url.match(pattern); if (arr) { return '//' + arr[2]; } else { return url; } } /** * 把buffer转b64 * 参考1:https://stackoverflow.com/questions/27375908/crypto-js-read-and-decrypt-file * 擦靠2:https://gist.github.com/jonleighton/958841 * @param {*} arrayBuffer * @returns */ function base64ArrayBuffer(arrayBuffer) { var base64 = '' var encodings = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/' var bytes = new Uint8Array(arrayBuffer) var byteLength = bytes.byteLength var byteRemainder = byteLength % 3 var mainLength = byteLength - byteRemainder var a, b, c, d var chunk // Main loop deals with bytes in chunks of 3 for (var i = 0; i < mainLength; i = i + 3) { // Combine the three bytes into a single integer chunk = (bytes[i] << 16) | (bytes[i + 1] << 8) | bytes[i + 2] // Use bitmasks to extract 6-bit segments from the triplet a = (chunk & 16515072) >> 18 // 16515072 = (2^6 - 1) << 18 b = (chunk & 258048) >> 12 // 258048 = (2^6 - 1) << 12 c = (chunk & 4032) >> 6 // 4032 = (2^6 - 1) << 6 d = chunk & 63 // 63 = 2^6 - 1 // Convert the raw binary segments to the appropriate ASCII encoding base64 += encodings[a] + encodings[b] + encodings[c] + encodings[d] } // Deal with the remaining bytes and padding if (byteRemainder == 1) { chunk = bytes[mainLength] a = (chunk & 252) >> 2 // 252 = (2^6 - 1) << 2 // Set the 4 least significant bits to zero b = (chunk & 3) << 4 // 3 = 2^2 - 1 base64 += encodings[a] + encodings[b] + '==' } else if (byteRemainder == 2) { chunk = (bytes[mainLength] << 8) | bytes[mainLength + 1] a = (chunk & 64512) >> 10 // 64512 = (2^6 - 1) << 10 b = (chunk & 1008) >> 4 // 1008 = (2^6 - 1) << 4 // Set the 2 least significant bits to zero c = (chunk & 15) << 2 // 15 = 2^4 - 1 base64 += encodings[a] + encodings[b] + encodings[c] + '=' } return base64 } /** * 调试log,只有_DEBUG_全局变量为true才会输出. */ function debugLog() { if (typeof(_DEBUG_) != 'undefined') { if (_DEBUG_ == true) { console.log(...arguments) } } } /** * 获取自己的上传服务的url。 * @param {*} url * @returns */ function getMyUploadUrl(url) { return slashesUrl(window._CONFIG_.sysconfig.uploadServerBaseUrl + url); } /** * 获取自己的后台API服务url * @param {*} url * @returns */ function getMyApiUrl(url) { return slashesUrl(window._CONFIG_.sysconfig.apiServerBaseUrl + url); } /** * 获取存储服务器组配置信息. */ function getStorageServersConfig() { layui.use(['jquery', 'madmin', 'popup'], function () { let $ = layui.jquery; let madmin = layui.madmin; let popup = layui.popup; let config = madmin.getConfig(); window._PLUP_SERVER_URI_ = getMyUploadUrl('/uploader.php'); // 依赖 getConfig $.ajax( { type:'GET', url: getMyUploadUrl('/sg_server_config.php?upload_token='+ window._UPLOAD_TOKEN_), data: {}, async: false, // 注意,因为初始化,优先这里要同步. dataType: 'json', beforeSend : function() { }, complete: function() { }, error : function() { popup.failure('获取上传服务器请求出错'); }, success: function(s) { if (s.code == 200) { window._UPLOAD_SERVER_CONFIG_ = s.data; } else { popup.failure('['+ data.code +']' + data.message); } } } ); }); } /** * 拼接待解密的完整URL. * @param {*} url * @param {*} convertSlashes * @returns */ function concatUrl(url, convertSlashes) { let baseUrl = ''; if (url.lastIndexOf('|') > -1) { // 找到分隔符. let arrData = url.split('|'); let flag = arrData[0]; let relativeUrl = arrData[1]; if (window._UPLOAD_SERVER_CONFIG_.servers.hasOwnProperty(flag)) { baseUrl = window._UPLOAD_SERVER_CONFIG_.servers[flag]['url']; var resultUrl = baseUrl + relativeUrl; if (convertSlashes) { resultUrl = slashesUrl(resultUrl); } return resultUrl; } else { return ''; } } else { return ''; } } /** * 在属性里获取url. * @param {*} ele * @returns */ function getUrlInAttrs(ele) { return layui.use(['jquery'], function () { let $ = layui.jquery; let b64 = $(ele).attr('data-b64'); if (b64) { return $(ele).attr('data-b64'); } else { return ''; } }); } /** * 解密基于arrayBuffer数据. * @param {*} buffers * @returns */ function aes128ecbDecodeByBuffer(buffers) { let encodedData = base64ArrayBuffer(buffers); // 这个地方很重要! let options = { iv: '', mode: CryptoJS.mode.ECB, padding: CryptoJS.pad.Pkcs7 }; let keyObj = CryptoJS.enc.Utf8.parse(window._AES_KEY_); // 必须是对象key let decrypted = CryptoJS.AES.decrypt(encodedData, keyObj, options); return decrypted; } /** * 拼接dataURL. * @param {*} b64 * @returns */ function concatImageDataUrl(b64) { return "data:image/png;base64," + b64; } /** * 现代浏览器Fetch异步下载并解密图片. * @param {*} url * @returns */ function fetchImageFile(url) { return fetch(url, { method: 'GET' // headers: { // Authorization: 'Bearer ' + token, // 'Accept': 'application/json' // } }).then( // 必须是arrayBuffer response => { if (response.ok) { return response.arrayBuffer(); } else { return Promise.reject({ status: response.status, statusText: response.statusText }); } } ).then(respRaw => { let ext = getFileExt(url); let strB64 = ""; if (ext == 'ceb') { // 仅对ceb扩展名,进行解密. let decrypted = aes128ecbDecodeByBuffer(respRaw); strB64 = decrypted.toString(CryptoJS.enc.Base64); } else { strB64 = base64ArrayBuffer(respRaw); } let dataUrl = concatImageDataUrl(strB64); return dataUrl; }).catch(error => { }); } /** * 获取文件扩展名,不包括dot. * @param {*} file * @returns */ function getFileExt(file) { let ext = file.substring(file.lastIndexOf('.') + 1); return ext.toLowerCase(); } /** * 渲染datahref * @param {*} ele * @param {*} dataHref */ function renderDataHref(ele, dataHref) { layui.use(['jquery'], function () { let $ = layui.jquery; $(ele).attr('href', dataHref); }); } /** * 渲染data * @param {*} ele * @param {*} dataUrl */ function renderDataUrl(ele, dataUrl) { layui.use(['jquery'], function () { let $ = layui.jquery; $(ele).attr('src', dataUrl); }); } /** * 单个对象渲染图片(依赖jQuery) * @param {*} ele */ function onceRender(ele) { layui.use(['jquery'], function () { let $ = layui.jquery; let originUrl = ''; let dataCebUrl = $(ele).attr('data-ceb-url'); let srcValue = $(ele).attr('src'); // 优先取data-ceb-url值,因为直接放src属性里的图片,会报404. if (typeof(dataCebUrl) != 'undefined' && dataCebUrl != '') { originUrl = dataCebUrl; } else if (typeof(srcValue) != 'undefined' && srcValue != '') { originUrl = srcValue; } if (originUrl.lastIndexOf('|') > -1) { let b64Url = originUrl; let convertSlashes = 1; // let b64Url = $(ele).attr('data-b64'); let fullUrl = concatUrl(b64Url, convertSlashes); if (fullUrl != '') { // 备份一次原始图片地址 $(ele).attr('data-ceb-url', originUrl); // 合法的才渲染. let promiseResult = fetchImageFile(fullUrl); promiseResult.then(dataUrl => { renderDataUrl(ele, dataUrl); }); } } }); } /** * 下载app地址处理 * @param ele */ function appDownloadRender(ele){ layui.use(['jquery'], function () { let $ = layui.jquery; let dataHref = $(ele).attr('href'); if (typeof(dataHref) == 'undefined' || dataHref === '') { return false; } // 拆分 if (dataHref.lastIndexOf('|') > -1) { let arrData = dataHref.split('|'); let flag = arrData[0]; let relativeUrl = arrData[1]; // 合并 if (window._UPLOAD_SERVER_CONFIG_.servers.hasOwnProperty(flag)) { let baseUrl = window._UPLOAD_SERVER_CONFIG_.servers[flag]['url']; var resultUrl = baseUrl + relativeUrl; $(ele).attr('href',resultUrl); } } }); } /** * 页面初始化dom加载完毕后渲染所有img标签. */ function onloadRender() { layui.use(['jquery'], function () { let $ = layui.jquery; $(function() { $('img').each(function (index, ele) { onceRender(ele); }); //app下载地址修改 $('.app-download').each(function (index,ele){ appDownloadRender(ele); }); }); }); } /** * 获取同字段名数组的值. * 因为layui表单获取同字段名数组时,无法正常给数组结构。 * @param {*} fieldName * @param {*} fieldItems * @returns */ function getLayuiArrFieldValue(fieldName, fieldItems) { let arrFields = []; let arrData = []; if (fieldItems && Object.keys(fieldItems).length > 0) { for (const keyName in fieldItems) { if (fieldItems.hasOwnProperty(keyName)) { var strPattern = '^(' + fieldName +')\\[\\d+\\]$'; var reg = new RegExp(strPattern, 'i') var result = keyName.match(reg); if (result) { arrFields.push(result[0]); arrData.push(fieldItems[keyName]); } } } } return arrData; }