import { cloneDeep , throttle , debounce } from 'lodash' ; import { IHomeRouterItemMeta } from '@/router/home-router' ; import { IUserType } from '@/types/store' ; import { IRouterItem } from '@/types/project' ; interface IUtils { cutString : ( str : string , len : number ) => string ; getIntersect : ( a : any [ ] , b : any [ ] ) => any [ ] | null ; debounce : ( func : ( ... args : any [ ] ) => any , wait ? : number ) => any ; throttle : ( func : ( ) => any , wait ? : number ) => any ; getRandomStr : ( n ? : number ) => string ; getTypeOf : ( obj : any ) => string ; insertItem : ( item : any , arr : any [ ] ) => void ; sortByOrder : ( source : any [ ] ) => any [ ] ; deepClone : < T = any > ( data : T ) => T ; hasPermission : ( permissions : string [ ] , route : IRouterItem | IHomeRouterItemMeta , user : IUserType ) => boolean ; getScrollBarSize : ( fresh : boolean ) => number ; shallowEqual : ( obj_1 : object , obj_2 : object ) => boolean ; } const Utils = { } as IUtils ; /** 参数说明：
 * 根据长度截取先使用字符串，超长部分追加…
 * str 对象字符串
 * len 目标字节长度
 * 返回值： 处理结果字符串
 */ Utils . cutString = ( str , len ) : string => { if ( str . length * 2 <= len ) { return str ; } let strlen = 0 ; let s = '' ; for ( let i = 0 ; i < str . length ; i ++ ) { s += str . charAt ( i ) ; if ( str . charCodeAt ( i ) > 128 ) { strlen += 2 ; if ( strlen >= len ) { return `${ s . substring ( 0 , s . length - 1 ) }...` ; } } else { strlen += 1 ; if ( strlen >= len ) { return `${ s . substring ( 0 , s . length - 2 ) }...` ; } } } return s ; } ; param { Array } a param { Array } b Utils . getIntersect = ( a , b ) : any [ ] | null => { if ( a . constructor === Array && b . constructor === Array ) { const set1 = new Set < any [ ] > ( a ) ; const set2 = new Set < any [ ] > ( b ) ; return Array . from ( new Set ( [ ... set1 ] . filter ( x => set2 . has ( x ) ) ) ) ; } return null ; } ; param { * } func param { * } wait Utils . debounce = ( func , wait = 50 ) : any => debounce ( func , wait ) ; param { * } func param { * } wait Utils . throttle = ( func , wait = 50 ) : any => throttle ( func , wait ) ; param { Number } n Utils . getRandomStr = ( n = 6 ) : string => { let str = '' ; const chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz1234567890' ; for ( let i = 0 ; i < n ; i += 1 ) { str += chars . charAt ( Math . floor ( Math . random ( ) * 62 ) ) ; } return str ; } ; function getTypeOf ( obj ) { const { toString } = Object . prototype ; const map = { '[object Boolean]' : 'boolean' , '[object Number]' : 'number' , '[object String]' : 'string' , '[object Function]' : 'function' , '[object Array]' : 'array' , '[object Date]' : 'date' , '[object RegExp]' : 'regExp' , '[object Undefined]' : 'undefined' , '[object Null]' : 'null' , '[object Object]' : 'object' , '[object Symbol]' : 'symbol' } ; return map [ toString . call ( obj ) ] ; } function insertItem ( item , arr ) { const { order } = item ; if ( typeof arr [ order ] !== 'number' ) { arr [ order ] = item ; return ; } let moveBegin = 0 ; let moveEnd = 0 ; let pos = 0 ; let i = order + 1 ; while ( arr [ i ] ) { if ( arr [ i ] . order > order ) { if ( ! moveBegin ) { moveBegin = i ; pos = i ; } } i += 1 ; } if ( moveBegin ) { moveEnd = i ; } else { pos = i ; } if ( ! moveEnd ) { arr [ pos ] = item ; return ; } for ( let i = moveEnd ; i >= moveBegin ; i -= 1 ) { arr [ i + 1 ] = arr [ i ] ; } arr [ pos ] = item ; } param { Array } source Utils . sortByOrder = ( source = [ ] ) : any [ ] => { if ( ! Array . isArray ( source ) ) { console . error ( 'sortByOrder 传入参数不符合要求, 应为数组' , source ) ; return source ; } const tmp = [ ] ; let target = [ ] ; for ( let i = 0 ; i < source . length ; i += 1 ) { if ( typeof source [ i ] . order !== 'number' ) { continue ; } let { order } = source [ i ] ; if ( order < 0 ) { order = source . length + order ; if ( order < 0 ) { order = 0 ; } } source [ i ] . order = Math . floor ( order ) ; insertItem ( source [ i ] , tmp ) ; } for ( let i = 0 , j = 0 ; i < source . length ; i += 1 ) { if ( typeof source [ i ] . order === 'number' ) { continue ; } while ( tmp [ j ] ) { j += 1 ; } tmp [ j ] = source [ i ] ; } target = tmp . filter ( item => ! ! item ) ; return target ; } ; param { * } data Utils . deepClone = < T = any > ( data ) : T => cloneDeep ( data ) ; /**
 * 判断权限
 */ Utils . hasPermission = ( permissions , route , user ) : boolean => { if ( user && user . admin ) { return true ; } const { permission } = route ; if ( permission ) { return permissions . some ( ( auth ) => permission . indexOf ( auth ) > - 1 ) ; } return true ; } ; let cached ; param { boolean } fresh returns { number } export function getScrollBarSize ( fresh ) { if ( fresh || cached === undefined ) { const inner = document . createElement ( 'div' ) ; inner . style . width = '100%' ; inner . style . height = '200px' ; const outer = document . createElement ( 'div' ) ; const outerStyle = outer . style ; outerStyle . position = 'absolute' ; outerStyle . top = '0px' ; outerStyle . left = '0px' ; outerStyle . pointerEvents = 'none' ; outerStyle . visibility = 'hidden' ; outerStyle . width = '200px' ; outerStyle . height = '150px' ; outerStyle . overflow = 'hidden' ; outer . appendChild ( inner ) ; document . body . appendChild ( outer ) ; const widthContained = inner . offsetWidth ; outer . style . overflow = 'scroll' ; let widthScroll = inner . offsetWidth ; if ( widthContained === widthScroll ) { widthScroll = outer . clientWidth ; } document . body . removeChild ( outer ) ; cached = widthContained - widthScroll ; } return cached ; } /**
 * plain object 的浅比较
 */ Utils . shallowEqual = ( obj_1 , obj_2 ) : boolean => { if ( getTypeOf ( obj_1 ) !== 'object' || getTypeOf ( obj_2 ) !== 'object' ) { return false ; } const keys_1 = Object . keys ( obj_1 ) ; const keys_2 = Object . keys ( obj_2 ) ; if ( keys_1 . length !== keys_2 . length ) { return false ; } const isKeyValueEqual = ( arr ) => arr . every ( item => obj_1 [ item ] === obj_2 [ item ] ) ; return isKeyValueEqual ( keys_1 ) && isKeyValueEqual ( keys_2 ) ; } ; export default Utils ;