diff --git a/hg-monitor-web-base/src/main/resources/static/src/controller/commonDetail.js b/hg-monitor-web-base/src/main/resources/static/src/controller/commonDetail.js index 5027d6e..4cf9bf0 100644 --- a/hg-monitor-web-base/src/main/resources/static/src/controller/commonDetail.js +++ b/hg-monitor-web-base/src/main/resources/static/src/controller/commonDetail.js @@ -3859,7 +3859,11 @@ layui.define(['laytpl', 'admin', 'form', 'table', 'echarts', 'sessions', 'xmSele return; } //url(/src/style/img/shutdown.png) - title +=`<span id="title-shutdown" data-id=${resId} style="padding:0 5px;width:600px;display: inline-block;position: relative;top: 0px;left:20px;"></span>` + title +=`<span id="title-shutdown" data-id=${resId} style="flex:1;padding:0 5px;width:600px;display: inline-block;position: relative;top: 0px;left:20px;"></span>` + // ztq 2023-06-01 + title += `<div style="width:60px;display:flex;justify-content: flex-end"><a class="layui-icon res-view-addSnapshot" data-id=${resId} lay-tips="创建快照" style=" margin:0 10px"> <img width="20" src="/src/style/img/snapshotadd.png" ></a>`; + title += `<a class="layui-icon res-view-history" data-id=${resId} data-resname=${res.resName} data-ip=${ip} data-restypename=${res.resTypeName} data-adminname=${res.adminName} lay-tips="快照历史记录" style=""> <img width="20" src="/src/style/img/snapshothistory.png" ></a></div>`; + obj.openNewWin(url, title, params, editFlag, fn, cancelfn, type,sign_); }, error: function () { @@ -3870,6 +3874,10 @@ layui.define(['laytpl', 'admin', 'form', 'table', 'echarts', 'sessions', 'xmSele title += `<a class="layui-icon layui-icon-rate" data-id=${resId} lay-tips="加入收藏夹"></a>`; title += `<a class="layui-icon filterList" data-id=${resId} lay-tips="指标过滤清单" style="margin-left: 10px"><i class="iconfont"></i></a>`; title += `<a class="layui-icon res-view-relation-topo" data-id=${resId} lay-tips="查看资源关系拓扑" style="margin-left: 10px"><i class="iconfont"></i></a>`; + // ztq 23-06-01 + title += `<a class="layui-icon res-view-ping" data-id=${resId} data-resname=${res.resName} data-ip=${ip} data-restypename=${res.resTypeName} data-adminname=${res.adminName} lay-tips="历史数据" style="margin-left: 10px;position:relative;top:-3px;"> <img width="20" src="./src/style/img/ping.png" ></a>`; + title += `<div style="width:60px;display:flex;justify-content: flex-end"><a class="layui-icon res-view-addSnapshot" data-id=${resId} lay-tips="创建快照" style=" margin: 0 10px"> <img width="20" src="./src/style/img/snapshotadd.png" ></a>`; + title += `<a class="layui-icon res-view-history" data-id=${resId} data-resname=${res.resName} data-ip=${ip} data-restypename=${res.resTypeName} data-adminname=${res.adminName} lay-tips="快照历史记录" style=""> <img width="20" src="./src/style/img/snapshothistory.png" ></a></div>`; if (resCategory === 'share' && hardwareFlag.endsWith("Y")) { title += `<a class="layui-icon res-view-assets-details" data-ip=${ip} data-name=${name} data-restype=${resType} data-id=${resId} lay-tips="资产配置信息"><i class="iconfont"></i></a>`; } @@ -3921,7 +3929,7 @@ layui.define(['laytpl', 'admin', 'form', 'table', 'echarts', 'sessions', 'xmSele obj.loadResAlarm(params.resId); view('commonViewModel').render(url).then(function (res) { layer.open({ - title: [name, 'font-size:20px;background-color: #d0ddec;'], + title: [name, 'font-size:20px;background-color: #d0ddec;display:flex;align-items: center; justify-content: flex-start;'], type: 1, id: md5(url), area: area , @@ -4129,6 +4137,43 @@ layui.define(['laytpl', 'admin', 'form', 'table', 'echarts', 'sessions', 'xmSele // layer.close(detailTips); // } // }) + + // ztq 23-06-01 + $('a.res-view-addSnapshot').unbind('click').on('click', function () { + var resId = $(this).data('id'); + layer.confirm('将创建该资源的所有快照信息,请确认', { + btn: ['确定', '取消'] //按钮 + }, function () { + admin.req({ + url: common.domainName + '/api-web/snapshot/his/add?access_token=' + layui.sessions.getToken().access_token +'&resId=' + resId + , type: 'get' + , done: function (res) { + if (res.success) { + layer.msg('操作成功!', {offset: '15px', icon: 1, time: 2000}); + } else { + layer.msg(res.msg, {offset: '15px', icon: 7, time: 2000}); + } + } + }); + }); + }); + $('a.res-view-history').unbind('click').on('click', function () { + let name = $(this).data('resname')+' |'+$(this).data('restypename')+' |'+$(this).data('ip')+' |'+'历史快照数据'; + let paramStr = '?resId=' + $(this).data('id'); + layer.open({ + title: [name, 'font-size:18px;'], + type: 2, + area: ['65%', '90%'], + shadeClose: true,//开启遮罩层 + id: 'res-history', + content: ['/vue3/index.html#/vue3/snapshot/history' + paramStr, 'no'], + cancel: function () { + clearTimeout(); + } + }); + }); + + //start lsq 增加停机状态跑马灯效果 2022-05-24 let resId= $('#title-shutdown').data("id"); admin.req({ diff --git a/hg-monitor-web-base/src/main/resources/static/src/controller/myNoticeIndex.js b/hg-monitor-web-base/src/main/resources/static/src/controller/myNoticeIndex.js new file mode 100644 index 0000000..ebcd715 --- /dev/null +++ b/hg-monitor-web-base/src/main/resources/static/src/controller/myNoticeIndex.js @@ -0,0 +1,702 @@ +//通知查询 +layui.define(['table', 'form', 'admin', 'layer', 'common','sessions', 'xmSelect', 'echarts','laydate'], function (exports) { + var $ = layui.$; + var form = layui.form; + var layer = layui.layer; + var admin = layui.admin; + var table = layui.table; + var common = layui.common; + var domainName = common.domainName; + var xmSelect = layui.xmSelect; + var echarts = layui.echarts; + var laydate = layui.laydate; + + //对外暴露的接口 + exports('myNoticeIndex', function (data) { + var resTypeSelect = {}; //资源类型下拉框 + var busIdSelect = {}; //业务类型下拉框 + var userSelect = {}; //通知用户下拉框 + var busId = ''; + var resType = ''; + var userNames = ''; + var sessions = layui.sessions; + var accessToken = sessions.getToken()['access_token']; + var noticeUserChart = echarts.init(document.getElementById('my_notice_chart_user')); + var noticeTypeChart = echarts.init(document.getElementById('my_notice_chart_type')); + // var noticeUserChartNew = echarts.init(document.getElementById('my_notice_chart_user_new')); + // lsq 告警指标 2022-07-05 + var alarmKpi= ''; + //回车搜索 + $('#notice_search_keyword').keydown(function (e) { + if (e.keyCode === 13) { + reloadData(); + } + }); + //查询按钮点击事件 + $('#noticeSearchQueryBtn').on('click',function () { + reloadData(); + }) + + //发送状态 + form.on('select(notice_search_isSend)', function(){ + reloadData(); + }); + + $('#queryMore').on('click',function(){ + queryData(); + }); + + $('button[data-period]').on('click',function(){ + var that = $(this); + that.addClass('active'); + that.removeClass('layui-btn-primary'); + var currentVal = that.attr('data-period'); + $.each($('button[data-period]'), function(index , el){ + var itemEl = $(el); + var val = itemEl.attr('data-period'); + if(currentVal != val){ + itemEl.addClass('layui-btn-primary'); + itemEl.removeClass('active'); + } + }); + + // yyyy-MM-dd HH:mm:ss - yyyy-MM-dd HH:mm:ss + if(currentVal == 'custom'){ + laydate.render({ + elem: '#dataPeriodCustom', //指定元素 + range: true, + type: 'datetime', + isInitValue: false, + isPreview: false, + value : new Date(), + format:'yyyy-MM-dd HH:mm:ss', + show: true, //直接显示 + done: function(value, date, endDate){ + that.attr('data-val',value); + reloadData(); + } + }); + return; + } + reloadData(); + }); + + + + form.render(); + + getChartData(); + //渲染表格 + var noticeTable = table.render({ + elem: '#myNoticeSearchTable' + , url: domainName + '/api-web/notice/myPage' + , where:{ + access_token:accessToken, + keyword: $('#notice_search_keyword').val(), + busId: busId, + resType: resType, + usernames:userNames, + isSend: $('#notice_search_isSend').val(), + alarmKpi: $("#myNoticeAlarmKpiSearchBox").val(), + way:$('#myNoticeWaySearchBox').val(), + dataPeriod: $('button[data-period].active').attr('data-period'), + timeRange: $('button[data-period].active').attr('data-val') + } + , height: 'full-380' + , page: { + layout: ['count', 'prev', 'page', 'next', 'limit', 'skip'] + ,theme: '#1E9FFF'//自定义分页主题颜色 + } + , end: function(e){ + form.render(); + } + , even: true + , cols: [[ + {title: '序号', align: "center", type: 'numbers',width: '3%'} + , {field: 'typeName', title: '通知类型', align: 'center', sort: true, width:130} + , {field: 'way', title: '通知方式', align: 'center', sort: true, width:120, + templet: function (d){ + switch (d.way){ + case 'wechat': + return '<div class="small-icon small-icon-wechat"></div>' + break; + case 'email': + return '<div class="small-icon small-icon-email"></div>' + break; + case 'message': + return '<div class="small-icon small-icon-msg"></div>' + break; + default: + return '<div class="small-icon small-icon-msg"></div>' + break; + + } + }} + // , {field: 'targetId', title: '通知对象', align: 'center', sort: true, width:180} + , {field: 'content', title: '通知内容', align: 'left', sort: true, minWidth: 300,} + , {field: 'nickname', title: '通知用户', align: 'center', sort: true, width:200} + , {field: 'noticeTime', title: '通知时间', align: 'center', sort: true, width:180} + // , {field: 'createTime',title: '入库时间',align: 'center', sort: true,width:180} + , {title: '操作', align: 'center',width: 80,fixed: 'right', + templet: function (d) { + var str = ''; + if (d.ipAddr && d.ipAddr !== '') { + str += `ip地址 : ${d.ipAddr}</br>` + } + if (d.resName && d.resName !== '') { + str += `资源名称 : ${d.resName}</br>` + } + if (d.busName && d.busName !== '') { + str += `业务名称 : ${d.busName}</br>` + } + if (d.kpiName && d.kpiName !== '') { + str += `指标名称 : ${d.kpiName}</br>` + } + if (d.reportType && d.reportType !== '') { + str += `报表类型 : ${d.reportType}</br>` + } + if (d.alarmTimes && d.alarmTimes !== '') { + str += `告警次数 : ${d.alarmTimes}次</br>` + } + if (str.trim() !== '') { + return `<div><button lay-tips="${str}" type="button" class="layui-btn layui-btn-xs layui-btn-normal"><i class="layui-icon layui-icon-star-fill"></i></button></div>` + } else { + return `<div><button type="button" class="layui-btn layui-btn-xs layui-btn-normal"><i class="layui-icon layui-icon-star-fill"></i></button></div>` + + } + } + } + ]], + done:function () { + + } + }); + //用户下拉框 joke add 20211209 + /*$.ajax({ + url: `${common.domainName}/api-web/notice/getNoticeUsers?access_token=${accessToken}`, + method: 'GET', + success: function (response) { + if (response && response.success){ + userSelect = xmSelect.render({ + el: '#notice_user_list', + name: 'users', + tips: '=接收人=', + //开启搜索 + filterable: true, + radio: true, + clickClose: true, + height: '170px', + tree: { + show: true, + showFolderIcon: true, + showLine: true, + strict: false, + indent: 20 + }, + model: { + label: { + type: 'text' + } + }, + prop: { + name: 'nickname', + value: 'username' + }, + data: response.data, + on: function (data) { + if (data.arr && data.arr.length > 0){ + userNames = data.arr[0].username; + } else { + userNames = ''; + } + reloadData(); + } + }); + }else{ + layer.msg('获取资源类型失败', {icon: 2}); + } + if(userSelect){ + //追加样式 + $('#notice_user_list').find('.xm-body').eq(0).css("width","230px"); + } + } + });*/ + + //绑定业务下拉选择数据 joke add 20211209 + admin.req({ + url: domainName + '/api-web/notice/getNoticeBusTypes', + success: function (response) { + if (response && response.success) { + var busTypeList = response.data; + // 影响业务下拉框 + busIdSelect = xmSelect.render({ + el: '#my_notice_search_busId', + name: 'bizId', + tips: '=业务类型=', + //开启搜索 + filterable: true, + radio: true, + clickClose: true, + height: '170px', + tree: { + show: true, + showFolderIcon: true, + showLine: true, + strict: false, + indent: 20 + }, + model: { + label: { + type: 'text' + } + }, + prop: { + name: 'busTypeName', + value: 'busId' + }, + data: busTypeList, + on: function (data) { + if (data.isAdd){ + busId = data.arr[0].busId; + } else { + busId = ''; + } + reloadData(); + } + }); + if(busIdSelect){ + //追加样式 + $('#my_notice_search_busId').find('.xm-body').eq(0).css("width","230px"); + } + } else { + layer.msg('获取业务失败', {icon: 2}); + } + }, + error: function () { + layer.msg('获取业务失败', {icon: 2}); + } + }); + //资源类型下拉框 joke add 20211209 + $.ajax({ + url: `${common.domainName}/api-web/notice/getNoticeResTypes?access_token=${accessToken}`, + method: 'GET', + success: function (res) { + // 资源类型下拉框 + if (res && res.success){ + var resTypeList = res.data; + resTypeSelect = xmSelect.render({ + el: '#my_notice_search_resType', + name: "resType", + tips: '=资源类型=', + filterable: true, + radio: true, + clickClose: true, + prop: { + name: 'resTypeName', + value: 'resTypeCode' + }, + tree: { + show: true, + showFolderIcon: true, + showLine: true, + strict: false, + indent: 20 + }, + model: { + label: { + type: 'text' + } + }, + height: '170px', + data: resTypeList, + on: function (data) { + if (data.isAdd){ + resType = data.arr[0].resTypeCode; + } else { + resType = ''; + } + reloadData(); + } + }); + if(busIdSelect){ + //追加样式 + $('#my_notice_search_resType').find('.xm-body').eq(0).css("width","230px"); + } + }else{ + layer.msg('获取资源类型失败', {icon: 2}); + } + + } + }); + // lsq 告警指标下拉列表 2022-07-05 + $.ajax({ + url: common.domainName + '/api-web/manage/kpi/findKpiInAlarm?access_token='+accessToken+'&tableName=b_alarm', + type: "get", + success:function (res) { + var kpis = res.data; + var html = '<option value="">=指标名称=</option>' + $.each(kpis,function (i,e) { + html+='<option value="'+e.kpiId+'">'+e.kpiName+'</option>' + }) + $("#myNoticeAlarmKpiSearchBox").html(''); + $("#myNoticeAlarmKpiSearchBox").append(html); + form.render(); + } + }) + //lsq 通知方式下拉列表 2022-07-07 + $.ajax({ + url: domainName + '/api-web/manage/ddic/findSucDdics/notice_type?access_token='+accessToken, + type: "POST", + success:function (res) { + var ways = res.data; + var html = '<option value="">=通知方式=</option>' + $.each(ways,function (i,e) { + html+='<option value="'+e.ddicCode+'">'+e.ddicName+'</option>' + }) + $("#myNoticeWaySearchBox").html(''); + $("#myNoticeWaySearchBox").append(html); + form.render(); + } + }) + + //刷新表格 + function reloadTable() { + noticeTable.reload({ + page: { + curr: 1 + }, + where:{ + access_token:accessToken, + keyword: $('#notice_search_keyword').val(), + busId: busId, + resType: resType, + isSend: $('#notice_search_isSend').val(), + usernames:userNames, + page: 1, + alarmKpi: $("#myNoticeAlarmKpiSearchBox").val(), + way:$('#myNoticeWaySearchBox').val(), + dataPeriod: $('button[data-period].active').attr('data-period'), + timeRange: $('button[data-period].active').attr('data-val') + } + }); + } + + //未读人员 + function loadNoticeChart(echartObject,xData,yData) { + var series = [{ + name: '通知次数', + data: yData, + barWidth: 20, + type: 'bar', + label: { + show: true, + position: 'top', + textStyle: { + color: '#555' + }, + }, + itemStyle: { + normal: { + color: (params) => { + var colors = ['#b6c2ff', '#96edc1', '#fcb75b']; + return colors[params.dataIndex % 3] + } + } + }, + emphasis: { + itemStyle: { + color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [ + { offset: 0, color: '#2378f7' }, + { offset: 0.7, color: '#2378f7' }, + { offset: 1, color: '#83bff6' } + ]) + } + }, + }] + + var option = { + tooltip: { + trigger: 'axis', + axisPointer: { + type: 'shadow' + } + }, + grid: [{ + top: 20, + bottom: 45, + left: 40, + right: 5 + }], + xAxis: [{ + type: 'category', + data: xData, + axisLabel: { + color: '#333', + show: true, + interval:0, + rotate:15 + }, + axisLine: { + lineStyle: { + color: '#e7e7e7' + } + }, + axisTick: { + lineStyle: { + color: '#e7e7e7' + } + }, + zlevel: 1 + }], + yAxis: [{ + type: 'value', + gridIndex: 0, + axisLabel: { + color: '#333' + }, + splitLine: { + lineStyle: { + type: 'dashed' + } + }, + axisLine: { + lineStyle: { + color: '#ccc' + } + }, + axisTick: { + lineStyle: { + color: '#ccc' + } + } + }], + series: series, + dataZoom: [ + { + type: 'inside' + } + ], + } + echartObject.setOption(option) + const zoomSize = 6; + echartObject.on('click', function (params) { + echartObject.dispatchAction({ + type: 'dataZoom', + startValue: xData[Math.max(params.dataIndex - zoomSize / 2, 0)], + endValue: + xData[Math.min(params.dataIndex + zoomSize / 2, yData.length - 1)] + }); + }); + } + /********************单独加载更多****************************/ + function loadNoticeMoreChart(echartObject,xData,yData) { + var series = [{ + name: '通知次数', + data: yData, + barWidth: 20, + type: 'bar', + label: { + show: true, + position: 'top', + textStyle: { + color: '#555' + }, + }, + itemStyle: { + normal: { + color: (params) => { + var colors = ['#b6c2ff', '#96edc1', '#fcb75b']; + return colors[params.dataIndex % 3] + } + } + }, + emphasis: { + itemStyle: { + color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [ + { offset: 0, color: '#2378f7' }, + { offset: 0.7, color: '#2378f7' }, + { offset: 1, color: '#83bff6' } + ]) + } + }, + }] + + var option = { + tooltip: { + trigger: 'axis', + axisPointer: { + type: 'shadow' + } + }, + grid: [{ + top: 20, + bottom: 70, + left: 30, + right: 5 + }], + xAxis: [{ + type: 'category', + data: xData, + axisLabel: { + color: '#333', + show: true, + interval:0, + rotate:15 + }, + axisLine: { + lineStyle: { + color: '#e7e7e7' + } + }, + axisTick: { + lineStyle: { + color: '#e7e7e7' + } + }, + zlevel: 1 + }], + yAxis: [{ + type: 'value', + gridIndex: 0, + axisLabel: { + color: '#333' + }, + splitLine: { + lineStyle: { + type: 'dashed' + } + }, + axisLine: { + lineStyle: { + color: '#ccc' + } + }, + axisTick: { + lineStyle: { + color: '#ccc' + } + } + }], + series: series, + dataZoom: [ + { type: 'slider', + show: true, + xAxisIndex: [0], + left: '1%', + bottom: -5, + start: 0, + end: 20 //初始化滚动条 + } + ], + } + echartObject.setOption(option) + window.onresize=function(){ + echartObject.resize(); + } + // const zoomSize = 6; + // echartObject.on('click', function (params) { + // echartObject.dispatchAction({ + // type: 'dataZoom', + // startValue: xData[Math.max(params.dataIndex - zoomSize / 2, 0)], + // endValue: + // xData[Math.min(params.dataIndex + zoomSize / 2, yData.length - 1)] + // }); + // }); + } + //获取图表数据 + function getChartData() { + var where = { + access_token:accessToken, + keyword: $('#notice_search_keyword').val(), + busId: busId, + resType: resType, + isSend: $('#notice_search_isSend').val(), + alarmKpi: $("#myNoticeAlarmKpiSearchBox").val(), + way:$('#myNoticeWaySearchBox').val(), + dataPeriod: $('button[data-period].active').attr('data-period'), + timeRange: $('button[data-period].active').attr('data-val') + }; + + $.ajax({ + url: `${common.domainName}/api-web/notice/myGroupByType`, + method: 'GET', + data: where, + success: function (res) { + var xData = []; + var yData = []; + if (res && res.map) { + $.each(res.map.typeList,function (i,v) { + xData.push(v) + }) + yData = res.map.countList; + } + loadNoticeChart(noticeTypeChart,xData,yData) + } + }) + + $.ajax({ + url: `${common.domainName}/api-web/notice/myGroupByUser`, + method: 'GET', + data: where, + success: function (res) { + if (res && res.data) { + var yData = res.data.map(item=>item.count); + var xData = res.data.map(item=>item.noticeTime); + //展示前20条数据 @Editor LH + loadNoticeChart(noticeUserChart,xData.slice(0, 15), yData.slice(0, 15)); + } + } + }) + } + + function reloadData(){ + getChartData(); + reloadTable(); + } + function queryData(){ + var $content = $('#more_info'); + layer.open({ + type: 1 + , title: '人员分组统计' //不显示标题栏 + , area: ["91%", "500px"] + , id: 'aaa' //设定一个id,防止重复弹出 + , btn:['取消'] + , content: $content.html() + , success: function (layero, index) { + var where = { + access_token:accessToken, + keyword: $('#notice_search_keyword').val(), + busId: busId, + resType: resType, + isSend: $('#notice_search_isSend').val(), + alarmKpi: $("#myNoticeAlarmKpiSearchBox").val(), + way:$('#myNoticeWaySearchBox').val(), + dataPeriod: $('button[data-period].active').attr('data-period'), + timeRange: $('button[data-period].active').attr('data-val') + }; + var noticeTypeChartNew = echarts.init(document.getElementById('my_notice_chart_type_new')); + $.ajax({ + url: `${common.domainName}/api-web/notice/myGroupByUser`, + method: 'GET', + data: where, + success: function (res) { + if (res && res.data) { + var yData = res.data.map(item=>item.count); + var xData = res.data.map(item=>item.noticeTime); + //展示前20条数据 @Editor LH + loadNoticeMoreChart(noticeTypeChartNew,xData, yData); + } + } + }) + } + , yes: function (index, layero) { + layer.close(index); //执行关闭 + // if (fn && fn()) { + // fn() + // layer.close(index); //如果设定了yes回调,需进行手工关闭 + // } + } + }); + } + }); +}); diff --git a/hg-monitor-web-base/src/main/resources/static/src/controller/snapshot_detail.js b/hg-monitor-web-base/src/main/resources/static/src/controller/snapshot_detail.js new file mode 100644 index 0000000..df15516 --- /dev/null +++ b/hg-monitor-web-base/src/main/resources/static/src/controller/snapshot_detail.js @@ -0,0 +1,149 @@ +layui.define(['commonDetail', 'common', 'sessions'], function (exports) { + var commonDetail = layui.commonDetail; + var $ = layui.$ + , laytpl = layui.laytpl + //对外暴露的接口 + exports('snapshot_detail', function (data) { + var common = layui.common; + var sessions = layui.sessions; + var table = layui.table; + var view = layui.view; + var laytpl = layui.laytpl; + var resId = ''; + var batchNo = ''; + var showFlag = common.getUrlParam("show"); + if (showFlag && showFlag == '0') { + resId = common.getUrlParam("resId"); + batchNo = common.getUrlParam("batchNo"); + } else { + resId = data.resId; + batchNo = data.batchNo; + } + findAllSnapshot(); + + commonDetail.bindTips(); + + function findAllSnapshot() { + // 删除所有的子元素 + $('#table_arr_body').empty(); + let url = common.domainName + '/api-web/snapshot/info?resId='+ resId + '&batchNo='+batchNo +'&access_token='+sessions.getToken().access_token; + $.ajax({ + url: url, + type: 'get', + async: false, + success: function (res) { + if (res.success){ + if (res.object.snapshotResState){ + commonDetail.snapshotRenderResHealth(res.object.snapshotResState); + } + commonDetail.anapshotRenderTextCols('hostminicomputerpartition_jbxx',res.object.snapshotBaseInformationList,2); + if (res.object.importantInformationList != null && res.object.importantInformationList.length > 0){ + commonDetail.anapshotRenderTextCols('hostminicomputerpartition_sysfile',res.object.importantInformationList,2); + }else { + $("#hostminicomputerpartition_sysfile").html('<div style="text-align:center;"><span style="line-height: 150px; padding:20px;font-style:normal;">暂无数据</span></div>') + } + commonDetail.snapshotRenderActiveAlarms("告警列表","snapshow_active_alram", res.object.snapshotAlamList); + console.log(res.object.snapshotRecordList); + let tableArr = res.object.snapshotRecordList; + let domTableArr=''; + // 渲染生成节点 + tableArr.forEach((item,index)=>{ + domTableArr+=` + <div class="lay-row"> + <div class="lay-row-item"> + <h5 class="lay-row-title">${item.name} + <span class="layui-table-link" id="snapshot_wkinfoDownload_${index}" + style="margin-left: 10px;">下载</span> + <span class="layui-table-link" id="snapshot_wkinfoMore_${index}">更多</span> + </h5> + <div id="snapshot_wkinfo_${index}"></div> + </div> + </div> + ` + }) + // console.log(domTableArr); + $('#table_arr_body').append(domTableArr) + + // 渲染节点表格数据 + tableArr.forEach((item,index)=>{ + let cols = []; + let datas = []; + item.header.map((headerItem,headerIndex)=>{ + if (headerItem.unit){ + cols.push({ + field:headerItem.id,title:headerItem.name+'('+headerItem.unit+')',sort:true,align:"center", + }) + }else { + cols.push({ + field:headerItem.id,title:headerItem.name,sort:true,align:"center", + }) + } + }) + item.content.map((contItem,contIndex)=>{ + let obj = {}; + contItem.map((v,i)=>{ + obj[v.kpiId] = v.kpiValue + }) + datas.push(obj) + }) + + /*console.log('cols--------------',cols); + console.log('datas--------------',datas);*/ + // 创建渲染实例 + table.render({ + elem: `#snapshot_wkinfo_${index}` + ,page: false + ,data: datas + ,cols: [cols] + ,done(response, curr, count){ + delete response.data[0].LAY_TABLE_INDEX // + let keys = response.data[0] + let params = { + kpiId:Object.keys(keys).join(','), + resId:resId, + batchNo:batchNo, + tableName:item.name, + flagPrefix:item.flagPrefix + } + // 点击下载的方法 + $(`#snapshot_wkinfoDownload_${index}`).unbind('click').on('click',()=>{ + let url = `${common.domainName}/api-web/snapshot/info/download?kpiId=${params.kpiId}&resId=${params.resId}&batchNo=${params.batchNo}&tableName=${params.tableName}&flagPrefix=${params.flagPrefix}&access_token=${sessions.getToken().access_token}` + window.open(url) + }) + // 点击更多的方法 + $(`#snapshot_wkinfoMore_${index}`).unbind('click').on('click',()=>{ + view('commonViewModel').render("template/detail/snapshot_detail_more").then(function (res) { + layer.open({ + title: ["更多", 'font-size:18px;'], + type: 1, + shadeClose: true,//开启遮罩层 + area: ['90%', '690px'], + content: laytpl(res.body).render(JSON.stringify(params)) + }); + }); + }) + } + ,error(){ + + } + }) + }) + }else { + layer.msg(res.msg, { + icon: 7, time: 2000 + }); + } + } + }) + } + + + + //定时任务 + // var timer = setInterval(function () { + // findAllSnapshot() + // }, commonDetail.timerTime); + // commonDetail.detailTimer.push(timer); + + }); +}); diff --git a/hg-monitor-web-base/src/main/resources/static/src/style/img/ping.png b/hg-monitor-web-base/src/main/resources/static/src/style/img/ping.png new file mode 100644 index 0000000..fb18961 Binary files /dev/null and b/hg-monitor-web-base/src/main/resources/static/src/style/img/ping.png differ diff --git a/hg-monitor-web-base/src/main/resources/static/src/style/img/snapshotadd.png b/hg-monitor-web-base/src/main/resources/static/src/style/img/snapshotadd.png new file mode 100644 index 0000000..e808acf Binary files /dev/null and b/hg-monitor-web-base/src/main/resources/static/src/style/img/snapshotadd.png differ diff --git a/hg-monitor-web-base/src/main/resources/static/src/style/img/snapshothistory.png b/hg-monitor-web-base/src/main/resources/static/src/style/img/snapshothistory.png new file mode 100644 index 0000000..f91987b Binary files /dev/null and b/hg-monitor-web-base/src/main/resources/static/src/style/img/snapshothistory.png differ diff --git a/hg-monitor-web-base/src/main/resources/static/src/views/baseconfig/myNotice/index.html b/hg-monitor-web-base/src/main/resources/static/src/views/baseconfig/myNotice/index.html new file mode 100644 index 0000000..cbc1b26 --- /dev/null +++ b/hg-monitor-web-base/src/main/resources/static/src/views/baseconfig/myNotice/index.html @@ -0,0 +1,145 @@ +<style> + .layui-card-echart .lay-row-title { + font-size: 14px; + line-height: 2; + padding: 2px 10px; + background: #f6f6f6; + margin: 0px 3px; + /*display: block;*/ + /*float: left;*/ + + } +</style> + + +<title>我的通知</title> +<article class="page-container"> + <div class="page-panel"> + <div class="main"> + <div class="layui-card" style="overflow: hidden"> + <div class="layui-card-header" style=" padding: 0 3px;"> + <div class="layui-status search_panel"> + <form style="padding:5px 0 0 0;" class="layui-form layui-card-header layuiadmin-card-header-auto" lay-filter="notice_search_form"> + <div class="layui-form-item"> + <div class="layui-inline"> + <div class="layui-input-inline layui-input-inline--long"> + <input type="text" id="notice_search_keyword" name="keyword" lay-tips="关键字检索包含 </br>资源名称</br>ip地址</br>通知内容" placeholder="输入关键字,回车搜索" autocomplete="off" class="layui-input"> + </div> + </div> + <!--资源类型--> + <div class="layui-inline"> + <div class="layui-input-inline layui-input-inline--long"> + <div class="xm-select-demo" id="my_notice_search_resType"></div> + </div> + </div> + <!--用户列表--> +<!-- <div class="layui-inline">--> +<!-- <div class="layui-input-inline layui-input-inline--long">--> +<!-- <div class="xm-select-demo" id="notice_user_list"></div>--> +<!-- </div>--> +<!-- </div>--> + <!--业务类型--> + <div class="layui-inline"> + <div class="layui-input-inline layui-input-inline--long"> + <div class="xm-select-demo" id="my_notice_search_busId"></div> + </div> + </div> + <!--发送状态--> + <!--<div class="layui-inline"> + <div class="layui-input-inline layui-input-inline--long"> + <select id="notice_search_isSend" lay-filter="notice_search_isSend"> + <option value="1">已发送</option> + <option value="">待发送</option> + </select> + </div> + </div>--> + <!--lsq 告警指标 2022-07-05--> + <div class="layui-inline"> + <div class="layui-input-inline"> + <select name="alarmKpi" lay-filter="alarmKpiSearch" lay-search="" id="myNoticeAlarmKpiSearchBox"> + </select> + </div> + </div> + <!--lsq 通知方式 2022-07-05--> + <div class="layui-inline"> + <div class="layui-input-inline"> + <select name="way" lay-filter="noticeWaySearch" llay-search="" id="myNoticeWaySearchBox"> + </select> + </div> + </div> + <div class="layui-inline"> + <div class="layui-btn-group"> + <button type="button" class="layui-btn layui-btn-primary" data-period="all">全部</button> + <button type="button" class="layui-btn active" data-period="today">今天</button> + <button type="button" class="layui-btn layui-btn-primary" data-period="week">本周</button> + <button type="button" class="layui-btn layui-btn-primary" data-period="month">本月</button> + <button type="button" class="layui-btn layui-btn-primary" data-period="custom" id="dataPeriodCustom">自定义</button> + </div> + </div> + <div class="layui-inline"> + <button id="noticeSearchQueryBtn" type="button" class="layui-btn layui-btn-normal" ><i + class="layui-icon layui-icon-search"></i>查询 + </button> + </div> + </div> + </form> + + </div> + </div> + <div style="display: flex" class="layui-card-echart"> + <div style="flex-grow: 3;width: 66%!important;" > + <div class="lay-row-title" id="personTotal"> 人员分组统计 <div style=" float:right;"><button type="button" style="color:#1e9fff" id="queryMore">查看更多</button></div></div> + + <div class="pie-chart" id="my_notice_chart_user"></div> + </div> + <div style="flex-grow: 1"> + <h5 class="lay-row-title">分类分组统计</h5> + <div class="pie-chart" id="my_notice_chart_type"></div> + </div> +<!-- <div style="flex-grow: 1">--> +<!-- <div class="layui-tab layui-tab-card" lay-filter="report-tab">--> +<!-- <ul class="layui-tab-title">--> +<!-- <li class="layui-this">未读信息</li>--> +<!-- <li>未报信息</li>--> +<!-- <li>未处理告警信息</li>--> +<!-- </ul>--> +<!-- <div class="layui-tab-content tab-content">--> +<!-- <div class="layui-tab-item layui-show">--> +<!-- <div class="pie-chart-clone" id="chart-noRead-report"></div>--> +<!-- </div>--> +<!-- <div class="layui-tab-item">--> +<!-- <div class="pie-chart-clone" id="chart-noReport-report"></div>--> +<!-- </div>--> +<!-- <div class="layui-tab-item">--> +<!-- <div class="pie-chart-clone" id="chart-noAlarm-report"></div>--> +<!-- </div>--> +<!-- </div>--> +<!-- </div>--> +<!-- </div>--> + </div> + <div class="layui-card-body" style="margin-top: 25px"> + <table id="myNoticeSearchTable"></table> + </div> + </div> + </div> + </div> + <textarea class="hide" id="my-noticeIndex-params">{{d}}</textarea> +</article> +<!--上传弹框--> +<script id="more_info" type="text/html"> + <div style="align:center;padding: 20px;height: 330px"> + <div class="lay-row-title" lay-tips="灰色拖动条可以左右拉缩并拖动展示其它数据"> 人员分组统计 </div> + <div class="pie-chart" style="height: 100%" id="my_notice_chart_type_new"></div> + </div> +</script> +<script> + var params = document.getElementById("my-noticeIndex-params").value; + layui.use('myNoticeIndex', function (fn) { + if(params.indexOf("{{d") !== -1){ + fn(); + } else { + fn(JSON.parse(params)); + } + }); +</script> + diff --git a/hg-monitor-web-base/src/main/resources/static/src/views/snapshot/index.html b/hg-monitor-web-base/src/main/resources/static/src/views/snapshot/index.html new file mode 100644 index 0000000..8245aa9 --- /dev/null +++ b/hg-monitor-web-base/src/main/resources/static/src/views/snapshot/index.html @@ -0,0 +1,2 @@ +<title>快照管理</title> +<iframe src="/vue3/index.html#/vue3/snapshot" frameborder="0" class="layadmin-iframe" style="height: 99.5%!important;"/> \ No newline at end of file diff --git a/hg-monitor-web-base/src/main/resources/static/src/views/snapshotOverview/index.html b/hg-monitor-web-base/src/main/resources/static/src/views/snapshotOverview/index.html new file mode 100644 index 0000000..5216764 --- /dev/null +++ b/hg-monitor-web-base/src/main/resources/static/src/views/snapshotOverview/index.html @@ -0,0 +1,2 @@ +<title>快照概览</title> +<iframe src="/vue3/index.html#/vue3/snapshotOverview" frameborder="0" class="layadmin-iframe" style="height: 99.5%!important;"/> \ No newline at end of file diff --git a/hg-monitor-web-base/src/main/resources/static/src/views/template/detail/snapshot_detail.html b/hg-monitor-web-base/src/main/resources/static/src/views/template/detail/snapshot_detail.html new file mode 100644 index 0000000..6430556 --- /dev/null +++ b/hg-monitor-web-base/src/main/resources/static/src/views/template/detail/snapshot_detail.html @@ -0,0 +1,57 @@ +<!--快照详细页面--> +<article class="page-container template"> + <div class="page-panel"> + <div class="main"> + <div class="layui-card"> + <div class="layui-card-body"> + <div class="lay-row"> + <div class="lay-row-item" style="max-width: 200px"> + <h5 class="lay-row-title">资源状态</h5> + <div class="res-state" id="hostminicomputerpartition_resstate"> + <div class="res-state-pie res-state-pie--good">优</div> + <ul> + <li>严重告警:0</li> + <li>重要告警:0</li> + <li>一般告警:0</li> + </ul> + </div> + </div> + <div class="lay-row-item lay-row-item--half" style="width: calc(100% - 200px)"> + <h5 class="lay-row-title">基本信息<i class="iconfont detail_base_info" + data-id="hostminicomputerpartition_jbxx"></i></h5> + <ul class="info-table" id="hostminicomputerpartition_jbxx"> + </ul> + </div> + </div> + <div class="lay-row"> + <div class="lay-row-item lay-row-item--half" style="width: calc(100% - 10px)"> + <h5 class="lay-row-title">性能信息<i class="iconfont detail_base_info" + data-id="hostminicomputerpartition_sysfile"></i></h5> + <ul class="info-table" id="hostminicomputerpartition_sysfile"></ul> + </div> + </div> + <div id="table_arr_body"> + </div> + <div class="lay-row"> + <div class="lay-row-item"> + <h5 class="lay-row-title">告警列表</h5> + <div id="snapshow_active_alram"></div> + </div> + </div> + </div> + </div> + </div> + </div> +</article> +<textarea id="snapshot_detail_param_id" style="display: none;">{{d}}</textarea> +<script> + layui.use('snapshot_detail', function (fn) { + var $ = layui.$; + var parm = $("#snapshot_detail_param_id").val(); + if (parm.indexOf('{{d') != -1) { + fn(); + } else { + fn(JSON.parse(parm)); + } + }); +</script> diff --git a/hg-monitor-web-base/src/main/resources/static/vue3/public/css/base.css b/hg-monitor-web-base/src/main/resources/static/vue3/public/css/base.css index 001c6a2..953aa57 100644 --- a/hg-monitor-web-base/src/main/resources/static/vue3/public/css/base.css +++ b/hg-monitor-web-base/src/main/resources/static/vue3/public/css/base.css @@ -51,7 +51,13 @@ .container .cm-card .search .condition div { margin-right: 2px !important; margin-bottom: 3px !important; - width: 250px !important; + /*width: 250px !important;*/ +} +.container .cm-card .search .condition.esData-conditon div { + margin-bottom: 0px !important; +} +.container .cm-card .search .condition.ping div { + margin-bottom: 0px !important; } .container .cm-card .search .btns { diff --git a/hg-monitor-web-base/src/main/resources/static/vue3/src/components/common/inputbiztypetree/index.html b/hg-monitor-web-base/src/main/resources/static/vue3/src/components/common/inputbiztypetree/index.html index f3e8684..1ab514b 100644 --- a/hg-monitor-web-base/src/main/resources/static/vue3/src/components/common/inputbiztypetree/index.html +++ b/hg-monitor-web-base/src/main/resources/static/vue3/src/components/common/inputbiztypetree/index.html @@ -1,6 +1,6 @@ <div> <el-select @visible-change="selectClose" v-model="modelValueLabel" :filter-method="selectFilterMethod" - style="min-width: 120px;" :size="size" placeholder="所属系统" :filterable="isFilter" clearable + style="min-width: 120px;" :size="$global.elementConfig.size.input" placeholder="所属系统" :filterable="isFilter" clearable :collapse-tags="true" @change="selectChangeMethod"> <el-option :value="modelValue" style="height: auto;padding: 0;"> <el-tree ref="bizTree" :data="list" :check-on-click-node="true" :default-expand-all="isDefaultAll" diff --git a/hg-monitor-web-base/src/main/resources/static/vue3/src/components/common/inputrestypetree/index.html b/hg-monitor-web-base/src/main/resources/static/vue3/src/components/common/inputrestypetree/index.html index 731c1b3..0a29f89 100644 --- a/hg-monitor-web-base/src/main/resources/static/vue3/src/components/common/inputrestypetree/index.html +++ b/hg-monitor-web-base/src/main/resources/static/vue3/src/components/common/inputrestypetree/index.html @@ -1,6 +1,6 @@ <div> <el-select @visible-change="selectClose" v-model="modelValueLabel" :filter-method="selectFilterMethod" - style="min-width: 120px;" :size="size" placeholder="资源类型" :filterable="isFilter" clearable + style="min-width: 120px;" :size="$global.elementConfig.size.input" placeholder="资源类型" :filterable="isFilter" clearable :collapse-tags="true" @change="selectChangeMethod"> <el-option :value="modelValue" style="height: auto;padding: 0;"> <el-tree ref="resTypeTree" :data="list" :check-on-click-node="true" :default-expand-all="isDefaultAll" diff --git a/hg-monitor-web-base/src/main/resources/static/vue3/src/components/common/inputusertree/index.html b/hg-monitor-web-base/src/main/resources/static/vue3/src/components/common/inputusertree/index.html new file mode 100644 index 0000000..0304fee --- /dev/null +++ b/hg-monitor-web-base/src/main/resources/static/vue3/src/components/common/inputusertree/index.html @@ -0,0 +1,13 @@ +<div> + <el-select :size="$global.elementConfig.size.input" :collapse-tags="true" :filter-method="selectFilterMethod" :filterable="isFilter" + @change="selectChangeMethod" @visible-change="selectClose" clearable placeholder="选择用户" + style="min-width: 120px;" v-model="modelValueLabel"> + <el-option :value="modelValue" style="height: auto;padding: 0;"> + <el-tree :check-on-click-node="true" :check-strictly="false" :data="list" :default-expand-all="isDefaultAll" + :empty-text="emptyText" :expand-on-click-node="true" :filter-node-method="filterNode" + :props="defaultProps" :show-checkbox="isMultiple" :show-checkbox="checkbox" @check-change="handleCheckChange" + node-key="id" node-key="id" ref="userTree"> + </el-tree> + </el-option> + </el-select> +</div> diff --git a/hg-monitor-web-base/src/main/resources/static/vue3/src/components/common/inputusertree/index.js b/hg-monitor-web-base/src/main/resources/static/vue3/src/components/common/inputusertree/index.js new file mode 100644 index 0000000..005fbaf --- /dev/null +++ b/hg-monitor-web-base/src/main/resources/static/vue3/src/components/common/inputusertree/index.js @@ -0,0 +1,131 @@ +export default { + template: '', + name: 'user-tree-input', + props: { + // echoObj 可以用于回显,它的值为需要回显的对象,多个时可以使用数组 + echoObj: {}, + // 是否开启搜索 + isFilter: { + default: true + }, + // 尺寸 + size: { + default: '' + }, + placeholderText: { + default: '选择用户' + }, + isTag: { + default: true + }, + isDefaultAll: { + default: true + }, + // 点击节点是否展开 + expandClickNode: { + default: false + }, + // 字段key,用于取出数据中的名字 + fieldName: { + default: 'title' + }, + emptyText: { + default: '无匹配项' + }, + // 字段key, 数据中的id + fieldId: { + default: '' + }, + // 配置是否可多选 + isMultiple: { + type: Boolean, + default: true + }, + + }, + data() { + return { + defaultProps: { + children: 'children', + label: 'nickname' + }, + list: [], + // 实际选中值 + modelValue: [], + // 下拉框绑定值(选中值名字) + modelValueLabel: [] + } + }, + methods: { + selectClose(bool) { + if (bool) { + this.selectFilterMethod('') + } + }, + selectFilterMethod(val) { + // 下拉框调用tree树筛选 + this.$refs.userTree.filter(val) + }, + selectChangeMethod(e) { + var arrNew = [] + var dataLength = this.modelValue.length + var eLength = e.length + for (var i = 0; i < dataLength; i++) { + for (var j = 0; j < eLength; j++) { + if (e[j] === JSON.parse('this.modelValue[i].' + this.fieldName)) { + arrNew.push(this.modelValue[i]) + } + } + } + // 设置勾选的值 + this.$refs.userTree.setCheckedNodes(arrNew) + }, + filterNode(value, data) { + if (!value) return true + + return data[this.fieldName].indexOf(value) !== -1 + }, + handleCheckChange(data, checked, indeterminate) { + let that = this; + + var selectArr = []; + selectArr.push(data); + // data[that.defaultProps.children].forEach(function (v) { + // selectArr.push(data); + // }); + + if (checked) { + // 已选中 + that.modelValue = that.modelValue.concat(selectArr) + } else { + that.modelValue.forEach(function (v, i) { + selectArr.forEach(function (v1) { + if (v.busId == v1.busId) { + that.modelValue.splice(i, 1); + } + }) + }) + } + that.modelValueLabel = that.modelValue.map(function (v) { + return v[that.defaultProps.label]; + }); + that.$emit('callback', this.modelValue) + } + }, + watch: {}, + mounted() { + let that = this; + //加载资源列表 + const {proxy} = Vue.getCurrentInstance() + // 加载列表 + proxy.$http.get("/api-user/users/getAll", {}, function (res) { + if (res) { + that.list = res; + } + }) + }, + created() { + + + } +} diff --git a/hg-monitor-web-base/src/main/resources/static/vue3/src/main.js b/hg-monitor-web-base/src/main/resources/static/vue3/src/main.js index 3ecd490..c886e27 100644 --- a/hg-monitor-web-base/src/main/resources/static/vue3/src/main.js +++ b/hg-monitor-web-base/src/main/resources/static/vue3/src/main.js @@ -46,7 +46,9 @@ Promise.all([ //所属系统 .component('cm-biz-type-tree-input', Vue.defineAsyncComponent(() => myImport('components/common/inputbiztypetree/index'))) //时间范围组件 - .component('cm-date-range-influx', Vue.defineAsyncComponent(() => myImport('components/common/dateRange/indexInflux'))); + .component('cm-date-range-influx', Vue.defineAsyncComponent(() => myImport('components/common/dateRange/indexInflux'))) + //告警通知统计信息 + .component('cm-user-type-tree-input', Vue.defineAsyncComponent(() => myImport('components/common/inputusertree/index'))) // // 自定义指令 diff --git a/hg-monitor-web-base/src/main/resources/static/vue3/src/router/index.js b/hg-monitor-web-base/src/main/resources/static/vue3/src/router/index.js index 6b8039f..241d106 100644 --- a/hg-monitor-web-base/src/main/resources/static/vue3/src/router/index.js +++ b/hg-monitor-web-base/src/main/resources/static/vue3/src/router/index.js @@ -93,6 +93,24 @@ const routes = [{ name: 'busyConfig', component: () => myImport('views/busyConfig/index') }, + //快照管理 + { + path: '/vue3/snapshot', + name: 'snapshot', + component: () => myImport('views/snapshot/index') + }, + //快照历史 + { + path: '/vue3/snapshot/history', + name: 'snapshotHistory', + component: () => myImport('views/snapshot/history/index') + }, + //快照概览 + { + path: '/vue3/snapshotOverview', + name: 'snapshotOverview', + component: () => myImport('views/snapshotOverview/index') + }, //license { path: '/vue3/license', diff --git a/hg-monitor-web-base/src/main/resources/static/vue3/src/script/global.js b/hg-monitor-web-base/src/main/resources/static/vue3/src/script/global.js index 71c6054..383198c 100644 --- a/hg-monitor-web-base/src/main/resources/static/vue3/src/script/global.js +++ b/hg-monitor-web-base/src/main/resources/static/vue3/src/script/global.js @@ -287,7 +287,11 @@ global.openDetail = (resId, resType, proxy) => { } }) } - +//跳转详情页 +global.openNewWin = (url, name, params, editFlag, fn, cancelfn, type, sign) => { + let lyaui = global.layui; + lyaui.commonDetail.openNewWin(url, name, params, editFlag, fn, cancelfn, type, sign) +} /** * @description 打开选择layUI弹窗 * @author XuHaoJie diff --git a/hg-monitor-web-base/src/main/resources/static/vue3/src/views/snapshot/history/index.html b/hg-monitor-web-base/src/main/resources/static/vue3/src/views/snapshot/history/index.html new file mode 100644 index 0000000..f20417f --- /dev/null +++ b/hg-monitor-web-base/src/main/resources/static/vue3/src/views/snapshot/history/index.html @@ -0,0 +1,68 @@ +<div :style="{'height':height+'px','max-height':height+'px','padding':'10px 0 10px 10px','background':'#fff','box-sizing':'border-box'}" + class="container"> + <div :style="{'height':'100%','padding-top':'3px'}" + class="cm-card"> + <div class="search"> + <div class="condition ping"> + <el-form-item> + <el-date-picker + :size="$global.elementConfig.size.input" + end-placeholder="开始时间" + placeholder="开始时间" + type="datetime" + v-model="search.startTime" + value-format="YYYY-MM-DD HH:mm:ss" + /> + + </el-form-item> + <el-form-item> + <el-date-picker + :size="$global.elementConfig.size.input" + end-placeholder="结束时间" + placeholder="结束时间" + type="datetime" + v-model="search.endTime" + value-format="YYYY-MM-DD HH:mm:ss" + /> + </el-form-item> + <el-form-item> + <el-button :size="$global.elementConfig.size.button" type="primary" @click="getDataList">查询</el-button> + </el-form-item> + <el-form-item> + <el-button :size="$global.elementConfig.size.button" @click="deleteHistory">删除</el-button> + </el-form-item> + </div> + </div> + <div class="search-table"> + <cm-table-page :columns="tableData.columns" :dataList="tableData.dataList" :height="(height - 110)" + :loading="false" :pageSize="search.pageSize" :showBorder="true" + :showIndex="true" :showPage="true" :showSelection="true" + :showTools="true" :total="tableData.count" @loaddata="loaddata" @selectionChange="selectionChange"> + <template #default="{row,prop,column}"> + <div v-if="prop == 'state'"> + <div v-if="row.state == 0"> + <el-tag>创建中</el-tag> + </div> + <div v-if="row.state == 1"> + <el-tag type="success">已创建</el-tag> + </div> + <div v-if="row.state == 2"> + <el-tag type="danger">创建失败</el-tag> + </div> + </div> + </template> + <template #tools="{scope}"> + <div class="list-handle"> + <span class="icon-bg"> + <i @click="handleDetail(scope.row)" class="el-icon-document" title="查看详情"></i> + </span> + <span class="icon-bg"> + <i @click="handleDelete(scope.row)" class="el-icon-delete" title="删除"></i> + </span> + </div> + </template> + </cm-table-page> + </div> + </div> +</div> + diff --git a/hg-monitor-web-base/src/main/resources/static/vue3/src/views/snapshot/history/index.js b/hg-monitor-web-base/src/main/resources/static/vue3/src/views/snapshot/history/index.js new file mode 100644 index 0000000..1cb7e45 --- /dev/null +++ b/hg-monitor-web-base/src/main/resources/static/vue3/src/views/snapshot/history/index.js @@ -0,0 +1,159 @@ +export default { + name: 'snapshotHistory', + template: '', + components: {}, + props: [], + setup(props, {attrs, slots, emit}) { + const {proxy} = Vue.getCurrentInstance(); + let height = Vue.ref(window.innerHeight); + let resId = Vue.ref(''); + //选择的数据 + let selectionData = Vue.ref([]); + let search = Vue.ref({ + pageNum: 1, + pageSize: 20, + startTime: '', + endTime: '', + keyWord: '' + + }); + let selectionChange = (val) => { + selectionData.value = val; + } + //表格字段 + let tableData = Vue.ref({ + count: 0, + dataList: [], + columns: [ + { + prop: 'createUser', + label: '快照创建人', + sortable: true, + align: 'center', + width: '250' + }, + { + prop: 'createTime', + label: '快照创建时间', + sortable: true, + align: 'center', + width: '300' + }, + { + prop: 'state', + label: '同步状态', + sortable: true, + align: 'center', + width: '170' + }, + { + prop: 'batchNo', + label: '批次号', + sortable: true, + align: 'center', + } + ] + }) + // 获取列表 + let getDataList = () => { + let params = { + resId: resId.value, + startTime: search.value.startTime, + endTime: search.value.endTime, + keyWord: search.value.keyword, + pageNum:search.value.pageNum, + pageSize: search.value.pageSize + } + proxy.$http.get(`/api-web/snapshot/his/getList`, params, function (res) { + if (res.success) { + tableData.value.dataList = res.data; + tableData.value.count = res.count; + } else { + tableData.value.dataList = []; + tableData.value.count = 0; + } + }); + } + //删除快照历史数据 + let handleDelete = (row) =>{ + let params = { + resId: resId.value, + batchNo: row.batchNo + } + deleteSnapshot(params); + } + //多选删除 + let deleteHistory = () =>{ + if (selectionData.value.length > 0) { + let id = []; + let batchNo = []; + selectionData.value.map(item => { + id.push(item.resId); + batchNo.push(item.batchNo); + }) + let params = { + resId: id.toString(), + batchNo: batchNo.toString() + } + deleteSnapshot(params); + }else { + proxy.$global.showMsg("请选择需要删除的历史快照数据","warning"); + } + } + //删除 + let deleteSnapshot = (param) =>{ + proxy.$global.confirm('确认删除吗?', function () { + proxy.$http.get(`/api-web/snapshot/his/delete`, param, function (res) { + if (res.success) { + proxy.$global.showMsg("删除成功","success"); + getDataList(); + } else { + proxy.$global.showMsg("删除失败","error"); + } + }); + }); + } + + + //获取resId + let getResId = () => { + resId.value = proxy.$route.query.resId; + } + let loaddata = ({page, limit}) => { + search.value.pageNum = page; + search.value.pageSize = limit; + getDataList(); + } + //快照详情 + let handleDetail = (row)=>{ + proxy.$global.openNewWin('template/detail/snapshot_detail', row.createUser+'在'+row.createTime+'创建的'+row.resName+'的快照', {resId:row.resId,'batchNo':row.batchNo},false); + } + + //查看资源详情 + let goResDetail = (row) => { + proxy.$global.openDetail(row.resId, row.resType, proxy); + } + // 挂载完 + Vue.onMounted(() => { + getResId(); + getDataList(); + }) + + + return { + height, + resId, + getDataList, + tableData, + search, + loaddata, + goResDetail, + handleDelete, + handleDetail, + selectionChange, + deleteHistory, + deleteSnapshot + } + } + +} diff --git a/hg-monitor-web-base/src/main/resources/static/vue3/src/views/snapshot/index.html b/hg-monitor-web-base/src/main/resources/static/vue3/src/views/snapshot/index.html new file mode 100644 index 0000000..0d4e246 --- /dev/null +++ b/hg-monitor-web-base/src/main/resources/static/vue3/src/views/snapshot/index.html @@ -0,0 +1,174 @@ +<div class="container" :style="{'height':height+'px','max-height':height+'px','padding':'10px 0 10px 10px','background':'#fff','box-sizing':'border-box'}"> + <div class="cm-card" :style="{'height':'100%','padding-top':'3px'}"> + <div class="search"> + <div class="condition esData-conditon" style="justify-content: space-between;width: 100%;"> + <el-form :inline="true"> + <el-form-item> + <el-tooltip placement="bottom-start"> + <template #content> 资源名称 <br /> 资源ip <br /> 业务名称</template> + <el-input clearable :size="$global.elementConfig.size.input" v-model="queryParams.keyWord" placeholder="关键字检索" /> + </el-tooltip> + </el-form-item> + <el-form-item> + <el-dropdown> + <cm-res-type-tree-input @callback="getResType" clearable collapseTags multiple/> + </el-dropdown> + </el-form-item> + <el-form-item> + <el-dropdown> + <cm-biz-type-tree-input @callback="getBizType" clearable collapseTags multiple/> + </el-dropdown> + </el-form-item> + <el-form-item> + <el-button @click="handleQuery" :size="$global.elementConfig.size.button" type="primary">查询</el-button> + </el-form-item> + </el-form> + <el-button-group> + <el-button @click="handleBtnGroup('today')" :type="queryParams.time=='today'?'primary':''">今天</el-button> + <el-button @click="handleBtnGroup('week')" :type="queryParams.time=='week'?'primary':''">近7天</el-button> + <el-button @click="handleBtnGroup('month')" :type="queryParams.time=='month'?'primary':''">近30天</el-button> + <el-button @click="handleBtnGroup('quarter')" :type="queryParams.time=='quarter'?'primary':''">近90天</el-button> + <el-popover + v-model:visible="visiblePopover" + :width="420" + placement="bottom-end"> + <template #reference> + <el-button @click="handleBtnGroup(4)" :type="queryParams.time!='today' && queryParams.time!='week' && queryParams.time!='month' && queryParams.time!='quarter'?'primary':''">自定义</el-button> + </template> + <el-date-picker + format="YYYY-MM-DD HH:mm:ss" + value-format="YYYY-MM-DD HH:mm:ss" + @change="handleChangeDatetime" + v-model="datetimerange" + type="datetimerange" + range-separator="-" + start-placeholder="开始时间" + end-placeholder="结束时间" + /> + </el-popover> + </el-button-group> + </div> + </div> + + <el-row :gutter="20" style="padding: 3px 10px;"> + <el-col :span="8"> + <h3 class="page-item-title-h3">资源类型快照量TOP5</h3> + <div ref="bizChartsRefs" style="width: 100%;height: 320px;border: 1px solid #e4e4e4;"></div> + </el-col> + <el-col :span="8"> + <h3 class="page-item-title-h3">业务系统快照量TOP5</h3> + <div ref="devChartsRefs" style="width: 100%;height: 320px;border: 1px solid #e4e4e4;"></div> + </el-col> + <el-col :span="8"> + <h3 class="page-item-title-h3">快照量</h3> + <div ref="snapshotChartsRefs" style="width: 100%;height: 320px;border: 1px solid #e4e4e4;"></div> + </el-col> + </el-row> + + <div class="search-table"> + <h3 style="text-align: left;color:#2b9eef;">快照信息</h3> + <cm-table-page :columns="tableData.columns" :dataList="tableData.dataList" + :height="height - 550" + :loading="false" + :pageSize="queryParams.pageSize" + :showBorder="true" + :showIndex="true" + :showPage="true" + :showSelection="false" + :showTools="true" + :total="queryParams.count" + @loaddata="loaddata"> + <template #default="{row,prop,column}"> + <div v-if="prop == 'resName'"> + <!-- 资源名称点击事件 --> + <el-tooltip placement="top"> + <el-button @click.prevent="goResDetail(row)" size="small" type="text"> + <span class="">{{row.resName}}</span> + </el-button> + <template #content>{{row.resName}}</template> + </el-tooltip> + </div> + <div v-if="prop == 'busTypeName'"> + <div v-if="(row.busTypeName || '').split(',').length <= '3'"> + <div v-if="row.busTypeName != null && row.busTypeName.indexOf(',') != -1" v-for="item in row.busTypeName.split(',')"> + <el-tooltip placement="top"> + <template #content>{{item}}</template> + <el-tag style="margin: 2px;" type="info" class="mx-1" effect="light">{{item}}</el-tag> + </el-tooltip> + </div> + <div v-else-if="row.busTypeName != null && row.busTypeName.indexOf(',') == -1 "> + <el-tooltip placement="top"> + <template #content>{{row.busTypeName}}</template> + <el-tag type="info" class="mx-1" effect="light">{{row.busTypeName}}</el-tag> + </el-tooltip> + </div> + </div> + <div v-else> + <el-button @click="goBus(row)" size="small" type="text"> + <span>共计:{{row.nickname.split(',').length}}个业务</span> + </el-button> + </div> + </div> + <div v-if="prop == 'nickname'"> + <div v-if="(row.nickname || '').split(',').length <= '3'"> + <div v-if="row.nickname != null && row.nickname.indexOf(',') != -1" v-for="item in row.nickname.split(',')"> + <el-tooltip placement="top"> + <template #content>{{item}}</template> + <el-tag style="margin: 2px;" type="info" class="mx-1" effect="light">{{item}}</el-tag> + </el-tooltip> + </div> + <div v-else-if="row.nickname != null && row.nickname.indexOf(',') == -1 "> + <el-tooltip placement="top"> + <template #content>{{row.nickname}}</template> + <el-tag type="info" class="mx-1" effect="light">{{row.nickname}}</el-tag> + </el-tooltip> + </div> + </div> + <div v-else> + <el-button @click="goBus(row)" size="small" type="text"> + <span>共计:{{row.nickname.split(',').length}}个业务负责人</span> + </el-button> + </div> + </div> + <div v-if="prop == 'admin'"> + <div v-if="row.admin != null"> + <el-tooltip placement="top"> + <template #content>{{row.admin}}</template> + <el-tag type="info" class="mx-1" effect="light">{{row.admin}}</el-tag> + </el-tooltip> + </div> + </div> + <div v-if="prop == 'createUser'"> + <div v-if="row.createUser != null"> + <el-tooltip placement="top"> + <template #content>{{row.createUser}}</template> + <el-tag type="info" class="mx-1" effect="light">{{row.createUser}}</el-tag> + </el-tooltip> + </div> + </div> + </template> + <template #tools="{scope}"> + <div class="list-handle"> + <span class="icon-bg" @click="handleDetail(scope.row)"> + <i class="el-icon-document" title="详情"></i> + </span> + <span class="icon-bg"@click="handleDel(scope.row)"> + <i class="el-icon-delete"></i> + </span> + </div> + </template> + </cm-table-page> + </div> + </div> +</div> + +<cm-dialog :showDialogVisible="showBus" :showFooter="false" :title="title" @hidedialog="cancelBtn" + width="700px"> + <template v-slot> + <div class="dialog"> + <div v-model="busType" v-for="item in busType" style="display: inline-block"> + <el-tag type="info" class="mx-1" effect="light">{{item}}</el-tag> + </div> + </div> + </template> +</cm-dialog> diff --git a/hg-monitor-web-base/src/main/resources/static/vue3/src/views/snapshot/index.js b/hg-monitor-web-base/src/main/resources/static/vue3/src/views/snapshot/index.js new file mode 100644 index 0000000..06f6ad2 --- /dev/null +++ b/hg-monitor-web-base/src/main/resources/static/vue3/src/views/snapshot/index.js @@ -0,0 +1,481 @@ +export default { + name:"snapshot", + template:"", + setup(props, {attrs, slots, emit}){ + const {proxy} = Vue.getCurrentInstance(); + let height = Vue.ref(window.innerHeight); + let formSize = Vue.ref('default'); + let datetimerange = Vue.ref([]); + let visiblePopover = Vue.ref(false); + let queryParams = Vue.ref({ + keyWord:'', + resType:'', + busId:'', + time:"week", + pageNum: 1, + pageSize: 10, + count:0, + }) + let btnGroupType = Vue.ref(0); + //表格字段 + let tableData = Vue.ref({ + count: 0, + dataList: [], + columns: [ + { + prop: 'resTypeName', + label: '资源类型', + sortable: true, + align: 'center', + width: '200', + }, + { + prop: 'resName', + label: '资源名称', + sortable: true, + align: 'center' + }, + { + prop: 'ip', + label: 'IP地址', + sortable: true, + align: 'center', + width: '130' + }, { + prop: 'admin', + label: '负责人', + sortable: true, + align: 'center', + width: '130' + }, { + prop: 'busTypeName', + label: '所属业务系统', + sortable: true, + align: 'center', + width: '270' + }, + { + prop: 'nickname', + label: '业务系统负责人', + sortable: true, + align: 'center', + width: '150' + }, + { + prop: 'createUser', + label: '快照创建人', + sortable: true, + align: 'center', + width: '130' + }, + { + prop: 'createTime', + label: '快照创建时间', + sortable: true, + align: 'center', + width: '170' + }, + ] + }) + + let loaddata = ({page, limit}) => { + queryParams.value.pageNum = page; + queryParams.value.pageSize = limit; + getDataList(); + getEchartsData(); + } + + let getResType = (arr) => { + let types = arr.map(function (v) { + return v.id; + }); + queryParams.value.resType = types.join(','); + } + let getBizType = (arr) => { + let types = arr.map(function (v) { + return v.busId; + }); + queryParams.value.busId = types.join(','); + } + + // 获取列表 + let getDataList = () => { + // console.log(queryParams.value); + proxy.$http.get(`/api-web/snapshot/manage/getList`,queryParams.value,(res)=>{ + // console.log(res.data); + tableData.value.dataList = res.data; + queryParams.value.count = res.count; + },(err)=>{ + console.log(err); + }) + }; + // 查询事件 + let handleQuery = ()=> { + queryParams.value.pageSize=10; + queryParams.value.pageNum=1; + getDataList(); + getEchartsData(); + } + // 按钮组点击事件 + let handleBtnGroup = (val)=>{ + queryParams.value.time = val; + if (val == 4){ + visiblePopover.value = !visiblePopover.value; + }else{ + visiblePopover.value = false; + getDataList(); + getEchartsData(); + } + }; + + // echarts + let bizChartsRefs = Vue.ref(null); + let devChartsRefs = Vue.ref(null); + let snapshotChartsRefs = Vue.ref(null); + let bizCharts = Vue.ref('') + let devCharts = Vue.ref('') + let snapshotCharts = Vue.ref('') + let showBus = Vue.ref(false); + let title = Vue.ref(''); + let busType = Vue.ref(); + let getEcharts = ()=>{ + bizCharts = echarts.init(bizChartsRefs.value); + let bizOption = { + grid:{ + top:"8%", + bottom:"8%", + left:"4%", + containLabel:true, + }, + tooltip: { + trigger: 'axis', + axisPointer: { + type: 'shadow', + } + }, + color:"#60a0f7", + xAxis: { + type: 'category', + data: [], + axisTick:false, + axisLabel: { + interval: 0, + formatter: val => { + // 一行字数 + const max = 6 + // 标签长度 + const valLength = val.length + // 换行数 + const rowNum = valLength / 6 + if (valLength > 6) { + return val.slice(0,5) + '...'; + } else { + return val + } + } + } + }, + yAxis: { + type: 'value', + axisLine:{ + show:true, + }, + //分隔线样式 + splitLine:{ + show:true, + lineStyle:{ + type:'dashed' + } + } + }, + series: [ + { + data: [], + type: 'bar', + barWidth: 26,//设置柱状图大小 + itemStyle:{ + borderRadius:[20,20,0,0] + } + } + ] + } + bizCharts.setOption(bizOption); + + devCharts = echarts.init(devChartsRefs.value); + let devOption = { + grid:{ + top:"8%", + bottom:"8%", + left:"4%", + containLabel:true, + }, + tooltip: { + trigger: 'axis', + axisPointer: { + type: 'shadow', + } + }, + color:"#60a0f7", + xAxis: { + type: 'category', + data: [], + axisTick:false, + axisLabel: { + interval: 0, + formatter: val => { + // 一行字数 + const max = 6 + // 标签长度 + const valLength = val.length + // 换行数 + const rowNum = valLength / 6 + if (valLength > 6) { + return val.slice(0,5) + '...'; + } else { + return val + } + } + } + }, + yAxis: { + type: 'value', + axisLine:{ + show:true, + }, + //分隔线样式 + splitLine:{ + show:true, + lineStyle:{ + type:'dashed' + } + } + }, + series: [ + { + data: [], + type: 'bar', + barWidth: 26,//设置柱状图大小 + itemStyle:{ + borderRadius:[20,20,0,0] + } + } + ] + } + devCharts.setOption(devOption); + + snapshotCharts = echarts.init(snapshotChartsRefs.value); + let shapshotOption = { + grid:{ + top:"8%", + bottom:"8%", + left:"4%", + containLabel:true, + }, + tooltip: { + trigger: 'axis', + axisPointer: { + type: 'shadow', + } + }, + color:"#60a0f7", + xAxis: { + type: 'category', + data: [], + axisTick:false, + }, + yAxis: { + type: 'value', + axisLine:{ + show:true, + }, + //分隔线样式 + splitLine:{ + show:true, + lineStyle:{ + type:'dashed' + } + } + }, + series: [ + { + data: [], + type: 'bar', + barWidth: 26,//设置柱状图大小 + itemStyle:{ + borderRadius:[20,20,0,0] + } + } + ] + } + snapshotCharts.setOption(shapshotOption); + } + + let getEchartsData = ()=>{ + let resTypeData = { + xaxis:[], + yaxis:[], + } + proxy.$http.get(`/api-web/snapshot/manage/resTypeTop`,queryParams.value,(res)=>{ + // console.log(res.object); + res.object.forEach(item=>{ + resTypeData.xaxis.push(item.xaxis); + resTypeData.yaxis.push(item.yaxis) + }) + bizCharts.setOption({ + xAxis:{ + data:resTypeData.xaxis, + }, + series:[ + { + data:resTypeData.yaxis + } + ] + }); + },(err)=>{ + console.log(err); + }) + + let busTypeData = { + xaxis:[], + yaxis:[], + } + proxy.$http.get(`/api-web/snapshot/manage/busTop`,queryParams.value,(res)=>{ + // console.log(res.object); + res.object.forEach(item=>{ + busTypeData.xaxis.push(item.xaxis); + busTypeData.yaxis.push(item.yaxis) + }) + devCharts.setOption({ + xAxis:{ + data:busTypeData.xaxis, + }, + series:[ + { + data:busTypeData.yaxis + } + ] + }); + },(err)=>{ + console.log(err); + }) + + let snapshotNumData = { + xaxis:[], + yaxis:[], + } + proxy.$http.get(`/api-web/snapshot/manage/snapshotNum`,queryParams.value,(res)=>{ + // console.log(res.object); + res.object.forEach(item=>{ + snapshotNumData.xaxis.push(item.xaxis); + snapshotNumData.yaxis.push(item.yaxis) + }) + snapshotCharts.setOption({ + xAxis:{ + data:snapshotNumData.xaxis, + }, + series:[ + { + data:snapshotNumData.yaxis + } + ] + }); + },(err)=>{ + console.log(err); + }) + } + + // 时间范围快捷键 修改事件 + let handleChangeDatetime = (value)=>{ + visiblePopover.value = false; + queryParams.value.time = value.join(','); + getDataList(); + getEchartsData(); + } + + // 表格删除事件 + let handleDel = (row)=>{ + // console.log(row); + proxy.$global.confirm("确认删除吗?", function () { + deleteItems([row.resId],[row.batchNo]); + }) + } + //删除 + let deleteItems = (ids,nos) => { + let params = { + resId: ids.toString(), + batchNo:nos.toString(), + } + proxy.$http.get('/api-web/snapshot/his/delete', params, function (res) { + if (res && res.success) { + proxy.$global.showMsg('删除成功'); + handleQuery() + } + }) + } + + //快照详情 + let handleDetail = (row)=>{ + // console.log(row); + // proxy.$global.openNewWin('template/detail/snapshot_detail_v1', "快照详情", {resId:row.resId,'batchNo':row.batchNo},false); + proxy.$global.openNewWin('template/detail/snapshot_detail', row.createUser+'在'+row.createTime+'创建的'+row.resName+'的快照', {resId:row.resId,'batchNo':row.batchNo},false); + } + + //查看资源详情 + let goResDetail = (row) => { + proxy.$global.openDetail(row.resId, row.resType, proxy); + } + + //查看业务系统 + let goBus = (row) => { + title.value = row.resName+'所属业务系统信息'; + let busTypeAdmin = []; + for (let i = 0; i < row.busTypeName.split(',').length; i++) { + for (let j = 0; j < row.nickname.split(',').length; j++) { + if (i==j){ + busTypeAdmin.push(row.busTypeName.split(',')[i]+'('+row.nickname.split(',')[i]+')') + } + } + } + busType.value = busTypeAdmin; + showBus.value = true; + + } + //关闭弹框 + let cancelBtn = () => { + showBus.value = false; + } + + Vue.onMounted(()=>{ + getEcharts(); + getDataList(); + getEchartsData(); + }) + + return{ + height, + formSize, + queryParams, + tableData, + btnGroupType, + bizChartsRefs, + devChartsRefs, + snapshotChartsRefs, + handleBtnGroup, + datetimerange, + visiblePopover, + handleChangeDatetime, + getResType, + getBizType, + handleQuery, + loaddata, + handleDel, + handleDetail, + goResDetail, + goBus, + showBus, + cancelBtn, + title, + busType + } + } +} diff --git a/hg-monitor-web-base/src/main/resources/static/vue3/src/views/snapshotOverview/index.html b/hg-monitor-web-base/src/main/resources/static/vue3/src/views/snapshotOverview/index.html new file mode 100644 index 0000000..3b41b30 --- /dev/null +++ b/hg-monitor-web-base/src/main/resources/static/vue3/src/views/snapshotOverview/index.html @@ -0,0 +1,182 @@ +<div class="container" :style="{'height':height+'px','max-height':height+'px','padding':'10px 0 10px 10px','background':'#fff','box-sizing':'border-box'}"> + <div class="cm-card" :style="{'height':'100%','padding-top':'3px'}"> + <div class="search"> + <div class="condition esData-conditon" style="justify-content: space-between;width: 100%;"> + <el-form :inline="true"> + <el-form-item> + <el-tooltip placement="bottom-start"> + <template #content> 资源名称 <br /> 资源ip <br /> 业务名称</template> + <el-input clearable :size="$global.elementConfig.size.input" v-model="queryParams.keyWord" placeholder="关键字检索" /> + </el-tooltip> + </el-form-item> + <el-form-item> + <el-dropdown> + <cm-res-type-tree-input @callback="getResType" clearable collapseTags multiple/> + </el-dropdown> + </el-form-item> + <el-form-item> + <el-dropdown> + <cm-biz-type-tree-input @callback="getBizType" clearable collapseTags multiple/> + </el-dropdown> + </el-form-item> + <el-form-item> + <el-dropdown> + <cm-user-type-tree-input @callback="getUser" clearable collapseTags multiple/> + </el-dropdown> + </el-form-item> + <el-form-item> + <el-button @click="handleQuery" :size="$global.elementConfig.size.button" type="primary">查询</el-button> + </el-form-item> + </el-form> + <el-button-group> + <el-button @click="handleBtnGroup('today')" :type="queryParams.time=='today'?'primary':''">今天</el-button> + <el-button @click="handleBtnGroup('week')" :type="queryParams.time=='week'?'primary':''">近7天</el-button> + <el-button @click="handleBtnGroup('month')" :type="queryParams.time=='month'?'primary':''">近30天</el-button> + <el-button @click="handleBtnGroup('quarter')" :type="queryParams.time=='quarter'?'primary':''">近90天</el-button> + <el-popover + v-model:visible="visiblePopover" + :width="420" + placement="bottom-end"> + <template #reference> + <el-button @click="handleBtnGroup(4)" :type="queryParams.time!='today' && queryParams.time!='week' && queryParams.time!='month' && queryParams.time!='quarter'?'primary':''">自定义</el-button> + </template> + <el-date-picker + format="YYYY-MM-DD HH:mm:ss" + value-format="YYYY-MM-DD HH:mm:ss" + @change="handleChangeDatetime" + v-model="datetimerange" + type="datetimerange" + range-separator="-" + start-placeholder="开始时间" + end-placeholder="结束时间" + /> + </el-popover> + </el-button-group> + </div> + </div> + + <el-row :gutter="20" style="padding: 3px 10px;"> + <el-col :span="12"> + <h3 style="text-align: left;color:#2b9eef;">资源类型快照量TOP5</h3> + <div ref="bizChartsRefs" style="width: 100%;height: 320px;border: 1px solid #e4e4e4;"></div> + </el-col> + <el-col :span="12"> + <h3 style="text-align: left;color:#2b9eef;">业务系统快照量TOP5</h3> + <div ref="devChartsRefs" style="width: 100%;height: 320px;border: 1px solid #e4e4e4;"></div> + </el-col> + <el-col :span="12"> + <h3 style="text-align: left;color:#2b9eef;">人员快照量</h3> + <div ref="peopleSSChartsRefs" style="width: 100%;height: 320px;border: 1px solid #e4e4e4;"></div> + </el-col> + <el-col :span="12"> + <h3 style="text-align: left;color:#2b9eef;">快照量</h3> + <div ref="snapshotChartsRefs" style="width: 100%;height: 320px;border: 1px solid #e4e4e4;"></div> + </el-col> + </el-row> + + + <div class="search-table"> + <h3 style="text-align: left;color:#2b9eef;">快照信息</h3> + <cm-table-page :columns="tableData.columns" :dataList="tableData.dataList" + :height="height - 365" + :loading="false" + :pageSize="queryParams.pageSize" + :showBorder="true" + :showIndex="true" + :showPage="true" + :showSelection="false" + :showTools="true" + :total="queryParams.count" + @loaddata="loaddata"> + <template #default="{row,prop,column}"> + <div v-if="prop == 'resName'"> + <!-- 资源名称点击事件 --> + <el-tooltip placement="top"> + <el-button @click.prevent="goResDetail(row)" size="small" type="text"> + <span class="">{{row.resName}}</span> + </el-button> + <template #content>{{row.resName}}</template> + </el-tooltip> + </div> + <div v-if="prop == 'busTypeName'"> + <div v-if="(row.busTypeName || '').split(',').length <= '3'"> + <div v-if="row.busTypeName != null && row.busTypeName.indexOf(',') != -1" v-for="item in row.busTypeName.split(',')"> + <el-tooltip placement="top"> + <template #content>{{item}}</template> + <el-tag style="margin: 2px;" type="info" class="mx-1" effect="light">{{item}}</el-tag> + </el-tooltip> + </div> + <div v-else-if="row.busTypeName != null && row.busTypeName.indexOf(',') == -1 "> + <el-tooltip placement="top"> + <template #content>{{row.busTypeName}}</template> + <el-tag type="info" class="mx-1" effect="light">{{row.busTypeName}}</el-tag> + </el-tooltip> + </div> + </div> + <div v-else> + <el-button @click="goBus(row)" size="small" type="text"> + <span>共计:{{row.nickname.split(',').length}}个业务</span> + </el-button> + </div> + </div> + <div v-if="prop == 'nickname'"> + <div v-if="(row.nickname || '').split(',').length <= '3'"> + <div v-if="row.nickname != null && row.nickname.indexOf(',') != -1" v-for="item in row.nickname.split(',')"> + <el-tooltip placement="top"> + <template #content>{{item}}</template> + <el-tag style="margin: 2px;" type="info" class="mx-1" effect="light">{{item}}</el-tag> + </el-tooltip> + </div> + <div v-else-if="row.nickname != null && row.nickname.indexOf(',') == -1 "> + <el-tooltip placement="top"> + <template #content>{{row.nickname}}</template> + <el-tag type="info" class="mx-1" effect="light">{{row.nickname}}</el-tag> + </el-tooltip> + </div> + </div> + <div v-else> + <el-button @click="goBus(row)" size="small" type="text"> + <span>共计:{{row.nickname.split(',').length}}个业务负责人</span> + </el-button> + </div> + </div> + <div v-if="prop == 'admin'"> + <div v-if="row.admin != null"> + <el-tooltip placement="top"> + <template #content>{{row.admin}}</template> + <el-tag type="info" class="mx-1" effect="light">{{row.admin}}</el-tag> + </el-tooltip> + </div> + </div> + <div v-if="prop == 'createUser'"> + <div v-if="row.createUser != null"> + <el-tooltip placement="top"> + <template #content>{{row.createUser}}</template> + <el-tag type="info" class="mx-1" effect="light">{{row.createUser}}</el-tag> + </el-tooltip> + </div> + </div> + </template> + <template #tools="{scope}"> + <div class="list-handle"> + <span class="icon-bg" @click="handleDetail(scope.row)"> + <i class="el-icon-document" title="详情"></i> + </span> + </div> + </template> + </cm-table-page> + </div> + </div> +</div> + +<cm-dialog :showDialogVisible="showBus" :showFooter="false" :title="title" @hidedialog="cancelBtn" + width="700px"> + <template v-slot> + <div class="dialog"> + <div v-model="busType" v-for="item in busType" style="display: inline-block"> + <el-tag type="info" class="mx-1" effect="light">{{item}}</el-tag> + </div> + </div> + </template> +</cm-dialog> + diff --git a/hg-monitor-web-base/src/main/resources/static/vue3/src/views/snapshotOverview/index.js b/hg-monitor-web-base/src/main/resources/static/vue3/src/views/snapshotOverview/index.js new file mode 100644 index 0000000..878ab2c --- /dev/null +++ b/hg-monitor-web-base/src/main/resources/static/vue3/src/views/snapshotOverview/index.js @@ -0,0 +1,534 @@ +export default { + name:"snapshotOverview", + template:"", + setup(props,{attrs,slots,emit}){ + const {proxy} = Vue.getCurrentInstance(); + let height = Vue.ref(window.innerHeight); + let btnGroupType = Vue.ref(0); + let datetimerange = Vue.ref([]); + let visiblePopover = Vue.ref(false); + let queryParams = Vue.ref({ + keyWord:'', + resType:'', + busId:'', + userName:'', + time:"week", + pageNum: 1, + pageSize: 10, + count:0, + }) + //表格字段 + let tableData = Vue.ref({ + dataList: [], + columns: [ + { + prop: 'resTypeName', + label: '资源类型', + sortable: true, + align: 'center', + width: '200', + }, + { + prop: 'resName', + label: '资源名称', + sortable: true, + align: 'center' + }, + { + prop: 'ip', + label: 'IP地址', + sortable: true, + align: 'center', + width: '130' + }, { + prop: 'admin', + label: '负责人', + sortable: true, + align: 'center', + width: '130' + }, { + prop: 'busTypeName', + label: '所属业务系统', + sortable: true, + align: 'center', + width: '270' + }, + { + prop: 'nickname', + label: '业务系统负责人', + sortable: true, + align: 'center', + width: '150' + }, + { + prop: 'createUser', + label: '快照创建人', + sortable: true, + align: 'center', + width: '130' + }, + { + prop: 'createTime', + label: '快照创建时间', + sortable: true, + align: 'center', + width: '170' + }, + ] + }) + + let loaddata = ({page, limit}) => { + queryParams.value.pageNum = page; + queryParams.value.pageSize = limit; + getDataList(); + } + // 获取列表 + let getDataList = () => { + proxy.$http.get(`/api-web/snapshot/overview/getList`,queryParams.value,(res)=>{ + tableData.value.dataList = res.data; + queryParams.value.count = res.count; + },(err)=>{ + console.log(err); + }) + }; + + let getEchartsData = ()=>{ + let resTypeData = { + xaxis:[], + yaxis:[], + } + proxy.$http.get(`/api-web/snapshot/overview/resTypeTop`,queryParams.value,(res)=>{ + res.object.forEach(item=>{ + resTypeData.xaxis.push(item.xaxis); + resTypeData.yaxis.push(item.yaxis) + }) + bizCharts.setOption({ + xAxis:{ + data:resTypeData.xaxis, + }, + series:[ + { + data:resTypeData.yaxis + } + ] + }); + },(err)=>{ + console.log(err); + }) + + let busTypeData = { + xaxis:[], + yaxis:[], + } + proxy.$http.get(`/api-web/snapshot/overview/busTop`,queryParams.value,(res)=>{ + res.object.forEach(item=>{ + busTypeData.xaxis.push(item.xaxis); + busTypeData.yaxis.push(item.yaxis) + }) + devCharts.setOption({ + xAxis:{ + data:busTypeData.xaxis, + }, + series:[ + { + data:busTypeData.yaxis + } + ] + }); + },(err)=>{ + console.log(err); + }) + + let snapshotNumData = { + xaxis:[], + yaxis:[], + } + proxy.$http.get(`/api-web/snapshot/overview/snapshotNum`,queryParams.value,(res)=>{ + res.object.forEach(item=>{ + snapshotNumData.xaxis.push(item.xaxis); + snapshotNumData.yaxis.push(item.yaxis) + }) + snapshotCharts.setOption({ + yAxis:{ + data:snapshotNumData.xaxis, + }, + series:[ + { + data:snapshotNumData.yaxis + } + ] + }); + },(err)=>{ + console.log(err); + }) + + var peopleSSChartsData = []; + proxy.$http.get(`/api-web/snapshot/overview/snapshotNumByUser`,queryParams.value,(res)=>{ + res.object.forEach(item=>{ + let list = {}; + list.name = item.xaxis + '('+item.yaxis+ ')'; + list.value = item.yaxis; + peopleSSChartsData.push(list); + }) + console.log(peopleSSChartsData); + peopleSSCharts.setOption({ + series:[ + { + data:peopleSSChartsData + } + ] + }); + },(err)=>{ + console.log(err); + }) + } + // 查询事件 + let handleQuery = ()=> { + queryParams.value.pageSize=10; + queryParams.value.pageNum=1; + getDataList(); + getEchartsData(); + } + let getResType = (arr) => { + let types = arr.map(function (v) { + return v.id; + }); + queryParams.value.resType = types.join(','); + } + let getBizType = (arr) => { + let types = arr.map(function (v) { + return v.busId; + }); + queryParams.value.busId = types.join(','); + } + let getUser = (arr) => { + let types = arr.map(function (v) { + return v.username; + }); + queryParams.value.userName = types.join(','); + } + + // 按钮组点击事件 + let handleBtnGroup = (val)=>{ + queryParams.value.time = val; + if (val == 4){ + visiblePopover.value = !visiblePopover.value; + }else{ + visiblePopover.value = false; + getDataList(); + getEchartsData(); + } + }; + + // echarts + let bizChartsRefs = Vue.ref(null); + let devChartsRefs = Vue.ref(null); + let snapshotChartsRefs = Vue.ref(null); + let peopleSSChartsRefs = Vue.ref(null); + let bizCharts = Vue.ref(''); + let devCharts = Vue.ref(''); + let snapshotCharts = Vue.ref(''); + let peopleSSCharts = Vue.ref(''); + let showBus = Vue.ref(false); + let title = Vue.ref(''); + let busType = Vue.ref(); + let getEcharts = ()=>{ + bizCharts = echarts.init(bizChartsRefs.value); + let bizOption = { + grid:{ + top:"8%", + bottom:"4%", + left:"2%", + containLabel:true, + }, + tooltip: { + trigger: 'axis', + axisPointer: { + type: 'shadow', + } + }, + color:"#60a0f7", + xAxis: { + type: 'category', + data: [], + axisTick:false, + axisLabel: { + interval: 0, + formatter: val => { + // 标签长度 + const valLength = val.length + if (valLength > 8) { + return val.slice(0,7) + '...'; + } else { + return val + } + } + } + }, + yAxis: { + type: 'value', + axisLine:{ + show:true, + }, + //分隔线样式 + splitLine:{ + show:true, + lineStyle:{ + type:'dashed' + } + } + }, + series: [ + { + data: [], + type: 'bar', + barWidth: 26,//设置柱状图大小 + itemStyle:{ + borderRadius:[20,20,0,0] + } + } + ] + } + bizCharts.setOption(bizOption); + + devCharts = echarts.init(devChartsRefs.value); + let devOption = { + grid:{ + top:"8%", + bottom:"4%", + left:"2%", + containLabel:true, + }, + tooltip: { + trigger: 'axis', + axisPointer: { + type: 'shadow', + } + }, + color:"#60a0f7", + xAxis: { + type: 'category', + data: [], + axisTick:false, + axisLabel: { + interval: 0, + formatter: val => { + // 标签长度 + const valLength = val.length + if (valLength > 8) { + return val.slice(0,7) + '...'; + } else { + return val + } + } + } + }, + yAxis: { + type: 'value', + axisLine:{ + show:true, + }, + //分隔线样式 + splitLine:{ + show:true, + lineStyle:{ + type:'dashed' + } + } + }, + series: [ + { + data: [], + type: 'bar', + barWidth: 26,//设置柱状图大小 + itemStyle:{ + borderRadius:[20,20,0,0] + } + } + ] + } + devCharts.setOption(devOption); + + snapshotCharts = echarts.init(snapshotChartsRefs.value); + let shapshotOption = { + grid:{ + top:"8%", + bottom:"8%", + left:"2%", + containLabel:true, + }, + tooltip: { + trigger: 'axis', + axisPointer: { + type: 'shadow', + } + }, + color:"#EF8166", + xAxis: { + type: 'value', + axisLine:{ + show:true, + }, + //分隔线样式 + splitLine:{ + show:true, + lineStyle:{ + type:'dashed' + } + } + }, + yAxis: { + type: 'category', + data: [], + axisTick:false, + }, + series: [ + { + data: [], + type: 'bar', + barWidth: 26,//设置柱状图大小 + itemStyle:{ + borderRadius:[0,20,20,0] + } + } + ] + } + snapshotCharts.setOption(shapshotOption); + + peopleSSCharts = echarts.init(peopleSSChartsRefs.value); + let peopleOption = { + grid:{ + top:"14%", + bottom:"8%" + }, + //color:"#60a0f7", + tooltip: { + trigger: 'item' + }, + legend: { + orient: 'vertical', + top:"middle", + right:"10%", + itemWidth:35, + icon:"rect", + }, + series: [ + { + data: [], + center: ['40%', '50%'], + type: 'pie', + //高亮状态的扇区和标签样式。 + emphasis: { + label: { + show: true + }, + itemStyle: { + shadowBlur: 10, + shadowOffsetX: 0, + shadowColor: 'rgba(0, 0, 0, 0.5)' + } + }, + label: { + show: false + }, + } + ] + } + peopleSSCharts.setOption(peopleOption); + } + // 表格删除事件 + let handleDel = (row)=>{ + // console.log(row); + proxy.$global.confirm("确认删除吗?", function () { + deleteItems([row.resId],[row.batchNo]); + }) + } + //删除 + let deleteItems = (ids,nos) => { + let params = { + resId: ids.toString(), + batchNo:nos.toString(), + } + proxy.$http.get('/api-web/snapshot/his/delete', params, function (res) { + if (res && res.success) { + proxy.$global.showMsg('删除成功'); + handleQuery(); + } + }) + } + //快照详情 + let handleDetail = (row)=>{ + proxy.$global.openNewWin('template/detail/snapshot_detail', row.createUser+'在'+row.createTime+'创建的'+row.resName+'的快照', {resId:row.resId,'batchNo':row.batchNo},false); + } + + + //查看业务系统 + let goBus = (row) => { + title.value = row.resName+'所属业务系统信息'; + let busTypeAdmin = []; + for (let i = 0; i < row.busTypeName.split(',').length; i++) { + for (let j = 0; j < row.nickname.split(',').length; j++) { + if (i==j){ + busTypeAdmin.push(row.busTypeName.split(',')[i]+'('+row.nickname.split(',')[i]+')') + } + } + } + busType.value = busTypeAdmin; + showBus.value = true; + + } + //关闭弹框 + let cancelBtn = () => { + showBus.value = false; + } + + //查看资源详情 + let goResDetail = (row) => { + proxy.$global.openDetail(row.resId, row.resType, proxy); + } + + // 时间范围快捷键 修改事件 + let handleChangeDatetime = (value)=>{ + visiblePopover.value = false; + queryParams.value.time = value.join(','); + getDataList(); + getEchartsData(); + } + + + + Vue.onMounted(()=>{ + getEcharts(); + getEchartsData(); + getDataList(); + }) + + return { + height, + tableData, + queryParams, + btnGroupType, + loaddata, + handleBtnGroup, + bizChartsRefs, + devChartsRefs, + snapshotChartsRefs, + peopleSSChartsRefs, + datetimerange, + visiblePopover, + handleChangeDatetime, + handleDel, + goResDetail, + handleDetail, + goBus, + showBus, + cancelBtn, + title, + busType, + getResType, + getBizType, + handleQuery, + getUser + } + } +}