/*
* @overview 自己常用的工具类定义
* @copyright GPL-3.0-only
* @author WhiteSevs
* @version 0.1
*/
let Utils = {};
/*
* @param {string|function} func - 需要捕获错误的函数或函数格式的字符串
* @param {object} params - 该函数的参数和捕获到错误的函数的参数,类型为数组Array
* @param {string|function} errorFunc - 捕获到错误后执行的函数或函数格式的字符串
* @example Utils.tryCatch("(pam)=>{console.log('this is a function and params is' + pam[0])}",["参数1"],"()=>{console.log('对错误进行处理判断')}");
*/
Utils.tryCatch = (func, params, errorFunc) => {
/* 捕获错误 */
if (typeof func !== "object" && typeof func !== "string") {
throw "参数 func 类型必须为function类型或者string类型"
}
if (params != null && typeof params !== "object") {
throw "参数 params 类型必须为object类型"
}
if (errorFunc != null && typeof errorFunc !== "object" && typeof errorFunc !== "string") {
throw "参数 errorFunc 类型必须为function类型或者string类型"
}
var result = null;
try {
result = typeof func === "string" ? window.eval(func) : func(params);
} catch (error) {
console.log("%c" + (func.name ? func.name : func + "出现错误"), "color: #f20000");
console.log("%c" + ("错误原因:" + error), "color: #f20000");
console.trace(func);
result = typeof func === "string" ? window.eval(errorFunc) : errorFunc(params);
} finally {
return result;
}
};
/*
* @description 格式化时间字符串
* @param {string} str - 字符串格式的时间,例如:2022-11-21 00:00:00,或者是 00:00:00
* @return {number} - 返回时间戳
* @example Utils.formatTextToTimeStamp("2022-11-21 00:00:00");
*/
Utils.formatTextToTimeStamp = (text) => {
/* 把字符串格式的时间(完整,包括日期和时间)格式化成时间戳 */
if (typeof text !== 'string') {
throw "参数 text 必须为string类型";
};
if (text.length === 8) {
/* 参数只有时间 */
var today = new Date();
text = today.getFullYear() + "-" + (today.getMonth() + 1) + "-" + today.getDate() + " " + text;
};
text = text.substring(0, 19);
text = text.replace(/-/g, '/');
var timestamp = new Date(text).getTime();
return timestamp;
};
/*
* @description 定位网页中字符串位置并标亮,注意,该字符串必须是能在网页中看得到的,隐藏的是无法定位的
* @param {string} str - 需要寻找的字符串
* @param {boolean} caseSensitive - 区分大小写
* @return {boolean} true/false - 找到为true,否则false
* @example Utils.findWindowPageString("xxxxx");
* @exampleResult true
*/
Utils.findWindowPageString = (str,caseSensitive=false) => {
var TRange = null;
var strFound;
if (window.find) {
// CODE FOR BROWSERS THAT SUPPORT window.find
strFound = self.find(str,caseSensitive,true,true,false);
if (strFound && self.getSelection && !self.getSelection().anchorNode) {
strFound = self.find(str,caseSensitive,true,true,false)
}
if (!strFound) {
strFound = self.find(str, 0, 1)
while (self.find(str, 0, 1))
continue
}
} else if (navigator.appName.indexOf("Microsoft") != -1) {
// EXPLORER-SPECIFIC CODE
if (TRange != null) {
TRange.collapse(false)
strFound = TRange.findText(str)
if (strFound)
TRange.select()
}
if (TRange == null || strFound == 0) {
TRange = self.document.body.createTextRange()
strFound = TRange.findText(str)
if (strFound)
TRange.select()
}
} else if (navigator.appName == "Opera") {
alert("Opera browsers not supported, sorry...")
return;
};
return strFound ? true:false;
}
/*
* @description 格式化byte为KB、MB、GB、TB、PB、EB、ZB、YB、BB、NB、DB
* @param {number} bitSize - 字节
* @param {boolean} addType - 是否添加单位,默认添加
* @return {string|number} - 添加单位就是字符串,否则为float类型,保留两位
* @example Utils.formatByteToSize("812304");
* @exampleResult
*/
Utils.formatByteToSize = (byteSize, addType = true) => { // B字节转KB、MB、GB
byteSize = parseInt(byteSize);
if (isNaN(byteSize)) {
throw "参数 byteSize 格式不正确";
}
var result = 0;
var resultType = "KB";
var sizeData = {};
sizeData.KB = 1024;
sizeData.MB = sizeData.KB * sizeData.KB;
sizeData.GB = sizeData.MB * sizeData.KB;
sizeData.TB = sizeData.GB * sizeData.KB;
sizeData.PB = sizeData.TB * sizeData.KB;
sizeData.EB = sizeData.PB * sizeData.KB;
sizeData.ZB = sizeData.EB * sizeData.KB;
sizeData.YB = sizeData.ZB * sizeData.KB;
sizeData.BB = sizeData.YB * sizeData.KB;
sizeData.NB = sizeData.BB * sizeData.KB;
sizeData.DB = sizeData.NB * sizeData.KB;
for (key in sizeData) {
result = byteSize / sizeData[key];
resultType = key;
if (sizeData.KB >= result) {
break;
}
};
result = result.toFixed(2);
result = addType ? result + resultType.toString() : parseFloat(result);
return result;
}
/*
* @description 数组按照内部某个值的大小比对排序,如[{"time":"2022-1-1"},{"time":"2022-2-2"}]
* @param {string} propertyName - 数组内部项的某个属性的名称
* @param {boolean} sortByDesc - 排序方式为倒序,值为true或false,默认为true
* @return {object} - 返回比较排序完成的数组
* @example [{"time":"2022-1-1"},{"time":"2022-2-2"}].sort(Utils.sortListByProperty("time"))
* @example [{"time":"2022-1-1"},{"time":"2022-2-2"}].sort(Utils.sortListByProperty("time",false))
*/
Utils.sortListByProperty = (propertyName, sortByDes = true) => {
if (typeof sortByDesc !== 'boolean') {
throw "参数 sortByDesc 必须为boolean类型";
};
return function (after_obj, before_obj) {
var beforeValue = before_obj[propertyName]; /* 前 */
var aferValue = after_obj[propertyName]; /* 后 */
if (sortByDesc) {
if (aferValue > beforeValue) {
return -1
} else if (aferValue < beforeValue) {
return 1
} else {
return 0
}
} else {
if (aferValue < beforeValue) {
return -1
} else if (aferValue > beforeValue) {
return 1
} else {
return 0
}
}
}
};
/*
* @description Array添加一个内部属性,数组根据相同的字段合并成字符串
* @example [{"name":"Array内部方法: "},{"name":"mergeToString"}].mergeToString("name");
*/
Utils.setArrayPropertyMergeToString = () => {
Array.prototype.mergeToString = function (propertyName) {
if (propertyName == null) {
throw "参数 propertyName 不能为null";
}
var content = "";
Array.from(this).forEach((item) => {
content = content + item[propertyName];
})
return content
}
};
/*
* @description JSON内所有的值转为Array数组
* @param {object} _json_ - JSON数据
* @return {object} - 返回数组
* @example Utils.jsonAllValueToArray({"Utils":"jsonToArray","return","Array"});
* @exampleResult ['jsonToArray', 'Array']
*/
Utils.jsonAllValueToArray = (_json_) => {
if (typeof _json_ !== 'object') {
throw "参数 _json_ 必须为object类型"
}
var retArray = [];
Object.keys(_json_).forEach(function (key) {
retArray = retArray.concat(_json_[key]);
})
return retArray;
};
/*
* @description JSON格式的字符串转为JSON对象
* @param {string} text - JSON格式的字符串
* @return {object} - 返回JSON对象
* @example Utils.jsonStrToObject('{"Utils":"jsonStrToObject","return","json"}');
* @exampleResult {"Utils":"jsonStrToObject","return","json"}
*/
Utils.jsonStrToObject = (text) => {
if (typeof text !== 'string') {
throw "参数 text 类型必须为string类型"
}
return window.eval("(" + _json_str_ + ")");
};
/*
* @description 获取数组的随机值
* @param {string} array - 数组数据
* @return {string} - 返回数组的随机值
* @example Utils.getArrayRandValue(["Utils","getArrayRandValue"]);
* @exampleResult getArrayRandValue
*/
Utils.getArrayRandValue = (_array_) => {
return _array_[Math.floor(Math.random() * _array_.length)];
};
/*
* @description 获取两个数字区间的随机值
* @param {number} number - 数字区间
* @param {number} number2 - 数字区间
* @return {number} - 返回两个数字区间的随机值
* @example Utils.getRandNumber(1,10);
* @exampleResult 5
* @example Utils.getRandNumber(10,1);
* @exampleResult 8
*/
Utils.getRandNumber = (number, number2) => {
if (typeof number !== "number") {
throw "参数 number 必须为number类型";
}
if (typeof number2 !== "number") {
throw "参数 number2 必须为number类型";
}
var leftNumber = number > number2 ? number2 : number;
var rightNumber = number > number2 ? number : number2;
return Math.round(Math.random() * (rightNumber - leftNumber)) + leftNumber;
};
/*
* @description 获取格式化后的Date类型时间
* @param {string} text - 需要格式化的字符串
* @param {string} types - 格式化成的显示类型
* yyyy 年
* MM 月
* dd 天
* HH 时 (24小时制)
* hh 时 (12小时制)
* mm 分
* ss 秒
* @return {string} - 返回格式化后的时间
* @example Utils.getFormatTime("2022-08-21 23:59:00","HH:mm:ss");
* @exampleResult 23:59:00
*/
Utils.getFormatTime = (text, types) => {
if (typeof text !== "string") {
throw "参数 text 必须为字符串";
}
if (typeof types !== "string") {
throw "参数 types 必须为字符串";
}
function _checkTime_(i) {
/* 校验时间补0 */
if (i < 10) return "0" + i;
return i;
}
function _timeSystemChange_(_hour_) {
/* 时间制修改 24小时制转12小时制 */
return _hour_ > 12 ? _hour_ - 12 : _hour_;
};
var time = timestamp != null ? new Date(text) : new Date();
var timeRegexp = {
"yyyy": time.getFullYear(),
/* 年 */
"MM": _checkTime_(time.getMonth() + 1),
/* 月 */
"dd": _checkTime_(time.getDate()),
/* 日 */
"HH": _checkTime_(time.getHours()),
/* 时 (24小时制) */
"hh": _checkTime_(_timeSystemChange_(time.getHours())),
/* 时 (12小时制) */
"mm": _checkTime_(time.getMinutes()),
/* 分 */
"ss": _checkTime_(time.getSeconds()),
/* 秒 */
};
Object.keys(timeRegexp).forEach(function (key) {
var replaecRegexp = new RegExp(key, "g");
types = types.replace(replaecRegexp, timeRegexp[key]);
});
return text;
},
/*
* @description 【手机】检测点击的地方是否在该元素区域内
* @param {object} obj - 需要检测的DOM元素
* @return {boolean} - 返回true或false
* @example Utils.checkClickInDOM(document.querySelector(".xxx"));
* @exampleResult false
*/
Utils.checkClickInDOM = (obj) => {
if (typeof obj !== "object") {
throw "参数 obj 类型必须为object类型";
}
var x = Number(window.event.clientX) /* 鼠标相对屏幕横坐标 */
var y = Number(window.event.clientY) /* 鼠标相对屏幕纵坐标 */
var obj_x_left = Number(obj.getBoundingClientRect().left) /* obj相对屏幕的横坐标 */
var obj_x_right = Number(
obj.getBoundingClientRect().left + obj.clientWidth
) /* obj相对屏幕的横坐标+width */
var obj_y_bottom = Number(
obj.getBoundingClientRect().top + obj.clientHeight
) /* obj相对屏幕的纵坐标+height */
var obj_y_top = Number(obj.getBoundingClientRect().top) /* obj相对屏幕的纵坐标 */
if ((x >= obj_x_left && x <= obj_x_right && y >= obj_y_top && y <= obj_y_bottom) || obj.outerHTML.indexOf(window.event.target.innerHTML) != -1) {
return true
} else {
return false
}
};
/*
* @description 同步执行延时函数
* @param {object|string} fnStr - 需要延时的函数或字符串格式的函数
* @param {number} delayTime - 需要检测的DOM元素
* @return {All|无返回值} - 返回自定义类型数据或者无返回
* @example await Utils.asyncSetTimeOut(xxxFunction, 2500);
* @exampleResult xxx
* @example await Utils.asyncSetTimeOut("()=>{console.log(12345)}", 2500);
* @exampleResult 无返回值
*/
Utils.asyncSetTimeOut = (fnStr, delayTime) => {
if (typeof fnStr !== "function" && typeof fnStr !== "string") {
throw "参数 fnStr 类型必须为function类型或者string类型"
};
if (typeof delayTime !== "number") {
throw "参数 delayTime 类型必须为number类型"
};
return new Promise(res => {
setTimeout(() => {
res(Utils.tryCatch(fnStr));
}, delayTime);
})
};
/*
* @description 同步执行foreach函数,遍历数组
* @param {object} arrayData - 需要遍历的数组
* @param {function} handleDataFunction - 对该数组进行操作的函数,该函数的参数为数组格式的参数,[数组下标,数组项]
* @return 无返回值
* @example await Utils.asyncArrayForEach([1,2,3],xxxFunction);
*/
Utils.asyncArrayForEach = (arrayData, handleDataFunction) => {
if (typeof arrayData !== "object") {
throw "参数 arrayData 类型必须为object类型"
}
if (typeof handleDataFunction !== "object" && typeof handleDataFunction !== "string") {
throw "参数 handleDataFunction 类型必须为object或者string类型"
}
return Promise.all(
Array.from(arrayData).map(async (item, index) => {
await Utils.tryCatch(handleDataFunction, [index, item]);
})
);
};
/*
* @description 同步延迟xxx毫秒
* @param {number} delayTime - 需要遍历的数组
* @return {无返回值}
* @example await Utils.sleep(2500); - 同步延时2500毫秒
*/
Utils.sleep = (delayTime) => {
if (typeof delayTime !== "number") {
throw "参数 delayTime 类型必须为number类型"
}
return new Promise(res => {
setTimeout(() => {
res();
}, delayTime);
})
};
/*
* @description 注册(不可用)全局函数Cookies
* @function Cookies.get("key")
* @param {string|number} key - 需要获取的cookie的key
* @return {string} 获取到的cookie值或者为空
* @function Cookies.set("key","value",8400);
* @param {string|number} key - 需要设置的cookie的key
* @param {All} key - 需要设置的cookie的value
* @param {number} time - 需要设置的cookie的过期时间
* @return 无返回值
* @example Utils.registerWindowCookies();
* Cookies.get("xxxx");
*/
Utils.registerWindowCookies = () => {
/*! js-cookie v3.0.1 | MIT */
(function (global, factory) {
typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() :
typeof define === 'function' && define.amd ? define(factory) :
(global = global || self, (function () {
var current = global.Cookies;
var exports = global.Cookies = factory();
exports.noConflict = function () {
global.Cookies = current;
return exports;
};
}()));
}(this, (function () {
'use strict';
/* eslint-disable no-var */
function assign(target) {
for (var i = 1; i < arguments.length; i++) {
var source = arguments[i];
for (var key in source) {
target[key] = source[key];
}
}
return target
}
/* eslint-enable no-var */
/* eslint-disable no-var */
var defaultConverter = {
read: function (value) {
if (value[0] === '"') {
value = value.slice(1, -1);
}
return value.replace(/(%[\dA-F]{2})+/gi, decodeURIComponent)
},
write: function (value) {
return encodeURIComponent(value).replace(
/%(2[346BF]|3[AC-F]|40|5[BDE]|60|7[BCD])/g,
decodeURIComponent
)
}
};
/* eslint-enable no-var */
/* eslint-disable no-var */
function init(converter, defaultAttributes) {
function set(key, value, attributes) {
if (typeof document === 'undefined') {
return
}
attributes = assign({}, defaultAttributes, attributes);
if (typeof attributes.expires === 'number') {
attributes.expires = new Date(Date.now() + attributes.expires * 864e5);
}
if (attributes.expires) {
attributes.expires = attributes.expires.toUTCString();
}
key = encodeURIComponent(key)
.replace(/%(2[346B]|5E|60|7C)/g, decodeURIComponent)
.replace(/[()]/g, escape);
var stringifiedAttributes = '';
for (var attributeName in attributes) {
if (!attributes[attributeName]) {
continue
}
stringifiedAttributes += '; ' + attributeName;
if (attributes[attributeName] === true) {
continue
}
/* Considers RFC 6265 section 5.2:
...
3. If the remaining unparsed-attributes contains a %x3B (";")
character:
Consume the characters of the unparsed-attributes up to,
not including, the first %x3B (";") character.
... */
stringifiedAttributes += '=' + attributes[attributeName].split(';')[0];
}
return (document.cookie =
key + '=' + converter.write(value, key) + stringifiedAttributes)
}
function get(key) {
if (typeof document === 'undefined' || (arguments.length && !key)) {
return
}
/* To prevent the for loop in the first place assign an empty array
in case there are no cookies at all. */
var cookies = document.cookie ? document.cookie.split('; ') : [];
var jar = {};
for (var i = 0; i < cookies.length; i++) {
var parts = cookies[i].split('=');
var value = parts.slice(1).join('=');
try {
var foundKey = decodeURIComponent(parts[0]);
jar[foundKey] = converter.read(value, foundKey);
if (key === foundKey) {
break
}
} catch (e) {}
}
return key ? jar[key] : jar
}
return Object.create({
set: set,
get: get,
remove: function (key, attributes) {
set(
key,
'',
assign({}, attributes, {
expires: -1
})
);
},
withAttributes: function (attributes) {
return init(this.converter, assign({}, this.attributes, attributes))
},
withConverter: function (converter) {
return init(assign({}, this.converter, converter), this.attributes)
}
}, {
attributes: {
value: Object.freeze(defaultAttributes)
},
converter: {
value: Object.freeze(converter)
}
})
}
var api = init(defaultConverter, {
path: '/'
});
/* eslint-enable no-var */
return api;
})))
},
/*
* @description base64转blob
* @param {string} dataurl - base64的数据
* @return {string} blob的链接
* @example Utils.base64ToBlob("data:image/jpeg;base64,.....");
* @exampleResult blob://xxxxxxx
*/
Utils.base64ToBlob = (dataurl) => {
if (typeof dataurl !== "string") {
throw "参数 dataurl 类型必须为string类型";
}
var arr = dataurl.split(','),
mime = arr[0].match(/:(.*?);/)[1],
bstr = atob(arr[1]),
n = bstr.length,
u8arr = new Uint8Array(n);
while (n--) {
u8arr[n] = bstr.charCodeAt(n);
}
return new Blob([u8arr], {
type: mime
});
},
/*
* @description base64转File对象
* @param {string} dataurl - base64的数据
* @return {string} blob的链接
* @example Utils.base64ToFile("data:image/jpeg;base64,.....");
* @exampleResult object
*/
Utils.base64ToFile = (dataurl, fileName) => {
if (typeof dataurl !== "string") {
throw "参数 dataurl 类型必须为string类型";
}
if (typeof fileName !== "string") {
throw "参数 fileName 类型必须为string类型";
}
var arr = dataurl.split(','),
mime = arr[0].match(/:(.*?);/)[1],
bstr = atob(arr[1]),
n = bstr.length,
u8arr = new Uint8Array(n);
while (n--) {
u8arr[n] = bstr.charCodeAt(n);
}
return new File([u8arr], fileName, {
type: mime
});
};
/*
* @description blob转File对象
* @param {string} theBlob - 需要转换的blob的链接
* @param {string} fileName - 转换成的File对象的文件名称
* @return {object} File对象
* @example Utils.blobToFile("blob://xxxxx");
* @exampleResult object
*/
Utils.blobToFile = (theBlob, fileName) => {
if (typeof theBlob !== "string") {
throw "参数 theBlob 类型必须为string类型";
}
if (typeof fileName !== "string") {
throw "参数 fileName 类型必须为string类型";
}
theBlob.lastModifiedDate = new Date();
theBlob.name = fileName;
return theBlob;
},
/*
* @description 同步File对象转base64
* @param {object} file - 需要转换的File对象
* @return {string} base64格式的数据
* @example await Utils.asyncFileToBase64(object);
* @exampleResult data:image/jpeg:base64/,xxxxxx
*/
Utils.asyncFileToBase64 = (file) => {
var reader = new FileReader();
reader.readAsDataURL(file);
return new Promise(res => {
reader.onload = function (e) {
res(e.target.result);
}
})
};
/*
* @description 下载base64格式的数据
* @param {string} base64Content - 需要转换的base64数据
* @param {string} fileName - 需要保存的文件名
* @example Utils.downloadBase64("data:image/jpeg:base64/,xxxxxx");
*/
Utils.downloadBase64 = (base64Content, fileName) => {
var aLink = document.createElement('a');
var blob = Utils.base64ToBlob(base64Content);
var evt = document.createEvent('HTMLEvents');
evt.initEvent('click', true, true) // initEvent 不加后两个参数在FF下会报错 事件类型,是否冒泡,是否阻止浏览器的默认行为
aLink.download = fileName;
aLink.href = URL.createObjectURL(blob);
aLink.click();
};
/*
* @description 判断是否是手机访问
* @return {boolean} - 返回如果是手机true,否则false
* @example Utils.isPhone();
* @exampleResult true
*/
Utils.isPhone = () => {
return Boolean(/(iPhone|iPad|iPod|iOS|Android)/i.test(navigator.userAgent));
};
/*
* @description 判断dz论坛是否是手机端显示
* @return {boolean} - 返回如果是手机端显示true,否则false
* @example Utils.discuzEnvIsMobile();
* @exampleResult true
*/
Utils.discuzEnvIsMobile = () => {
var _unsafeWindow_ = window;
if (typeof unsafeWindow !== "undefined") {
_unsafeWindow_ = unsafeWindow;
};
return _unsafeWindow_.$.hasOwnProperty("fn");
};
/*
* @description 自定义字典,用于new
* @example new let dictionary = Utils.Dictionary();
* @example dictionary.set("xxx","xxx");
* @example dictionary.get("xxx");
* @example dictionary.has("xxx");
*/
Utils.Dictionary = function () {
this.items = {};
//检查是否有某一个键
this.has = function (key) {
return this.items.hasOwnProperty(key);
}
//为字典添加某一个值
this.set = function (key, val) {
this.items[key] = val;
}
//删除某一个键
this.delete = function (key) {
if (this.has(key)) {
delete this.items[key];
return true;
}
return false;
}
//查找某一特定项
this.get = function (key) {
return this.has(key) ? this.items[key] : undefined;
}
//返回字典中的所有值
this.values = function () {
var res = [];
for (var prop in this.items) {
if (this.has(prop)) {
res.push(this.items[prop]);
}
}
return res;
}
//清空字典
this.clear = function () {
this.items = {};
}
//获取字典的长度
this.size = function () {
return Object.keys(this.items).length;
}
//获取字典所有的键
this.keys = function () {
return Object.keys(this.items);
}
//返回字典本身
this.getItems = function () {
return this.items;
}
};