util.ts 25 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810
  1. import { _decorator, Component } from "cc";
  2. const { ccclass, property } = _decorator;
  3. @ccclass("util")
  4. export class util {
  5. /**
  6. * !#zh 拷贝object。
  7. */
  8. /**
  9. * 深度拷贝
  10. * @param {any} sObj 拷贝的对象
  11. * @returns
  12. */
  13. public static clone(sObj: any) {
  14. if (sObj === null || typeof sObj !== "object") {
  15. return sObj;
  16. }
  17. let s: { [key: string]: any } = {};
  18. if (sObj.constructor === Array) {
  19. s = [];
  20. }
  21. for (let i in sObj) {
  22. if (sObj.hasOwnProperty(i)) {
  23. s[i] = this.clone(sObj[i]);
  24. }
  25. }
  26. return s;
  27. }
  28. /**
  29. * 将object转化为数组
  30. * @param { any} srcObj
  31. * @returns
  32. */
  33. public static objectToArray(srcObj: { [key: string]: any }) {
  34. let resultArr: any[] = [];
  35. // to array
  36. for (let key in srcObj) {
  37. if (!srcObj.hasOwnProperty(key)) {
  38. continue;
  39. }
  40. resultArr.push(srcObj[key]);
  41. }
  42. return resultArr;
  43. }
  44. /**
  45. * !#zh 将数组转化为object。
  46. */
  47. /**
  48. * 将数组转化为object。
  49. * @param { any} srcObj
  50. * @param { string} objectKey
  51. * @returns
  52. */
  53. public static arrayToObject(srcObj: any, objectKey: string) {
  54. let resultObj: { [key: string]: any } = {};
  55. // to object
  56. for (var key in srcObj) {
  57. if (!srcObj.hasOwnProperty(key) || !srcObj[key][objectKey]) {
  58. continue;
  59. }
  60. resultObj[srcObj[key][objectKey]] = srcObj[key];
  61. }
  62. return resultObj;
  63. }
  64. /**
  65. * 根据权重,计算随机内容
  66. * @param {arrany} weightArr
  67. * @param {number} totalWeight 权重
  68. * @returns
  69. */
  70. public static getWeightRandIndex(weightArr: [], totalWeight: number) {
  71. let randWeight: number = Math.floor(Math.random() * totalWeight);
  72. let sum: number = 0;
  73. for (var weightIndex: number = 0; weightIndex < weightArr.length; weightIndex++) {
  74. sum += weightArr[weightIndex];
  75. if (randWeight < sum) {
  76. break;
  77. }
  78. }
  79. return weightIndex;
  80. }
  81. /**
  82. * 从n个数中获取m个随机数
  83. * @param {Number} n 总数
  84. * @param {Number} m 获取数
  85. * @returns {Array} array 获取数列
  86. */
  87. public static getRandomNFromM(n: number, m: number) {
  88. let array: any[] = [];
  89. let intRd: number = 0;
  90. let count: number = 0;
  91. while (count < m) {
  92. if (count >= n + 1) {
  93. break;
  94. }
  95. intRd = this.getRandomInt(0, n);
  96. var flag = 0;
  97. for (var i = 0; i < count; i++) {
  98. if (array[i] === intRd) {
  99. flag = 1;
  100. break;
  101. }
  102. }
  103. if (flag === 0) {
  104. array[count] = intRd;
  105. count++;
  106. }
  107. }
  108. return array;
  109. }
  110. /**
  111. * 获取随机整数
  112. * @param {Number} min 最小值
  113. * @param {Number} max 最大值
  114. * @returns
  115. */
  116. public static getRandomInt(min: number, max: number) {
  117. let r: number = Math.random();
  118. let rr: number = r * (max - min + 1) + min;
  119. return Math.floor(rr);
  120. }
  121. /**
  122. * 获取字符串长度
  123. * @param {string} render
  124. * @returns
  125. */
  126. public static getStringLength(render: string) {
  127. let strArr: string = render;
  128. let len: number = 0;
  129. for (let i: number = 0, n = strArr.length; i < n; i++) {
  130. let val: number = strArr.charCodeAt(i);
  131. if (val <= 255) {
  132. len = len + 1;
  133. } else {
  134. len = len + 2;
  135. }
  136. }
  137. return Math.ceil(len / 2);
  138. }
  139. /**
  140. * 判断传入的参数是否为空的Object。数组或undefined会返回false
  141. * @param obj
  142. */
  143. public static isEmptyObject(obj: any) {
  144. let result: boolean = true;
  145. if (obj && obj.constructor === Object) {
  146. for (var key in obj) {
  147. if (obj.hasOwnProperty(key)) {
  148. result = false;
  149. break;
  150. }
  151. }
  152. } else {
  153. result = false;
  154. }
  155. return result;
  156. }
  157. /**
  158. * 判断是否是新的一天
  159. * @param {Object|Number} dateValue 时间对象 todo MessageCenter 与 pve 相关的时间存储建议改为 Date 类型
  160. * @returns {boolean}
  161. */
  162. public static isNewDay(dateValue: any) {
  163. // todo:是否需要判断时区?
  164. var oldDate: any = new Date(dateValue);
  165. var curDate: any = new Date();
  166. var oldYear = oldDate.getYear();
  167. var oldMonth = oldDate.getMonth();
  168. var oldDay = oldDate.getDate();
  169. var curYear = curDate.getYear();
  170. var curMonth = curDate.getMonth();
  171. var curDay = curDate.getDate();
  172. if (curYear > oldYear) {
  173. return true;
  174. } else {
  175. if (curMonth > oldMonth) {
  176. return true;
  177. } else {
  178. if (curDay > oldDay) {
  179. return true;
  180. }
  181. }
  182. }
  183. return false;
  184. }
  185. /**
  186. * 获取对象属性数量
  187. * @param {object}o 对象
  188. * @returns
  189. */
  190. public static getPropertyCount(o: Object) {
  191. var n, count = 0;
  192. for (n in o) {
  193. if (o.hasOwnProperty(n)) {
  194. count++;
  195. }
  196. }
  197. return count;
  198. }
  199. /**
  200. * 返回一个差异化数组(将array中diff里的值去掉)
  201. * @param array
  202. * @param diff
  203. */
  204. public static difference(array: [], diff: any) {
  205. let result: any[] = [];
  206. if (array.constructor !== Array || diff.constructor !== Array) {
  207. return result;
  208. }
  209. let length = array.length;
  210. for (let i: number = 0; i < length; i++) {
  211. if (diff.indexOf(array[i]) === -1) {
  212. result.push(array[i]);
  213. }
  214. }
  215. return result;
  216. }
  217. public static _stringToArray(string: string) {
  218. // 用于判断emoji的正则们
  219. var rsAstralRange = '\\ud800-\\udfff';
  220. var rsZWJ = '\\u200d';
  221. var rsVarRange = '\\ufe0e\\ufe0f';
  222. var rsComboMarksRange = '\\u0300-\\u036f';
  223. var reComboHalfMarksRange = '\\ufe20-\\ufe2f';
  224. var rsComboSymbolsRange = '\\u20d0-\\u20ff';
  225. var rsComboRange = rsComboMarksRange + reComboHalfMarksRange + rsComboSymbolsRange;
  226. var reHasUnicode = RegExp('[' + rsZWJ + rsAstralRange + rsComboRange + rsVarRange + ']');
  227. var rsFitz = '\\ud83c[\\udffb-\\udfff]';
  228. var rsOptVar = '[' + rsVarRange + ']?';
  229. var rsCombo = '[' + rsComboRange + ']';
  230. var rsModifier = '(?:' + rsCombo + '|' + rsFitz + ')';
  231. var reOptMod = rsModifier + '?';
  232. var rsAstral = '[' + rsAstralRange + ']';
  233. var rsNonAstral = '[^' + rsAstralRange + ']';
  234. var rsRegional = '(?:\\ud83c[\\udde6-\\uddff]){2}';
  235. var rsSurrPair = '[\\ud800-\\udbff][\\udc00-\\udfff]';
  236. var rsOptJoin = '(?:' + rsZWJ + '(?:' + [rsNonAstral, rsRegional, rsSurrPair].join('|') + ')' + rsOptVar + reOptMod + ')*';
  237. var rsSeq = rsOptVar + reOptMod + rsOptJoin;
  238. var rsSymbol = '(?:' + [rsNonAstral + rsCombo + '?', rsCombo, rsRegional, rsSurrPair, rsAstral].join('|') + ')';
  239. var reUnicode = RegExp(rsFitz + '(?=' + rsFitz + ')|' + rsSymbol + rsSeq, 'g');
  240. var hasUnicode = function (val) {
  241. return reHasUnicode.test(val);
  242. };
  243. var unicodeToArray = function (val) {
  244. return val.match(reUnicode) || [];
  245. };
  246. var asciiToArray = function (val) {
  247. return val.split('');
  248. };
  249. return hasUnicode(string) ? unicodeToArray(string) : asciiToArray(string);
  250. }
  251. // 模拟传msg的uuid
  252. public static simulationUUID() {
  253. function s4() {
  254. return Math.floor((1 + Math.random()) * 0x10000)
  255. .toString(16)
  256. .substring(1);
  257. }
  258. return s4() + s4() + '-' + s4() + '-' + s4() + '-' +
  259. s4() + '-' + s4() + s4() + s4();
  260. }
  261. public static trim(str: string) {
  262. return str.replace(/(^\s*)|(\s*$)/g, "");
  263. }
  264. /**
  265. * 判断当前时间是否在有效时间内
  266. * @param {String|Number} start 起始时间。带有时区信息
  267. * @param {String|Number} end 结束时间。带有时区信息
  268. */
  269. public static isNowValid(start, end) {
  270. var startTime = new Date(start);
  271. var endTime = new Date(end);
  272. var result = false;
  273. if (startTime.getDate() + '' !== 'NaN' && endTime.getDate() + '' !== 'NaN') {
  274. var curDate = new Date();
  275. result = curDate < endTime && curDate > startTime;
  276. }
  277. return result;
  278. }
  279. /**
  280. * 返回相隔天数
  281. * @param start
  282. * @param end
  283. * @returns
  284. */
  285. public static getDeltaDays(start: any, end: any) {
  286. start = new Date(start);
  287. end = new Date(end);
  288. let startYear: number = start.getFullYear();
  289. let startMonth: number = start.getMonth() + 1;
  290. let startDate: number = start.getDate();
  291. let endYear: number = end.getFullYear();
  292. let endMonth: number = end.getMonth() + 1;
  293. let endDate: number = end.getDate();
  294. start = new Date(startYear + '/' + startMonth + '/' + startDate + ' GMT+0800').getTime();
  295. end = new Date(endYear + '/' + endMonth + '/' + endDate + ' GMT+0800').getTime();
  296. let deltaTime = end - start;
  297. return Math.floor(deltaTime / (24 * 60 * 60 * 1000));
  298. }
  299. /**
  300. * 获取数组最小值
  301. * @param array 数组
  302. * @returns
  303. */
  304. public static getMin(array: number[]) {
  305. let result: number = null!;
  306. if (array.constructor === Array) {
  307. let length = array.length;
  308. for (let i = 0; i < length; i++) {
  309. if (i === 0) {
  310. result = Number(array[0]);
  311. } else {
  312. result = result > Number(array[i]) ? Number(array[i]) : result;
  313. }
  314. }
  315. }
  316. return result;
  317. }
  318. /**
  319. * 格式化两位小数点
  320. * @param time
  321. * @returns
  322. */
  323. public static formatTwoDigits(time: number) {
  324. //@ts-ignore
  325. return (Array(2).join(0) + time).slice(-2);
  326. }
  327. /**
  328. * 根据格式返回时间
  329. * @param date 时间
  330. * @param fmt 格式
  331. * @returns
  332. */
  333. public static formatDate(date: Date, fmt: string) {
  334. let o = {
  335. "M+": date.getMonth() + 1, //月份
  336. "d+": date.getDate(), //日
  337. "h+": date.getHours(), //小时
  338. "m+": date.getMinutes(), //分
  339. "s+": date.getSeconds(), //秒
  340. "q+": Math.floor((date.getMonth() + 3) / 3), //季度
  341. "S": date.getMilliseconds() //毫秒
  342. };
  343. if (/(y+)/.test(fmt)) fmt = fmt.replace(RegExp.$1, (date.getFullYear() + "").substr(4 - RegExp.$1.length));
  344. for (let k in o)
  345. if (new RegExp("(" + k + ")").test(fmt)) fmt = fmt.replace(RegExp.$1, (RegExp.$1.length === 1) ? (o[k]) : (("00" + o[k]).substr(("" + o[k]).length)));
  346. return fmt;
  347. }
  348. /**
  349. * 获取格式化后的日期(不含小时分秒)
  350. */
  351. public static getDay() {
  352. let date: Date = new Date();
  353. return date.getFullYear() + '-' + (date.getMonth() + 1) + '-' + date.getDate();
  354. }
  355. /**
  356. * 格式化名字,XXX...
  357. * @param {string} name 需要格式化的字符串
  358. * @param {number}limit
  359. * @returns {string} 返回格式化后的字符串XXX...
  360. */
  361. public static formatName(name: string, limit: number) {
  362. limit = limit || 6;
  363. var nameArray = this._stringToArray(name);
  364. var str = '';
  365. var length = nameArray.length;
  366. if (length > limit) {
  367. for (var i = 0; i < limit; i++) {
  368. str += nameArray[i];
  369. }
  370. str += '...';
  371. } else {
  372. str = name;
  373. }
  374. return str;
  375. }
  376. /**
  377. * 格式化钱数,超过10000 转换位 10K 10000K 转换为 10M
  378. * @param {number}money 需要被格式化的数值
  379. * @returns {string}返回 被格式化的数值
  380. */
  381. public static formatMoney(money: number) {
  382. let arrUnit: string[] = ['', 'K', 'M', 'G', 'T', 'P', 'E', 'Z', 'Y', 'B', 'N', 'D'];
  383. let strValue: string = '';
  384. for (let idx: number = 0; idx < arrUnit.length; idx++) {
  385. if (money >= 10000) {
  386. money /= 1000;
  387. } else {
  388. strValue = Math.floor(money) + arrUnit[idx];
  389. break;
  390. }
  391. }
  392. if (strValue === '') {
  393. strValue = Math.floor(money) + 'U'; //超过最大值就加个U
  394. }
  395. return strValue;
  396. }
  397. /**
  398. * 格式化数值
  399. * @param {number}value 需要被格式化的数值
  400. * @returns {string}返回 被格式化的数值
  401. */
  402. public static formatValue(value: number) {
  403. let arrUnit: string[] = [];
  404. let strValue: string = '';
  405. for (let i = 0; i < 26; i++) {
  406. arrUnit.push(String.fromCharCode(97 + i));
  407. }
  408. for (let idx: number = 0; idx < arrUnit.length; idx++) {
  409. if (value >= 10000) {
  410. value /= 1000;
  411. } else {
  412. strValue = Math.floor(value) + arrUnit[idx];
  413. break;
  414. }
  415. }
  416. return strValue;
  417. }
  418. /**
  419. * 根据剩余秒数格式化剩余时间 返回 HH:MM:SS
  420. * @param {Number} leftSec
  421. */
  422. public static formatTimeForSecond(leftSec: number, withoutSeconds: boolean = false) {
  423. let timeStr: string = '';
  424. let sec: number = Math.floor(leftSec % 60);
  425. let leftMin: number = Math.floor(leftSec / 60);
  426. leftMin = leftMin < 0 ? 0 : leftMin;
  427. let hour: number = Math.floor(leftMin / 60);
  428. let min: number = leftMin % 60;
  429. if (hour > 0) {
  430. timeStr += hour > 9 ? hour.toString() : '0' + hour;
  431. timeStr += ':';
  432. } else {
  433. timeStr += '00:';
  434. }
  435. timeStr += min > 9 ? min.toString() : '0' + min;
  436. if (!withoutSeconds) {
  437. timeStr += ':';
  438. timeStr += sec > 9 ? sec.toString() : '0' + sec;
  439. }
  440. return timeStr;
  441. }
  442. /**
  443. * 根据剩余毫秒数格式化剩余时间 返回 HH:MM:SS
  444. *
  445. * @param {Number} ms
  446. */
  447. public static formatTimeForMillisecond(ms: number): Object {
  448. let second: number = Math.floor(ms / 1000 % 60);
  449. let minute: number = Math.floor(ms / 1000 / 60 % 60);
  450. let hour: number = Math.floor(ms / 1000 / 60 / 60);
  451. return { 'hour': hour, 'minute': minute, 'second': second };
  452. }
  453. /**
  454. * 将数组内容进行随机排列
  455. * @param {Array}arr 需要被随机的数组
  456. * @returns
  457. */
  458. public static rand(arr: []): [] {
  459. let arrClone = this.clone(arr);
  460. // 首先从最大的数开始遍历,之后递减
  461. for (let i: number = arrClone.length - 1; i >= 0; i--) {
  462. // 随机索引值randomIndex是从0-arrClone.length中随机抽取的
  463. const randomIndex: number = Math.floor(Math.random() * (i + 1));
  464. // 下面三句相当于把从数组中随机抽取到的值与当前遍历的值互换位置
  465. const itemIndex: number = arrClone[randomIndex];
  466. arrClone[randomIndex] = arrClone[i];
  467. arrClone[i] = itemIndex;
  468. }
  469. // 每一次的遍历都相当于把从数组中随机抽取(不重复)的一个元素放到数组的最后面(索引顺序为:len-1,len-2,len-3......0)
  470. return arrClone;
  471. }
  472. /**
  473. * 获得开始和结束两者之间相隔分钟数
  474. *
  475. * @static
  476. * @param {number} start
  477. * @param {number} end
  478. * @memberof Util
  479. */
  480. public static getOffsetMimutes(start: number, end: number) {
  481. let offSetTime: number = end - start;
  482. let minute: number = Math.floor((offSetTime % (1000 * 60 * 60)) / (1000 * 60));
  483. return minute;
  484. }
  485. /**
  486. * 返回指定小数位的数值
  487. * @param {number} num
  488. * @param {number} idx
  489. */
  490. public static formatNumToFixed(num: number, idx: number = 0) {
  491. return Number(num.toFixed(idx));
  492. }
  493. /**
  494. * 用于数值到达另外一个目标数值之间进行平滑过渡运动效果
  495. * @param {number} targetValue 目标数值
  496. * @param {number} curValue 当前数值
  497. * @param {number} ratio 过渡比率
  498. * @returns
  499. */
  500. public static lerp(targetValue: number, curValue: number, ratio: number = 0.25) {
  501. let v: number = curValue;
  502. if (targetValue > curValue) {
  503. v = curValue + (targetValue - curValue) * ratio;
  504. } else if (targetValue < curValue) {
  505. v = curValue - (curValue - targetValue) * ratio;
  506. }
  507. return v;
  508. }
  509. /**
  510. * 数据解密
  511. * @param {String} str
  512. */
  513. public static decrypt(b64Data: string) {
  514. let n: number = 6;
  515. if (b64Data.length % 2 === 0) {
  516. n = 7;
  517. }
  518. let decodeData = '';
  519. for (var idx = 0; idx < b64Data.length - n; idx += 2) {
  520. decodeData += b64Data[idx + 1];
  521. decodeData += b64Data[idx];
  522. }
  523. decodeData += b64Data.slice(b64Data.length - n + 1);
  524. decodeData = this._base64Decode(decodeData);
  525. return decodeData;
  526. }
  527. /**
  528. * 数据加密
  529. * @param {String} str
  530. */
  531. public static encrypt(str: string) {
  532. let b64Data = this._base64encode(str);
  533. let n: number = 6;
  534. if (b64Data.length % 2 === 0) {
  535. n = 7;
  536. }
  537. let encodeData: string = '';
  538. for (let idx = 0; idx < (b64Data.length - n + 1) / 2; idx++) {
  539. encodeData += b64Data[2 * idx + 1];
  540. encodeData += b64Data[2 * idx];
  541. }
  542. encodeData += b64Data.slice(b64Data.length - n + 1);
  543. return encodeData;
  544. }
  545. //public method for encoding
  546. /**
  547. * base64加密
  548. * @param {string}input
  549. * @returns
  550. */
  551. private static _base64encode(input: string) {
  552. let keyStr: string = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=";
  553. let output: string = "", chr1: number, chr2: number, chr3: number, enc1: number, enc2: number, enc3: number, enc4: number, i: number = 0;
  554. input = this._utf8Encode(input);
  555. while (i < input.length) {
  556. chr1 = input.charCodeAt(i++);
  557. chr2 = input.charCodeAt(i++);
  558. chr3 = input.charCodeAt(i++);
  559. enc1 = chr1 >> 2;
  560. enc2 = ((chr1 & 3) << 4) | (chr2 >> 4);
  561. enc3 = ((chr2 & 15) << 2) | (chr3 >> 6);
  562. enc4 = chr3 & 63;
  563. if (isNaN(chr2)) {
  564. enc3 = enc4 = 64;
  565. } else if (isNaN(chr3)) {
  566. enc4 = 64;
  567. }
  568. output = output +
  569. keyStr.charAt(enc1) + keyStr.charAt(enc2) +
  570. keyStr.charAt(enc3) + keyStr.charAt(enc4);
  571. }
  572. return output;
  573. }
  574. /**
  575. * utf-8 加密
  576. * @param string
  577. * @returns
  578. */
  579. private static _utf8Encode(string: string) {
  580. string = string.replace(/\r\n/g, "\n");
  581. let utftext: string = "";
  582. for (let n: number = 0; n < string.length; n++) {
  583. let c: number = string.charCodeAt(n);
  584. if (c < 128) {
  585. utftext += String.fromCharCode(c);
  586. } else if ((c > 127) && (c < 2048)) {
  587. utftext += String.fromCharCode((c >> 6) | 192);
  588. utftext += String.fromCharCode((c & 63) | 128);
  589. } else {
  590. utftext += String.fromCharCode((c >> 12) | 224);
  591. utftext += String.fromCharCode(((c >> 6) & 63) | 128);
  592. utftext += String.fromCharCode((c & 63) | 128);
  593. }
  594. }
  595. return utftext;
  596. }
  597. /**
  598. * utf-8解密
  599. * @param utftext
  600. * @returns
  601. */
  602. private static _utf8Decode(utftext: string) {
  603. let string = "";
  604. let i: number = 0;
  605. let c: number = 0;
  606. let c1: number = 0;
  607. let c2: number = 0;
  608. let c3: number = 0;
  609. while (i < utftext.length) {
  610. c = utftext.charCodeAt(i);
  611. if (c < 128) {
  612. string += String.fromCharCode(c);
  613. i++;
  614. } else if ((c > 191) && (c < 224)) {
  615. c2 = utftext.charCodeAt(i + 1);
  616. string += String.fromCharCode(((c & 31) << 6) | (c2 & 63));
  617. i += 2;
  618. } else {
  619. c2 = utftext.charCodeAt(i + 1);
  620. c3 = utftext.charCodeAt(i + 2);
  621. string += String.fromCharCode(((c & 15) << 12) | ((c2 & 63) << 6) | (c3 & 63));
  622. i += 3;
  623. }
  624. }
  625. return string;
  626. }
  627. /**
  628. * base64解密
  629. * @param {string}input 解密字符串
  630. * @returns
  631. */
  632. private static _base64Decode(input: string) {
  633. let keyStr: string = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=";
  634. let output: string = "";
  635. let chr1: number;
  636. let chr2: number;
  637. let chr3: number;
  638. let enc1: number;
  639. let enc2: number;
  640. let enc3: number;
  641. let enc4: number;
  642. let i: number = 0;
  643. input = input.replace(/[^A-Za-z0-9\+\/\=]/g, "");
  644. while (i < input.length) {
  645. enc1 = keyStr.indexOf(input.charAt(i++));
  646. enc2 = keyStr.indexOf(input.charAt(i++));
  647. enc3 = keyStr.indexOf(input.charAt(i++));
  648. enc4 = keyStr.indexOf(input.charAt(i++));
  649. chr1 = (enc1 << 2) | (enc2 >> 4);
  650. chr2 = ((enc2 & 15) << 4) | (enc3 >> 2);
  651. chr3 = ((enc3 & 3) << 6) | enc4;
  652. output = output + String.fromCharCode(chr1);
  653. if (enc3 != 64) {
  654. output = output + String.fromCharCode(chr2);
  655. }
  656. if (enc4 != 64) {
  657. output = output + String.fromCharCode(chr3);
  658. }
  659. }
  660. output = this._utf8Decode(output);
  661. return output;
  662. }
  663. /**
  664. * 获取当前机型性能是否为低端机
  665. */
  666. public static checkIsLowPhone(): Boolean {
  667. if (window.wx) {
  668. //微信性能数值参考:https://developers.weixin.qq.com/minigame/dev/guide/performance/perf-benchmarkLevel.html
  669. let nowBenchmarkLevel: number = -1; //nowBenchmarkLevel = -1性能未知
  670. const sys = window.wx.getSystemInfoSync();
  671. const isIOS = sys.system.indexOf('iOS') >= 0;
  672. if (isIOS) {
  673. //微信不支持IO性能等级
  674. const model = sys.model;
  675. // iPhone 5s 及以下 设定为超低端机
  676. const ultraLowPhoneType = ['iPhone1,1', 'iPhone1,2', 'iPhone2,1', 'iPhone3,1', 'iPhone3,3', 'iPhone4,1', 'iPhone5,1', 'iPhone5,2', 'iPhone5,3', 'iPhone5,4', 'iPhone6,1', 'iPhone6,2'];
  677. // iPhone 6 ~ iPhone SE 设定为超低端机
  678. const lowPhoneType = ['iPhone6,2', 'iPhone7,1', 'iPhone7,2', 'iPhone8,1', 'iPhone8,2', 'iPhone8,4'];
  679. // iPhone 7 ~ iPhone X 设定为中端机
  680. const middlePhoneType = ['iPhone9,1', 'iPhone9,2', 'iPhone9,3', 'iPhone9,4', 'iPhone10,1', 'iPhone10,2', 'iPhone10,3', 'iPhone10,4', 'iPhone10,5', 'iPhone10,6'];
  681. // iPhone XS 及以上 设定为高端机
  682. const highPhoneType = ['iPhone11,2', 'iPhone11,4', 'iPhone11,6', 'iPhone11,8', 'iPhone12,1', 'iPhone12,3', 'iPhone12,5', 'iPhone12,8'];
  683. for (let i = 0; i < ultraLowPhoneType.length; i++) {
  684. if (model.indexOf(ultraLowPhoneType[i]) >= 0)
  685. nowBenchmarkLevel = 5;
  686. }
  687. for (let i = 0; i < lowPhoneType.length; i++) {
  688. if (model.indexOf(lowPhoneType[i]) >= 0)
  689. nowBenchmarkLevel = 10;
  690. }
  691. for (let i = 0; i < middlePhoneType.length; i++) {
  692. if (model.indexOf(middlePhoneType[i]) >= 0)
  693. nowBenchmarkLevel = 20;
  694. }
  695. for (let i = 0; i < highPhoneType.length; i++) {
  696. if (model.indexOf(highPhoneType[i]) >= 0)
  697. nowBenchmarkLevel = 30;
  698. }
  699. } else {
  700. nowBenchmarkLevel = sys.benchmarkLevel;
  701. }
  702. if (nowBenchmarkLevel < 22) { //22的具体参数可参考微信官方
  703. return true;
  704. } else {
  705. return false;
  706. }
  707. } else {
  708. return false;
  709. }
  710. }
  711. }