module.exports = { // ********** 其他 ********** // /** * 判断对象是否是字符串类型 * * @author Wetion * @date 2019-03-22 * @param {object} obj * @returns {Boolean} */ isString (obj) { return Object.prototype.toString.call(obj) == '[object String]'; }, /** * 判断对象是否是数字类型 * * @author Wetion * @date 2019-03-22 * @param {object} obj * @returns {Boolean} */ isNumber (obj) { return Object.prototype.toString.call(obj) == '[object Number]' && !isNaN(obj); }, /** * 判断对象是否是布尔类型 * * @author Wetion * @date 2019-03-22 * @param {object} obj * @returns {Boolean} */ isBoolean (obj) { return Object.prototype.toString.call(obj) == '[object Boolean]'; }, /** * 判断对象是否是数组类型 * * @author Wetion * @date 2019-03-22 * @param {object} obj * @returns {Boolean} */ isArray (obj) { return Object.prototype.toString.call(obj) == '[object Array]'; }, /** * 判断对象是否是字典类型 * * @author Wetion * @date 2019-03-22 * @param {object} obj * @returns {Boolean} */ isObject (obj) { return Object.prototype.toString.call(obj) == '[object Object]'; }, /** * 判断对象是否是未定义类型 * * @author Wetion * @date 2019-03-22 * @param {object} obj * @returns {Boolean} */ isUndefined (obj) { return Object.prototype.toString.call(obj) == '[object Undefined]'; }, /** * 判断对象是否是函数类型 * * @author Wetion * @date 2019-03-22 * @param {object} obj * @returns {Boolean} */ isFunction (obj) { return Object.prototype.toString.call(obj) == '[object Function]'; }, /** * 判断对象是否是空类型 * * @author Wetion * @date 2019-03-22 * @param {object} obj * @returns {Boolean} */ isNull (obj) { return Object.prototype.toString.call(obj) == '[object Null]'; }, /** * 判断对象是否是标志类型 * * @author Wetion * @date 2019-03-22 * @param {object} obj * @returns {Boolean} */ isSymbol (obj) { return Object.prototype.toString.call(obj) == '[object Symbol]'; }, /** * @description 整型长度补零 * @author Wetion * @date 2019-05-21 * @param {Number} num * @param {Number} length * @returns {String} */ prefixInteger (num, length) { return (Array(length).join('0') + num).slice(-length); }, /** * 拷贝对象 * * @author Wetion * @date 2019-03-22 * @param {object} obj 仅支持 Number, String, Array, Object, Boolean * @returns {object} */ clone (obj) { return JSON.parse(JSON.stringify(obj)); }, // ********** Array ********** // /** * Buffer转字数组 * * @author Wetion * @date 2019-03-22 * @param {ArrayBuffer} buffer * @returns {Uint8Array} */ bufferToUint8 (buffer) { let v = new DataView(buffer, 0); let a = new Array(); for (let i = 0; i < v.byteLength; i++) { a[i] = v.getUint8(i); } return a; }, /** * Buffer转字符串 * * @author Wetion * @date 2019-03-22 * @param {ArrayBuffer} buffer * @returns {string} */ bufferToString (buffer) { return String.fromCharCode.apply(undefined, new Uint8Array(buffer)); }, /** * 数组转Buffer * * @author Wetion * @date 2019-03-22 * @param {Uint8Array} arr * @returns {ArrayBuffer} */ uint8ToBuffer (arr) { let b = new ArrayBuffer(arr.length); let v = new DataView(b, 0); for (let i = 0; i < arr.length; i++) { v.setUint8(i, arr[i]); } return b; }, /** * Uint8数组转字符串 * * @author Wetion * @date 2019-03-22 * @param {Uint8Array} arr * @returns {String} */ uint8ToString (arr){ let dataString = ''; for (let i = 0; i < arr.length; i++) { dataString += String.fromCharCode(arr[i]); } return dataString; }, /** * utf8字符数组转字符串 * * @author Wetion * @date 2019-03-22 * @param {Array} arr * @returns {String} */ utf8ToString (arr) { if (typeof arr === 'string') { return undefined; } let utf = ''; for (let i = 0; i < arr.length; i++) { if (arr[i] == undefined) { break; } let one = arr[i].toString(2); let v = one.match(/^1+?(?=0)/); if (v && one.length == 8) { let bytesLength = v[0].length; let store = arr[i].toString(2).slice(7 - bytesLength); for (let st = 1; st < bytesLength; st++) { store += arr[st + i].toString(2).slice(2); } utf += String.fromCharCode(parseInt(store, 2)); i += bytesLength - 1; } else { utf += String.fromCharCode(arr[i]); } } return utf; }, /** * 数组查找元素 * * @author Wetion * @date 2019-03-22 * @param {Array} arr * @param {object} obj 要查找的对象 * @returns {Number} 下标或-1 */ arraySearch (arr, obj) { for (let i in arr){ if (arr[i] == obj){ return i; } } return -1; }, /** * 数组删除对象 * * @author Wetion * @date 2019-03-22 * @param {Array} arr * @param {object} obj 要删除的对象 * @returns {Boolean} 删除结果 成功/失败 */ arrayRemove (arr, obj) { let index = this.arraySearch(arr, obj); if (index > -1) { arr.splice(index, 1); return true; } return false; }, /** * 数组中是否存在某个对象 * * @author Wetion * @date 2019-03-22 * @param {Array} arr * @param {object} obj * @returns {Boolean} */ arrayIsExist (arr, obj) { let index = this.arraySearch(arr, obj); return index > -1 ? true : false; }, /** * 数组去重 (用的是Array的from方法) * * @author Wetion * @date 2019-03-22 * @param {Array} arr * @returns {Array} 去重后的数组 */ arrayUnique (arr) { return Array.from(new Set(arr)); }, /** * 将数组乱序输出 * * @author Wetion * @date 2019-03-22 * @param {Array} arr * @returns {Array} 打乱后的数组 */ arrayUpset (arr) { return arr.sort(function (){ return Math.random() - 0.5; }); }, /** * 获取数组的最大值,最小值,只针对数字类型的数组 * * @author Wetion * @date 2019-03-22 * @param {Array} arr * @param {Number} type 0:最小值,1:最大值 * @returns {Number} */ arrayCompare (arr, type) { if (type == 1){ return Math.max.apply(undefined, arr); } else { return Math.min.apply(undefined, arr); } }, /** * 得到数组的和,只针对数字类型数组 * * @author Wetion * @date 2019-03-22 * @param {Array} arr * @returns {Number} 和 */ arraySum (arr) { let sum = 0; for (let i = 0, len = arr.length; i < len; i++){ sum += arr[i]; } return sum; }, /** * 数组的平均值,只针对数字类型数组,小数点可能会有很多位,这里不做处理,处理了使用就不灵活了! * * @author Wetion * @date 2019-03-22 * @param {Array} arr * @returns {Number} 平均值 */ arrayAverage (arr) { let sum = this.arraySum(arr); let average = sum / arr.length; return average ; }, /** * 随机获取数组中的某个元素 * * @author Wetion * @date 2019-03-22 * @param {Array} arr * @returns {object} 随机获取的对象 */ arrayRandom (arr) { return arr[Math.floor(Math.random() * arr.length)]; }, /** * 统计某个元素在数组中出现的次数 * * @author Wetion * @date 2019-03-22 * @param {Array} arr * @param {object} obj * @returns {Number} 出现的次数 */ arrayElementCount (arr, obj) { let num = 0; for (let i = 0, len = arr.length; i < len; i++) { if (obj == arr[i]) { num++; } } return num; }, /** * @description 判断数组是否包含另一个数组 * @author Wetion * @date 2019-05-22 * @param {Array} aa * @param {Array} bb * @returns */ arrayIsContained (aa, bb) { if (!(aa instanceof Array) || !(bb instanceof Array) || ((aa.length < bb.length))) { return false; } for (let i = 0; i < bb.length; i++) { let flag = false; for (let j = 0; j < aa.length; j++){ if (aa[j] == bb[i]){ flag = true; break; } } if (flag == false){ return flag; } } return true; }, // ********** String ********** // /** * 字符串转Buffer * * @author Wetion * @date 2019-03-22 * @param {String} str * @returns {ArrayBuffer} */ stringToBuffer (str) { let buf = new ArrayBuffer(str.length * 2); // 每个字符占用2个字节 let bufView = new Uint16Array(buf); for (let i = 0, strLen = str.length; i < strLen; i++) { bufView[i] = str.charCodeAt(i); } return buf; }, /** * 字符串转Uint8数组 * * @author Wetion * @date 2019-03-22 * @param {String} str * @returns {Uint8Array} */ stringToUint8 (str){ let arr = []; for (let i = 0, j = str.length; i < j; ++i) { arr.push(str.charCodeAt(i)); } return new Uint8Array(arr); }, /** * 字符串转utf8字符数组 * * @author Wetion * @date 2019-03-22 * @param {String} str * @returns {Array} */ stringToUTF8 (str) { let back = []; for (let i = 0; i < str.length; i++) { let code = str.charCodeAt(i); if (0x00 <= code && code <= 0x7f) { back.push(code); } else if (0x80 <= code && code <= 0x7ff) { back.push((192 | (31 & (code >> 6)))); back.push((128 | (63 & code))); } else if ((0x800 <= code && code <= 0xd7ff) || (0xe000 <= code && code <= 0xffff)) { back.push((224 | (15 & (code >> 12)))); back.push((128 | (63 & (code >> 6)))); back.push((128 | (63 & code))); } } for (let i = 0; i < back.length; i++) { back[i] &= 0xff; } return back; }, // ********** 正则表达式 ********** // /** * 验证输入的字符串是否是有效的IP地址 * * @author Wetion * @date 2019-03-22 * @param {String} str * @returns {Boolean} */ isIP (str) { let re = /^(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$/; return re.test(str); }, /** * 判断是否是有效的端口(0~65535) * * @author Wetion * @date 2019-03-22 * @param {Number} num * @returns {Boolean} */ isPort (num) { let re = /^([0-9]|[1-9]\d|[1-9]\d{2}|[1-9]\d{3}|[1-5]\d{4}|6[0-4]\d{3}|65[0-4]\d{2}|655[0-2]\d|6553[0-5])$/; return re.test(num); }, /** * 验证输入的字符串是否是域名 * * @author Wetion * @date 2019-03-22 * @param {String} str * @returns {Boolean} */ isDomain (str) { let re = /^(?=^.{3,255}$)[a-zA-Z0-9][-a-zA-Z0-9]{0,62}(\.[a-zA-Z0-9][-a-zA-Z0-9]{0,62})+$/; return re.test(str); }, /** * 验证输入的字符串是否是URL * * @author Wetion * @date 2019-03-22 * @param {String} str * @returns {Boolean} */ isUrl (str) { let strRegex = '^((https|http|ftp|rtsp|mms)?://)' + '?(([0-9a-z_!~*().&=+$%-]+: )?[0-9a-z_!~*().&=+$%-]+@)?' // ftp的user@ + '(([0-9]{1,3}.){3}[0-9]{1,3}' // IP形式的URL- 199.194.52.184 + '|' // 允许IP和DOMAIN(域名) + '([0-9a-z_!~*()-]+.)*' // 域名- www. + '([0-9a-z][0-9a-z-]{0,61})?[0-9a-z].' // 二级域名 + '[a-z]{2,6})' // first level domain- .com or .museum + '(:[0-9]{1,4})?' // 端口- :80 + '((/?)|' // a slash isn't required if there is no file name + '(/[0-9a-z_!~*().;?:@&=+$,%#-]+)+/?)$'; let re = new RegExp(strRegex); return re.test(str); }, /** * https -> http * * @author libo * @date 2020-01-06 * @param {*} url * @returns */ httpsToHttp (url) { return url.replace(/^https/, 'http'); }, /** * 验证输入的EMAIL格式是否正确 * * @author Wetion * @date 2019-03-22 * @param {String} str * @returns {Boolean} */ isEmail (str) { let re = /^\w+([-+.]\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*$/; return re.test(str); }, /** * 验证输入的手机号码是否正确 * * @author Wetion * @date 2019-03-22 * @param {String} str * @returns {Boolean} */ isMobile (str) { let re = /^1[3456789]\d{9}$/; return re.test(str); }, /** * 验证输入的昵称格式是否有效 正确格式为:只能中英文,数字,下划线,减号 * * @author Wetion * @date 2019-03-22 * @param {String} str * @returns {Boolean} */ isNickname (str) { let re = /^[\u4e00-\u9fa5A-Za-z0-9-_]*$/; return re.test(str); }, /** * 判断是否是真实姓名 * * @author libo * @date 2019-06-21 * @param {String} str * @returns {Boolean} */ isRealName (str) { let re = /^[\u4E00-\u9FA5]{2,4}$/; return re.test(str); }, /** * 验证输入的密码格式是否有效 正确格式为:以字母开头,长度在6-18之间,只能包含字符、数字和下划线 * * @author Wetion * @date 2019-03-22 * @param {String} str * @returns {Boolean} */ isPassword (str) { let re = /^[a-zA-Z]\w{5,17}$/; return re.test(str); }, /** * 验证输入的身份证号格式是否有效(15位或18位数字) * * @author Wetion * @date 2019-03-22 * @param {String} str * @returns {Boolean} */ isIdCard (str) { let re = /^[1-9]\d{5}(18|19|([23]\d))\d{2}((0[1-9])|(10|11|12))(([0-2][1-9])|10|20|30|31)\d{3}[0-9Xx]$/; return re.test(str); }, // ********** Random ********** // /** * 随机整数 * * @author Pyden * @date 2019-04-10 * @param {Int} minInt 最小的整数 * @param {Int} maxInt 最大的整数 * @returns {Int} */ randomInt (minInt, maxInt) { if (minInt === undefined) { return 0; } if (minInt == maxInt) { return minInt; } if (maxInt != undefined) { return parseInt(Math.random() * (maxInt - minInt + 1) + minInt, 10); } else { // 等价于: randomInt(1, minInt) return parseInt(Math.random() * minInt + 1, 10); } }, /** * @description 随机权重下标 * @author Wetion * @date 2019-06-10 * @param {Array} arr 数字数组如:[1,2,3] * @returns */ randomWeightIndex (arr){ let index = 0; let totalWeight = this.arraySum(arr); let random = Math.random() * totalWeight; if (random <= arr[0]){ return 0; } else if (random >= arr[arr.length - 1]){ index = arr.length - 1; return index; } else { for (let i = 0 ;i < arr.length; i++){ if (random <= arr[i]){ index = i; } else if (random > arr[i] && random <= arr[i + 1]){ index = i + 1; break; } else if (random > arr[i] && random <= arr[ i + 1] ){ index = i + 1; break; } } } return index; }, // 依据权重,返回选择结果 randomConfByWeight (list, key) { let subkey = key || 'weight'; let weights = []; let sum = 0; for (const v of list) { let weight = v[subkey] || 0; sum = sum + weight; weights.push(sum); } if (sum == 0) { let randomIndex = G.FuncUtils.randomInt(1, list.length); return list[randomIndex - 1]; } let r = this.randomInt(1, sum); for (let i = 0; i < weights.length; i++) { const v = weights[i]; if (r <= v) { return list[i]; } } return undefined; }, /** * @description 获取数值格式化 * @author Wetion * @date 2019-07-01 * @param {Number} num * @returns {String} */ getNumericalFmt (num) { if (typeof num !== 'number') { return '0'; } let numstr = ''; if (num >= 100000000000) { let yi = Math.floor(num / 100000000); numstr = String(yi) + '亿'; } else if (num >= 100000000) { let wan = Math.floor(num / 10000); numstr = String(wan) + '万'; } else { numstr = String(num); } return numstr; }, getPackageNumericalFmt (num) { if (typeof num !== 'number') { return '0'; } let numstr = ''; if (num >= 100000000) { let yi = Math.floor(num / 100000000); numstr = String(yi) + '亿'; } else if (num >= 100000) { let wan = Math.floor(num / 10000); numstr = String(wan) + '万'; } else { numstr = String(num); } return numstr; }, /** * 给数字前补“0” * * @author Pyden * @date 2019-12-26 * @param {Integer} num * @param {Integer} length * @param {String} [char='0'] * @returns */ numberPadding (num, length, char = '0') { for (let len = (num + '').length; len < length; len++) { num = char + num; } return num; }, /** * 从身份证中获取生日 * * @author zzk * @param {String} [char='0'] * @returns */ getBirthByIdCard (idCard) { idCard = idCard.toString(); let num = idCard.length; if (num == 15 || num == 18) { let birth = idCard.slice(6, 14); return birth; } return undefined; }, getAgeByBirth (birth) { if (birth && birth != '' ) { let nowTimestamp = G.TimeUtils.getCurrentTime(); let now = new Date(parseInt(nowTimestamp) * 1000); let age = now.getFullYear() - Number(birth.slice(0, 4)) - 1; if (age < 0 ) return 0; let month = Number(birth.slice(5, 6)); if (now.getMonth() > month) { age = age + 1; } if (now.getMonth() == Number(birth.slice(4, 6)) && now.getDate() >= Number(birth.slice(6, 8))) age = age + 1; return age; } return 18; }, /** * 原始路径转为混淆路径 * @param {String} originPath * @param {String} pwd * @returns String */ originToHxPath (originPath, pwd) { pwd = this.generatePwdArr(pwd); let arr = []; let length = originPath.length; for (let index = 0; index < length; index++) { const element = originPath.charAt(index); let newWord = element; if (element !== '/' && element !== '-') { newWord = pwd[element]; } arr.push(newWord); } return arr.join(''); }, /** * 混淆路径转为原始路径 * @param {String} hxPath * @param {String} pwd * @returns String */ hxToOriginPath (hxPath, pwd) { pwd = this.generatePwdArr(pwd); let newPwd = this.invertPassword(pwd); let arr = []; pwd = newPwd; let length = hxPath.length; for (let index = 0; index < length; index++) { const element = hxPath.charAt(index); let newWord = element; if (element !== '/' && element !== '-') { newWord = pwd[element]; } arr.push(newWord); } return arr.join(''); }, /** * 翻转密码 key-value =》 value - key * @param {Array} pwd * @returns Array */ invertPassword (pwd) { let newArr = []; for (const key in pwd) { if (pwd.hasOwnProperty(key)) { const element = pwd[key]; newArr[element] = key; } } return newArr; }, generatePwdArr (pwd) { let keys = ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f']; let arr = []; for (let index = 0; index < keys.length; index++) { let key = keys[index]; arr[key] = pwd.charAt(index); } return arr; }, // 解析周期刷新时间 json parseCircleTimes (jsonList, suffix) { let type = jsonList.m; if (!G.FuncUtils.isNumber(type)) { cc.error('参数错误,没有m'); type = undefined; } let hour = jsonList.hour || 0; hour = this.numberPadding(hour, 2); let min = jsonList.min || 0; min = this.numberPadding(min, 2); let day = jsonList.day || 0; let month = jsonList.month || 0; switch (type) { case 0: var hour1 = jsonList.hour || 0; var hour2 = hour1 + 12; hour1 = this.numberPadding(hour1, 2); return cc.js.formatStr('%s:%s和\n%s:%s%s', hour1, min, hour2, min, suffix); case 1: return cc.js.formatStr('每天%s:%s%s', hour, min, suffix); case 2: return cc.js.formatStr('每周%s的\n%s:%s%s', day, hour, min, suffix); case 3: return cc.js.formatStr('每月%s号\n%s:%s%s', day, hour, min, suffix); case 4: { let nowTimestamp = G.TimeUtils.getCurrentTime(); let myDate = new Date(parseInt(nowTimestamp) * 1000); let tMonth = myDate.getMonth() + 1; let tDay = myDate.getDate(); let tHour = myDate.getHours(); let tMin = myDate.getMinutes(); // 计算季节开始时间 let quarterStart = parseInt(tMonth / 3) * 3; let needUpate = false; // 当前时间大于本季度刷新时间时,需要更新为下一个季度刷新时间 if (tMonth > quarterStart + month) { needUpate = true; } else if (tMonth == quarterStart + month) { if (tDay > day) { needUpate = true; } else if (tDay === day) { if (tHour > hour) { needUpate = true; } else if (tHour == hour) { if (tMin > min) { needUpate = true; } } } } if (needUpate){ quarterStart = quarterStart + 3; if (quarterStart >= 12) { quarterStart = quarterStart % 12; } } // 起始月份超过12的时候需要转为0 if (quarterStart >= 12) { quarterStart = parseInt(quarterStart % 12); } return cc.js.formatStr('%s月%s号\n%s:%s%s', quarterStart + month, day, hour, min, suffix); } case 5: return cc.js.formatStr('每年%s月%s号\n%s:%s%s', month, day, hour, min, suffix); } } };