app.js 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627
  1. window.rootUrl = window.location.protocol + '//' + window.location.host;
  2. window._AUTH_INFO_ = "AUTH_MANAGER";
  3. window._CONFIG_ = {}; // 后台管理配置.
  4. window._UPLOAD_TOKEN_ = 'GAkucH8'; // 上传通信token
  5. window._UPLOAD_SERVER_CONFIG_ = {}; // 上传服务器配置信息.
  6. window._PLUP_PATH_ = rootUrl + 'app/assets/js/plupload-2.3.7/'; // Plupload 引用资源相对路径.
  7. window._PLUP_SERVER_URI_ = ''; // Plupload服务端URI,有配置以来,预先空字符串.
  8. window._PLUP_FILE_FIELD_NAME_ = 'upload_files'; // 上传文件的表单字段名
  9. window._AES_KEY_ = 'Iz9IhtcyKbYJynAd'; // AES加密的key
  10. layui.extend({
  11. mhttp: "{/}"+ rootUrl +"/app/modules/mhttp", // ajax请求组件
  12. madmin: "{/}"+ rootUrl +"/app/modules/madmin", // admin组件
  13. });
  14. String.prototype.trim = function (char, type) {
  15. if (char) {
  16. if (type == 'left') {
  17. return this.replace(new RegExp('^\\'+char+'+', 'g'), '');
  18. } else if (type == 'right') {
  19. return this.replace(new RegExp('\\'+char+'+$', 'g'), '');
  20. }
  21. return this.replace(new RegExp('^\\'+char+'+|\\'+char+'+$', 'g'), '');
  22. }
  23. return this.replace(/^\s+|\s+$/g, '');
  24. };
  25. String.prototype.rtrim = function (s) {
  26. return this.trim(s, 'right');
  27. };
  28. String.prototype.ltrim = function (s) {
  29. return this.trim(s, 'left');
  30. };
  31. /**
  32. * 获取应用环境.
  33. * @returns
  34. */
  35. function getAppEnv()
  36. {
  37. var appEnv = 'prod';
  38. var hostAndPort = window.location.host;
  39. var devReg = /(127\.0\.0\.1|localhost)/;
  40. var qaReg = /(test)/;
  41. // 设置应用所在环境.
  42. if (devReg.test(hostAndPort)) {
  43. appEnv = 'dev';
  44. } else if (qaReg.test(hostAndPort)) {
  45. appEnv = 'test';
  46. } else {
  47. appEnv = 'prod';
  48. }
  49. return appEnv;
  50. }
  51. /**
  52. * 获取应用配置.
  53. * @returns
  54. */
  55. function getAppConfigPath()
  56. {
  57. var path = 'config/ignore/pear.config.yml';
  58. var url = window.location.protocol + '//' + window.location.host + '/' + path;
  59. return url;
  60. }
  61. /**
  62. * 格式化时长,格式00:00:00
  63. * @param {*} duration
  64. * @returns
  65. */
  66. function formatDuration(duration)
  67. {
  68. duration = parseFloat(duration);
  69. var hour = 60 * 60;
  70. var pHour = duration / hour;
  71. var strHour = '0';
  72. if (pHour > 0) {
  73. strHour = parseInt(pHour).toString()
  74. }
  75. strHour = strHour.padStart(2, '0');
  76. var pMinute = parseInt(duration % hour / 60);
  77. var strMinute = pMinute.toString().padStart(2, '0');
  78. var pSecond = parseInt(duration % hour % 60);
  79. var strSecond = pSecond.toString().padStart(2, '0');
  80. var result = strHour + ":" + strMinute + ":" + strSecond;
  81. return result;
  82. }
  83. function httpRequestPostData(data)
  84. {
  85. return {
  86. "data": data,
  87. "handshake": ""
  88. };
  89. }
  90. function httpRequestPagesParseData(res)
  91. {
  92. let total = 0;
  93. if (res.data.total){
  94. total = res.data.total;
  95. }
  96. return {
  97. "code": res.code,
  98. "msg": res.message,
  99. "data" : res.data.data,
  100. "count": total
  101. };
  102. }
  103. function cbRespnseRedirectLogin(data)
  104. {
  105. localStorage.removeItem(window._AUTH_INFO_);
  106. layer.alert('['+ data.code +']' + data.msg + ', 请重新登陆', {
  107. title: '错误信息',
  108. icon: 2,
  109. closeBtn: 1,
  110. shade: 0.5,
  111. shadeClose: false,
  112. end: function () {
  113. parent.location.href = window.rootUrl + '/login.html';
  114. }
  115. });
  116. }
  117. function cbRespnse401(data)
  118. {
  119. // refreshToken();
  120. localStorage.removeItem(window._AUTH_INFO_);
  121. layer.alert('['+ data.code +']' + data.msg + ', 请重新登陆', {
  122. title: '错误信息',
  123. icon: 2,
  124. closeBtn: 1,
  125. shade: 0.5,
  126. shadeClose: false,
  127. end: function () {
  128. parent.location.href = window.rootUrl + '/login.html';
  129. }
  130. });
  131. }
  132. function cbRespnseReloadPage(data, message)
  133. {
  134. // localStorage.removeItem(window._AUTH_INFO_);
  135. layer.alert('请求异常,请联系客服!', {
  136. title: '错误信息',
  137. icon: 2,
  138. closeBtn: 1,
  139. shade: 0.5,
  140. shadeClose: false,
  141. end: function () {
  142. // parent.location.reload();
  143. }
  144. });
  145. }
  146. function getMyDetail()
  147. {
  148. var info = localStorage.getItem(window._AUTH_INFO_);
  149. return JSON.parse(info);
  150. }
  151. function getMyUid()
  152. {
  153. var detail = getMyDetail();
  154. if (detail) {
  155. return detail.manager_uid;
  156. } else {
  157. return '';
  158. }
  159. }
  160. function refreshToken()
  161. {
  162. layui.use(['mhttp', 'popup'], function () {
  163. var mhttp = layui.mhttp;
  164. var popup = layui.popup;
  165. var postData = {
  166. "manager_uid": getMyUid(),
  167. "old_token": mhttp.ajax.getToken()
  168. };
  169. var ret = mhttp.ajax({
  170. url: "/auth/refresh/token",
  171. data : postData,
  172. // 同步.
  173. async: false
  174. });
  175. ret.then((data) => {
  176. if (data.code == 200) {
  177. // 设置token
  178. mhttp.ajax.setToken(data.data.token);
  179. } else {
  180. console.log('刷新token');
  181. // 错误提示.
  182. popup.failure('['+ data.code +']' + data.message);
  183. }
  184. });
  185. });
  186. }
  187. function threadBizCodeNoParams(code, func)
  188. {
  189. // if (code == 401) {
  190. // func.call(null);
  191. // }
  192. }
  193. /**
  194. * 格式化为相对协议.
  195. * @param {*} url
  196. * @returns
  197. */
  198. function slashesUrl(url)
  199. {
  200. var pattern = /^(http|https)\:\/\/(.*?)$/i;
  201. var arr = url.match(pattern);
  202. if (arr) {
  203. return '//' + arr[2];
  204. } else {
  205. return url;
  206. }
  207. }
  208. /**
  209. * 把buffer转b64
  210. * 参考1:https://stackoverflow.com/questions/27375908/crypto-js-read-and-decrypt-file
  211. * 擦靠2:https://gist.github.com/jonleighton/958841
  212. * @param {*} arrayBuffer
  213. * @returns
  214. */
  215. function base64ArrayBuffer(arrayBuffer) {
  216. var base64 = ''
  217. var encodings = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/'
  218. var bytes = new Uint8Array(arrayBuffer)
  219. var byteLength = bytes.byteLength
  220. var byteRemainder = byteLength % 3
  221. var mainLength = byteLength - byteRemainder
  222. var a, b, c, d
  223. var chunk
  224. // Main loop deals with bytes in chunks of 3
  225. for (var i = 0; i < mainLength; i = i + 3) {
  226. // Combine the three bytes into a single integer
  227. chunk = (bytes[i] << 16) | (bytes[i + 1] << 8) | bytes[i + 2]
  228. // Use bitmasks to extract 6-bit segments from the triplet
  229. a = (chunk & 16515072) >> 18 // 16515072 = (2^6 - 1) << 18
  230. b = (chunk & 258048) >> 12 // 258048 = (2^6 - 1) << 12
  231. c = (chunk & 4032) >> 6 // 4032 = (2^6 - 1) << 6
  232. d = chunk & 63 // 63 = 2^6 - 1
  233. // Convert the raw binary segments to the appropriate ASCII encoding
  234. base64 += encodings[a] + encodings[b] + encodings[c] + encodings[d]
  235. }
  236. // Deal with the remaining bytes and padding
  237. if (byteRemainder == 1) {
  238. chunk = bytes[mainLength]
  239. a = (chunk & 252) >> 2 // 252 = (2^6 - 1) << 2
  240. // Set the 4 least significant bits to zero
  241. b = (chunk & 3) << 4 // 3 = 2^2 - 1
  242. base64 += encodings[a] + encodings[b] + '=='
  243. } else if (byteRemainder == 2) {
  244. chunk = (bytes[mainLength] << 8) | bytes[mainLength + 1]
  245. a = (chunk & 64512) >> 10 // 64512 = (2^6 - 1) << 10
  246. b = (chunk & 1008) >> 4 // 1008 = (2^6 - 1) << 4
  247. // Set the 2 least significant bits to zero
  248. c = (chunk & 15) << 2 // 15 = 2^4 - 1
  249. base64 += encodings[a] + encodings[b] + encodings[c] + '='
  250. }
  251. return base64
  252. }
  253. /**
  254. * 调试log,只有_DEBUG_全局变量为true才会输出.
  255. */
  256. function debugLog()
  257. {
  258. if (typeof(_DEBUG_) != 'undefined') {
  259. if (_DEBUG_ == true) {
  260. console.log(...arguments)
  261. }
  262. }
  263. }
  264. /**
  265. * 获取自己的上传服务的url。
  266. * @param {*} url
  267. * @returns
  268. */
  269. function getMyUploadUrl(url)
  270. {
  271. return slashesUrl(window._CONFIG_.sysconfig.uploadServerBaseUrl + url);
  272. }
  273. /**
  274. * 获取自己的后台API服务url
  275. * @param {*} url
  276. * @returns
  277. */
  278. function getMyApiUrl(url)
  279. {
  280. return slashesUrl(window._CONFIG_.sysconfig.apiServerBaseUrl + url);
  281. }
  282. /**
  283. * 获取存储服务器组配置信息.
  284. */
  285. function getStorageServersConfig()
  286. {
  287. layui.use(['jquery', 'madmin', 'popup'], function () {
  288. let $ = layui.jquery;
  289. let madmin = layui.madmin;
  290. let popup = layui.popup;
  291. let config = madmin.getConfig();
  292. window._PLUP_SERVER_URI_ = getMyUploadUrl('/uploader.php'); // 依赖 getConfig
  293. $.ajax(
  294. {
  295. type:'GET',
  296. url: getMyUploadUrl('/sg_server_config.php?upload_token='+ window._UPLOAD_TOKEN_),
  297. data: {},
  298. async: false, // 注意,因为初始化,优先这里要同步.
  299. dataType: 'json',
  300. beforeSend : function() {
  301. },
  302. complete: function() {
  303. },
  304. error : function() {
  305. popup.failure('获取上传服务器请求出错');
  306. },
  307. success: function(s) {
  308. if (s.code == 200) {
  309. window._UPLOAD_SERVER_CONFIG_ = s.data;
  310. } else {
  311. popup.failure('['+ data.code +']' + data.message);
  312. }
  313. }
  314. }
  315. );
  316. });
  317. }
  318. /**
  319. * 拼接待解密的完整URL.
  320. * @param {*} url
  321. * @param {*} convertSlashes
  322. * @returns
  323. */
  324. function concatUrl(url, convertSlashes)
  325. {
  326. let baseUrl = '';
  327. if (url.lastIndexOf('|') > -1) {
  328. // 找到分隔符.
  329. let arrData = url.split('|');
  330. let flag = arrData[0];
  331. let relativeUrl = arrData[1];
  332. if (window._UPLOAD_SERVER_CONFIG_.servers.hasOwnProperty(flag)) {
  333. baseUrl = window._UPLOAD_SERVER_CONFIG_.servers[flag]['url'];
  334. var resultUrl = baseUrl + relativeUrl;
  335. if (convertSlashes) {
  336. resultUrl = slashesUrl(resultUrl);
  337. }
  338. return resultUrl;
  339. } else {
  340. return '';
  341. }
  342. } else {
  343. return '';
  344. }
  345. }
  346. /**
  347. * 在属性里获取url.
  348. * @param {*} ele
  349. * @returns
  350. */
  351. function getUrlInAttrs(ele)
  352. {
  353. return layui.use(['jquery'], function () {
  354. let $ = layui.jquery;
  355. let b64 = $(ele).attr('data-b64');
  356. if (b64) {
  357. return $(ele).attr('data-b64');
  358. } else {
  359. return '';
  360. }
  361. });
  362. }
  363. /**
  364. * 解密基于arrayBuffer数据.
  365. * @param {*} buffers
  366. * @returns
  367. */
  368. function aes128ecbDecodeByBuffer(buffers)
  369. {
  370. let encodedData = base64ArrayBuffer(buffers); // 这个地方很重要!
  371. let options = {
  372. iv: '',
  373. mode: CryptoJS.mode.ECB,
  374. padding: CryptoJS.pad.Pkcs7
  375. };
  376. let keyObj = CryptoJS.enc.Utf8.parse(window._AES_KEY_); // 必须是对象key
  377. let decrypted = CryptoJS.AES.decrypt(encodedData, keyObj, options);
  378. return decrypted;
  379. }
  380. /**
  381. * 拼接dataURL.
  382. * @param {*} b64
  383. * @returns
  384. */
  385. function concatImageDataUrl(b64)
  386. {
  387. return "data:image/png;base64," + b64;
  388. }
  389. /**
  390. * 现代浏览器Fetch异步下载并解密图片.
  391. * @param {*} url
  392. * @returns
  393. */
  394. function fetchImageFile(url)
  395. {
  396. return fetch(url, {
  397. method: 'GET'
  398. // headers: {
  399. // Authorization: 'Bearer ' + token,
  400. // 'Accept': 'application/json'
  401. // }
  402. }).then(
  403. // 必须是arrayBuffer
  404. response => {
  405. if (response.ok) {
  406. return response.arrayBuffer();
  407. } else {
  408. return Promise.reject({
  409. status: response.status,
  410. statusText: response.statusText
  411. });
  412. }
  413. }
  414. ).then(respRaw => {
  415. let ext = getFileExt(url);
  416. let strB64 = "";
  417. if (ext == 'ceb') {
  418. // 仅对ceb扩展名,进行解密.
  419. let decrypted = aes128ecbDecodeByBuffer(respRaw);
  420. strB64 = decrypted.toString(CryptoJS.enc.Base64);
  421. } else {
  422. strB64 = base64ArrayBuffer(respRaw);
  423. }
  424. let dataUrl = concatImageDataUrl(strB64);
  425. return dataUrl;
  426. }).catch(error => {
  427. });
  428. }
  429. /**
  430. * 获取文件扩展名,不包括dot.
  431. * @param {*} file
  432. * @returns
  433. */
  434. function getFileExt(file)
  435. {
  436. let ext = file.substring(file.lastIndexOf('.') + 1);
  437. return ext.toLowerCase();
  438. }
  439. /**
  440. * 渲染datahref
  441. * @param {*} ele
  442. * @param {*} dataHref
  443. */
  444. function renderDataHref(ele, dataHref)
  445. {
  446. layui.use(['jquery'], function () {
  447. let $ = layui.jquery;
  448. $(ele).attr('href', dataHref);
  449. });
  450. }
  451. /**
  452. * 渲染data
  453. * @param {*} ele
  454. * @param {*} dataUrl
  455. */
  456. function renderDataUrl(ele, dataUrl)
  457. {
  458. layui.use(['jquery'], function () {
  459. let $ = layui.jquery;
  460. $(ele).attr('src', dataUrl);
  461. });
  462. }
  463. /**
  464. * 单个对象渲染图片(依赖jQuery)
  465. * @param {*} ele
  466. */
  467. function onceRender(ele)
  468. {
  469. layui.use(['jquery'], function () {
  470. let $ = layui.jquery;
  471. let originUrl = '';
  472. let dataCebUrl = $(ele).attr('data-ceb-url');
  473. let srcValue = $(ele).attr('src');
  474. // 优先取data-ceb-url值,因为直接放src属性里的图片,会报404.
  475. if (typeof(dataCebUrl) != 'undefined' && dataCebUrl != '') {
  476. originUrl = dataCebUrl;
  477. } else if (typeof(srcValue) != 'undefined' && srcValue != '') {
  478. originUrl = srcValue;
  479. }
  480. if (originUrl.lastIndexOf('|') > -1) {
  481. let b64Url = originUrl;
  482. let convertSlashes = 1;
  483. // let b64Url = $(ele).attr('data-b64');
  484. let fullUrl = concatUrl(b64Url, convertSlashes);
  485. if (fullUrl != '') {
  486. // 备份一次原始图片地址
  487. $(ele).attr('data-ceb-url', originUrl);
  488. // 合法的才渲染.
  489. let promiseResult = fetchImageFile(fullUrl);
  490. promiseResult.then(dataUrl => {
  491. renderDataUrl(ele, dataUrl);
  492. });
  493. }
  494. }
  495. });
  496. }
  497. /**
  498. * 下载app地址处理
  499. * @param ele
  500. */
  501. function appDownloadRender(ele){
  502. layui.use(['jquery'], function () {
  503. let $ = layui.jquery;
  504. let dataHref = $(ele).attr('href');
  505. if (typeof(dataHref) == 'undefined' || dataHref === '') {
  506. return false;
  507. }
  508. // 拆分
  509. if (dataHref.lastIndexOf('|') > -1) {
  510. let arrData = dataHref.split('|');
  511. let flag = arrData[0];
  512. let relativeUrl = arrData[1];
  513. // 合并
  514. if (window._UPLOAD_SERVER_CONFIG_.servers.hasOwnProperty(flag)) {
  515. let baseUrl = window._UPLOAD_SERVER_CONFIG_.servers[flag]['url'];
  516. var resultUrl = baseUrl + relativeUrl;
  517. $(ele).attr('href',resultUrl);
  518. }
  519. }
  520. });
  521. }
  522. /**
  523. * 页面初始化dom加载完毕后渲染所有img标签.
  524. */
  525. function onloadRender()
  526. {
  527. layui.use(['jquery'], function () {
  528. let $ = layui.jquery;
  529. $(function() {
  530. $('img').each(function (index, ele) {
  531. onceRender(ele);
  532. });
  533. //app下载地址修改
  534. $('.app-download').each(function (index,ele){
  535. appDownloadRender(ele);
  536. });
  537. });
  538. });
  539. }
  540. /**
  541. * 获取同字段名数组的值.
  542. * 因为layui表单获取同字段名数组时,无法正常给数组结构。
  543. * @param {*} fieldName
  544. * @param {*} fieldItems
  545. * @returns
  546. */
  547. function getLayuiArrFieldValue(fieldName, fieldItems)
  548. {
  549. let arrFields = [];
  550. let arrData = [];
  551. if (fieldItems && Object.keys(fieldItems).length > 0) {
  552. for (const keyName in fieldItems) {
  553. if (fieldItems.hasOwnProperty(keyName)) {
  554. var strPattern = '^(' + fieldName +')\\[\\d+\\]$';
  555. var reg = new RegExp(strPattern, 'i')
  556. var result = keyName.match(reg);
  557. if (result) {
  558. arrFields.push(result[0]);
  559. arrData.push(fieldItems[keyName]);
  560. }
  561. }
  562. }
  563. }
  564. return arrData;
  565. }