mofang-mopai-utils
Version:
Use it in Mopai system
325 lines (307 loc) • 8.36 kB
text/typescript
/**
* 魔方魔派系统工具包
*/
import MofangMopaiCalculator from "./mofang-mopai-calculator"
import MofangCalculatorV2 from "./mofang-calculator-v2"
/**
* 深拷贝
* @param data { any }
* @returns any
*/
function deepCopy<T>(data: T): T {
let d: any
if (typeof data === 'object') {
if (Array.isArray(data)) {
d = []
for (let i = 0, len = data.length; i < len; i++) d[i] = deepCopy(data[i])
} else if (data === null) {
d = null
} else if (data.constructor === RegExp) {
d = data
} else if (Object.keys(data).length) {
d = {}
for (const key in data) {
const k = key
d[k] = deepCopy(data[k])
}
} else {
d = data
}
} else {
d = data
}
return d
}
/**
* 防抖
* @param fn {Function}
* @param delay {number}
* @returns {Function}
*/
function debounce<T = Function>(fn: T, delay: number = 200): T {
let timer: ReturnType<typeof setTimeout>
if (typeof fn !== 'function') {
throw new TypeError('类型错误,传入函数不是一个方法')
}
return function (this: unknown) {
const args = arguments
clearTimeout(timer)
timer = setTimeout(() => {
fn.apply(this, args)
}, delay)
} as any
}
/**
* 节流
* @param fn - The function to be throttled.
* @param delay - The number of milliseconds to delay.
* @returns A new throttled function.
*/
function throttle<T = Function>(fn: T, delay: number = 200): T {
let isRunning: boolean = false
if (typeof fn !== 'function') {
throw new TypeError('类型错误,传入函数不是一个方法')
}
return function (this: unknown) {
const args = arguments
if (isRunning) return
isRunning = true
fn.apply(this, args)
setTimeout(() => {
isRunning = false
}, delay)
} as any
}
/**
* 去重
* Returns a new array without duplicate elements.
* @param arr - The array to remove duplicates from.
* @returns A new array without duplicate elements.
*/
function unique<T>(arr: []): T {
if (!Array.isArray(arr)) {
throw new TypeError('类型错误,传入参数不是一个Array')
}
let list: any[] = []
for (const value of arr) {
if (typeof value === "object" && value !== null) {
if (list.every((v) => JSON.stringify(v) !== JSON.stringify(value))) {
list.push(value);
}
} else if (value !== undefined && list.indexOf(value) === -1) {
list.push(value);
}
}
return list as T
}
/**
* Flattens an array of arrays into a single level array.
*
* @param arr - the array to flatten
* @returns a new array with all the elements of the original array, regardless of their nesting level
*/
function flat<T>(arr: T): T {
if (!Array.isArray(arr)) {
throw new TypeError('类型错误,传入参数不是一个Array')
}
return arr.reduce((prev, cur: any) => {
return prev.concat(Array.isArray(cur) ? flat(cur) : cur)
}, [])
}
/**
* 过滤掉object中的无效键值
* @param data object
* @returns object
*/
function getValidObject<T = Record<string, any>>(data: T): T {
if (typeof data !== 'object' && Object.prototype.toString.call(data) !== '[object Object]') {
throw new TypeError('类型错误,传入参数不是一个Object')
}
let obj = {} as T
for (const key in data) {
const value: any = data[key]
let isEnable = false
if (typeof value === 'object' && value !== null) {
isEnable = isEmpty(value)
} else {
isEnable = value || value === 0
}
isEnable && (obj[key] = value)
}
return obj
}
/**
* 基于前端的计算器
* @param formula { string } 计算公式
* @returns number 计算结果
*
* @example
* calc('1.2+0.3*0.02+4') // return 5.206
*/
function calc(formula: string): number{
const ca = new MofangMopaiCalculator(formula)
return ca.get()
}
function calcV2(number1: number, number2: number, method: string): number {
return MofangCalculatorV2(number1, number2, method)
}
function getUUID(len: number = 32): string {
const chars = Array.from('0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz')
const uuid: string[] = []
const radix = len
for (let i = 0; i < len; i++) uuid[i] = chars[0 | Math.random() * radix]
return uuid.join('')
}
/**
* 判断Pbject或Array是否为空
* @param data { object | array }
* @returns boolean
*/
function isEmpty(data: Object): boolean {
if (Array.isArray(data)) {
return data.length === 0
} else {
return Object.keys(data).length === 0
}
}
function isNotEmpty(data: Object): boolean {
return !isEmpty(data)
}
/**
* 格式化数组分组
* @param arr
* @returns array
*/
function zip<T>(...args: any): T {
if (!args || !Array.isArray(args) || args.some(item => !Array.isArray(item))) {
throw new TypeError('类型错误,传入参数错误')
}
const resultList = [] as any[]
args.forEach((list: [], listIdx: number) => {
list.forEach((item: any, itemIdx: number) => {
if (!resultList[itemIdx]) resultList[itemIdx] = []
resultList[itemIdx][listIdx] = item
})
})
return resultList as T
}
function unzip<T>(...args: any): T {
if (!args || !Array.isArray(args) || args.some(item => !Array.isArray(item))) {
throw new TypeError('类型错误,传入参数错误')
}
let len = 0
const resultList = [] as any[]
args.forEach((list: [], listIdx: number) => {
if (len === 0) {
len = list.length
}
if (len !== list.length) {
throw new TypeError('they are not same length Array in list')
}
list.forEach((item: any, itemIdx: number) => {
if (!resultList[itemIdx]) resultList[itemIdx] = []
resultList[itemIdx][listIdx] = item
})
})
return resultList as T
}
/**
* 判断object|array中是否存在指定参数
* @param keyname { string }
* @param data { object | array }
* @returns boolean
*/
function isExist(keyname: string, data: Object): boolean {
if (Array.isArray(data)) {
return data.indexOf(keyname) > -1
} else {
const keys = Object.keys(data)
return keys.indexOf(keyname) > -1
}
}
/**
* 判断数据类型
* @param data { any }
* @returns string 数据的类型,小写
*/
function whichTypeOf(data: any): string {
if (typeof data === 'object') {
return Array.isArray(data) ? 'array' : Object.prototype.toString.call(data) === '[object Object]' ? 'object' : 'unknownType'
} else {
return typeof data
}
}
/**
* 动态置入script标签,引用js文件
* @param src { string } js文件链接
* @param cb { function } 状态回调
* @returns promise 状态回调
*/
function loadJs(src: string, cb?: Function): Promise<string> {
const script = document.createElement('script')
script.type = 'text/javascript'
script.src = src
document.getElementsByTagName('head')[0].appendChild(script)
return new Promise((resolve, rejects) => {
script.onload = () => {
cb?.('ok')
resolve('ok')
}
script.onerror = () => {
cb?.('error')
rejects('error')
}
})
}
const toolkit = {
deepCopy,
debounce,
throttle,
unique,
getValidObject,
calc,
calcV2,
getUUID,
isEmpty,
isNotEmpty,
zip,
unzip,
isExist,
whichTypeOf,
loadJs,
flat,
}
declare const window: Window
interface Window {
[key: string]: any
}
/**
* 设置window全局utils
* @param keyname { string } 键名 [default: $utils]
*/
function setGlobalUtils(keyname: string) {
let key = keyname || '$utils'
if (window as Window) {
!window[key] && (window[key] = toolkit)
}
}
export {
deepCopy,
debounce,
throttle,
unique,
getValidObject,
calc,
calcV2,
getUUID,
isEmpty,
isNotEmpty,
zip,
unzip,
isExist,
whichTypeOf,
loadJs,
setGlobalUtils,
flat,
toolkit as default
}