在lib目录下新建util.js文件,里面存放项目中常用的工具类:
import { Enumify } from 'enumify'
import JSEncrypt from 'jsencrypt'
// 生成一个随机id
function newRandomId () {
let randomId = ''
for (let i = 1; i <= 32; i++) {
const n = Math.floor(Math.random() * 16.0).toString(16)
randomId += n
if (i === 8 || i === 12 || i === 16 || i === 20) {
randomId += '-'
}
}
return randomId
}
/**
* 函数防抖
* @param func 需要防抖的实际方法
* @param wait 延迟执行毫秒数
* @param immediate true 表立即执行,false 表非立即执行
*/
function debounce (func, wait, immediate) {
let timeout
return function () {
const that = this
const args = arguments
if (timeout) clearTimeout(timeout)
if (immediate) {
const callNow = !timeout
timeout = setTimeout(function () {
timeout = null
}, wait)
if (callNow) func.apply(that, args)
} else {
timeout = setTimeout(function () {
func.apply(that, args)
}, wait)
}
}
}
/**
* 函数节流
* @param func 需要节流的实际方法
* @param wait 延迟执行毫秒数(需要控制的时间长度)
* @param type 1 表时间戳版,2 表定时器版
*/
function throttle (func, wait, type) {
if (type === 1) {
const previous = 0 // 第一次执行的时候是0,第一次点击的时候肯定大于这个数,所以会立马执行
} else if (type === 2) {
let timeout
}
return function () {
const that = this
const args = arguments
if (type === 1) {
const now = Date.now() // 实际执行的时间
if (now - previous > wait) {
// 执行的时间是不是比上次执行的时间大于需要延迟的时间,大于,则执行
func.apply(that, args)
previous = now // 执行了以后,重置上一次执行的时间为刚刚执行这次函数的时间,下次执行就用这个时间为基准
}
} else if (type === 2) {
if (!timeout) {
timeout = setTimeout(function () {
timeout = null
func.apply(that, args)
}, wait)
}
}
}
}
/**
* 冻结对象的属性 防止篡改
* @param {对象} TargetObj
* @returns
*/
function getEnum (TargetObj) {
if (TargetObj instanceof Function) {
const enumInstance = new TargetObj()
if (!(enumInstance instanceof Enumify)) {
throw new Error('类型不对')
}
freezeObj(TargetObj)
return TargetObj
} else if (typeof EnumObj === 'object') {
freezeObj(TargetObj)
return TargetObj
}
}
/**
* 一层层冻结目标对象
* @param { Object } targetObj
*/
function freezeObj (targetObj) {
if (
!['object', 'function'].includes(typeof targetObj) ||
targetObj === null
) {
return
}
let i
for (i in targetObj) {
// 判断当前复制的对象是否为对象类型数据
if (typeof targetObj[i] === 'object') {
Object.freeze(targetObj[i])
}
}
}
/**
* 获取路径上的参数对象
* @returns {Object}
*/
function getCurrentRouteQuery () {
const query = {}
const search =
location.href.split('?').length > 1 && location.href.split('?')[1] // url参数
const urlParams = search && search.split('&') // url参数数组
if (urlParams && urlParams.length) {
urlParams.forEach((item) => {
const list = item.split('=')
query[list[0]] = list[1] ? decodeURI(list[1]) : ''
})
}
return query
}
/**
* 下载
*/
function saveBlobToFile (res, fileName) {
const regFilename = /filename=([^;]+)/i
if (res.headers['content-disposition']) {
// 从header获取并转化
const resFileName = decodeURIComponent(
res.headers['content-disposition'].match(regFilename)[1]
)
const blob = res.data
if (navigator.msSaveBlob) {
navigator.msSaveBlob(blob, resFileName)
} else {
const oA = document.createElement('a')
try {
oA.href = URL.createObjectURL(blob)
} catch (err) {
const binaryData = []
binaryData.push(blob)
oA.href = window.URL.createObjectURL(
new Blob(binaryData, { type: 'application/zip' })
)
}
oA.download = fileName || resFileName
oA.click()
}
}
}
/**
* 暂停进程(模拟)
* @param {any} time
* @returns {any}
*/
async function sleep (time) {
return new Promise((resolve) => setTimeout(resolve, time))
}
/**
* 等待并执行 定时间检查是否满足allow条件 当允许时 执行func
* @param {function} allow 满足等待的条件
* @param {function} func
* @param {number} time=200
*/
async function waitToRun (allow, func, time = 200) {
if (!allow()) {
await sleep(time)
return waitToRun(allow, func, time)
} else {
return func()
}
}
// # utils of tree
/**
* 树 遍历访问器
* @param {any} tree
* @param {any} callback
* @returns {any}
*/
function forEachTreeNode (tree, callback) {
if (!tree && typeof tree !== 'object') return
const loop = (treeArr = [], parent, allAncestors) => {
treeArr.forEach((item, idx, children) => {
callback(item, idx, children, parent, allAncestors)
if (item.children) {
loop(item.children, item, [...allAncestors, item])
}
})
}
// 数组 or 对象
// eslint-disable-next-line no-unused-expressions
tree.length
? loop(tree, null, [])
: (callback(tree, null, null, null), loop(tree.children, tree, []))
}
/**
* 获取 vm.$route.query
* 并 将值全部转换为 字符串形式 避免数字类型的值刷新后成为字符串 造成判断错误
* eg. routeQuey.call(this)
* @param initialObj 初始对象 在此基础上赋值
* @returns {any}
*/
function getRouteQuery (initialObj) {
const { query } = this.$route // 路由
return Object.keys(query).reduce(
(acc, cur) => ({
...acc,
[cur]: query[cur] + ''
}),
initialObj
)
}
/**
* form 重置校验 未传则重置全部 需要绑定 this 为当前vue实例
* @param {any} propArr 需要重置的prop数组
* @returns {any}
*/
function resetFormValidates (propArr = []) {
this.$nextTick(() => {
if (!this.$refs.formRef) return
const formRef = this.$refs.formRef.elRef || this.$refs.formRef
propArr.length
? propArr.forEach((prop) => formRef.resetValidate(prop))
: formRef.resetValidates()
})
}
/**
* setTimeout 短轮询
* @param func 被执行的请求promise函数 返回的结果bol会作为是否中断轮询的标识
* @param wait 执行时间间隔
* @param limit 最大请求次数 超过限制则会强制结束 默认20次
* @param count 递归用 请求次数 从1开始
* @param callback 回调
* @param count 请求次数
* @param isEnd 是否结束
*/
function polling (func, { wait, limit = 20, count = 1 }, callback) {
if (!func) return
const str = Object.prototype.toString.call(func)
// 获取中断标志的函数
const getBreakFlag = async () => {
if (str.includes('AsyncFunction') || str.includes('Promise')) {
const res = await func()
return res
} else {
return func()
}
}
setTimeout(async () => {
const breakFlag = await getBreakFlag()
if (count >= limit || breakFlag) {
callback && callback(count, true)
clearTimeout(polling)
} else {
callback && callback(count, false)
polling(func, { wait, limit, count: ++count }, callback)
}
}, wait)
}
/**
* 深度assign两个对象( 非对象类型将取后面的值 )
*/
export const deepAssign = (srcObj, mergedFromObj) => {
const isObject = (tar) =>
Object.prototype.toString.call(tar).includes('Object')
const isArray = (tar) => Object.prototype.toString.call(tar).includes('Array')
// 支持深层次链式调用 防止报错
const optionalChaining = (obj, ...rest) => {
let temp = obj
for (const key of rest) {
if (temp === undefined) return undefined
temp = (temp || {})[key]
}
return temp
}
const loop = (obj, path = []) => {
const cache = {}
for (const key in obj) {
const curPath = [...path, key]
if (isObject(obj[key])) {
cache[key] = loop(obj[key], curPath)
} else if (isArray(obj[key])) {
cache[key] = Object.values(loop(obj[key], curPath))
} else {
const mergedVal = optionalChaining(mergedFromObj, ...curPath)
cache[key] =
mergedVal !== undefined && typeof mergedVal !== 'object'
? mergedVal
: obj[key]
}
}
return cache
}
return loop(srcObj)
}
// 获取显示时间范围
function getPastTime (month) {
const time = new Date()
const yy = time.getFullYear() // 获取完整的年份(4位,1970-???)
const M = time.getMonth() + 1 // 获取当前月份(0-11,0代表1月),
const d = time.getDate() // 获取当前日(1-31)
const H = time.getHours() // 获取当前小时数(0-23)
const m = time.getMinutes() // 获取当前分钟数(0-59)
const s = time.getSeconds() // 获取当前秒数(0-59)
// 获取指定的过去时间
const past = M - month
const pastM = past <= 0 ? (past + 12 + '') : past > 9 ? (past + '') : '0' + past
// 小于9的,在前面加0
const MM = M > 9 ? M : '0' + M
const dd = d > 9 ? d : '0' + d
const HH = H > 9 ? H : '0' + H
const mm = m > 9 ? m : '0' + m
const ss = s > 9 ? s : '0' + s
// 指定的过去时间
const pastY = past <= 0 ? yy - 1 : yy
let pastD = dd
if (pastM === '02' && pastD > 28) { // 判断是否为闰年
pastD = ((pastY % 4 === 0 && pastY % 100 !== 0) || pastY % 400 === 0) ? 29 : 28
} else if ((pastM === '04' || pastM === '06' || pastM === '09' || pastM === '11') && pastD === 31) {
pastD = 30
}
const PastTime = pastY + '-' + pastM + '-' + pastD + ' ' + HH + ':' + mm + ':' + ss
// 当前时间
const nowTime = yy + '-' + MM + '-' + dd + ' ' + HH + ':' + mm + ':' + ss
return [PastTime, nowTime]
}
function pickerOptionsRelative () {
const shortcuts = [
{
text: '今日',
onClick (picker) {
const start = new Date()
start.setHours(0, 0, 0, 0)
const end = new Date()
end.setHours(23, 59, 59, 0)
picker.$emit('pick', [start, end], true)
}
},
{
text: '昨日',
onClick (picker) {
const start = new Date()
start.setTime(start.getTime() - 3600 * 1000 * 24)
start.setHours(0, 0, 0, 0)
const end = new Date()
end.setTime(end.getTime() - 3600 * 1000 * 24)
end.setHours(23, 59, 59, 0)
picker.$emit('pick', [start, end], true)
}
},
{
text: '本周',
onClick (picker) {
const end = new Date()
const start = new Date()
// 现在星期几;0代表星期天,6代表星期六
const thisDay = start.getDay() || 7
start.setTime(start.getTime() - 3600 * 1000 * 24 * (thisDay - 1))
end.setTime(end.getTime() + 3600 * 1000 * 24 * (7 - thisDay))
start.setHours(0, 0, 0, 0)
end.setHours(23, 59, 59, 0)
picker.$emit('pick', [start, end], true)
}
},
{
text: '上周',
onClick (picker) {
// 上周开始时间
const starta = new Date()
const first = starta.getDate() - starta.getDay() - 6
const startDate = new Date(starta.setDate(first))
const start = new Date(startDate)
start.setHours(0, 0, 0, 0)
// 上周结束时间
const currentDate = new Date()
const firsts = currentDate.getDate() - currentDate.getDay() - 6
const last = firsts + 6
const endDate = new Date(currentDate.setDate(last))
const end = new Date(endDate)
end.setHours(23, 59, 59, 0)
picker.$emit('pick', [start, end], true)
}
},
{
text: '本月',
onClick (picker) {
const currentDate = new Date()
const end = new Date()
const start = new Date()
// end.setTime(start.getTime() - 3600 * 1000 * 24)
start.setDate(1)
// 获取当前月天数
const currentMonth = new Date(
currentDate.getFullYear(),
currentDate.getMonth() + 1,
0
)
const currentMonthDay = currentMonth.getDate()
end.setDate(currentMonthDay)
start.setHours(0, 0, 0, 0)
end.setHours(23, 59, 59, 0)
picker.$emit('pick', [start, end], true)
}
},
{
text: '上月',
onClick (picker) {
// 获取当前时间
const currentDate = new Date()
// 获得当前月份0-11
let currentMonth = currentDate.getMonth()
// 获得当前年份4位年
let currentYear = currentDate.getFullYear()
// 获得上一个月的第一天
if (currentMonth === 0) {
currentMonth = 11 // 月份为上年的最后月份
currentYear-- // 年份减1
return new Date(currentYear, currentMonth, 1)
} else {
// 否则,只减去月份
currentMonth--
}
const start = new Date(currentYear, currentMonth, 1)
// 获取当前时间
const currentDates = new Date()
// 获得当前月份0-11
let currentMonths = currentDates.getMonth()
// 获得当前年份4位年
// let currentYears = currentDates.getFullYear()
// 当为12月的时候年份需要加1
// 月份需要更新为0 也就是下一年的第一个月
if (currentMonths === 11) {
// currentYears++
currentMonths = 0
} else {
// 否则只是月份增加,以便求的下一月的第一天
currentMonths++
}
// 一天的毫秒数
const millisecond = 1000 * 60 * 60 * 24
// 求出上月的最后一天
const aa = new Date()
const thisMonth = aa.getMonth()
// 获得当前年份4位年
const thisYear = aa.getFullYear()
// 求出本月第一天
const firstDay = new Date(thisYear, thisMonth, 1)
const lastDay = new Date(firstDay.getTime() - millisecond)
const end = new Date(lastDay)
start.setHours(0, 0, 0, 0)
end.setHours(23, 59, 59, 0)
picker.$emit('pick', [start, end], true)
}
},
// {
// text: '本季度',
// onClick (picker) {
// var oDate = new Date()
// var thisYear = oDate.getFullYear()
// var thisMonth = oDate.getMonth() + 1
// var n = Math.ceil(thisMonth / 3) // 季度
// var Month = n * 3 - 1
// var start = new Date(thisYear, Month - 2, 1)
// var end = new Date()
// end.setTime(end.getTime() - 3600 * 1000 * 24)
// picker.$emit('pick', [start, end])
// },
// },
{
text: '本年',
onClick (picker) {
const end = new Date()
const start = new Date()
start.setMonth(0)
start.setDate(1)
end.setMonth(11)
end.setDate(31)
start.setHours(0, 0, 0, 0)
end.setHours(23, 59, 59, 0)
// end.setTime(end.getTime() - 3600 * 1000 * 24)
picker.$emit('pick', [start, end], true)
}
},
{
text: '上年',
onClick (picker) {
// 获取当前时间
const currentDate = new Date()
// 获得当前年份4位年
const currentYear = currentDate.getFullYear() - 1
// 本年第一天
const start = new Date(currentYear, 0, 1)
// 本年最后一天
const end = new Date(currentYear, 11, 31)
start.setHours(0, 0, 0, 0)
end.setHours(23, 59, 59, 0)
picker.$emit('pick', [start, end], true)
}
},
{
text: '过去七天', // 近一周
onClick (picker) {
const end = new Date()
const start = new Date()
end.setTime(start.getTime() - 3600 * 1000 * 24)
start.setTime(start.getTime() - 3600 * 1000 * 24 * 7)
start.setHours(0, 0, 0, 0)
end.setHours(23, 59, 59, 0)
picker.$emit('pick', [start, end], true)
}
},
{
text: '过去30天', // 近一月
onClick (picker) {
const end = new Date()
const start = new Date()
end.setTime(start.getTime() - 3600 * 1000 * 24)
start.setTime(start.getTime() - 3600 * 1000 * 24 * 30)
start.setHours(0, 0, 0, 0)
end.setHours(23, 59, 59, 0)
picker.$emit('pick', [start, end], true)
}
},
{
text: '过去90天', // 近三月
onClick (picker) {
const end = new Date()
const start = new Date()
end.setTime(start.getTime() - 3600 * 1000 * 24)
start.setTime(start.getTime() - 3600 * 1000 * 24 * 90)
start.setHours(0, 0, 0, 0)
end.setHours(23, 59, 59, 0)
picker.$emit('pick', [start, end], true)
}
},
{
text: '过去180天', // 近半年
onClick (picker) {
const end = new Date()
const start = new Date()
end.setTime(start.getTime() - 3600 * 1000 * 24)
start.setTime(start.getTime() - 3600 * 1000 * 24 * 180)
start.setHours(0, 0, 0, 0)
end.setHours(23, 59, 59, 0)
picker.$emit('pick', [start, end], true)
}
}
// {
// text: '近一年',
// onClick (picker) {
// const end = new Date()
// const start = new Date()
// end.setTime(start.getTime() - 3600 * 1000 * 24)
// start.setTime(start.getTime() - 3600 * 1000 * 24 * 365)
// picker.$emit('pick', [start, end])
// },
// },
// {
// text: '自定义',
// type: '1',
// onClick (picker) {
// const end = new Date()
// const start = new Date()
// end.setTime(start.getTime() - 3600 * 1000 * 24)
// start.setTime(start.getTime() - 3600 * 1000 * 24 * 180)
// picker.$emit('pick', [start, end], true)
// },
// },
]
return { shortcuts }
}
function getBreadCrumb (bread) {
// 如果不是单机版,全部配置全部改为高级配置
try {
if (window.top.createBreadList && window.top.createBreadList() && window.top.createBreadList().length) {
return window.top.createBreadList()
} else {
return bread
}
} catch (error) {
return bread
}
}
// 格式化日期
function formatDate (timeDate, fmt) {
if (timeDate) {
let time = null
if (typeof timeDate === 'object') {
time = timeDate
} else {
time = new Date(timeDate)
if (time instanceof Date && isNaN(time.getTime())) {
// 不是合法日期格式,则为ie,需要做时间转换
if (timeDate.split('.')[1]) { timeDate = timeDate.split('.')[0] + '+' + timeDate.split('.')[1].split('+')[1] }
time = new Date(timeDate.replace(/-/g, '/'))
}
}
if (!fmt) fmt = 'yyyy-MM-dd hh:mm:ss.S'
const o = {
'M+': time.getMonth() + 1, // 月份
'd+': time.getDate(), // 日
'h+': time.getHours(), // 小时
'm+': time.getMinutes(), // 分
's+': time.getSeconds(), // 秒
'q+': Math.floor((time.getMonth() + 3) / 3), // 季度
S: time.getMilliseconds() // 毫秒
}
if (/(y+)/.test(fmt)) fmt = fmt.replace(RegExp.$1, (time.getFullYear() + '').substr(4 - RegExp.$1.length))
for (const k in o) {
if (new RegExp('(' + k + ')').test(fmt)) fmt = fmt.replace(RegExp.$1, (RegExp.$1.length === 1) ? (o[k]) : (('00' + o[k]).substr(('' + o[k]).length)))
}
return fmt
} else {
return timeDate || '--'
}
}
// 下载文件
function saveBoloToFile (blob, fileName) {
if (navigator.msSaveBlob) {
navigator.msSaveBlob(blob, fileName)
} else {
const oA = document.createElement('a')
oA.href = URL.createObjectURL(blob)
oA.download = fileName
oA.click()
}
}
/**
* @Desc: post方式打开新窗口
*/
function openPostWindow (url, name, obj) {
const tempForm = document.createElement('form')
tempForm.id = 'tempForm1'
tempForm.method = 'get'
tempForm.action = url
tempForm.target = '_self'
for (const p in obj) {
const hideInput = document.createElement('input')
hideInput.type = 'hidden'
hideInput.name = p
hideInput.value = obj[p]
tempForm.appendChild(hideInput)
}
if (window.addEventListener) {
tempForm.addEventListener('onsubmit', function () { openWindow(name) })
} else if (window.attachEvent) {
tempForm.attachEvent('onsubmit', function () { openWindow(name) })
}
document.body.appendChild(tempForm)
tempForm.submit()
document.body.removeChild(tempForm)
}
function openWindow (name) {
window.open('about:blank', name, 'height=400, width=400, top=0, left=0, toolbar=yes, menubar=yes, scrollbars=yes, resizable=yes,location=yes, status=yes')
}
// 格式化数字
function formatData (n) {
if (!n || isNaN(n)) return
const b = parseInt(n).toString()
const len = b.length
if (len <= 3) { return b }
const r = len % 3
return r > 0 ? b.slice(0, r) + ',' + b.slice(r, len).match(/\d{3}/g).join(',') : b.slice(r, len).match(/\d{3}/g).join(',')
}
function setEncryptLong2 () {
// 扩展加解密方法
const b64map = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/'
const b64pad = '='
function hex2b64 (h) {
let i
let c
let ret = ''
for (i = 0; i + 3 <= h.length; i += 3) {
c = parseInt(h.substring(i, i + 3), 16)
ret += b64map.charAt(c >> 6) + b64map.charAt(c & 63)
}
if (i + 1 === h.length) {
c = parseInt(h.substring(i, i + 1), 16)
ret += b64map.charAt(c << 2)
} else if (i + 2 === h.length) {
c = parseInt(h.substring(i, i + 2), 16)
ret += b64map.charAt(c >> 2) + b64map.charAt((c & 3) << 4)
}
while ((ret.length & 3) > 0) {
ret += b64pad
}
return ret
}
JSEncrypt.prototype.encryptLong2 = function (string) {
const k = this.getKey()
try {
let ct = ''
// RSA每次加密117bytes,需要辅助方法判断字符串截取位置
// 1.获取字符串截取点
const bytes = []
bytes.push(0)
let byteNo = 0
let c
const len = string.length
let temp = 0
for (let i = 0; i < len; i++) {
c = string.charCodeAt(i)
if (c >= 0x010000 && c <= 0x10FFFF) {
byteNo += 4
} else if (c >= 0x000800 && c <= 0x00FFFF) {
byteNo += 3
} else if (c >= 0x000080 && c <= 0x0007FF) {
byteNo += 2
} else {
byteNo += 1
}
if ((byteNo % 245) >= 242 || (byteNo % 245) === 0) {
if (byteNo - temp >= 114) {
bytes.push(i)
temp = byteNo
}
}
}
// 2.截取字符串并分段加密
if (bytes.length > 1) {
for (let j = 0; j < bytes.length - 1; j++) {
let str
if (j === 0) {
str = string.substring(0, bytes[j + 1] + 1)
} else {
str = string.substring(bytes[j] + 1, bytes[j + 1] + 1)
}
const t1 = k.encrypt(str)
ct += t1
}
;
if (bytes[bytes.length - 1] !== string.length - 1) {
const lastStr = string.substring(bytes[bytes.length - 1] + 1)
ct += k.encrypt(lastStr)
}
return hex2b64(ct)
}
const t = k.encrypt(string)
const y = hex2b64(t)
return y
} catch (ex) {
return false
}
}
}
function removeFailList (list, value) {
if (!list) return
const index = list.indexOf(value)
if (index >= 0) {
list.splice(index, 1)
}
}
/**
* @func generateUppercaseLetterList
* @desc 获取26个大写英文字母的数组
* @return []
*/
function generateUppercaseLetterList () {
const CHARCODE_A_UC = 65
const uppercaseAlphabet = new Array(26).fill(null).map((v, i) => String.fromCharCode(CHARCODE_A_UC + i))
return uppercaseAlphabet
}
/**
* 数字串加逗号分隔
*/
function splitForComma (num) {
if (!num) return 0
const arr = num.toString().split('').reverse()
const resArr = []
arr.forEach((item, index) => {
resArr.push(item)
if ((index + 1) % 3 === 0 && index !== arr.length - 1) resArr.push(',')
})
return resArr.reverse().join('')
}
let deepCopy = (targetObj) => {
// 若不是对象类型或是null类型,直接输出
if (typeof targetObj !== 'object' || targetObj === null) {
return targetObj
}
let i
// 根据目标是Array类型还是object来设置目标参数的类型
let target = Array.isArray(targetObj) ? [] : {}
for (i in targetObj) {
// 判断当前复制的对象是否为对象类型数据
if (typeof targetObj[i] === 'object') {
target[i] = deepCopy(targetObj[i])
} else {
target[i] = targetObj[i]
}
}
return target
}
/**
* 根据容器获取容器里面的html字符串 把css样式转换为内联样式 以便生成可直接离线访问的html文档或者svg文件
* @param {Document} svgContent
* @returns
*/
function getEleStrFormSvg (svgContent) {
if (!svgContent) {
return ''
}
const svgContainer = svgContent.tagName === 'svg' ? svgContent : svgContent.querySelector('svg')
if (!svgContainer) {
return ''
}
const contentDom = svgContainer.cloneNode(true)
const svgChildren = contentDom.querySelectorAll('svg')
for (const svg of svgChildren) {
if (svg === contentDom) continue
const parent = svg.parentNode
const imgDom = getImgReplaceSvg(svg)
parent.replaceChild(imgDom, svg)
}
const sheets = document.styleSheets
const sheetsArry = Array.from(sheets)
sheetsArry.forEach(sheetContent => {
console.log('sheetContent==', sheetContent)
const { rules, cssRules } = sheetContent
// cssRules兼容火狐
const rulesArry = Array.from(rules || cssRules || [])
rulesArry.forEach(rule => {
const { selectorText, style } = rule
// 全局样式不处理
if (selectorText !== '*') {
// 兼容某些样式在转换的时候会报错
try {
const select = contentDom.querySelectorAll(selectorText)
const origin = svgContent.querySelectorAll(selectorText)
Array.from(select).forEach((dom, index) => {
let i = 0
const domStyle = window.getComputedStyle(origin[index], null)
while (style[i]) {
// 式表里的className是驼峰式,转换下便对应上了
const newName = style[i].replace(/-\w/g, function (x) {
return x.slice(1).toUpperCase()
})
dom.style[style[i]] = domStyle[newName]
i++
}
})
} catch (e) {
console.log('转换成行内样式失败')
}
}
})
})
return contentDom.outerHTML
}
function getImgReplaceSvg (svgNode) {
const dom = document.createElement('img')
dom.style.width = 32 + 'px'
dom.style.height = 32 + 'px'
let svg = svgNode.outerHTML.trim()
let canvas = document.createElement('canvas')
canvas.width = svgNode.getBoundingClientRect().width
canvas.height = svgNode.getBoundingClientRect().height
canvg(canvas, svg)
dom.src = canvas.toDataURL('image/png')
return dom
}
// 进行正则表达式转义编码
function encodeRegExp (keyword) {
const reg = /[[($^.\]*\\?+{}|)]/gi
return keyword.replace(reg, (key) => `\\${key}`)
}
/**
* 获取以千分隔的数字
* @param num 数字
*/
function getThousandSplitNum (num, isNumber = false) {
if (!isNumber && (typeof num !== 'number' || !num)) {
return num
}
let minusSymbol = '' // 负数标志
if (num < 0) {
num = -num
minusSymbol = '-'
}
let numStr = num.toString()
let [intStr, floatStr] = numStr.split('.')
if (intStr.length < 3) {
return minusSymbol + numStr
}
const strArr = []
for (let i = intStr.length; i > 0; i = i - 3) {
strArr.push(intStr.substring(i - 3, i))
}
strArr.reverse()
return minusSymbol + strArr.join(',') + (floatStr ? '.' + floatStr : '')
}
/**
* findeLastIndex 兼容低版本浏览器
* @param {*} target
*/
function findArrayLastIndex (list = [], findFunc) {
let index = -1
if (!findFunc || typeof findFunc !== 'function') {
return -1
}
const length = list.length
for (let i = length - 1; i >= 0; i--) {
if (findFunc(list[i], i)) {
index = i
break
}
}
return index
}
function getActualWidthOfChars (text, options = {}) {
const { size = 14, family = 'Microsoft YaHei' } = options
const canvas = document.createElement('canvas')
const ctx = canvas.getContext('2d')
ctx.font = `${size}px ${family}`
const metrics = ctx.measureText(text)
const actual = Math.abs(metrics.actualBoundingBoxLeft) + Math.abs(metrics.actualBoundingBoxRight)
return Math.max(metrics.width, actual)
}
export {
splitForComma,
generateUppercaseLetterList,
pushToFailList,
hasOwn,
setEncryptLong2,
newRandomId,
debounce,
throttle,
getEnum,
getCurrentRouteQuery,
saveBlobToFile,
waitToRun,
forEachTreeNode,
getRouteQuery,
resetFormValidates,
polling,
getPastTime,
pickerOptionsRelative,
getBreadCrumb,
formatDate,
saveBoloToFile,
openPostWindow,
formatData,
deepCopy,
getEleStrFormSvg,
encodeRegExp,
getThousandSplitNum,
findArrayLastIndex,
getActualWidthOfChars
}