other 其他
ts
/**
* 获取浏览器标识(PC)
*/
export function getPcBrowserType() {
const agent = navigator.userAgent.toLowerCase() // 取得浏览器的userAgent字符串
const isOpera = agent.indexOf('opera') > -1 // 判断是否Opera浏览器
const isIE = agent.indexOf('compatible') > -1 && agent.indexOf('msie') > -1 && !isOpera // 判断是否IE浏览器
const isEdge = agent.indexOf('edge') > -1 // 判断是否IE的Edge浏览器
const isFirefox = agent.indexOf('firefox') > -1 // 判断是否Firefox浏览器
const isSafari = agent.indexOf('safari') > -1 && agent.indexOf('chrome') === -1 // 判断是否Safari浏览器
const isChrome = agent.indexOf('chrome') > -1 && agent.indexOf('safari') > -1 // 判断Chrome浏览器
const isIE11 = agent.indexOf('trident') > -1 && agent.indexOf('rv:11.0') > -1
return {
agent,
isOpera,
isEdge,
isFirefox,
isSafari,
isChrome,
isIE11,
isIE: (isIE && agent.replace(/.*msie (\d+)\.\d+;.*/g, '$1')) || 0
}
}
/**
* 客户端检测(移动端)
*/
export function getAppBrowserType() {
const json = {
userAgent: navigator.userAgent.toLowerCase(),
isAndroid: Boolean(navigator.userAgent.match(/android/gi)),
isIos: Boolean(navigator.userAgent.match(/iphone|ipod|ipad/gi)),
isWeChat: Boolean(navigator.userAgent.match(/MicroMessenger/gi)),
isQQ: Boolean(navigator.userAgent.match(/ QQ/gi)),
isQQBrowser: Boolean(navigator.userAgent.match(/MQQBrowser/gi)),
isUCBrowser: Boolean(navigator.userAgent.match(/UCBrowser/gi)),
isSafari: Boolean(/Safari/.test(navigator.userAgent) && !/Chrome/.test(navigator.userAgent)),
iosVersion: ''
}
let iosVersion: any = json.userAgent.match(/os\s*(\d+)/)
iosVersion = iosVersion ? iosVersion[1] || 0 : 0
json.iosVersion = iosVersion
return json
}
/**
* 字符串形式的ip转整数形式
* @param ipString
*/
export function ipStringToInteger(ipString: string) {
if (!ipString) {
throw new Error('ipString 找不到')
}
if (
!/^(?:\d|[1-9]\d|1\d{2}|2[0-4]\d|25[0-5])(?:\.(?:\d|[1-9]\d|1\d{2}|2[0-4]\d|25[0-5])){3}$/.test(
ipString
)
) {
throw new Error('ipString 不是正确的ip')
}
const binaryString = ipString
.split('.')
.map(s => parseInt(s, 10).toString(2).padStart(8, '0'))
.join('')
return parseInt(binaryString, 2)
}
/**
* 根据cidr获取ip范围段,数字形式
* @param ipWithSubnet 192.168.0.1/24
*/
export function getIpRange(ipWithSubnet: string) {
const [ipStr, subnetStr] = ipWithSubnet.split('/')
const ip = ipStringToInteger(ipStr)
const subnet = parseInt(subnetStr, 10)
// eslint-disable-next-line no-bitwise
const mask = 0xffffffff << (32 - subnet)
// eslint-disable-next-line no-bitwise
const networkAddress = ip & mask
// eslint-disable-next-line no-bitwise
const broadcastAddress = networkAddress + (1 << (32 - subnet)) - 1
// eslint-disable-next-line no-bitwise
const minIp = (networkAddress + 1) >>> 0 // 无符号右移位
// eslint-disable-next-line no-bitwise
const maxIp = (broadcastAddress - 1) >>> 0 // 无符号右移位
return [minIp, maxIp]
}
/**
* 基于promise和async/await封装的延迟执行
* @param ms 延迟执行的毫秒数
*/
export function sleep(ms: number): Promise<void> {
return new Promise<void>(resolve => {
setTimeout(() => {
resolve()
}, ms)
})
}
/**
* 对比两个对象的差异,并返回增加的和减少的属性
* @param oldObj
* @param newObj
*/
export function diffObject(oldObj: object, newObj: object) {
const hasKey = (obj: object, k: string) => Object.prototype.hasOwnProperty.call(obj, k)
/** 增加 */
const increase = {}
/** 减少 */
const decrease = {}
/** 对于newObj已经判断过的key */
const usedKeys: string[] = []
// 过滤old
for (const key in oldObj) {
if (hasKey(oldObj, key)) {
const k = key as keyof typeof oldObj
if (hasKey(newObj, k)) {
usedKeys.push(k)
if (oldObj[k] != newObj[k]) {
// 如果值不相等,新增和减少都要有
increase[k] = newObj[k]
decrease[k] = oldObj[k]
}
} else {
decrease[k] = oldObj[k]
}
}
}
// 过滤没比对过的new
for (const key in newObj) {
if (usedKeys.includes(key)) continue
if (hasKey(newObj, key)) {
const k = key as keyof typeof newObj
increase[k] = newObj[k]
}
}
return {
/** 增加 */
increase,
/** 减少 */
decrease
}
}