UNPKG

ipink-util

Version:

util.js

1,002 lines (999 loc) 25.5 kB
import { isString, isNumber, isSafari, isIpad, isIphone, isIpod, isToday, isMini } from './is.mjs'; import { getPageUrl } from './get.mjs'; import { getEnv, ENV_TYPE, isMiniProgram } from './env.mjs'; import { getSdk, win } from './config.mjs'; import { toast } from './toast.mjs'; import { Storage } from './cache.mjs'; const base64EncodeChars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; const base64DecodeChars = new Array( -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 62, -1, -1, -1, 63, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, -1, -1, -1, -1, -1, -1, -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, -1, -1, -1, -1, -1, -1, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, -1, -1, -1, -1, -1 ); function base64encode(str) { let out = "", i = 0, len = str.length; let c1, c2, c3; while (i < len) { c1 = str.charCodeAt(i++) & 255; if (i == len) { out += base64EncodeChars.charAt(c1 >> 2); out += base64EncodeChars.charAt((c1 & 3) << 4); out += "=="; break; } c2 = str.charCodeAt(i++); if (i == len) { out += base64EncodeChars.charAt(c1 >> 2); out += base64EncodeChars.charAt((c1 & 3) << 4 | (c2 & 240) >> 4); out += base64EncodeChars.charAt((c2 & 15) << 2); out += "="; break; } c3 = str.charCodeAt(i++); out += base64EncodeChars.charAt(c1 >> 2); out += base64EncodeChars.charAt((c1 & 3) << 4 | (c2 & 240) >> 4); out += base64EncodeChars.charAt((c2 & 15) << 2 | (c3 & 192) >> 6); out += base64EncodeChars.charAt(c3 & 63); } return out; } function base64decode(str) { if (str == "" || str == null || str == void 0) { return ""; } let c1, c2, c3, c4; let i = 0, len = str.length, out = ""; while (i < len) { do { c1 = base64DecodeChars[str.charCodeAt(i++) & 255]; } while (i < len && c1 == -1); if (c1 == -1) break; do { c2 = base64DecodeChars[str.charCodeAt(i++) & 255]; } while (i < len && c2 == -1); if (c2 == -1) break; out += String.fromCharCode(c1 << 2 | (c2 & 48) >> 4); do { c3 = str.charCodeAt(i++) & 255; if (c3 == 61) return out; c3 = base64DecodeChars[c3]; } while (i < len && c3 == -1); if (c3 == -1) break; out += String.fromCharCode((c2 & 15) << 4 | (c3 & 60) >> 2); do { c4 = str.charCodeAt(i++) & 255; if (c4 == 61) return out; c4 = base64DecodeChars[c4]; } while (i < len && c4 == -1); if (c4 == -1) break; out += String.fromCharCode((c3 & 3) << 6 | c4); } return out; } function navigateBack(delta) { delta = delta || 1; if (typeof window !== "undefined" && window.history) { window.history.go(Number("-" + delta)); return; } let sdk2 = getSdk(); try { if (sdk2) { typeof uni !== "undefined" ? uni.navigateBack({ delta }) : wx.navigateBack({ delta }); } } catch (e) { } } const compareVersion = (v1, v2) => { const v1s = v1.split("."); const v2s = v2.split("."); const len = Math.max(v1s.length, v2s.length); while (v1s.length < len) { v1s.push("0"); } while (v2s.length < len) { v2s.push("0"); } for (let i = 0; i < len; i++) { const num1 = parseInt(v1s[i]); const num2 = parseInt(v2s[i]); if (num1 > num2) { return 1; } else if (num1 < num2) { return -1; } } return 0; }; function uuid(sign = "-") { let d = (/* @__PURE__ */ new Date()).getTime(); let uuid2 = `xxxxxxxx${sign}xxxx${sign}4xxx${sign}yxxx${sign}xxxxxxxxxxxx`.replace(/[xy]/g, function(c) { var r = (d + Math.random() * 16) % 16 | 0; d = Math.floor(d / 16); return (c == "x" ? r : r & 3 | 8).toString(16); }); return uuid2; } function fillStr(target, fill, len) { if (!isString(target) && !isNumber(target)) return target; if (isNumber(target)) target = "" + target; for (var i = 0; i < len; i++) { target += fill; } return target; } const converNumber = (num, type, fixed = 1) => { num = "" + num; let left = num.split(".")[0]; let right = num.split(".")[1] || ""; let rl = right.length; let fl = left.length; if (type === "en") { let conver = { "K": 1e3, "W": 1e4, "M": 1e6, "B": 1e9 }; let symbol = fl <= 4 ? "K" : fl <= 6 ? "W" : fl <= 12 ? "M" : "B"; let value = (+left / conver[symbol]).toFixed(fixed); let _vr = value.split(".")[1] || ""; if (_vr.length > fixed) { value = value.split(".")[0] + _vr.slice(0, fixed); } return value + symbol; } if (type === "cn") { let conver = { " ": 1, "万": 1e4, "亿": 1e8 }; let _symbol = fl <= 5 ? " " : fl <= 11 ? "万" : "亿"; let _value = (+left / conver[_symbol]).toFixed(fixed); let _vr = ("" + _value).split(".")[1] || ""; if (_vr.length > fixed) { _value = ("" + _value).split(".")[0] + _vr.slice(0, fixed); } return _value + _symbol; } if (type === "sp") { right = rl <= fixed ? fillStr(right, "0", fixed - rl) : right.slice(0, fixed); let count = 0; let arr = []; for (let i = left.length - 1; i >= 0; i--) { if (count % 3 === 0 && count !== 0) { arr.unshift(","); } arr.unshift(left[i]); count++; } return arr.join("") + "." + right; } return "" + num; }; const firstCharCase = (str) => str.slice(0, 1).toUpperCase() + str.slice(1).toLowerCase(); function findTargetAndRemove(arr, target, options) { const { key = "id", type = "unshift" } = options || {}; const index = arr.findIndex((item) => { if ((isString(item) || isNumber(item)) && item === target) return item; const _item = item; const _target = target; if (_item[key] == _target[key]) { return item; } }); if (index == -1) { arr[type](target); } else { const _target = arr.splice(index, 1); arr[type](Object.keys(target).length == 1 ? _target : target); } return arr; } function handlerPromise(promiseList) { return promiseList.map( (promise) => promise.then((res) => res, (err) => err) ); } function allSettled(promiseList) { return Promise.all(handlerPromise(promiseList)); } function debounce(func, time, immediate) { if (!time || time <= 0) return func; let timeId = void 0; return function() { if (timeId) clearTimeout(timeId); if (immediate) { const isCall = !timeId; timeId = setTimeout(() => { timeId = null; }, time); if (isCall) { func.apply(this, arguments); } } else { timeId = setTimeout(() => { func.apply(this, arguments); }, time); } }; } function throttle(func, time) { let timeId = void 0, start; return function(...args) { let now = (/* @__PURE__ */ new Date()).getTime(); if (!start) start = now; if (now - start > time) { clearTimeout(timeId); timeId = start = now = void 0; func.apply(this, args); } else { if (timeId) return; timeId = setTimeout(() => { func.apply(this, args); timeId = start = now = void 0; }, time); } }; } function copyValue(val, options) { const { tip, success, fail } = options || {}; if (typeof document !== "undefined" && window && window.getSelection) { let platform = ""; if (isSafari() || isIpad() || isIphone() || isIpod()) platform = "ios"; try { if (platform == "ios") { window.getSelection().removeAllRanges(); let inputDom = document.createElement("input"); document.body.appendChild(inputDom); inputDom.style.opacity = 0; inputDom.value = val; let range = document.createRange(); range.selectNode(inputDom); window.getSelection().addRange(range); inputDom.select(); inputDom.setSelectionRange(0, inputDom.value.length); document.execCommand("copy"); window.getSelection().removeAllRanges(); document.body.removeChild(inputDom); } else { var _input = document.createElement("input"); _input.value = val; document.body.appendChild(_input); _input.select(); document.execCommand("Copy"); _input.remove(); } tip && toast(tip); success && success(); } catch (error) { fail && fail(error); } return; } try { let params = { data: val, success: () => { tip && toast(tip); success && success(); }, fail: (e) => fail && fail(e) }; typeof uni !== "undefined" ? uni.setClipboardData(params) : wx.setClipboardData(params); } catch (e) { fail && fail(e); } } function hasKey(obj, key) { return Object.prototype.hasOwnProperty.call(obj, key); } const setTitleName = (title = "") => { if (typeof window !== "undefined" && typeof document !== "undefined") { try { let url = getPageUrl(); if (url.indexOf("base64=1") > -1) { title = decodeURIComponent(base64decode(title)); } } catch (e) { title = ""; } const env = getEnv(); if (ENV_TYPE.MY === env) { document.title = title; return; } else if (ENV_TYPE.ALIPAY === env) { const setAlipayTitle = () => { AlipayJSBridge.call("setTitle", { title }); }; if (window.AlipayJSBridge && AlipayJSBridge) { setAlipayTitle(); } else { document.addEventListener("AlipayJSBridgeReady", setAlipayTitle, false); } return; } } let sdk2 = getSdk(); if (sdk2) { let params = { title, fail: () => { if (typeof document !== "undefined") document.title = title; } }; typeof uni !== "undefined" ? uni.setNavigationBarTitle(params) : wx.setNavigationBarTitle(params); } }; const desensitization = (str, begin = 3, end = begin) => { if (!str || str.length <= begin + end) return str; end = str.length - end; let firstStr = str.slice(0, begin); let lastStr = str.slice(end); let middleStr = str.substring(begin, Math.abs(end)).replace(/[\s\S]/ig, "*"); let tempStr = firstStr + middleStr + lastStr; return tempStr; }; const getRefInfo = (ref, that, options) => { if (!options) { options = { size: true, rect: true, scrollOffset: true }; } let sdk2 = getSdk(); if (!sdk2) return Promise.resolve(null); return new Promise((resolve) => { if (!ref) { resolve(null); } try { let view = uni.createSelectorQuery().in(that).select(ref); view.fields(options, (data) => { resolve(data ? { ...data, ref } : null); }).exec(); } catch (e) { resolve(null); } }); }; const getLocation = async (options) => { const { callback, success, fail, complete, isToast = false, isUseRefuseTime = false, initWxSdkCallback } = options || {}; return new Promise(async (resolve) => { if (isUseRefuseTime) { const refuseTime = Storage.getItem("IsRefuseGetLocation"); if (refuseTime && isToday(refuseTime)) { callback && callback(false, {}); return resolve(null); } } let isAlipay = false, err = null; if (typeof document !== "undefined" && win) { try { let env = getEnv(); if (env == ENV_TYPE.ALIPAY || env == ENV_TYPE.MY) { isAlipay = true; window.AlipayJSBridge && AlipayJSBridge.call("getCurrentLocation", { bizType: "$s" }, (result) => { if (result.error) { callback && callback(); if (result.error == 11) { AlipayJSBridge.call("showAuthGuide", { bizType: "$s", authType: "LBS" }, function(r) { fail && fail({ ...result, errMsg: result.errorMessage }); }); } else { fail && fail({ ...result, errMsg: result.errorMessage }); toast(result.errorMessage); } complete && complete(); resolve(null); } else { callback && callback(result); success && success(result); complete && complete(result); resolve(result); } }); return; } else if (env == ENV_TYPE.WX || env == ENV_TYPE.WXMINI) { if (initWxSdkCallback) { await initWxSdkCallback(); } wx.getLocation({ // 默认为wgs84的 gps 坐标,如果要返回直接给 openLocation 用的火星坐标,可传入'gcj02' type: "gcj02", success: (res) => { callback && callback(res); success && success(res); complete && complete(res); resolve(res); }, fail: (e) => { callback && callback(); fail && fail(e); complete && complete(); resolve(null); }, cancel: function(res) { callback && callback(); fail && fail({ errMsg: res.errMsg || "用户拒绝授权获取地理位置信息" }); complete && complete(); resolve(null); if (isUseRefuseTime) { const result = confirm("用户拒绝授权获取地理位置,今日是否不再提示!"); if (result) { Storage.setItem("IsRefuseGetLocation", /* @__PURE__ */ new Date()); } } } }); return; } else if (env == ENV_TYPE.SWAN && typeof swan !== "undefined" && swan.getLocation) { swan.getLocation({ type: "gcj02", success: (res) => { callback && callback(res); success && success(res); complete && complete(res); resolve(res); }, fail: (err2) => { callback && callback(); fail && fail(err2); complete && complete(); resolve(null); } }); return; } } catch (e) { err = { ...e || {}, errMsg: e?.errMsg || e?.message || "获取失败" }; } } try { let sdk2 = getSdk(); if (sdk2) { let type = "gcj02"; type = typeof document !== "undefined" && isAlipay ? "wgs84" : "gcj02"; if (isMini()) type = "wgs84"; uni.getLocation({ type, highAccuracyExpireTime: 1e3, success: (res) => { callback && callback(res); success && success(res); complete && complete(res); resolve(res); }, fail: (err2) => { callback && callback(); fail && fail(err2); complete && complete(); resolve(null); } }); return; } } catch (e) { err = { ...e || {}, errMsg: e?.errMsg || e?.message || "获取失败" }; } callback && callback(); fail && fail({ ...err || {}, errMsg: err?.errMsg || "获取失败" }); complete && complete(); resolve(null); }); }; let EARTH_RADIUS = 6378137; let PI = Math.PI; function getRad(d) { return d * PI / 180; } function getGreatCircleDistance(lng1, lat1, lng2, lat2) { let radLat1 = getRad(lat1); let radLat2 = getRad(lat2); let a = radLat1 - radLat2; let b = getRad(lng1) - getRad(lng2); let s = 2 * Math.asin(Math.sqrt(Math.pow(Math.sin(a / 2), 2) + Math.cos(radLat1) * Math.cos(radLat2) * Math.pow(Math.sin(b / 2), 2))); s = s * EARTH_RADIUS; s = Math.round(s * 1e4) / 1e4; return s; } function postMessage(options) { const env = getEnv(); return new Promise((resolve) => { if (typeof document !== "undefined" && win) { try { const { type, params = {}, success, fail } = options || {}; const msgData = { data: { type, params } }; const callBack = () => { resolve({ ok: true }); success({ ok: true }); }; switch (env) { case ENV_TYPE.MY: my.postMessage({ type, params }); my.onMessage = (e) => { const { ok, result, type: type2 } = e; if (ok) { if (typeof success == "function") { success(e); } resolve(e); } else { if (typeof fail == "function") { fail(e); } resolve({ ...e || {}, errMsg: e?.errMsg || e?.message || "获取信息失败" }); } }; break; case ENV_TYPE.WX: case ENV_TYPE.WXMINI: wx.miniProgram.postMessage(msgData); callBack(); break; case ENV_TYPE.SWAN: swan.webView.postMessage(msgData); callBack(); break; case ENV_TYPE.TT: tt.miniProgram.postMessage(msgData); callBack(); break; default: window.postMessage(msgData); callBack(); break; } } catch (e) { resolve({ ok: false, ...e || {} }); } } else { resolve({ ok: true, errMsg: "非浏览器环境调用" }); } }); } const backMainAppHome = (delta = 1) => { if (typeof document !== "undefined" && win) { const env = getEnv(); if (ENV_TYPE.WXMINI === env && typeof wx !== "undefined") { wx.miniProgram.navigateBack({ delta }); return true; } else if (ENV_TYPE.MY === env && typeof my !== "undefined") { my.navigateBack({ delta }); return true; } else if (ENV_TYPE.SWAN === env && typeof swan !== "undefined") { swan.webView.navigateBack({ delta }); return true; } else if (sdk) { if (typeof uni !== "undefined") { uni.webView?.navigateBack({ delta }); } else { wx.webView.navigateBack({ delta }); } return true; } if (typeof uni !== "undefined") { uni.navigateBack({ delta }); } else if (typeof wx !== "undefined") { wx.navigateBack({ delta }); } } return true; }; const checkWhiteScreen = (that, ref = ".content") => { try { that.$nextTick(() => { const query = uni.createSelectorQuery().in(that); query.select(ref).boundingClientRect((data) => { if (!data || data.height == 0) { window.location.reload(); } }).exec(); }); } catch (e) { } }; const BAR_CODE_TYPE = ["EAN_8", "EAN_13", "CODE_25", "CODE_39", "CODE_128", "UPC_A", "UPC_E"]; const scanCode = (options) => { const { success, cacheKey, jsCodeInfo = {} } = options || {}; const empty = { code: "" }; return new Promise(async (resolve) => { try { if (navigator.userAgent.indexOf("AlipayClient") >= 0) { if (isMini()) { my.onMessage = (e) => { var result = JSON.parse(e.messageDetail); let opt = { code: result.scanCode }; if (success) { success(opt); } resolve(opt); }; my.postMessage({ messageType: "scan" }); } else { if (window.AlipayJSBridge && AlipayJSBridge) { AlipayJSBridge.call( "scan", { scanType: ["qrCode", "barCode"] }, (result) => { let opt = { code: "" }; if (result.barCode) { opt.code = result.barCode; } if (result.qrCode) { opt.code = result.qrCode; } if (success) { success(opt); } resolve(opt); }, (err) => { toast("识别失败: " + JSON.stringify(err)); if (success) { success(empty); } resolve(empty); } ); } else { toast("扫码调用失败"); if (success) { success(empty); } resolve(empty); } } } else if (navigator.userAgent.indexOf("MicroMessenger") >= 0 && typeof wx !== "undefined") { if (isMiniProgram()) { wx.miniProgram.postMessage({ data: { type: "scan", params: { cacheKey } } }); if (success) { success(empty); } return resolve(empty); } wx.config({ debug: 0, ...jsCodeInfo || {}, jsApiList: ["scanQRCode"] // 必填,需要使用的JS接口列表,所有JS接口列表见附录2 }); wx.ready(() => { wx.scanQRCode({ needResult: 1, // 默认为0,扫描结果由微信处理,1则直接返回扫描结果, scanType: [ "qrCode", "barCode", "datamatrix" ], // 可以指定扫二维码还是一维码,默认二者都有 success: (result) => { let commaIndex = result.resultStr.indexOf(","); try { const target = BAR_CODE_TYPE.find((item) => item.toLocaleUpperCase() == result.resultStr.slice(0, commaIndex)); if (target) { result.resultStr = result.resultStr.slice( commaIndex + 1 ); } } catch (e) { } let opt = { code: result.resultStr }; if (success) { success(opt); } resolve(opt); }, fail: (res) => { toast(JSON.stringify(res)); if (success) { success(empty); } resolve(empty); } }); }); } else { uni.scanCode({ success: function(res) { let opt = { code: res.result }; if (success) { success(opt); } resolve(opt); }, fail() { toast("当前环境暂不支持扫码!"); if (success) { success(empty); } resolve(empty); } }); } } catch (e) { toast(e?.errMsg || e?.message || JSON.stringify(e)); if (success) { success(empty); } resolve(empty); } }); }; function flattenArray(arr) { let result = []; arr.forEach((item) => { if (Array.isArray(item)) { result = result.concat(flattenArray(item)); } else { result.push(item); } }); return result; } function buildHierarchyArray(arr, key) { let result = []; let map = {}; arr.forEach((item) => { map[item.id] = { ...item, children: [] }; }); arr.forEach((item) => { let pid = item[key]; if (!pid) { result.push(map[item.id]); } else { if (!pid) { result.push(map[item.id]); } else { map[pid].children.push(map[item.id]); } } }); return result; } function formatTree(nodeList, childKey, parentKey) { childKey = childKey || "id"; parentKey = parentKey || "pid"; const map = {}; for (var i = 0; i < nodeList.length; i++) { const item = nodeList[i]; const parentId = item[parentKey]; const childId = item[childKey]; if (!parentId) map[childId] = { ...item, children: [] }; } for (var i = 0; i < nodeList.length; i++) { const item = nodeList[i]; const parentId = item[parentKey]; if (item[parentId] && map[parentId] && map[parentId].children) { map[parentId].children.push(nodeList[i]); } } return Object.values(map); } export { BAR_CODE_TYPE, allSettled, backMainAppHome, base64decode, base64encode, buildHierarchyArray, checkWhiteScreen, compareVersion, converNumber, copyValue, debounce, desensitization, fillStr, findTargetAndRemove, firstCharCase, flattenArray, formatTree, getGreatCircleDistance, getLocation, getRefInfo, hasKey, navigateBack, postMessage, scanCode, setTitleName, throttle, uuid };