Merge branch 'master-500-dev' of http://113.200.75.45:82/monitor_v3/hg-monitor-w…
…eb into master-500-dev-xwx
Showing
20 changed files
with
963 additions
and
15 deletions
@@ -5,6 +5,10 @@ | @@ -5,6 +5,10 @@ | ||
5 | @import "../css/cacheData.css"; | 5 | @import "../css/cacheData.css"; |
6 | /*告警消除处理*/ | 6 | /*告警消除处理*/ |
7 | @import "../css/alarmsClear.css"; | 7 | @import "../css/alarmsClear.css"; |
8 | +/*日志详情*/ | ||
9 | +@import "../css/esData.css"; | ||
10 | +/*cmdb数据同步*/ | ||
11 | +@import "../css/cmdbdatasync.css"; | ||
8 | 12 | ||
9 | .d-flex { | 13 | .d-flex { |
10 | display: flex; | 14 | display: flex; |
1 | +.protocol-btn{ | ||
2 | + display: flex; | ||
3 | + justify-content: center; | ||
4 | + align-items: center; | ||
5 | +} | ||
6 | +.icon-add{ | ||
7 | + margin-left:10px; | ||
8 | + width:20px; | ||
9 | + height:20px; | ||
10 | + background: #1e9fff; | ||
11 | + display: flex; | ||
12 | + align-items: center; | ||
13 | + justify-content: center; | ||
14 | + cursor: pointer; | ||
15 | +} | ||
16 | +.protocol-btn i{ | ||
17 | + color:#ffffff; | ||
18 | +} |
1 | +.esData-detail-container{ | ||
2 | + padding:0 15px; | ||
3 | + min-height: 500px; | ||
4 | + max-height:800px; | ||
5 | + overflow: auto; | ||
6 | +} | ||
7 | +.esData-detail-container .info-title{ | ||
8 | + display: flex; | ||
9 | + justify-content: space-between; | ||
10 | + margin-bottom: 10px; | ||
11 | + padding-top:10px; | ||
12 | + font-size: 16px; | ||
13 | + margin-top:10px; | ||
14 | +} | ||
15 | +.esData-detail-container .info-content{ | ||
16 | + margin-bottom: 5px; | ||
17 | +} | ||
18 | +.esData-detail-container .info-content-body{ | ||
19 | + background: #ffffff; | ||
20 | + padding:10px 30px; | ||
21 | +} | ||
22 | +.esData-detail-container .content-body-info{ | ||
23 | + display: flex; | ||
24 | + align-items: center; | ||
25 | + justify-content: flex-start; | ||
26 | + flex-wrap: wrap; | ||
27 | +} | ||
28 | +.esData-detail-container .info-item{ | ||
29 | + width:33%; | ||
30 | + margin:8px 0; | ||
31 | + text-align: left; | ||
32 | +} | ||
33 | +.esData-detail-info-content{ | ||
34 | + text-align: left; | ||
35 | +} |
1 | <div > | 1 | <div > |
2 | <!-- 表格--> | 2 | <!-- 表格--> |
3 | <el-table :border="showBorder" v-loading="loading" :size="size" ref="multipleTable" @selection-change="handleSelectionChange" :data="dataList" stripe header-row-class-name="tbl-header-class" :height="height" | 3 | <el-table :border="showBorder" v-loading="loading" :size="size" ref="multipleTable" @selection-change="handleSelectionChange" :data="dataList" stripe header-row-class-name="tbl-header-class" :height="height" |
4 | - style="width: 100%;margin: 0px 0px; font-size:13.5px;"> | 4 | + style="width: 100%;margin: 0px 0px; font-size:13.5px;" :row-key="getRowKeys" :expand-row-keys="expands"> |
5 | + | ||
6 | + <el-table-column type="expand" v-if="showExpand"> | ||
7 | + <template #default="scope"> | ||
8 | + <slot name="expand" :scope="scope" > | ||
9 | + | ||
10 | + </slot> | ||
11 | + </template> | ||
12 | + </el-table-column> | ||
5 | <el-table-column v-if="showSelection && columns.length > 0" align="center" type="selection" width="55" /> | 13 | <el-table-column v-if="showSelection && columns.length > 0" align="center" type="selection" width="55" /> |
6 | <el-table-column v-if="showIndex && columns.length > 0" type="index" :label="indexLabel" align="center" width="50"/> | 14 | <el-table-column v-if="showIndex && columns.length > 0" type="index" :label="indexLabel" align="center" width="50"/> |
7 | 15 |
@@ -87,6 +87,21 @@ export default { | @@ -87,6 +87,21 @@ export default { | ||
87 | multipleSelection:{ | 87 | multipleSelection:{ |
88 | type:Array, | 88 | type:Array, |
89 | default:[] | 89 | default:[] |
90 | + }, | ||
91 | + //展开行 | ||
92 | + showExpand:{ | ||
93 | + type: Boolean, | ||
94 | + default: false | ||
95 | + }, | ||
96 | + //行数据的key | ||
97 | + getRowKeys:{ | ||
98 | + type: String, | ||
99 | + default: 'id' | ||
100 | + }, | ||
101 | + //是否默认展开所有行 | ||
102 | + expands:{ | ||
103 | + type: Array, | ||
104 | + default: [] | ||
90 | } | 105 | } |
91 | }, | 106 | }, |
92 | data() { | 107 | data() { |
@@ -103,6 +103,18 @@ const routes = [{ | @@ -103,6 +103,18 @@ const routes = [{ | ||
103 | name: 'busDoc', | 103 | name: 'busDoc', |
104 | component: () => myImport('views/busDoc/index') | 104 | component: () => myImport('views/busDoc/index') |
105 | }, | 105 | }, |
106 | + //日志 | ||
107 | + { | ||
108 | + path: '/esData', | ||
109 | + name: 'esDataIndex', | ||
110 | + component: () => myImport('views/esData/index'), | ||
111 | + }, | ||
112 | + //监控对接CMDB功能 | ||
113 | + { | ||
114 | + path: '/cmdbdatasync', | ||
115 | + name: 'cmdbdatasync', | ||
116 | + component: () => myImport('views/cmdbdatasync/index'), | ||
117 | + }, | ||
106 | ]; | 118 | ]; |
107 | 119 | ||
108 | // hash模式: createWebHashHistory | 120 | // hash模式: createWebHashHistory |
@@ -271,22 +271,28 @@ global.openDetail = (resId, resType, proxy) => { | @@ -271,22 +271,28 @@ global.openDetail = (resId, resType, proxy) => { | ||
271 | 271 | ||
272 | // 获取资源详情 | 272 | // 获取资源详情 |
273 | proxy.$http.get(`/api-web/v32/res/detail/${resId}`, {}, function (res) { | 273 | proxy.$http.get(`/api-web/v32/res/detail/${resId}`, {}, function (res) { |
274 | - if (res && res.map) { | ||
275 | - let data = res.map; | ||
276 | - | ||
277 | - provider = data.provider; | ||
278 | - ip = data.ip; | ||
279 | - resTypeName = data.resTypeName; | ||
280 | - adminName = data.adminName; | ||
281 | - manageIp = data.manageIp; | ||
282 | - collProtocol = data.collProtocol; | ||
283 | - name = data.resName; | ||
284 | - if(resType == ''){ | ||
285 | - resType = data.resType; | 274 | + if(res && res.success){ |
275 | + if (res && res.map) { | ||
276 | + let data = res.map; | ||
277 | + | ||
278 | + provider = data.provider; | ||
279 | + ip = data.ip; | ||
280 | + resTypeName = data.resTypeName; | ||
281 | + adminName = data.adminName; | ||
282 | + manageIp = data.manageIp; | ||
283 | + collProtocol = data.collProtocol; | ||
284 | + name = data.resName; | ||
285 | + if(resType == ''){ | ||
286 | + resType = data.resType; | ||
287 | + } | ||
288 | + | ||
289 | + lyaui.commonCols.detailPage(resId, resType, editFlag, provider, name, ip, resTypeName, adminName, manageIp, collProtocol); | ||
286 | } | 290 | } |
291 | + }else{ | ||
292 | + proxy.$global.showMsg('该资源暂未监控', "error"); | ||
287 | 293 | ||
288 | - lyaui.commonCols.detailPage(resId, resType, editFlag, provider, name, ip, resTypeName, adminName, manageIp, collProtocol); | ||
289 | } | 294 | } |
295 | + | ||
290 | }); | 296 | }); |
291 | } | 297 | } |
292 | 298 | ||
@@ -363,6 +369,15 @@ global.getAlarmLevel = (level) => { | @@ -363,6 +369,15 @@ global.getAlarmLevel = (level) => { | ||
363 | return params[level]; | 369 | return params[level]; |
364 | } | 370 | } |
365 | 371 | ||
372 | +global.getHealthDesc = (level) => { | ||
373 | + let params = { | ||
374 | + "3": {name: '优', color: '#7be00d'}, | ||
375 | + "2": {name: '良', color: '#f5a623'}, | ||
376 | + "1": {name: '中', color: '#d81e06'} | ||
377 | + } | ||
378 | + return params[level]; | ||
379 | +} | ||
380 | + | ||
366 | // 组件默认大小 medium / small / mini | 381 | // 组件默认大小 medium / small / mini |
367 | global.elementSize = ''; | 382 | global.elementSize = ''; |
368 | global.height = window.innerHeight - 20; | 383 | global.height = window.innerHeight - 20; |
1 | +<div class="cmdbdatasyncEdit-container" style="min-height: 500px;"> | ||
2 | + | ||
3 | + <div class="search-table"> | ||
4 | + <cm-table-page :columns="tableData.columns" :dataList="editTbaleData" | ||
5 | + :showIndex="true" | ||
6 | + @loaddata = "loaddata" | ||
7 | + :showSelection="false" | ||
8 | + :showBorder="true" | ||
9 | + :loading="false" | ||
10 | + :pageSize="pageSize" | ||
11 | + :showPage="false" | ||
12 | + :showTools="true" | ||
13 | + :showExpand="true" | ||
14 | + :getRowKeys="tableData.getRowKeys" | ||
15 | + :expands="tableData.expands" | ||
16 | + :height="height - 110"> | ||
17 | + <template #expand="{scope}"> | ||
18 | + aaa{{scope.row.expand}} | ||
19 | + </template> | ||
20 | + <template #default="{row,prop,column}"> | ||
21 | + <div> | ||
22 | + <el-input v-model="row[prop]" placeholder="Please input" /> | ||
23 | + <!--<el-select placeholder="请选择" size="small" style="width: 100%" | ||
24 | + @change="changeProperty(row,prop,column)" v-model="row[prop]" | ||
25 | + :multiple="false" | ||
26 | + collapse-tags clearable filterable placeholder="请选择"> | ||
27 | + <el-option label="是" :value="0"></el-option> | ||
28 | + <el-option label="否" :value="1"></el-option> | ||
29 | + </el-select>--> | ||
30 | + </div> | ||
31 | + </template> | ||
32 | + <template #tools="{scope}"> | ||
33 | + <div class="protocol-btn"> | ||
34 | + <span class="icon-add" @click="addProtocol" title="协议参数"><i class="el-icon-plus"></i></span> | ||
35 | + </div> | ||
36 | + </template> | ||
37 | + </cm-table-page> | ||
38 | + </div> | ||
39 | + <div class="save-button" style="text-align:right;"> | ||
40 | + <el-button type="primary" style="margin-top:20px;margin-right:10px;" @click="saveEdit">确定</el-button> | ||
41 | + </div> | ||
42 | +</div> |
hg-monitor-web-base/src/main/resources/static/vue3/src/views/cmdbdatasync/cmdbdatasyncEdit/index.js
0 → 100644
1 | +export default { | ||
2 | + name: 'cmdbdatasyncEdit', | ||
3 | + template: '', | ||
4 | + components: { | ||
5 | + | ||
6 | + }, | ||
7 | + props: { | ||
8 | + tableData:{ | ||
9 | + type:Object, | ||
10 | + default: {} | ||
11 | + } | ||
12 | + }, | ||
13 | + setup(props, {attrs, slots, emit}) { | ||
14 | + const {proxy} = Vue.getCurrentInstance(); | ||
15 | + let height = Vue.ref(window.innerHeight); | ||
16 | + let editTbaleData=Vue.ref(props.tableData.dataList); | ||
17 | + // let columns=Vue.ref(props.tableData.columns); | ||
18 | + // let getRowKeys=Vue.ref(props.tableData.getRowKeys); | ||
19 | + // let expands=Vue.ref(props.tableData.expands); | ||
20 | + //保存编辑 | ||
21 | + let saveEdit=()=>{ | ||
22 | + //保存接口 todo | ||
23 | + let param={ | ||
24 | + editTbaleData:editTbaleData.value, | ||
25 | + visibility:false | ||
26 | + } | ||
27 | + emit("callbackedit",param) | ||
28 | + } | ||
29 | + //添加协议 | ||
30 | + let addProtocol=()=>{ | ||
31 | + proxy.$global.layer.open({ | ||
32 | + title:'资源协议', | ||
33 | + id:'resManageChooseProtocolHtml', | ||
34 | + type:1, | ||
35 | + area: ['80%', '90%'], | ||
36 | + btn:['确定','取消'], | ||
37 | + scrollbar:true, | ||
38 | + success: function(){ | ||
39 | + proxy.$global.layui.view('resManageChooseProtocolHtml').render('/baseconfig/protocol/index',{'hasParam':'1'}); | ||
40 | + }, | ||
41 | + yes:function (index,layero) { | ||
42 | + var data = proxy.$global.layui.table.checkStatus('protocol_table').data; | ||
43 | + formData.ip = $('#resManageAddForm').find('input[name="ip"]').val(); | ||
44 | + formData.port = $('#resManageAddForm').find('input[name="port"]').val(); | ||
45 | + if(data.length>0){ | ||
46 | + createProtocolDom(data,false); | ||
47 | + form.render() | ||
48 | + layer.close(index); | ||
49 | + }else{ | ||
50 | + layer.msg("无选中的数据或当",{ offset: '15px' , icon: 7 , time: 2000 }) | ||
51 | + return false; | ||
52 | + } | ||
53 | + } | ||
54 | + }) | ||
55 | + } | ||
56 | + // 挂载完 | ||
57 | + Vue.onMounted(() => { | ||
58 | + }) | ||
59 | + | ||
60 | + | ||
61 | + return { | ||
62 | + height, | ||
63 | + editTbaleData, | ||
64 | + // columns, | ||
65 | + saveEdit, | ||
66 | + addProtocol, | ||
67 | + // getRowKeys, | ||
68 | + // expands | ||
69 | + } | ||
70 | + } | ||
71 | + | ||
72 | +} |
1 | +<div class="container" :style="{'height':height+'px','max-height':height+'px','display':'flex'}"> | ||
2 | + <div class="async-left-tree" style="width:200px;overflow-x: auto;background: #fff;border-right:1px solid #f2f2f2;"> | ||
3 | + <el-tree style="padding-top:10px;" class="tree-div" ref="roleTree" :data="treeData" :props="defaultProps" @node-click="handleNodeClick" | ||
4 | + node-key="id" :default-checked-keys="checkedKeys" | ||
5 | + /> | ||
6 | + </div> | ||
7 | + <div class="cm-card" :style="{'min-height':height+'px','max-height':height+'px','height':'100%','padding-top':'3px','flex':'1'}"> | ||
8 | + <div class="search"> | ||
9 | + <div class="condition"> | ||
10 | + <el-form-item > | ||
11 | + <el-input v-model="search.keyword" placeholder="关键字"></el-input> | ||
12 | + </el-form-item> | ||
13 | + <el-form-item > | ||
14 | + <el-button @click="getDataList">查询</el-button> | ||
15 | + </el-form-item> | ||
16 | + <el-form-item > | ||
17 | + <el-button @click="handleEdit">编辑</el-button> | ||
18 | + </el-form-item> | ||
19 | + <el-form-item > | ||
20 | + <el-button @click="handleRefresh">同步</el-button> | ||
21 | + </el-form-item> | ||
22 | + </div> | ||
23 | + </div> | ||
24 | + <div class="search-table"> | ||
25 | + <cm-table-page :columns="tableData.columns" :dataList="tableData.dataList" | ||
26 | + :showIndex="true" | ||
27 | + :total="tableData.count" | ||
28 | + @loaddata = "loaddata" | ||
29 | + @selectionChange="selectionChange" | ||
30 | + :showSelection="true" | ||
31 | + :showBorder="true" | ||
32 | + :loading="false" | ||
33 | + :pageSize="pageSize" | ||
34 | + :showPage="true" | ||
35 | + :showTools="true" | ||
36 | + :height="height - 110"> | ||
37 | + <template #default="{row,prop,column}"> | ||
38 | + <div v-if="prop == 'resName'"> | ||
39 | + <span class="resName-span" style="cursor: pointer;color:#1e9fff" @click="goResDetail(row.resId,row.resName,row.resType)">{{row.resName}}</span> | ||
40 | + </div> | ||
41 | + </template> | ||
42 | + <template #tools="{scope}"> | ||
43 | + <div class="list-handle"> | ||
44 | + <span class="icon-bg" @click="handleEdit(1,scope.row)"><i class="el-icon-edit-outline" title="编辑"></i></span> | ||
45 | + <span class="icon-bg" @click="handleRefresh(1,scope.row)"><i class="el-icon-refresh" title="同步"></i></span> | ||
46 | + </div> | ||
47 | + </template> | ||
48 | + </cm-table-page> | ||
49 | + </div> | ||
50 | + </div> | ||
51 | +</div> | ||
52 | + | ||
53 | +<!--弹框--> | ||
54 | +<cm-dialog :title="dialog.title" width="90%" :showDialogVisible="dialog.show" @hidedialog="hideDialog" :showFooter="false"> | ||
55 | + <template v-slot> | ||
56 | + <cmdbdatasyncEdit :tableData="dialog.tableData" @callbackedit="callbackedit"/> | ||
57 | + </template> | ||
58 | +</cm-dialog> | ||
59 | + |
1 | +export default { | ||
2 | + name: 'cmdbdatasync', | ||
3 | + template: '', | ||
4 | + components: { | ||
5 | + 'cmdbdatasyncEdit': Vue.defineAsyncComponent( | ||
6 | + () => myImport('views/cmdbdatasync/cmdbdatasyncEdit/index') | ||
7 | + ) | ||
8 | + }, | ||
9 | + props: [], | ||
10 | + setup(props, {attrs, slots, emit}) { | ||
11 | + const {proxy} = Vue.getCurrentInstance(); | ||
12 | + let height = Vue.ref(window.innerHeight); | ||
13 | + let defaultProps=Vue.ref({ | ||
14 | + children: 'children', | ||
15 | + label: 'title' | ||
16 | + }) | ||
17 | + let treeData=Vue.ref([]) // 所有的树结点 | ||
18 | + let defaultNode=Vue.ref(true);//默认节点 | ||
19 | + let resType=Vue.ref('');//选中的树节点值 | ||
20 | + let handleNodeClick=(data,node)=>{ | ||
21 | + //点击树节点,根据某个字段获取列表 todo | ||
22 | + console.log("*(*(*(*",data,node) | ||
23 | + proxy.$global.showMsg(data.id,'warning') | ||
24 | + resType.value=data.value; | ||
25 | + defaultNode.value=false; | ||
26 | + getDataList(); | ||
27 | + } | ||
28 | + | ||
29 | + let search = Vue.ref({ | ||
30 | + keyword: '', | ||
31 | + pageNum: 1, | ||
32 | + pageSize: 20, | ||
33 | + }); | ||
34 | + //表格字段 | ||
35 | + let tableData = Vue.ref({ | ||
36 | + count:0, | ||
37 | + dataList: [{ | ||
38 | + id:1, | ||
39 | + resName:'资源一' | ||
40 | + },{ | ||
41 | + id:2, | ||
42 | + resName:'资源34' | ||
43 | + }], | ||
44 | + columns: [ | ||
45 | + { | ||
46 | + prop: 'resName', | ||
47 | + label: '资源名称', | ||
48 | + sortable: true, | ||
49 | + align: 'center', | ||
50 | + width: '250' | ||
51 | + }, | ||
52 | + { | ||
53 | + prop: 'resTypeName', | ||
54 | + label: '资源类型', | ||
55 | + sortable: true, | ||
56 | + align: 'center', | ||
57 | + width: '200' | ||
58 | + }, { | ||
59 | + prop: 'host', | ||
60 | + label: 'IP地址', | ||
61 | + sortable: true, | ||
62 | + align: 'center', | ||
63 | + width: '200' | ||
64 | + }, { | ||
65 | + prop: 'type', | ||
66 | + label: '日志来源', | ||
67 | + sortable: true, | ||
68 | + align: 'center', | ||
69 | + width: '200' | ||
70 | + }, | ||
71 | + { | ||
72 | + prop: 'program', | ||
73 | + label: '日志类型', | ||
74 | + sortable: true, | ||
75 | + align: 'center', | ||
76 | + width: '200' | ||
77 | + }, | ||
78 | + { | ||
79 | + prop: 'message', | ||
80 | + label: '日志内容', | ||
81 | + sortable: true, | ||
82 | + align: 'center', | ||
83 | + }, | ||
84 | + ] | ||
85 | + }) | ||
86 | + let dialog = Vue.ref({ | ||
87 | + title : "编辑", | ||
88 | + show:false, | ||
89 | + tableData : {} | ||
90 | + }); | ||
91 | + let loaddata = ({page, limit}) => { | ||
92 | + search.value.pageNum = page; | ||
93 | + search.value.pageSize = limit; | ||
94 | + } | ||
95 | + let hideDialog = (flg) => { | ||
96 | + dialog.value.show = flg; | ||
97 | + } | ||
98 | + //全选事件 | ||
99 | + let selectionData=Vue.ref([]);//选择的数据 | ||
100 | + let selectionChange= (val) =>{ | ||
101 | + selectionData.value=val; | ||
102 | + } | ||
103 | + // 处理弹框 | ||
104 | + let handle = (row) =>{ | ||
105 | + hideDialog(true); | ||
106 | + dialog.value.tableData.dataList= row; | ||
107 | + dialog.value.tableData.columns=tableData.value.columns; | ||
108 | + dialog.value.tableData.getRowKeys= 'id'; | ||
109 | + let arr=[]; | ||
110 | + row.map(item=>{ | ||
111 | + arr.push(item.id) | ||
112 | + }) | ||
113 | + //默认展开第一行 | ||
114 | + dialog.value.tableData.expands= [arr[0]]; | ||
115 | + | ||
116 | + } | ||
117 | + //编辑 | ||
118 | + let handleEdit = (flag,row) =>{ | ||
119 | + if(flag==1){ | ||
120 | + handle([row]); | ||
121 | + }else{ | ||
122 | + if(selectionData.value.length>0){ | ||
123 | + handle(selectionData.value); | ||
124 | + }else{ | ||
125 | + proxy.$global.showMsg('请选择数据','warning') | ||
126 | + } | ||
127 | + } | ||
128 | + } | ||
129 | + //同步 todo | ||
130 | + let handleRefresh = (flag,row) =>{ | ||
131 | + if(flag==1){ | ||
132 | + //单个同步 row-->对象 | ||
133 | + }else{ | ||
134 | + //多选同步 selectionData.value-->数组 | ||
135 | + if(selectionData.value.length>0){ | ||
136 | + //... | ||
137 | + }else{ | ||
138 | + proxy.$global.showMsg('请选择数据','warning') | ||
139 | + } | ||
140 | + } | ||
141 | + } | ||
142 | + //编辑返回数据 | ||
143 | + let callbackedit=(obj)=>{ | ||
144 | + console.log("***",obj.editTbaleData,obj.visibility) | ||
145 | + hideDialog(obj.visibility) | ||
146 | + | ||
147 | + //obj.editTbaleData编辑后的数据,todo | ||
148 | + // getDataList();//获取列表数据 | ||
149 | + } | ||
150 | + //查看资源详情 | ||
151 | + let goResDetail=(resId,resName,resType)=>{ | ||
152 | + proxy.$global.openDetail(resId, resType, proxy); | ||
153 | + | ||
154 | + } | ||
155 | + //获取资源树数据 | ||
156 | + let getResData=()=>{ | ||
157 | + proxy.$http.post(`/api-web/attribute/getTree`, {}, function (res) { | ||
158 | + if (res && res.data) { | ||
159 | + treeData.value = res.data; | ||
160 | + } | ||
161 | + }); | ||
162 | + } | ||
163 | + // 获取列表 todo | ||
164 | + let getDataList = () => { | ||
165 | + if(defaultNode.value){ | ||
166 | + resType.value=treeData.value[0].children[0].value; | ||
167 | + } | ||
168 | + let params={ | ||
169 | + resType:resType.value, | ||
170 | + pageNum: search.value.pageNum, | ||
171 | + pageSize: search.value.pageSize, | ||
172 | + keyword:search.value.keyword | ||
173 | + } | ||
174 | + proxy.$http.post(`/api-web/`, params, function (res) { | ||
175 | + if (res && res.object) { | ||
176 | + tableData.value.dataList = res.object; | ||
177 | + tableData.value.count = parseInt(res.object.total); | ||
178 | + } else { | ||
179 | + tableData.value.dataList = []; | ||
180 | + tableData.value.count = 0; | ||
181 | + } | ||
182 | + }); | ||
183 | + } | ||
184 | + | ||
185 | + // 挂载完 | ||
186 | + Vue.onMounted(() => { | ||
187 | + // getDataList();//获取列表数据 | ||
188 | + getResData();//获取资源树数据 | ||
189 | + }) | ||
190 | + | ||
191 | + | ||
192 | + return { | ||
193 | + defaultProps, | ||
194 | + treeData, | ||
195 | + defaultNode, | ||
196 | + handleNodeClick, | ||
197 | + getResData, | ||
198 | + height, | ||
199 | + search, | ||
200 | + dialog, | ||
201 | + hideDialog, | ||
202 | + selectionChange, | ||
203 | + selectionData, | ||
204 | + handle, | ||
205 | + loaddata, | ||
206 | + tableData, | ||
207 | + getDataList, | ||
208 | + handleEdit, | ||
209 | + handleRefresh, | ||
210 | + callbackedit, | ||
211 | + goResDetail, | ||
212 | + resType | ||
213 | + } | ||
214 | + } | ||
215 | + | ||
216 | +} |
hg-monitor-web-base/src/main/resources/static/vue3/src/views/esData/esDataDetail/index.html
0 → 100644
1 | +<div class="esData-detail-container"> | ||
2 | + <el-descriptions | ||
3 | + class="" | ||
4 | + title="日志信息" | ||
5 | + :column="2" | ||
6 | + :size="size" | ||
7 | + border | ||
8 | + > | ||
9 | + <el-descriptions-item> | ||
10 | + <template #label> | ||
11 | + <div class="cell-item"> | ||
12 | + 资源名称 | ||
13 | + </div> | ||
14 | + </template> | ||
15 | + {{detail.resName}} | ||
16 | + </el-descriptions-item> | ||
17 | + <el-descriptions-item> | ||
18 | + <template #label> | ||
19 | + <div class="cell-item"> | ||
20 | + IP地址 | ||
21 | + </div> | ||
22 | + </template> | ||
23 | + {{detail.host}} | ||
24 | + </el-descriptions-item> | ||
25 | + <el-descriptions-item> | ||
26 | + <template #label> | ||
27 | + <div class="cell-item"> | ||
28 | + 资源类型 | ||
29 | + </div> | ||
30 | + </template> | ||
31 | + {{detail.resTypeName}} | ||
32 | + </el-descriptions-item> | ||
33 | + <el-descriptions-item> | ||
34 | + <template #label> | ||
35 | + <div class="cell-item"> | ||
36 | + 日志来源 | ||
37 | + </div> | ||
38 | + </template> | ||
39 | + {{detail.type}} | ||
40 | + </el-descriptions-item> | ||
41 | + <el-descriptions-item> | ||
42 | + <template #label> | ||
43 | + <div class="cell-item"> | ||
44 | + 日志类型 | ||
45 | + </div> | ||
46 | + </template> | ||
47 | + {{detail.program}} | ||
48 | + </el-descriptions-item> | ||
49 | + <el-descriptions-item> | ||
50 | + <template #label> | ||
51 | + <div class="cell-item"> | ||
52 | + 采集时间 | ||
53 | + </div> | ||
54 | + </template> | ||
55 | + {{detail.dbTimeStr}} | ||
56 | + </el-descriptions-item> | ||
57 | + <el-descriptions-item> | ||
58 | + <template #label> | ||
59 | + <div class="cell-item"> | ||
60 | + 日志时间 | ||
61 | + </div> | ||
62 | + </template> | ||
63 | + {{detail.logDate}} | ||
64 | + </el-descriptions-item> | ||
65 | + </el-descriptions> | ||
66 | + <div class="info-title"> | ||
67 | + <span style="font-weight:bold">日志内容</span> | ||
68 | + </div> | ||
69 | + <div class="esData-detail-info-content" v-html="detail.message"> | ||
70 | + </div> | ||
71 | +</div> |
hg-monitor-web-base/src/main/resources/static/vue3/src/views/esData/esDataDetail/index.js
0 → 100644
1 | +export default { | ||
2 | + name: 'esDataDetail', | ||
3 | + template: '', | ||
4 | + components: { | ||
5 | + | ||
6 | + }, | ||
7 | + props: { | ||
8 | + detail:{ | ||
9 | + type:Object, | ||
10 | + default: {} | ||
11 | + } | ||
12 | + }, | ||
13 | + setup(props, {attrs, slots, emit}) { | ||
14 | + const {proxy} = Vue.getCurrentInstance(); | ||
15 | + | ||
16 | + // 挂载完 | ||
17 | + Vue.onMounted(() => { | ||
18 | + }) | ||
19 | + | ||
20 | + | ||
21 | + return { | ||
22 | + | ||
23 | + } | ||
24 | + } | ||
25 | + | ||
26 | +} |
1 | +<div class="container" :style="{'height':height+'px','max-height':height+'px'}"> | ||
2 | + <div class="cm-card" :style="{'min-height':height+'px','max-height':height+'px','height':'100%','padding-top':'3px'}"> | ||
3 | + <div class="search"> | ||
4 | + <div class="condition"> | ||
5 | + <el-form-item > | ||
6 | + <el-input v-model="search.keyword" placeholder="=资源名称、日志内容="></el-input> | ||
7 | + </el-form-item> | ||
8 | + <el-form-item > | ||
9 | + <el-dropdown> | ||
10 | + <cm-res-type-tree-input multiple clearable collapseTags @callback="getResType"/> | ||
11 | + </el-dropdown> | ||
12 | + </el-form-item> | ||
13 | + <el-form-item > | ||
14 | + <el-select v-model="search.program" class="m-2" placeholder="日志类型" clearable> | ||
15 | + <el-option | ||
16 | + v-for="item in logTypeData" | ||
17 | + :key="item.ddicCode" | ||
18 | + :label="item.ddicName" | ||
19 | + :value="item.ddicCode" | ||
20 | + /> | ||
21 | + </el-select> | ||
22 | + </el-form-item> | ||
23 | + | ||
24 | + <el-form-item> | ||
25 | + <el-date-picker | ||
26 | + v-model="search.dateTime" | ||
27 | + type="datetimerange" | ||
28 | + range-separator="-" | ||
29 | + start-placeholder="开始时间" | ||
30 | + end-placeholder="结束时间" | ||
31 | + format="YYYY-MM-DD HH:mm:ss" | ||
32 | + value-format="YYYY-MM-DD HH:mm:ss" | ||
33 | + /> | ||
34 | + </el-form-item> | ||
35 | + <el-form-item > | ||
36 | + <el-button @click="getDataList">查询</el-button> | ||
37 | + </el-form-item> | ||
38 | + </div> | ||
39 | + </div> | ||
40 | + | ||
41 | + <div class="search-table"> | ||
42 | + <cm-table-page :columns="tableData.columns" :dataList="tableData.dataList" | ||
43 | + :showIndex="true" | ||
44 | + :total="tableData.count" | ||
45 | + @loaddata = "loaddata" | ||
46 | + :showSelection="false" | ||
47 | + :showBorder="true" | ||
48 | + :loading="false" | ||
49 | + :pageSize="search.pageSize" | ||
50 | + :showPage="true" | ||
51 | + :showTools="true" | ||
52 | + :height="height - 110"> | ||
53 | + <template #default="{row,prop,column}"> | ||
54 | + <div v-if="prop == 'resName'"> | ||
55 | + <span class="resName-span" style="cursor: pointer;color:#1e9fff" @click="goResDetail(row.resId,row.resName,row.resType)">{{row.resName}}</span> | ||
56 | + </div> | ||
57 | + <div v-if="prop == 'message'" > | ||
58 | + <el-tooltip > | ||
59 | + <template #content> | ||
60 | + <div style="max-width:400px;overflow: hidden; text-overflow: ellipsis;display: -webkit-box; -webkit-line-clamp: 5; -webkit-box-orient: vertical;"> | ||
61 | + {{row.message}} | ||
62 | + </div> | ||
63 | + </template> | ||
64 | + <div v-html="row.message" style="overflow: hidden; text-overflow: ellipsis;display: -webkit-box; -webkit-line-clamp: 1; -webkit-box-orient: vertical;"></div> | ||
65 | + </el-tooltip> | ||
66 | + </div> | ||
67 | + </template> | ||
68 | + <template #tools="{scope}"> | ||
69 | + <div class="list-handle"> | ||
70 | + <span class="icon-bg"> | ||
71 | + <i class="el-icon-view" title="查看" @click="handleView(scope.row)"></i> | ||
72 | + </span> | ||
73 | + </div> | ||
74 | + </template> | ||
75 | + </cm-table-page> | ||
76 | + </div> | ||
77 | + </div> | ||
78 | +</div> | ||
79 | + | ||
80 | +<!--弹框--> | ||
81 | +<cm-dialog :title="dialog.title" width="60%" :showDialogVisible="dialog.show" @hidedialog="hideDialog" :showFooter="false"> | ||
82 | + <template v-slot> | ||
83 | + <esDataDetail :detail="dialog.detail" /> | ||
84 | + </template> | ||
85 | +</cm-dialog> | ||
86 | + |
1 | +export default { | ||
2 | + name: 'esDataIndex', | ||
3 | + template: '', | ||
4 | + components: { | ||
5 | + 'esDataDetail': Vue.defineAsyncComponent( | ||
6 | + () => myImport('views/esData/esDataDetail/index') | ||
7 | + ) | ||
8 | + }, | ||
9 | + props: [], | ||
10 | + setup(props, {attrs, slots, emit}) { | ||
11 | + const {proxy} = Vue.getCurrentInstance(); | ||
12 | + let height = Vue.ref(window.innerHeight); | ||
13 | + let dateTime=Vue.ref([]) | ||
14 | + let search = Vue.ref({ | ||
15 | + program:'', | ||
16 | + sortBy:'dbTime', | ||
17 | + scopeBy:'dbTimeStr.keyword', | ||
18 | + keyword: '', | ||
19 | + type:'syslog', | ||
20 | + pageNum: 1, | ||
21 | + pageSize: 20, | ||
22 | + dateTime:[], | ||
23 | + resType:'', | ||
24 | + }); | ||
25 | + let dialog = Vue.ref({ | ||
26 | + title : "日志详情", | ||
27 | + show:false, | ||
28 | + esId : '' | ||
29 | + }); | ||
30 | + //表格字段 | ||
31 | + let tableData = Vue.ref({ | ||
32 | + count:0, | ||
33 | + dataList: [], | ||
34 | + columns: [ | ||
35 | + { | ||
36 | + prop: 'logDate', | ||
37 | + label: '日志时间', | ||
38 | + sortable: true, | ||
39 | + align: 'center', | ||
40 | + width: '250', | ||
41 | + }, | ||
42 | + { | ||
43 | + prop: 'resName', | ||
44 | + label: '资源名称', | ||
45 | + sortable: true, | ||
46 | + align: 'center', | ||
47 | + width: '250' | ||
48 | + }, | ||
49 | + { | ||
50 | + prop: 'resTypeName', | ||
51 | + label: '资源类型', | ||
52 | + sortable: true, | ||
53 | + align: 'center', | ||
54 | + width: '200' | ||
55 | + }, { | ||
56 | + prop: 'host', | ||
57 | + label: 'IP地址', | ||
58 | + sortable: true, | ||
59 | + align: 'center', | ||
60 | + width: '200' | ||
61 | + }, { | ||
62 | + prop: 'type', | ||
63 | + label: '日志来源', | ||
64 | + sortable: true, | ||
65 | + align: 'center', | ||
66 | + width: '200' | ||
67 | + }, | ||
68 | + { | ||
69 | + prop: 'program', | ||
70 | + label: '日志类型', | ||
71 | + sortable: true, | ||
72 | + align: 'center', | ||
73 | + width: '200' | ||
74 | + }, | ||
75 | + { | ||
76 | + prop: 'message', | ||
77 | + label: '日志内容', | ||
78 | + sortable: true, | ||
79 | + align: 'center', | ||
80 | + }, | ||
81 | + ] | ||
82 | + }) | ||
83 | + let resTypeArr = Vue.ref([]); | ||
84 | + let getResType = (arr) => { | ||
85 | + var types = arr.map(function (v) { | ||
86 | + return v.id; | ||
87 | + }); | ||
88 | + resTypeArr.value = types; | ||
89 | + search.value.resType=resTypeArr.value.join(','); | ||
90 | + // getDataList(); | ||
91 | + } | ||
92 | + //获取时间点 转年月日的方法 | ||
93 | + const getDateTime=(newDate)=>{ | ||
94 | + let dateTime=''; | ||
95 | + let year=newDate.getFullYear();//获取当前年 | ||
96 | + let month1=(newDate.getMonth()+1)+''; | ||
97 | + let month=timeFormat(month1);//获取当前月 | ||
98 | + let day=timeFormat(newDate.getDate());//获取当前日 | ||
99 | + let hours=timeFormat(newDate.getHours()+'');//获取当前时 | ||
100 | + let minutes=timeFormat(newDate.getMinutes()+'');//获取当前分 | ||
101 | + let seconds=timeFormat(newDate.getSeconds()+'');//获取当前秒 | ||
102 | + dateTime= year+'-'+month+'-'+day;//' '+hours+':'+minutes+':'+seconds; | ||
103 | + return dateTime; | ||
104 | + } | ||
105 | + //转换个位数为 00 | ||
106 | + let timeFormat =(number)=> { | ||
107 | + return number.length == 1 ? ('0' + number) : number | ||
108 | + } | ||
109 | + // 获取列表 | ||
110 | + let getDataList = () => { | ||
111 | + let nowDate=getDateTime(new Date()); | ||
112 | + let startTime=(search.value.dateTime && search.value.dateTime[0])?search.value.dateTime[0]:''; | ||
113 | + let endTime=(search.value.dateTime && search.value.dateTime[1])?search.value.dateTime[1]:''; | ||
114 | + let startDateStr=startTime?startTime.split(' ')[0]:''; | ||
115 | + let endDateStr=endTime?endTime.split(' ')[0]:''; | ||
116 | + let dateStr=''; | ||
117 | + if(search.value.dateTime && search.value.dateTime.length>0){ | ||
118 | + if(startDateStr!=endDateStr){ | ||
119 | + dateStr='log-syslog-search'; | ||
120 | + }else{ | ||
121 | + dateStr='log-syslog_'+startDateStr; | ||
122 | + | ||
123 | + } | ||
124 | + }else { | ||
125 | + dateStr='log-syslog_'+nowDate; | ||
126 | + } | ||
127 | + | ||
128 | + let params={ | ||
129 | + indexName:dateStr, | ||
130 | + pageNum: search.value.pageNum, | ||
131 | + pageSize: search.value.pageSize, | ||
132 | + type:search.value.type, | ||
133 | + sortBy:search.value.sortBy, | ||
134 | + scopeBy:search.value.scopeBy, | ||
135 | + startTime:startTime, | ||
136 | + endTime: endTime, | ||
137 | + resType:search.value.resType, | ||
138 | + param:{} | ||
139 | + } | ||
140 | + if(search.value.keyword){ | ||
141 | + params.param={ | ||
142 | + 'resName.keyword': search.value.keyword, | ||
143 | + 'host.keyword':search.value.keyword, | ||
144 | + 'message.keyword':search.value.keyword, | ||
145 | + } | ||
146 | + } | ||
147 | + if(search.value.program){ | ||
148 | + params['param']['program.keyword']=search.value.program; | ||
149 | + } | ||
150 | + proxy.$http.post(`/api-web/esData/list`, params, function (res) { | ||
151 | + if (res && res.object) { | ||
152 | + let dataList=res.object.content; | ||
153 | + let arr=[]; | ||
154 | + dataList.map(item=>{ | ||
155 | + arr.push(item[0]) | ||
156 | + }) | ||
157 | + tableData.value.dataList = arr; | ||
158 | + tableData.value.count = parseInt(res.object.total); | ||
159 | + } else { | ||
160 | + tableData.value.dataList = []; | ||
161 | + tableData.value.count = 0; | ||
162 | + } | ||
163 | + }); | ||
164 | + } | ||
165 | + | ||
166 | + let loaddata = ({page, limit}) => { | ||
167 | + search.value.pageNum = page; | ||
168 | + search.value.pageSize = limit; | ||
169 | + getDataList(); | ||
170 | + } | ||
171 | + | ||
172 | + let hideDialog = (flg) => { | ||
173 | + dialog.value.show = flg; | ||
174 | + } | ||
175 | + | ||
176 | + // 处理弹框 | ||
177 | + let handle = (row) =>{ | ||
178 | + hideDialog(true); | ||
179 | + dialog.value.detail = row; | ||
180 | + } | ||
181 | + | ||
182 | + //查看详情 | ||
183 | + let handleView = (row) =>{ | ||
184 | + handle(row); | ||
185 | + } | ||
186 | + //查看资源详情 | ||
187 | + let goResDetail=(resId,resName,resType)=>{ | ||
188 | + proxy.$global.openDetail(resId, resType, proxy); | ||
189 | + | ||
190 | + } | ||
191 | + //日志类型数据 | ||
192 | + let logTypeData=Vue.ref([]); | ||
193 | + let getLogType=()=>{ | ||
194 | + proxy.$http.post(`/api-web/manage/ddic/findSucDdics/LOG_SOURCE_TYPE`, {}, function (res) { | ||
195 | + if (res && res.data) { | ||
196 | + logTypeData.value = res.data; | ||
197 | + } | ||
198 | + }); | ||
199 | + } | ||
200 | + // 挂载完 | ||
201 | + Vue.onMounted(() => { | ||
202 | + getDataList(); | ||
203 | + getLogType(); | ||
204 | + }) | ||
205 | + | ||
206 | + | ||
207 | + return { | ||
208 | + logTypeData, | ||
209 | + getLogType, | ||
210 | + dateTime, | ||
211 | + height, | ||
212 | + search, | ||
213 | + dialog, | ||
214 | + hideDialog, | ||
215 | + handle, | ||
216 | + loaddata, | ||
217 | + tableData, | ||
218 | + getDataList, | ||
219 | + resTypeArr, | ||
220 | + getResType, | ||
221 | + handleView, | ||
222 | + goResDetail, | ||
223 | + getDateTime | ||
224 | + } | ||
225 | + } | ||
226 | + | ||
227 | +} |
@@ -198,6 +198,12 @@ const routes = [{ | @@ -198,6 +198,12 @@ const routes = [{ | ||
198 | name: 'busDoc', | 198 | name: 'busDoc', |
199 | component: () => myImport('views/busDoc/index') | 199 | component: () => myImport('views/busDoc/index') |
200 | }, | 200 | }, |
201 | + //日志 | ||
202 | + { | ||
203 | + path: '/esData', | ||
204 | + name: 'esDataIndex', | ||
205 | + component: () => myImport('views/esData/index'), | ||
206 | + }, | ||
201 | ]; | 207 | ]; |
202 | 208 | ||
203 | // hash模式: createWebHashHistory | 209 | // hash模式: createWebHashHistory |
@@ -359,6 +359,26 @@ layui.define(['view'], function(exports){ | @@ -359,6 +359,26 @@ layui.define(['view'], function(exports){ | ||
359 | //纠正首尾 | 359 | //纠正首尾 |
360 | return href.replace(/^(\/+)/, '/') | 360 | return href.replace(/^(\/+)/, '/') |
361 | .replace(new RegExp('\/' + setter.entry + '$'), '/'); //过滤路由最后的默认视图文件名(如:index) | 361 | .replace(new RegExp('\/' + setter.entry + '$'), '/'); //过滤路由最后的默认视图文件名(如:index) |
362 | + }, | ||
363 | + //封装获取cookie | ||
364 | + getCookie:function(name) { | ||
365 | + var arr, reg = new RegExp("(^| )" + name + "=([^;]*)(;|$)"); | ||
366 | + if (arr = document.cookie.match(reg)) | ||
367 | + return (arr[2]); | ||
368 | + else | ||
369 | + return null; | ||
370 | + }, | ||
371 | + setCookie:function (c_name, value, expiredays) { | ||
372 | + var exdate = new Date(); | ||
373 | + exdate.setDate(exdate.getDate() + expiredays); | ||
374 | + document.cookie = c_name + "=" + escape(value) + ((expiredays == null) ? "" : ";expires=" + exdate.toGMTString()); | ||
375 | + }, | ||
376 | + delCookie:function (name) { | ||
377 | + var exp = new Date(); | ||
378 | + exp.setTime(exp.getTime() - 1); | ||
379 | + var cval = getCookie(name); | ||
380 | + if (cval != null) | ||
381 | + document.cookie = name + "=" + cval + ";expires=" + exp.toGMTString(); | ||
362 | } | 382 | } |
363 | 383 | ||
364 | //…… | 384 | //…… |
@@ -169,7 +169,19 @@ const routes = [{ | @@ -169,7 +169,19 @@ const routes = [{ | ||
169 | path: '/alarmsubscribe/excludeKpi', | 169 | path: '/alarmsubscribe/excludeKpi', |
170 | name: 'alarmSubscribeExcludeKpi', | 170 | name: 'alarmSubscribeExcludeKpi', |
171 | component: () => myImport('views/alarmsubscribe/index') | 171 | component: () => myImport('views/alarmsubscribe/index') |
172 | - } | 172 | + }, |
173 | + //日志 | ||
174 | + { | ||
175 | + path: '/esData', | ||
176 | + name: 'esDataIndex', | ||
177 | + component: () => myImport('views/esData/index'), | ||
178 | + }, | ||
179 | + //监控对接CMDB功能 | ||
180 | + { | ||
181 | + path: '/cmdbdatasync', | ||
182 | + name: 'cmdbdatasync', | ||
183 | + component: () => myImport('views/cmdbdatasync/index'), | ||
184 | + }, | ||
173 | ]; | 185 | ]; |
174 | 186 | ||
175 | // hash模式: createWebHashHistory | 187 | // hash模式: createWebHashHistory |
-
Please register or login to post a comment