This repository has been archived on 2025-09-14. You can view files and clone it, but cannot push or open issues or pull requests.
Files
cyber-narrator-cn-ui/src/utils/tools.js
2022-04-27 16:18:29 +08:00

710 lines
20 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import { ElMessageBox, ElMessage } from 'element-plus'
import i18n from '@/i18n'
import _ from 'lodash'
import { storageKey, iso36112, topDomain } from '@/utils/constants'
import { getIso36112JsonData } from '@/utils/api'
import { format } from 'echarts'
import router from '@/router'
export const tableSort = {
// 是否需要排序
sortableShow (prop, from) {
switch (prop) {
case 'state': {
if (from === 'operationlog' || from === 'alertSilence') {
return false
}
break
}
case 'startAt': {
if (from === 'alertSilence') {
return false
}
break
}
case 'id':
case 'alertRule':
case 'severity':
case 'endAt':
case 'ID':
case 'HOST':
case 'SN':
case 'assetType':
case 'purchaseDate':
case 'pingStatus':
case 'dataCenter':
case 'cabinet':
case 'model':
case 'principal':
case 'asset':
case 'port':
case 'project':
case 'module':
case 'type':
case 'name':
case 'area':
case 'vendor':
case 'filename':
case 'updateAt':
case 'username':
case 'ip':
case 'operation':
case 'createDate':
case 'time':
case 'host':
case 'protocol':
case 'user':
case 'cmd':
case 'alertName':
case 'threshold':
case 'idc':
case 'alertNum':
case 'gname':
return 'custom'
default : return false
}
},
// prop字段
propTitle (prop, from) {
switch (from) {
case 'asset':
switch (prop) {
case 'ID': return 'ass.id'
case 'HOST': return 'ass.host'
case 'SN': return 'ass.sn'
case 'assetType': return 'sdtt.value'
case 'purchaseDate': return 'ass.purchase_date'
case 'state': return 'ass.state'
case 'pingStatus': return 'assp.rtt'
case 'dataCenter': return 'idc.name'
case 'cabinet': return 'cab.name'
case 'model': return 'mo.name'
case 'vendor': return 'sdt.value'
case 'principal': return 'su.username'
default : return prop
}
case 'alertMessage':
switch (prop) {
case 'id': return 'am.id'
case 'state': return 'am.state'
case 'alertRule': return 'ar.alert_name'
case 'severity': return 'am.severity'
case 'startAt': return 'am.start_at'
case 'endAt': return 'am.end_at'
default : return prop
}
case 'project':
switch (prop) {
case 'id': return 'e.id'
case 'asset': return 'a.host'
case 'port': return 'e.port'
case 'project': return 'p.name'
case 'module': return 'm.name'
case 'type': return 'm.type'
case 'state' :return 'es.state'
// case 'path': return'e.path';
default : return prop
}
case 'dc':
switch (prop) {
case 'id': return 'i.id'
case 'name': return 'i.name'
case 'area': return 'sa.name'
default : return prop
}
case 'endpointTab':
switch (prop) {
case 'id': return 'e.id'
case 'asset': return 'a.host'
case 'port': return 'e.port'
case 'project': return 'p.name'
case 'module': return 'm.name'
case 'type': return 'm.type'
case 'state' :return 'es.state'
// case 'path': return'e.path';
default : return prop
}
case 'model':
switch (prop) {
case 'id': return 'mo.id'
case 'name': return 'mo.name'
case 'type': return 'dictt.value'
case 'vendor': return 'dict.value'
default : return prop
}
case 'promServer':
switch (prop) {
case 'id': return 'id'
case 'idc': return 'idc_id'
case 'host': return 'host'
case 'port': return 'port'
case 'type': return 'type'
default : return prop
}
case 'mib':
switch (prop) {
case 'id': return 'sm.id'
case 'name': return 'sm.name'
case 'filename': return 'sm.file_name'
case 'updateAt': return 'sm.update_at'
default : return prop
}
case 'operationlog':
switch (prop) {
case 'id': return 'sl.id'
case 'username': return 'su.username'
case 'ip': return 'sl.ip'
case 'operation': return 'sl.operation'
case 'type': return 'sl.type'
case 'createDate': return 'sl.create_date'
case 'time': return 'sl.time'
default : return prop
}
case 'temrminallog':
switch (prop) {
case 'protocol': return 'protocol'
case 'startTime': return 'startTime'
default : return prop
}
case 'alertRules':
switch (prop) {
case 'id': return 'ar.id'
case 'alertName': return 'ar.alert_name'
case 'threshold': return 'ar.threshold'
case 'severity': return 'ar.severity'
default : return prop
}
case 'exprTemp':
switch (prop) {
case 'id': return 'id'
case 'name': return 'name'
case 'gname': return 'gname'
default : return prop
}
default: return prop
}
},
// 本地正序
asce (prop) {
return function (obj1, obj2) {
const { val1, val2 } = this.format(prop, obj1, obj2)
if (val1 < val2) {
return -1
} else if (val1 > val2) {
return 1
} else {
return 0
}
}
},
// 本地倒序
desc (prop) {
return function (obj1, obj2) {
const { val1, val2 } = this.format(prop, obj1, obj2)
if (val1 < val2) {
return 1
} else if (val1 > val2) {
return -1
} else {
return 0
}
}
},
format (prop, obj1, obj2) {
let val1 = obj1[prop]
let val2 = obj2[prop]
if (!isNaN(Number(val1)) && !isNaN(Number(val2)) && prop !== 'time') {
val1 = Number(val1)
val2 = Number(val2)
}
if (prop === 'time') {
val1 = tableSort.strTodate(val1)
val2 = tableSort.strTodate(val2)
}
if (prop === 'element') {
if (val1.alias) {
val1 = JSON.stringify(obj1[prop].alias).replace(/\s*/g, '')
} else {
val1 = JSON.stringify(obj1[prop].element).replace(/\s*/g, '')
}
if (val2.alias) {
val2 = JSON.stringify(obj2[prop].alias).replace(/\s*/g, '')
} else {
val2 = JSON.stringify(obj2[prop].element).replace(/\s*/g, '')
}
}
return { val1, val2 }
},
// 转化时间字符串为时间戳
strToDate (str) {
let date = str.trim()
date = date.substring(0, 19)
date = date.replace(/-/g, '/') // 必须把日期'-'转为'/'
return new Date(date).getTime()
}
}
/* cancel提醒保存指令 */
export const cancelWithChange = {
mounted (el, binding) {
if (!binding.value || !binding.value.object) return
const oldValue = JSON.parse(JSON.stringify(binding.value.object))
function domClick (e) {
const newValue = JSON.parse(JSON.stringify(binding.value.object))
if (!isEqual(oldValue, newValue)) {
ElMessageBox.confirm(i18n.global.t('tip.confirmCancel'), {
confirmButtonText: i18n.global.t('tip.yes'),
cancelButtonText: i18n.global.t('tip.no'),
type: 'warning'
}).then(() => {
if (binding.value.func) {
binding.value.func()
}
})
} else {
binding.value.func()
}
}
el.__vueDomClick__ = domClick
el.addEventListener('click', domClick)
},
unmounted (el, binding) {
// 解除事件监听
document.removeEventListener('click', el.__vueDomClick__)
delete el.__vueDomClick__
}
}
/* clickOutside指令 */
const exceptClassName = ['prevent-click-outside'] // clickOutside排除的class(白名单)
export const clickOutside = {
// 初始化指令
beforeMount (el, binding) {
/* let oldValue
try {
oldValue = JSON.parse(JSON.stringify(binding.value.object))
} catch (e) {
} */
function documentHandler (e) {
if (el.contains(e.target)) {
return false
} else {
let flag = true
const path = e.path || (e.composedPath && e.composedPath())
// eslint-disable-next-line no-labels
top: for (let i = 0; i < path.length; i++) {
for (let j = 0; j < exceptClassName.length; j++) {
if (path[i].className && path[i].className.indexOf(exceptClassName[j]) !== -1) {
flag = false
// eslint-disable-next-line no-labels
break top
}
}
}
if (!flag) {
return false
}
binding.value()
/* if (oldValue) {
const newValue = JSON.parse(JSON.stringify(binding.value.oldValue))
if (!isEqual(oldValue, newValue)) {
ElMessageBox.confirm('Confirm', { // TODO 国际化
confirmButtonText: 'Yes', // TODO 国际化
cancelButtonText: 'No', // TODO 国际化
type: 'warning'
}).then(() => {
if (binding.value.func) {
binding.value.func()
}
})
} else {
binding.value.func()
}
} else {
if (binding.arg) {
binding.value(e, binding.arg)
} else {
if (binding.value) {
binding.value(e)
}
}
} */
}
}
// 给当前元素绑定个私有变量方便在unbind中可以解除事件监听
el.__vueClickOutside__ = documentHandler
document.addEventListener('click', documentHandler)
},
unmounted (el, binding) {
// 解除事件监听
document.removeEventListener('click', el.__vueClickOutside__)
delete el.__vueClickOutside__
}
}
function noDataDomFactory () {
const noDataDom = document.createElement('div')
noDataDom.setAttribute('class', 'no-data')
noDataDom.innerText = 'No data'
return noDataDom
}
export const noData = {
updated (el, binding) {
if (el) {
if (binding.value) {
setTimeout(() => {
// 是否已有no data
let alreadyHasNoData = false
el.childNodes.forEach(node => {
if (node.classList && node.classList.value.indexOf('no-data') > -1) {
alreadyHasNoData = true
} else {
node.style && (node.style.display = 'none')
}
})
if (!alreadyHasNoData) {
el.insertBefore(noDataDomFactory(), el.childNodes[0])
}
})
} else {
setTimeout(() => {
for (let i = 0; i < el.childNodes.length; i++) {
const node = el.childNodes[i]
if (node.classList && node.classList.value.indexOf('no-data') > -1) {
el.removeChild(node)
break
}
}
el.childNodes.forEach(node => {
node.style && (node.style.display = '')
})
})
}
}
}
}
export function isEqual (o1, o2) {
const isEqualForInner = function (obj1, obj2) {
const o1 = obj1 instanceof Object
const o2 = obj2 instanceof Object
if (!o1 || !o2) {
return obj1 === obj2
}
if (Object.keys(obj1).length !== Object.keys(obj2).length) {
return false
}
for (const attr of Object.keys(obj1)) {
const t1 = obj1[attr] instanceof Object
const t2 = obj2[attr] instanceof Object
if (t1 && t2) {
if (!isEqualForInner(obj1[attr], obj2[attr])) {
return false
}
} else if (obj1[attr] !== obj2[attr]) {
return false
}
}
return true
}
return isEqualForInner(o1, o2)
}
/* 计算文本的实际width而不是length */
export function getTextRect (text, fontSize = 14) {
return format.getTextRect(text, `${fontSize}`)
}
/* url占位符处理 */
export function replaceUrlPlaceholder (url, params) {
_.forIn(params, (value, key) => {
url = url.replace('{{' + key + '}}', value)
})
url = url.replace(/{{(.*?)}}/g, '')
return url
}
// 双引号替换为单引号
export function doubleQuotationToSingle (content) {
return content.replace(/\"/g, "'")
}
// 双引号加斜杠转义
export function doubleQuotationEscape (content) {
return content.replace(/\"/g, '\\\"')
}
// 下划线转换驼峰
export function lineToHump (name) {
return name.replace(/\_(\w)/g, function (all, letter) {
return letter.toUpperCase()
})
}
// 驼峰转空格,首字母小写
export function humpToSpace (name) {
const str = name.replace(/([A-Z])/g, ' $1')
return str.split(' ').map(s => _.lowerFirst(s)).join(' ')
}
// 下划线转换空格
export function lineToSpace (name) {
if (_.isEmpty(name)) {
return ''
}
return name.replace(/\_(\w)/g, ' ')
}
// 驼峰转换下划线
export function humpToLine (name) {
if (_.isEmpty(name)) {
return ''
}
return name.replace(/([A-Z])/g, '_$1').toLowerCase()
}
// 排序功能:从大到小,降序排列
export function reverseSortBy (i) {
return function (a, b) {
return b[i] - a[i]
}
}
// 排序功能:从小到大,升序排列
export function sortBy (i) {
return function (a, b) {
return a[i] - b[i]
}
}
// echart图标y轴鼠标悬浮时显示标签所有内容
export function extensionEchartY (chart) {
// 判断是否创建过div框,如果创建过就不再创建了
// 该div用来盛放文本显示内容的方便对其悬浮位置进行处理
const id = document.getElementById('extension')
if (!id) {
const div = "<div id = 'extension' style=\"display:block\"></div>"
const contentDiv = document.createElement('div')
contentDiv.setAttribute('id', 'extension')
contentDiv.setAttribute('style', 'display:block')
document.documentElement.append(contentDiv)
}
chart.on('mouseover', function (params) {
// 注意这里我是以Y轴显示内容过长为例如果是x轴的话需要改为xAxis
if (params.componentType === 'yAxis') {
// 设置悬浮文本的位置以及样式
const extEle = document.getElementById('extension')
extEle.style.cssText = 'display:inline;position:absolute;' +
' padding: 12px;' +
' max-width: 400px !important;' +
' color: #666;' +
' background-color: rgb(255, 255, 255);' +
' font-size: 14px;' +
' line-height: 20px;' +
' font-weight:400; ' +
' font-family: "Microsoft YaHei"' +
' border-style: solid;' +
' border-width: 1px;' +
' border-radius: 4px;' +
' border-color: transparent !important;' +
' box-shadow: rgb(0 0 0 / 30%) 0px 0px 3px;' +
' white-space: nowrap;' +
' z-index: 99999999;'
extEle.innerHTML = params.value
document.documentElement.onmousemove = function (event) {
const extEle = document.getElementById('extension')
const xx = event.pageX - extEle.offsetWidth - 20
const yy = event.pageY + 20
extEle.style.cssText = extEle.style.cssText + 'top:' + yy + 'px;left:' + xx + 'px;'
}
}
})
chart.on('mouseout', function (params) {
// 注意这里我是以Y轴显示内容过长为例如果是x轴的话需要改为xAxis
if (params.componentType == 'yAxis') {
const extEle = document.getElementById('extension')
extEle.style.cssText = 'display:none;'
}
})
}
// 搜索功能:对象转字符串
export function objToStr (obj) {
return Object.keys(obj).map(k => {
return `${k}='${obj[k]}'`
}).join(' AND ')
}
// 搜索功能:字符串转对象
export function strToObj (n) {
const paramsArr = n.split(/\sAND\s/)
const paramsObj = {}
paramsArr.forEach(string => {
const param = string.split('=')
if (param.length > 1) {
let value = param[1].trim()
const valueArr = value.split(/[\"\']/g)
if (valueArr.length > 2) {
value = valueArr[1].trim()
}
paramsObj[param[0].trim()] = value
}
})
return paramsObj
}
// 加载geo数据
export function loadGeoData (key) {
const keys = []
if (key) {
keys.push(key)
} else {
keys.push(storageKey.iso36112Capital)
keys.push(storageKey.iso36112WorldLow)
}
keys.forEach(async k => {
if (!localStorage.getItem(k)) {
const data = await getIso36112JsonData(iso36112[k])
if (data) {
localStorage.setItem(k, JSON.stringify(data))
}
}
})
return localStorage.getItem(key)
}
/* 返回geodata对象 */
export function getGeoData (key) {
const data = localStorage.getItem(key)
if (data) {
return JSONParse(data)
} else {
return JSONParse(loadGeoData(key))
}
}
export function getCapitalGeo (countryId) {
const data = getGeoData(storageKey.iso36112Capital)
return data[countryId]
}
function JSONParse (data) {
const firstParse = JSON.parse(data)
if (typeof firstParse === 'string') {
return JSON.parse(firstParse)
} else {
return firstParse
}
}
export function copyValue (item) {
const str = item
const domUrl = document.createElement('input')
domUrl.value = JSON.stringify(str)
domUrl.id = 'creatDom'
document.body.appendChild(domUrl)
domUrl.select() // 选择对象
document.execCommand('Copy') // 执行浏览器复制命令
const creatDom = document.getElementById('creatDom')
creatDom.parentNode.removeChild(creatDom)
ElMessage.success(i18n.global.t('tip.copySuccess'))
}
export function computeSecondaryDomain (name) {
// 命中的顶级域名
let hitTopDomain = ''
// 同顶级域名比对
const hits = []
topDomain.forEach(td => {
const hitIndex = name.lastIndexOf(td)
if (hitIndex > -1 && hitIndex + td.length === name.length) {
hits.push(td)
}
})
if (hits.length > 0) {
hits.sort((a, b) => {
return b.split('.').length - a.split('.').length
})
hitTopDomain = hits[0]
} else {
const arr = name.split('.')
hitTopDomain = arr[arr.length - 1]
}
const index = name.lastIndexOf(hitTopDomain)
const preArr = name.substring(0, index).split('.')
return [preArr[preArr.length - 2], hitTopDomain].join('.')
}
export function getCurrentRoute () {
return router.currentRoute && router.currentRoute.path
}
// 判断数据相等
export function arrayIsEqual (arr1, arr2) {
if (arr1 === arr2) { // 如果2个数组对应的指针相同那么肯定相等同时也对比一下类型
return true
} else {
if (arr1.length !== arr2.length) {
return false
} else {
for (const i in arr1) { // 循环遍历对比每个位置的元素
if (arr1[i] !== arr2[i]) { // 只要出现一次不相等那么2个数组就不相等
return false
}
} // for循环完成没有出现不相等的情况那么2个数组相等
return true
}
}
}
// 字体长度缓存记录,{ 'fontSize': { 'limitWidth': { 'text': xxx } } }
const fontCache = {}
// 处理文本超长
export function truncateText (text, limitWidth, fontSize = 12, ellipsis = '...') {
if (!text || !limitWidth) {
return null
}
// hit cache
const cache = fontCache[`${fontSize}`] && fontCache[`${fontSize}`][`${limitWidth}`]
if (cache) {
const hit = Object.keys(cache).find(k => k === text)
if (hit) {
return cache[hit]
}
}
// 计算
const dom = document.createElement('span')
dom.classList.add('temp-dom')
dom.style.fontSize = `${fontSize}px`
dom.innerText = text
return dom.offsetWidth
}
export function scrollToTop (dom, toTop, duration, direction) {
const clientHeight = dom.clientHeight
const currentTop = dom.scrollTop
const totalScrollDistance = Math.abs(currentTop - toTop)
let scrollY = currentTop
let oldTimestamp = null
function step (newTimestamp) {
if (oldTimestamp !== null) {
if (direction === 'up') {
scrollY -= totalScrollDistance * (newTimestamp - oldTimestamp) / duration
console.info(scrollY)
if (scrollY < 0) {
dom.scrollTop = 0
return
}
dom.scrollTop = scrollY
} else if (direction === 'down') {
scrollY += totalScrollDistance * (newTimestamp - oldTimestamp) / duration
if (scrollY > clientHeight) {
dom.scrollTop = clientHeight
return
}
dom.scrollTop = scrollY
}
}
oldTimestamp = newTimestamp
window.requestAnimationFrame(step)
}
window.requestAnimationFrame(step)
}