ipink-util
Version:
util.js
1,002 lines (999 loc) • 25.5 kB
JavaScript
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 };