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
nezha-nezha-fronted/nezha-fronted/src/components/common/js/tools.js

696 lines
25 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 PerfectScrollbar from "perfect-scrollbar";
//top置顶按钮公共方法
export function toTop(type, wrap) {
if (type == 'el') {
let currentTop = wrap.scrollTop;
let interval = currentTop/10;
let intervalFunc = setInterval(function(){ //花200ms分10次回到顶部模拟动画效果
if (currentTop == 0) {
clearInterval(intervalFunc);
} else {
currentTop = (currentTop - interval) < interval*0.5 ? 0 : currentTop - interval;
wrap.scrollTop = currentTop;
}
}, 20);
} else {
let els = document.querySelectorAll(".el-table__body-wrapper");
if (wrap || wrap == 0) { //指定index的table__body
let currentTop = els[wrap].scrollTop;
let interval = currentTop/10;
let intervalFunc = setInterval(function(){ //花200ms分10次回到顶部模拟动画效果
if (currentTop == 0) {
clearInterval(intervalFunc);
} else {
currentTop = (currentTop - interval) < interval*0.5 ? 0 : currentTop - interval;
els[wrap].scrollTop = currentTop;
}
}, 20);
} else { //所有table__body
for (let i = 0; i < els.length; i++) {
let currentTop = els[i].scrollTop;
let interval = currentTop/10;
let intervalFunc = setInterval(function(){ //花200ms分10次回到顶部模拟动画效果
if (currentTop == 0) {
clearInterval(intervalFunc);
} else {
currentTop = (currentTop - interval) < interval*0.5 ? 0 : currentTop - interval;
els[i].scrollTop = currentTop;
}
}, 20);
}
}
}
}
/*弹窗点击外部后关闭*/
const exceptClassName = ["config-dropdown", "nz-pop", "el-picker", "chart-box-dropdown", 'metric-dropdown', 'el-cascader__dropdown', "asset-dropdown", "no-style-class", 'el-message-box','nz-dashboard-dropdown']; //clickoutside排除的class(白名单) no-style-class没有任何样式的class
export const clickoutside = {
// 初始化指令
bind(el, binding, vnode) {
function documentHandler(e) {
if (el.contains(e.target)) {
return false;
} else {
let flag = true;
let path = e.path || (e.composedPath && e.composedPath());
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;
break top;
}
}
}
if (!flag) {
return false;
}
}
// 判断指令中是否绑定了函数
if (binding.expression) {
// 如果绑定了函数 则调用那个函数此处binding.value就是handleClose方法
if (binding.arg) {
binding.value(e, binding.arg);
} else {
binding.value(e);
}
}
}
// 给当前元素绑定个私有变量方便在unbind中可以解除事件监听
el.__vueClickOutside__ = documentHandler;
document.addEventListener('mousedown', documentHandler);
},
unbind(el, binding) {
// 解除事件监听
document.removeEventListener('mousedown', el.__vueClickOutside__);
delete el.__vueClickOutside__;
},
};
/*el-table自定义滚动条*/
const el_scrollBar = el => {
if (el._ps_ instanceof PerfectScrollbar) {
el._ps_.update();
} else {
//el上挂一份属性
el._ps_ = new PerfectScrollbar(el, {minScrollbarLength: 25});
}
};
export const scrollBar = {
inserted(el, binding, vnode) {
const { arg } = binding;
if (arg === "el-table") {
el = el.querySelector(".el-table__body-wrapper");
!el && console.warn("未发现className为el-table__body-wrapper的dom");
} else if (arg === "el-dropdown") {
el = document.querySelector(".el-dropdown-menu");
!el && console.warn("未发现className为el-dropdown-menu的dom");
} else if (arg == "legend") {
el = el.querySelector(".legend-container");
!el && console.warn("未发现className为legend-container的dom");
}
// 启用x轴后不让原生滚动条出来作乱
if (el) {
vnode.context.$nextTick(() => {
if (arg === "xterm") {
el = el.querySelector(".xterm-viewport");
!el && console.warn("未发现className为xterm-viewport的dom");
}
if(arg==="metric-label-cascader"){
el = el.querySelector(".el-cascader__tags");
!el && console.warn("未发现className为el-cascader__tags的dom");
}
el.classList.add("ps");
el.addEventListener("ps-scroll-y", () => {
el.classList.add("ps");
});
el.addEventListener("ps-scroll-x", () => {
el.classList.add("ps");
});
//el上挂一份属性
el_scrollBar(el);
});
const rules = ["fixed", "absolute", "relative"];
if (!rules.includes(window.getComputedStyle(el, null).position)) {
console.error(
`perfect-scrollbar所在的容器的position属性必须是以下之一${rules.join(
"、"
)}`
);
}
}
},
componentUpdated(el, binding, vnode, oldVnode) {
const { arg, value } = binding;
if (arg === "el-table") {
el = el.querySelector(".el-table__body-wrapper");
!el && console.warn("未发现className为el-table__body-wrapper的dom");
} else if (arg === "el-dropdown") {
el = document.querySelector(".el-dropdown-menu");
!el && console.warn("未发现className为el-dropdown-menu的dom");
}else if (arg === "xterm") {
el = el.querySelector(".xterm-viewport");
!el && console.warn("未发现className为xterm-viewport的dom");
}else if(arg==="metric-label-cascader"){
el = el.querySelector(".el-cascader__tags");
!el && console.warn("未发现className为el-cascader__tags的dom");
}
setTimeout(() => {
el.classList.add("ps");
el.classList.add("ps--active-y");
el._ps_.update();
}, 1500)
try {
vnode.context.$nextTick(() => {
el_scrollBar(el);
if (value) {
el.querySelector(".ps__rail-x").classList.add("ps-scroll-" + value);
el.querySelector(".ps__rail-y").classList.add("ps-scroll-" + value);
}
});
} catch (error) {
console.error(error);
el_scrollBar(el);
}
},
};
// 底部上滑框窗口控制
export const bottomBoxWindow = {
// 鼠标拖动二级列表
listResize(vm, e) {
window.resizing = true;
let mainListDom = document.querySelector(".main-list"); //主列表
let subBoxDom = document.querySelector(".sub-box"); //副列表
let subListDom = document.querySelector(".sub-list"); //副列表
let contentRightDom = document.querySelector(".content-right"); //右侧内容区
let resizeBarHeight = 9; //resize横条高度
let minHeight = 15; //主、副列表最小高度限制为15
let contentHideHeight = 100; //主、副列表高度低于100时隐藏内容
let mainModalDom = document.querySelector(".main-modal"); //主列表遮罩
let resizeModalDom = document.querySelector(".resize-modal"); //副列表遮罩
let resizeBarDom = document.querySelector(".sub-list-resize"); //副列表遮罩
let contentRightHeight = contentRightDom.offsetHeight;//可视高度
//点击时俩dom的初始高度
let subInitialHeight = subListDom.offsetHeight+resizeBarHeight;
mainModalDom.style.display = "block";
resizeModalDom.style.height = `${subInitialHeight}px`;
resizeModalDom.style.display = "block";
resizeBarDom.style.display = "none";
let resizeModalEndHeight;
//点击时鼠标的Y轴位置
let mouseInitialY = e.clientY;
document.onmousemove = (e) => {
window.resizing = true;
e.preventDefault();
//得到鼠标拖动的距离
let mouseMoveY = e.clientY-mouseInitialY;
resizeModalEndHeight = subInitialHeight-mouseMoveY;
resizeModalDom.style.height = `${resizeModalEndHeight}px`;
// 主、副列表最小高度限制
if(resizeModalEndHeight > contentRightHeight-minHeight){
resizeModalDom.style.height = `${contentRightHeight-minHeight}px`;
}
if(resizeModalEndHeight < minHeight){
resizeModalDom.style.height = `${minHeight}px`;
}
};
document.onmouseup = () => {
window.resizing = false;
mainListDom.style.height = `${contentRightHeight-resizeModalEndHeight}px`;
subBoxDom.style.height = `${resizeModalEndHeight}px`;
subListDom.style.height = `${resizeModalEndHeight-resizeBarHeight}px`;
resizeModalDom.style.display = "none";
mainModalDom.style.display = "none";
resizeBarDom.style.display = "";
//当主副列表可视区域小于一定值时,不展示内容
if(contentRightHeight-resizeModalEndHeight <= contentHideHeight){
if (vm.bottomBox.mainResizeShow) {
vm.bottomBox.mainResizeShow = false;
}
} else {
if (!vm.bottomBox.mainResizeShow) {
vm.bottomBox.mainResizeShow = true;
}
}
if(resizeModalEndHeight < contentHideHeight){
if (vm.bottomBox.subResizeShow) {
vm.bottomBox.subResizeShow = false;
}
} else {
if (!vm.bottomBox.subResizeShow) {
vm.bottomBox.subResizeShow = true;
}
}
document.onmousemove = null;
document.onmouseup = null;
}
},
exitFullScreen(vm) {
window.resizing = true;
let contentRightDom = document.querySelector(".content-right"); //右侧内容区
let contentRightHeight = contentRightDom.offsetHeight;//可视高度
//主列表
document.querySelector(".main-list-with-sub").style.height = vm.bottomBox.mainListHeight ? vm.bottomBox.mainListHeight + 'px' : 'calc(50% - 4px)';
//副列表
document.querySelector(".sub-list").style.height = vm.bottomBox.mainListHeight ? contentRightHeight-vm.bottomBox.mainListHeight-9 + 'px' : 'calc(50% - 4px)';
setTimeout(() => {
if (document.querySelector(".main-list-with-sub").offsetHeight >= 100) {
vm.bottomBox.mainResizeShow = true;
}
if (document.querySelector(".sub-list").offsetHeight >= 100) {
vm.bottomBox.subResizeShow = true;
}
vm.bottomBox.isFullScreen = false;
window.resizing = false;
}, 210);
},
fullScreen(vm) {
window.resizing = true;
let contentRightDom = document.querySelector(".content-right"); //右侧内容区
let contentRightHeight = contentRightDom.offsetHeight;//可视高度
vm.bottomBox.isFullScreen = true;
//主列表
vm.bottomBox.mainListHeight = document.querySelector(".main-list-with-sub").offsetHeight; //记录全屏前主列表的高度
document.querySelector(".main-list-with-sub").style.height = '0';
vm.bottomBox.mainResizeShow = false;
//副列表
document.querySelector(".sub-list").style.height = contentRightHeight + 'px';
window.resizing = false;
},
showSubListWatch(vm, n) {
vm.bottomBox.inTransform = n;
if (!n) {
vm.mainTableHeight = vm.$tableHeight.normal; //重置table的高度
vm.tools.toTopBtnTop = vm.$tableHeight.toTopBtnTop;
vm.bottomBox.isFullScreen = false;
//移动分页组件的位置
let paginationTop = document.querySelector(".pagination-top");
let paginationBottom = document.querySelector(".pagination-bottom");
paginationTop.classList.remove("display-none");
if (paginationTop.classList.contains("pagination-top-show")) {
paginationTop.classList.remove("pagination-top-show");
}
if (!paginationTop.classList.contains("pagination-top-hide")) {
paginationTop.classList.add("pagination-top-hide");
}
setTimeout(() => {
paginationTop.classList.add("display-none");
paginationBottom.appendChild(paginationTop.removeChild(document.querySelector(".pagination")));
}, 210);
// 主列表恢复全屏
vm.bottomBox.mainResizeShow = vm.bottomBox.subResizeShow = true;
document.querySelector('.main-list').style.height = "";
//副列表高度清空
document.querySelector(".sub-list").style.height = "";
} else {
vm.mainTableHeight = vm.$tableHeight.openSubList.mainList; //重置table高度
vm.tools.toTopBtnTop = vm.$tableHeight.openSubList.toTopBtnTop;
//移动分页组件的位置
let paginationTop = document.querySelector(".pagination-top");
paginationTop.appendChild(document.querySelector(".pagination-bottom").removeChild(document.querySelector(".pagination")));
paginationTop.classList.remove("display-none");
setTimeout(() => {
if (paginationTop.classList.contains("pagination-top-hide")) {
paginationTop.classList.remove("pagination-top-hide");
}
if (!paginationTop.classList.contains("pagination-top-show")) {
paginationTop.classList.add("pagination-top-show");
}
}, 210);
}
}
};
export function stringTimeParseToUnix(stringTime){
let time=new Date(stringTime).getTime();
return time/1000;
}
export function unixTimeParseToString(unixTime,fmt='yyyy-MM-dd hh:mm:ss'){
let date=new Date(unixTime * 1000);
var o = {
"M+" : date.getMonth()+1, //月份
"d+" : date.getDate(), //日
"h+" : date.getHours(), //小时
"m+" : date.getMinutes(), //分
"s+" : date.getSeconds(), //秒
"q+" : Math.floor((date.getMonth()+3)/3), //季度
"S" : date.getMilliseconds() //毫秒
};
if(/(y+)/.test(fmt))
fmt=fmt.replace(RegExp.$1, (date.getFullYear()+"").substr(4 - RegExp.$1.length));
for(var 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;
}
//chart-resize工具
export const chartResizeTool = {
minHeight: 200, //图表最小高度
chartPaddingTop: 20, //图表padding-top
chartBlankHeight: 22, //图表空白占位高度(padding-top + border)
chartTableBlankHeight: 6, //表格型图表额外空白占位高度
chartBlankWidth: 20, //图表空白占位宽度
containerBlankWidth: 25, //容器空白占位宽度(#listContainer的padding
titleHeight: 28, //标题dom高度
stepHeight: 50, //单元高度
stepWidth(containerWidth) { //单元宽度,参数为容器总宽度
return (containerWidth-this.containerBlankWidth)/12;
},
calculateHeight(original) {
let height = Math.floor(original/this.stepHeight)*this.stepHeight;
if (height < this.minHeight) {
height = this.minHeight;
}
return height-this.chartBlankHeight;
},
start(vm, originalData, event) {
let data = JSON.parse(JSON.stringify(originalData)); //将初始对象复制,后续操作使用复制对象
let shadow = vm.$refs.resizeShadow; //缩放时底部阴影dom
if (!shadow) {
shadow = vm.$refs[0].resizeShadow;
}
let box = vm.$refs.resizeBox; //图表内容dom
if (!box) {
box = vm.$refs[0].resizeBox;
}
let chartPaddingTop = this.chartPaddingTop;
let chartBlankWidth = this.chartBlankWidth;
let chartBlankHeight = this.chartBlankHeight;
let titleHeight = this.titleHeight;
let stepWidth = this.stepWidth(document.getElementById('listContainer').offsetWidth);
let stepHeight = this.stepHeight;
let mouseOriginalX = event.clientX; //鼠标初始坐标
let mouseOriginalY = event.clientY;
let originalWidth = stepWidth*data.span; //图表、阴影初始宽高
let shadowNewWidth = originalWidth;
let originalHeight = data.height;
let shadowNewHeight = originalHeight;
//1.激活背景阴影
shadow.classList.add("resize-shadow-active");
//2.鼠标移动时调整resize-box的宽高同时监听宽高的变化变化量每达到step的50%时改变resize-shadow的尺寸并重绘resize-box内容
document.addEventListener("mousemove", moveListener);
//3.鼠标松开将resize-box宽高改为resize-shadow宽高结束
document.addEventListener("mouseup", mouseupListener);
function moveListener(e) {
let mouseX = e.clientX;
let mouseY = e.clientY;
//调整resize-box的宽高
box.style.width = `${originalWidth+(mouseX-mouseOriginalX)-chartBlankWidth}px`;
box.style.height = `${originalHeight+(mouseY-mouseOriginalY)-chartBlankHeight}px`;
//监听宽高的变化变化量每达到step的50%时改变resize-shadow的尺寸并重绘resize-box内容
let remainderWidth = (box.offsetWidth+chartBlankWidth-shadowNewWidth)%stepWidth; //宽的余数
let remainderHeight = (box.offsetHeight+chartBlankHeight-shadowNewHeight)%stepHeight; //高的余数
boxStepHandler(remainderWidth, remainderHeight);
}
function mouseupListener(e) {
//将resize-box的宽高设为resize-shadow的宽高
box.style.width = `${shadow.offsetWidth}px`;
box.style.height = `${Math.round(shadow.offsetHeight/10)*10}px`;
data.height = Math.round((box.offsetHeight+chartPaddingTop)/stepHeight)*stepHeight;
data.span = Math.round((box.offsetWidth+chartBlankWidth)/stepWidth);
//请求后台,保存变更
if (data.height != originalData.height || data.span != originalData.span) {
originalData.height = data.height;
originalData.span = data.span;
vm.$put("panel/" + vm.panelIdInner + "/charts/modify", originalData);
}
//关闭背景阴影
shadow.classList.remove("resize-shadow-active");
document.removeEventListener("mousemove", moveListener);
document.removeEventListener("mouseup", mouseupListener);
}
function boxStepHandler(width, height) { //param: 宽高变化量大于0放大小于0缩小
let widthChange = false;
let heightChange = false;
if (width > stepWidth/2) { //放大shadow宽
widthChange = true;
//判断是否因为百分数计算的宽度有小数的原因导致宽度超过当前行,使图表错误换行
let currentWidth = shadow.offsetWidth+stepWidth;
let currentSpan = Math.round((currentWidth+chartBlankWidth)/stepWidth);
let calcWidth = currentSpan*stepWidth-chartBlankWidth; //不会换行的宽度
shadow.style.width = `${calcWidth}px`;
} else if (width <= 0-(stepWidth/2)) { //缩小shadow宽
widthChange = true;
let currentWidth = shadow.offsetWidth-stepWidth;
let currentSpan = Math.round(currentWidth/stepWidth);
let calcWidth = currentSpan*stepWidth-chartBlankWidth; //不会换行的宽度
shadow.style.width = `${calcWidth}px`;
}
if (widthChange) {
shadowNewWidth = shadow.offsetWidth;
}
if (height > stepHeight/2) { //放大shadow高
heightChange = true;
shadow.style.height = `${Math.round(shadow.offsetHeight/10)*10+stepHeight}px`;
} else if (height <= 0-(stepHeight/2)) { //缩小shadow高
heightChange = true;
shadow.style.height = `${Math.round(shadow.offsetHeight/10)*10-stepHeight}px`;
}
if (heightChange) {
shadowNewHeight = shadow.offsetHeight+chartBlankHeight;
}
if (widthChange || heightChange) {
//step时chart重绘
if (box.classList.contains("resize-box-echarts")) { //echarts类型
vm.echartStore.resize({width: shadow.offsetWidth-16, height: shadow.offsetHeight-titleHeight-vm.$refs.legendArea.offsetHeight});
}
//chart外层宽高调整
let outerBox = document.getElementById(`chart-${data.id}`);
outerBox.style.height = `${shadow.offsetHeight+chartPaddingTop}px`;
outerBox.style.width = `${parseFloat(shadow.style.width.split("px")[0])+chartBlankWidth}px`;
}
}
}
};
//table 方法
export const tableSet = {
//是否需要排序
sortableShow(prop,from){
switch(prop){
// alert
case 'id':
case 'state': if(from === 'project' || from=== 'endpointTab'){return false}
case 'alertRule':
case 'severity':
case 'startAt':
case 'endAt':
// asset
case 'ID':
case 'HOST':
case 'SN':
case 'assetType':
case 'purchaseDate':
// case 'state':
case 'pingStatus':
case 'dataCenter':
case 'cabinet':
case 'model':
// case 'vendor':
case 'principal':
// project
// case 'id':
case 'asset':
case 'port':
case 'project':
case 'module':
case 'type':
// dc
// case 'id':
case 'name':
case 'area':
//endpointTab
// case 'id':
// case 'asset':
// case 'port':
// case 'project':
// case 'module':
// case 'type':
// model
// case 'id':
// case 'name':
// case 'type':
case 'vendor':
// promServer
// case 'id':
// case 'name':
// case 'type':
// case 'vendor':
// mib
// case 'id':
// case 'name':
case 'filename':
case 'updateAt':
// operationlog
// case 'id':
case 'username':
case 'ip':
case 'operation':
// case 'type':
case 'createDate':
case 'time':
// temrminallog
// case 'id':
case 'host':
// case 'port':
case 'protocol':
case 'user':
case 'cmd':
// case 'time':
//config
// case 'id':
case 'alertName':
case 'threshold':
// case 'severity':
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 '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 '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 'id': return 'id';
case 'host': return 'host';
case 'port': return 'port';
case 'protocol': return 'protocol';
case 'user': return 'user';
case 'cmd': return 'cmd';
case 'time': return 'time';
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;
}
default: break;
}
},
}
export function blankPromise() {
return new Promise(resolve => {resolve();});
}