ng-cw-v12
Version:
Angular UI Component Library
871 lines • 122 kB
JavaScript
import { isPlatformBrowser } from '@angular/common';
import { Inject, Injectable, PLATFORM_ID } from '@angular/core';
import { Subject } from 'rxjs';
import { debounceTime, throttleTime } from 'rxjs/operators';
import * as i0 from "@angular/core";
export class NcCommonService {
constructor(platformId, rendererFactory) {
this.platformId = platformId;
this.rendererFactory = rendererFactory;
// ---------------------经纬度---------------------
this.x_PI = 3.14159265358979324 * 3000.0 / 180.0;
this.PI = 3.1415926535897932384626;
this.a = 6378245.0;
this.ee = 0.00669342162296594323;
// ---------------------节流、防抖---------------------
this.debounceTasks = new Map();
this.throttleTasks = new Map();
// ---------------------消息提示---------------------
this.fullLoadingElement = null;
this.fullLoadingKeyframesStyle = null;
// ---------------------调试---------------------
/**
* 美化控制台打印(log info error warning success)
*/
this.console = {
log: (textOrTitle, content) => {
const title = !content ? 'Log' : textOrTitle;
const text = !content ? textOrTitle : content;
this.prettyPrint(title, text, '#909399');
},
info: (textOrTitle, content) => {
const title = !content ? 'Info' : textOrTitle;
const text = !content ? textOrTitle : content;
this.prettyPrint(title, text, '#40a9ff');
},
error: (textOrTitle, content) => {
const title = !content ? 'Error' : textOrTitle;
const text = !content ? textOrTitle : content;
this.prettyPrint(title, text, '#F56C6C');
},
warning: (textOrTitle, content) => {
const title = !content ? 'Warning' : textOrTitle;
const text = !content ? textOrTitle : content;
this.prettyPrint(title, text, '#E6A23C');
},
success: (textOrTitle, content) => {
const title = !content ? 'Success' : textOrTitle;
const text = !content ? textOrTitle : content;
this.prettyPrint(title, text, '#67C23A');
}
};
// 性能计时器
this.timers = {};
this.isBrowser = isPlatformBrowser(this.platformId);
this.renderer = this.rendererFactory.createRenderer(null, null);
}
// ---------------------数字类---------------------
/**
* 精确加法
* @param value1 第一个加数
* @param value2 第二个加数
* @returns 两数之和
*/
mathAdd(value1, value2) {
// 将浮点数转换为字符串
let aStr = value1.toString();
let bStr = value2.toString();
// 找到小数点后的位置
let aDecimals = (aStr.split('.')[1] || '').length;
let bDecimals = (bStr.split('.')[1] || '').length;
// 找到最大的小数位数
let maxDecimals = Math.max(aDecimals, bDecimals);
// 将浮点数转换为整数
let aInt = Math.round(value1 * Math.pow(10, maxDecimals));
let bInt = Math.round(value2 * Math.pow(10, maxDecimals));
// 进行整数加法
let resultInt = aInt + bInt;
// 将结果转换回浮点数
return resultInt / Math.pow(10, maxDecimals);
}
/**
* 精确减法
* @param value1 被减数
* @param value2 减数
* @returns 两数之差
*/
mathSubtract(value1, value2) {
// 将浮点数转换为字符串
let aStr = value1.toString();
let bStr = value2.toString();
// 找到小数点后的位置
let aDecimals = (aStr.split('.')[1] || '').length;
let bDecimals = (bStr.split('.')[1] || '').length;
// 找到最大的小数位数
let maxDecimals = Math.max(aDecimals, bDecimals);
// 将浮点数转换为整数
let aInt = Math.round(value1 * Math.pow(10, maxDecimals));
let bInt = Math.round(value2 * Math.pow(10, maxDecimals));
// 进行整数减法
let resultInt = aInt - bInt;
// 将结果转换回浮点数
return resultInt / Math.pow(10, maxDecimals);
}
/**
* 精确乘法
* @param value1 第一个乘数
* @param value2 第二个乘数
* @returns 两数之积
*/
mathMultiply(value1, value2) {
// 将浮点数转换为字符串
let aStr = value1.toString();
let bStr = value2.toString();
// 找到小数点后的位置
let aDecimals = (aStr.split('.')[1] || '').length;
let bDecimals = (bStr.split('.')[1] || '').length;
// 将浮点数转换为整数
let aInt = parseInt(aStr.replace('.', ''));
let bInt = parseInt(bStr.replace('.', ''));
// 进行整数乘法
let resultInt = aInt * bInt;
// 计算最终的小数位数
let totalDecimals = aDecimals + bDecimals;
// 将结果转换回浮点数
return resultInt / Math.pow(10, totalDecimals);
}
/**
* 精确除法
* @param value1 被除数
* @param value2 除数
* @returns 两数之商
*/
mathDivide(value1, value2) {
// 将浮点数转换为字符串
let aStr = value1.toString();
let bStr = value2.toString();
// 找到小数点后的位置
let aDecimals = (aStr.split('.')[1] || '').length;
let bDecimals = (bStr.split('.')[1] || '').length;
// 找到最大的小数位数
let maxDecimals = Math.max(aDecimals, bDecimals);
// 将浮点数转换为整数
let aInt = Math.round(value1 * Math.pow(10, maxDecimals));
let bInt = Math.round(value2 * Math.pow(10, maxDecimals));
// 进行整数除法并直接返回结果
return aInt / bInt;
}
/**
* 保留指定小数位数
* @param num 需要处理的数值
* @param len 要保留的小数位数
* @returns 处理后的数值,保留指定小数位数
*/
retainDecimal(num, len) {
const n = Math.pow(10, len);
return Math.round(num * n) / n;
}
/**
* 保留指定小数位数的百分比
* @param num 需要处理的数值
* @param len 要保留的小数位数
* @returns 处理后的百分比值,保留指定小数位数
*/
retainPercentDecimal(num, len) {
const n = Math.pow(10, len + 2);
return this.mathMultiply(Math.round(num * n) / n, 100);
}
// ---------------------存储---------------------
/**
* 设置Cookie
* @param key Cookie的键
* @param value Cookie的值
* @param ttl Cookie的生存时间(毫秒)
*/
setCookie(key, value, ttl) {
const expires = new Date(Date.now() + ttl).toUTCString();
document.cookie = `${key}=${encodeURIComponent(value)};expires=${expires};path=/`;
}
/**
* 获取Cookie
* @param key Cookie的键
* @returns Cookie的值,如果不存在则返回null
*/
getCookie(key) {
const match = document.cookie.match(new RegExp('(^| )' + key + '=([^;]+)'));
return match ? decodeURIComponent(match[2]) : null;
}
/**
* 删除指定的Cookie
* @param key 要删除的Cookie的键
*/
removeCookie(key) {
document.cookie = `${key}=;expires=Thu, 01 Jan 1970 00:00:00 GMT;path=/`;
}
/**
* 清除所有Cookie
*/
clearCookie() {
document.cookie.split(";").forEach(c => {
document.cookie = c.replace(/^ +/, "").replace(/=.*/, "=;expires=Thu, 01 Jan 1970 00:00:00 GMT;path=/");
});
}
/**
* 设置LocalStorage项
* @param key LocalStorage的键
* @param value LocalStorage的值
* @param ttl 可选的生存时间(毫秒)
*/
setLocalStorage(key, value, ttl) {
const item = { value, expiry: ttl ? Date.now() + ttl : null };
localStorage.setItem(key, JSON.stringify(item));
}
/**
* 获取LocalStorage项
* @param key LocalStorage的键
* @returns LocalStorage的值,如果不存在或已过期则返回null
*/
getLocalStorage(key) {
const itemStr = localStorage.getItem(key);
if (!itemStr)
return null;
const item = JSON.parse(itemStr);
if (item.expiry && Date.now() > item.expiry) {
localStorage.removeItem(key);
return null;
}
return item.value;
}
/**
* 删除指定的LocalStorage项
* @param key 要删除的LocalStorage项的键
*/
removeLocalStorage(key) {
localStorage.removeItem(key);
}
/**
* 清除所有LocalStorage项
*/
clearLocalStorage() {
localStorage.clear();
}
/**
* 设置SessionStorage项
* @param key SessionStorage的键
* @param value SessionStorage的值
*/
setSessionStorage(key, value) {
sessionStorage.setItem(key, JSON.stringify(value));
}
/**
* 获取SessionStorage项
* @param key SessionStorage的键
* @returns SessionStorage的值,如果不存在则返回null
*/
getSessionStorage(key) {
const item = sessionStorage.getItem(key);
return item ? JSON.parse(item) : null;
}
/**
* 删除指定的SessionStorage项
* @param key 要删除的SessionStorage项的键
*/
removeSessionStorage(key) {
sessionStorage.removeItem(key);
}
/**
* 清除所有SessionStorage项
*/
clearSessionStorage() {
sessionStorage.clear();
}
// ---------------------日期类---------------------
/**
* 格式化时间
* @param format 格式化模板,如 'yyyy-MM-dd HH:mm:ss',注意MM为月份、mm为分钟
* @param dateInput 可选。要格式化的日期,可以是Date对象、时间戳(number)或日期字符串,默认为当前时间
* @returns 格式化后的日期字符串
*/
formatDate(format, dateInput) {
if (!format) {
return '';
}
let date;
if (!dateInput) {
date = new Date();
}
else if (dateInput instanceof Date) {
date = dateInput;
}
else {
date = new Date(dateInput);
}
// 验证日期是否有效
if (isNaN(date.getTime())) {
console.warn('Invalid date input provided to formatDate');
return '';
}
const year = date.getFullYear().toString();
const month = (date.getMonth() + 1).toString().padStart(2, '0');
const day = (date.getDate()).toString().padStart(2, '0');
const hours = (date.getHours()).toString().padStart(2, '0');
const minutes = (date.getMinutes()).toString().padStart(2, '0');
const seconds = (date.getSeconds()).toString().padStart(2, '0');
return format
.replace('yyyy', year)
.replace('MM', month)
.replace('dd', day)
.replace('HH', hours)
.replace('mm', minutes)
.replace('ss', seconds);
}
/**
* 获取两日期间的所有日期
* @param startDate 开始日期
* @param endDate 结束日期
* @returns 日期数组
*/
getRangeDate(startDate, endDate) {
let datesArray = [];
let currentDate = new Date(startDate);
while (currentDate <= endDate) {
datesArray.push(new Date(currentDate));
currentDate.setDate(currentDate.getDate() + 1);
}
return datesArray;
}
/**
* 获取两日期间的天数
* @param startDate 开始日期
* @param endDate 结束日期
* @returns 天数
*/
getDaysBetween(startDate, endDate) {
const oneDay = 24 * 60 * 60 * 1000;
return Math.round(Math.abs((startDate.getTime() - endDate.getTime()) / oneDay));
}
// ---------------------数组、对象---------------------
/**
* 数组去重
* @param array 要去重的数组
* @param keyFn 可选的函数,用于从每个数组项中提取用于比较的键,例如:item => item.id
* @returns T[]
*/
uniqueArray(array, keyFn) {
if (!keyFn) {
return Array.from(new Set(array));
}
const seen = new Set();
return array.filter(item => {
const key = keyFn(item);
if (seen.has(key)) {
return false;
}
seen.add(key);
return true;
});
}
/**
* 数组排序
* @param array 要排序的数组
* @param sort 指定排序顺序,类型:NcOrderType,'asc' 为升序,'desc' 为降序
* @param keyFn 可选。可以是对象的键名或一个函数,用于从数组项中提取排序值,例如:'age'或 item => item.name.length
* @returns T[]
*/
sortArray(array, sort, key) {
return [...array].sort((a, b) => {
let valueA;
let valueB;
if (typeof key === 'function') {
valueA = key(a);
valueB = key(b);
}
else if (key) {
valueA = a[key];
valueB = b[key];
}
else {
valueA = a;
valueB = b;
}
if (valueA === valueB)
return 0;
if (typeof valueA === 'string' && typeof valueB === 'string') {
return sort === 'asc'
? valueA.localeCompare(valueB)
: valueB.localeCompare(valueA);
}
return sort === 'asc'
? (valueA < valueB ? -1 : 1)
: (valueB < valueA ? -1 : 1);
});
}
/**
* 判断对象是否为空
* @param obj
* @returns boolean
*/
isObjectEmpty(obj) {
return Object.keys(obj).length === 0;
}
/**
* 百度坐标系 (BD-09) 与火星坐标系 (GCJ-02) 的转换
* 即百度 转 谷歌、高德
* @param lng 经度
* @param lat 纬度
* @returns [lng, lat]
*/
bd09togcj02(lng, lat) {
var x_pi = 3.14159265358979324 * 3000.0 / 180.0;
var x = lng - 0.0065;
var y = lat - 0.006;
var z = Math.sqrt(x * x + y * y) - 0.00002 * Math.sin(y * x_pi);
var theta = Math.atan2(y, x) - 0.000003 * Math.cos(x * x_pi);
var gg_lng = z * Math.cos(theta);
var gg_lat = z * Math.sin(theta);
return [gg_lng, gg_lat];
}
/**
* 火星坐标系 (GCJ-02) 与百度坐标系 (BD-09) 的转换
* 即谷歌、高德 转 百度
* @param lng 经度
* @param lat 纬度
* @returns [lng, lat]
*/
gcj02tobd09(lng, lat) {
var z = Math.sqrt(lng * lng + lat * lat) + 0.00002 * Math.sin(lat * this.x_PI);
var theta = Math.atan2(lat, lng) + 0.000003 * Math.cos(lng * this.x_PI);
var bd_lng = z * Math.cos(theta) + 0.0065;
var bd_lat = z * Math.sin(theta) + 0.006;
return [bd_lng, bd_lat];
}
/**
* WGS84转火星坐标系 (GCJ-02)
* 即WGS84 转 谷歌、高德
* @param lng 经度
* @param lat 纬度
* @returns [lng, lat]
*/
wgs84togcj02(lng, lat) {
if (this.out_of_china(lng, lat)) {
return [lng, lat];
}
else {
var dlat = this.transformlat(lng - 105.0, lat - 35.0);
var dlng = this.transformlng(lng - 105.0, lat - 35.0);
var radlat = lat / 180.0 * this.PI;
var magic = Math.sin(radlat);
magic = 1 - this.ee * magic * magic;
var sqrtmagic = Math.sqrt(magic);
dlat = (dlat * 180.0) / ((this.a * (1 - this.ee)) / (magic * sqrtmagic) * this.PI);
dlng = (dlng * 180.0) / (this.a / sqrtmagic * Math.cos(radlat) * this.PI);
var mglat = lat + dlat;
var mglng = lng + dlng;
return [mglng, mglat];
}
}
/**
* 火星坐标系 (GCJ-02)转WGS84
* 即谷歌、高德 转 WGS84
* @param lng 经度
* @param lat 纬度
* @returns [lng, lat]
*/
gcj02towgs84(lng, lat) {
if (this.out_of_china(lng, lat)) {
return [lng, lat];
}
else {
var dlat = this.transformlat(lng - 105.0, lat - 35.0);
var dlng = this.transformlng(lng - 105.0, lat - 35.0);
var radlat = lat / 180.0 * this.PI;
var magic = Math.sin(radlat);
magic = 1 - this.ee * magic * magic;
var sqrtmagic = Math.sqrt(magic);
dlat = (dlat * 180.0) / ((this.a * (1 - this.ee)) / (magic * sqrtmagic) * this.PI);
dlng = (dlng * 180.0) / (this.a / sqrtmagic * Math.cos(radlat) * this.PI);
let mglat = lat + dlat;
let mglng = lng + dlng;
return [lng * 2 - mglng, lat * 2 - mglat];
}
}
transformlat(lng, lat) {
var ret = -100.0 + 2.0 * lng + 3.0 * lat + 0.2 * lat * lat + 0.1 * lng * lat + 0.2 * Math.sqrt(Math.abs(lng));
ret += (20.0 * Math.sin(6.0 * lng * this.PI) + 20.0 * Math.sin(2.0 * lng * this.PI)) * 2.0 / 3.0;
ret += (20.0 * Math.sin(lat * this.PI) + 40.0 * Math.sin(lat / 3.0 * this.PI)) * 2.0 / 3.0;
ret += (160.0 * Math.sin(lat / 12.0 * this.PI) + 320 * Math.sin(lat * this.PI / 30.0)) * 2.0 / 3.0;
return ret;
}
transformlng(lng, lat) {
var ret = 300.0 + lng + 2.0 * lat + 0.1 * lng * lng + 0.1 * lng * lat + 0.1 * Math.sqrt(Math.abs(lng));
ret += (20.0 * Math.sin(6.0 * lng * this.PI) + 20.0 * Math.sin(2.0 * lng * this.PI)) * 2.0 / 3.0;
ret += (20.0 * Math.sin(lng * this.PI) + 40.0 * Math.sin(lng / 3.0 * this.PI)) * 2.0 / 3.0;
ret += (150.0 * Math.sin(lng / 12.0 * this.PI) + 300.0 * Math.sin(lng / 30.0 * this.PI)) * 2.0 / 3.0;
return ret;
}
/**
* 判断是否在国内,不在国内则不做偏移
*/
out_of_china(lng, lat) {
return (lng < 72.004 || lng > 137.8347) || ((lat < 0.8293 || lat > 55.8271) || false);
}
/**
* 小数形式经纬度转度分秒形式(秒保留3位小数)
* @param digital 109.86330555555556
* @returns degrees '109°51′47.9″'
*/
digitalToDegrees(digital) {
let digitalString = digital.toString();
let index1 = digitalString.indexOf('.');
let du = index1 < 0 ? Number(digitalString) : Number(digitalString.substring(0, index1)); //109
let fen = 0;
let miao = 0;
if (index1 > 0) {
let strFen = Number("0" + digitalString.substring(index1)); //0.86330555555556
let strFenString = (strFen * 60).toString(); //'51.7983333333336'
let index2 = strFenString.indexOf('.');
if (index2 > 0) {
fen = Number(strFenString.substring(0, index2)); //51
let strMiao = Number("0" + strFenString.substring(index2)); //0.7983333333336
miao = Number((strMiao * 60).toFixed(3)); //47.900000000016 47.9
}
else {
fen = Number(strFenString);
}
}
return `${du}°${fen}′${miao}″`;
}
/**
* 度分秒形式经纬度转小数形式
* @param degrees '109°51′47.900000000016″'
* @returns digital 109.86330555555556
*/
degreesToDigital(degrees) {
let temp1 = degrees.split('°');
let temp2 = temp1[1].split('′');
let du = temp1[0];
let fen = temp2[0];
let miao = temp2[1].substring(0, temp2[1].length - 1);
return Number(du) + Number(fen) / 60 + Number(miao) / 3600;
}
/**
* 防抖(Debounce):适用于避免短时间内多次触发的场景,只有在事件停止触发后的一段时间才会执行。例如:搜索框输入,避免频繁的API请求。
* @param key 用于标识Subject的唯一键,不同防抖任务应使用不同的key,相同key的任务会共享首次设置的delay时间
* @param delay 防抖延迟时间(毫秒)
* @param fn 要防抖的函数
*/
debounce(key, delay, fn) {
let subject = this.debounceTasks.get(key);
if (!subject) {
subject = new Subject();
subject.pipe(debounceTime(delay)).subscribe(fnToExecute => {
fnToExecute();
});
this.debounceTasks.set(key, subject);
}
subject.next(fn);
}
/**
* 节流(Throttle):适用于限制事件在固定时间间隔内执行的场景,确保事件不会过于频繁地触发。例如:滚动页面时的事件处理,避免频繁的计算和渲染。
* @param key 用于标识Subject的唯一键,不同节流任务应使用不同的key,相同key的任务会共享首次设置的delay时间
* @param delay 节流延迟时间(毫秒)
* @param fn 要节流的函数
*/
throttle(key, delay, fn) {
let subject = this.throttleTasks.get(key);
if (!subject) {
subject = new Subject();
subject.pipe(throttleTime(delay)).subscribe(fnToExecute => {
fnToExecute();
});
this.throttleTasks.set(key, subject);
}
subject.next(fn);
}
/**
* 显示全屏加载中(全屏蒙版)
* @param content 可选。提示内容,默认:'加载中,请稍后...'
*/
showFullLoading(content = '加载中,请稍后...') {
if (this.fullLoadingElement) {
return;
}
this.fullLoadingElement = this.renderer.createElement('div');
this.renderer.addClass(this.fullLoadingElement, 'full-loading-container');
this.renderer.setStyle(this.fullLoadingElement, 'position', 'fixed');
this.renderer.setStyle(this.fullLoadingElement, 'top', '0');
this.renderer.setStyle(this.fullLoadingElement, 'left', '0');
this.renderer.setStyle(this.fullLoadingElement, 'width', '100%');
this.renderer.setStyle(this.fullLoadingElement, 'height', '100%');
this.renderer.setStyle(this.fullLoadingElement, 'background-color', 'rgba(0,0,0,0.5)');
this.renderer.setStyle(this.fullLoadingElement, 'display', 'flex');
this.renderer.setStyle(this.fullLoadingElement, 'flex-direction', 'column');
this.renderer.setStyle(this.fullLoadingElement, 'justify-content', 'center');
this.renderer.setStyle(this.fullLoadingElement, 'align-items', 'center');
this.renderer.setStyle(this.fullLoadingElement, 'z-index', '9999');
const spinner = this.renderer.createElement('div');
this.renderer.addClass(spinner, 'full-loading-spinner');
this.renderer.setStyle(spinner, 'border', '4px solid #f3f3f3');
this.renderer.setStyle(spinner, 'border-top', '4px solid #3498db');
this.renderer.setStyle(spinner, 'border-radius', '50%');
this.renderer.setStyle(spinner, 'width', '50px');
this.renderer.setStyle(spinner, 'height', '50px');
this.renderer.setStyle(spinner, 'animation', 'fullSpin 1s linear infinite');
const loadingText = this.renderer.createElement('div');
this.renderer.addClass(loadingText, 'full-loading-text');
this.renderer.setStyle(loadingText, 'color', 'white');
this.renderer.setStyle(loadingText, 'margin-top', '20px');
this.renderer.setStyle(loadingText, 'font-size', '18px');
this.renderer.setStyle(loadingText, 'letter-spacing', '1.5px');
this.renderer.appendChild(loadingText, this.renderer.createText(content));
const keyframes = `
@keyframes fullSpin {
0% { transform: rotate(0deg); }
100% { transform: rotate(360deg); }
}
`;
this.fullLoadingKeyframesStyle = this.renderer.createElement('style');
this.renderer.appendChild(this.fullLoadingKeyframesStyle, this.renderer.createText(keyframes));
this.renderer.appendChild(document.body, this.fullLoadingKeyframesStyle);
this.renderer.appendChild(this.fullLoadingElement, spinner);
if (content) {
this.renderer.appendChild(this.fullLoadingElement, loadingText);
}
this.renderer.appendChild(document.body, this.fullLoadingElement);
}
/**
* 移除全屏加载中(全屏蒙版)
*/
removeFullLoading() {
if (this.fullLoadingElement) {
this.renderer.removeChild(document.body, this.fullLoadingElement);
this.fullLoadingElement = null;
}
if (this.fullLoadingKeyframesStyle) {
this.renderer.removeChild(document.body, this.fullLoadingKeyframesStyle);
this.fullLoadingKeyframesStyle = null;
}
}
//美化打印
prettyPrint(title, content, color) {
console.log(`%c ${title} %c ${typeof content == 'object' ? '👇' : content} %c`, `background:${color};border:1px solid ${color}; padding: 1px; border-radius: 2px 0 0 2px; color: #fff;`, `border:1px solid ${color}; border-radius: 0 2px 2px 0; color: ${color};padding: 1px;`, 'background:transparent');
if (typeof content == 'object') {
console.table(content);
}
}
;
/**
* 开始性能计时器
* @param timerName 计时器名称
*/
startTimer(timerName) {
this.timers[timerName] = performance.now();
}
/**
* 结束性能计时器并返回持续时间
* @param timerName 计时器名称
* @returns 计时器持续时间(毫秒)
*/
endTimer(timerName) {
if (!this.timers[timerName]) {
console.warn(`计时器 "${timerName}" 不存在。`);
return 0;
}
const duration = performance.now() - this.timers[timerName];
delete this.timers[timerName];
return duration;
}
// ---------------------其他---------------------
/**
* 深克隆
* @param obj 被克隆对象
* @returns 克隆对象
*/
deepClone(obj, seen = new Map()) {
// Handle immutable types and functions
if (obj === null || typeof obj !== 'object') {
return obj;
}
// Handle circular references
if (seen.has(obj)) {
return seen.get(obj);
}
// Handle Date
if (obj instanceof Date) {
return new Date(obj.getTime());
}
// Handle RegExp
if (obj instanceof RegExp) {
const regExpClone = new RegExp(obj.source, obj.flags);
regExpClone.lastIndex = obj.lastIndex; // Preserve the lastIndex property
return regExpClone;
}
// Handle Array
if (Array.isArray(obj)) {
const arrClone = [];
seen.set(obj, arrClone);
for (const item of obj) {
arrClone.push(this.deepClone(item, seen));
}
return arrClone;
}
// Handle Set
if (obj instanceof Set) {
const setClone = new Set();
seen.set(obj, setClone);
for (const item of obj) {
setClone.add(this.deepClone(item, seen));
}
return setClone;
}
// Handle Map
if (obj instanceof Map) {
const mapClone = new Map();
seen.set(obj, mapClone);
for (const [key, value] of obj) {
mapClone.set(this.deepClone(key, seen), this.deepClone(value, seen));
}
return mapClone;
}
// Handle Object
const objClone = Object.create(Object.getPrototypeOf(obj));
seen.set(obj, objClone);
for (const key in obj) {
if (Object.prototype.hasOwnProperty.call(obj, key)) {
objClone[key] = this.deepClone(obj[key], seen);
}
}
return objClone;
}
/**
* 获取文件后缀
* @param filename string 文件名
* @returns extension
*/
getFileExtension(filename) {
if (!filename) {
return '';
}
const filenameArr = filename.split('.');
if (filenameArr.length == 0) {
return '';
}
else {
const extension = filenameArr.pop();
return extension.toLowerCase();
}
}
/**
* jsonp封装
* @param obj \{url: '', success: ()=> {}}
*/
jsonpFunction(obj) {
// 创建一个script标签;
var script = document.createElement("script");
// 给函数起名字,定义为全局函数;
var fnName = "jsonp" + new Date().getTime();
// window.aaa就是把aaa设置为全局变量!
window[fnName] = obj.success;
// 改变src,添加到head中
if (obj.url.includes('?')) {
script.src = obj.url + "&callback=" + fnName;
}
else {
script.src = obj.url + "?callback=" + fnName;
}
// 把script标签添加到head标签中,就会发送src的请求了
document.head.appendChild(script);
// 代码执行完毕,把script标签删除
script.onload = function () {
document.head.removeChild(script);
window[fnName] = undefined;
};
}
/**
* 生成随机颜色
* @returns HEX
*/
generateRandomColor() {
return '#' + Math.floor(Math.random() * 16777215).toString(16).padStart(6, '0');
}
/**
* 生成UUID
* @returns UUID
*/
generateUUID() {
return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, (c) => {
var r = Math.random() * 16 | 0, v = c == 'x' ? r : (r & 0x3 | 0x8);
return v.toString(16);
});
}
/**
* 验证密码强度(必须包含大、小写字母、数字、特殊字符至少三类,长度8-16位)
* @param password 待验证的密码
* @returns 密码是否符合要求
*/
passwordValidate(password) {
// 检查密码长度是否在8到16位之间
if (password.length < 8 || password.length > 16) {
return false;
}
// 定义正则表达式规则
let rC = {
lW: '[a-z]',
uW: '[A-Z]',
nW: '[0-9]',
sW: '[`~!@$%\^\&\(\)\-_\+=\{\}\[\]|\\:;\"\'<>,\.\?\/_]' // 特殊字符
};
/**
* 检查字符串是否匹配正则表达式
* @param str 待检查的字符串
* @param rStr 正则表达式字符串
* @returns 是否匹配
*/
function Reg(str, rStr) {
let reg = new RegExp(rStr);
return reg.test(str);
}
// 检查密码是否包含各种字符类型
let tR = {
l: Reg(password, rC.lW),
u: Reg(password, rC.uW),
n: Reg(password, rC.nW),
s: Reg(password, rC.sW) // 是否包含特殊字符
};
// 密码必须包含以下四种组合之一:
// 1. 小写字母 + 大写字母 + 数字
// 2. 小写字母 + 大写字母 + 特殊字符
// 3. 特殊字符 + 大写字母 + 数字
// 4. 特殊字符 + 小写字母 + 数字
return (tR.l && tR.u && tR.n) || (tR.l && tR.u && tR.s) || (tR.s && tR.u && tR.n) || (tR.s && tR.l && tR.n);
}
/**
* 复制到剪贴板
* @param text 待复制的内容
* @returns 复制是否成功
*/
copyToClipboard(text) {
try {
if (navigator.clipboard) {
//安全模式下(https localhost 127.0.0.1)
navigator.clipboard.writeText(text);
return true;
}
else {
//非安全模式
// 创建临时文本区域来复制纯文本
const textarea = document.createElement('textarea');
textarea.value = text;
textarea.style.position = 'absolute';
textarea.style.left = '-9999px';
document.body.appendChild(textarea);
textarea.select();
document.execCommand('copy');
document.body.removeChild(textarea);
return true;
}
}
catch (error) {
return false;
}
}
}
NcCommonService.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "12.1.5", ngImport: i0, type: NcCommonService, deps: [{ token: PLATFORM_ID }, { token: i0.RendererFactory2 }], target: i0.ɵɵFactoryTarget.Injectable });
NcCommonService.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "12.1.5", ngImport: i0, type: NcCommonService });
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "12.1.5", ngImport: i0, type: NcCommonService, decorators: [{
type: Injectable
}], ctorParameters: function () { return [{ type: Object, decorators: [{
type: Inject,
args: [PLATFORM_ID]
}] }, { type: i0.RendererFactory2 }]; } });
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY29tbW9uLnNlcnZpY2UuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi9wcm9qZWN0cy9jb21wb25lbnRzL2NvbW1vbi1zZXJ2aWNlL2NvbW1vbi5zZXJ2aWNlLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sRUFBRSxpQkFBaUIsRUFBRSxNQUFNLGlCQUFpQixDQUFDO0FBQ3BELE9BQU8sRUFBRSxNQUFNLEVBQUUsVUFBVSxFQUFFLFdBQVcsRUFBK0IsTUFBTSxlQUFlLENBQUM7QUFDN0YsT0FBTyxFQUFFLE9BQU8sRUFBRSxNQUFNLE1BQU0sQ0FBQztBQUMvQixPQUFPLEVBQUUsWUFBWSxFQUFFLFlBQVksRUFBRSxNQUFNLGdCQUFnQixDQUFDOztBQXNDNUQsTUFBTSxPQUFPLGVBQWU7SUFHeEIsWUFBeUMsVUFBa0IsRUFBVSxlQUFpQztRQUE3RCxlQUFVLEdBQVYsVUFBVSxDQUFRO1FBQVUsb0JBQWUsR0FBZixlQUFlLENBQWtCO1FBZ1p0RyxnREFBZ0Q7UUFFeEMsU0FBSSxHQUFHLG1CQUFtQixHQUFHLE1BQU0sR0FBRyxLQUFLLENBQUM7UUFDNUMsT0FBRSxHQUFHLHdCQUF3QixDQUFDO1FBQzlCLE1BQUMsR0FBRyxTQUFTLENBQUM7UUFDZCxPQUFFLEdBQUcsc0JBQXNCLENBQUM7UUF3SnBDLGtEQUFrRDtRQUUxQyxrQkFBYSxHQUFtQyxJQUFJLEdBQUcsRUFBRSxDQUFDO1FBQzFELGtCQUFhLEdBQW1DLElBQUksR0FBRyxFQUFFLENBQUM7UUF5Q2xFLGlEQUFpRDtRQUV6Qyx1QkFBa0IsR0FBdUIsSUFBSSxDQUFDO1FBQzlDLDhCQUF5QixHQUF1QixJQUFJLENBQUM7UUEwRTdELCtDQUErQztRQUUvQzs7VUFFRTtRQUNGLFlBQU8sR0FBa0I7WUFDckIsR0FBRyxFQUFFLENBQUMsV0FBZ0IsRUFBRSxPQUFZLEVBQUUsRUFBRTtnQkFDcEMsTUFBTSxLQUFLLEdBQUcsQ0FBQyxPQUFPLENBQUMsQ0FBQyxD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